设为首页 收藏本站
查看: 1759|回复: 0

[经验分享] 【kvm】流程解析学习和实践

[复制链接]

尚未签到

发表于 2015-10-10 09:48:13 | 显示全部楼层 |阅读模式
今天制作一个简单的kvm模型,并制作个简单的kernel用于执行,主要是了解kvm的io虚拟化,用于学你kvm的工作过程。
kvm是一个经过修改的qemu,kvm利用硬件虚拟化技术为qemu提供加速,主要有cpu虚拟化和内存虚拟化。qemu为kvm提供io的虚拟化
一下就是kvm中几个重要的函数,并且一会儿会用到
kvm_context_t  kvm_init(struct kvm_callbacks   *callbacks,
void                   *opaque);
int            kvm_create(kvm_context_t  kvm,
unsigned long  phys_mem_bytes,
void           **phys_mem);
int            kvm_create_vcpu(kvm_context_t  kvm,
int            slot);
void           *kvm_create_phys_mem(kvm_context_t  kvm,
unsigned long  phys_start,
unsigned long  len,
int            log,
int            writable);
int            kvm_run(kvm_context_t  kvm,
int            vcpu);




首先创建一个KVM进程,需要利用kvm_init函数,函数的第一个参数就是kvm_callbacks这是一个回调函数,就是当虚拟机执行了一些特权指令或者io指令是将会执行回调函数中内容。如果是io指令将会退出客户模式进入用户模式的qemu中模拟,并调用相应的函数。函数具体声明在libkvm.h
代码
之后调用kvm_create(),函数第二个参数是RAM大小和加载的程序地址。此时会为虚拟机分配一个vcpu。这个函数调用时并不会分配内存
调用kvm_create_vcpu()创建虚拟cpu。个数0-65。此函数由某线程调用添加vcpu的个数
kvm_create_phys_mem()是为虚拟机分配内存有几种方法之一
之后调用kvm_run启动vcpu和虚拟机,这个函数并不会返回,除非遇到1、io处理程序没有处理成功2、出现了一个kvm和虚拟机都无法处理的情况。
模拟kvm代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <libkvm.h>
#ifndef __RUNTIME_H__
#define __RUNTIME_H__
// port to use for general purpose output
#define IO_PORT_PSEUDO_SERIAL  0xf1
#endif /* __RUNTIME_H_ */
/* callback definitions as shown in Listing 2 go here */
static int my_inb(void *opaque, int16_t addr, uint8_t *data)
{ puts (&quot;inb&quot;); return 0; }
static int my_inw(void *opaque, uint16_t addr, uint16_t *data)
{ puts (&quot;inw&quot;); return 0; }
static int my_inl(void *opaque, uint16_t addr, uint32_t *data)
{ puts (&quot;inl&quot;); return 0; }
static int my_outb(void *opaque, uint16_t addr, uint8_t data)
{
if (addr == IO_PORT_PSEUDO_SERIAL)
if (isprint(data) || data == '\n')
putchar(data);
else
putchar('.');
else
printf(&quot;outb: %x, %d\n&quot;, addr, data);
fflush (NULL);
return 0;
}
static int my_outw(void *opaque, uint16_t addr, uint16_t data)
{ puts (&quot;outw&quot;); return 0; }
static int my_outl (void *opaque, uint16_t addr, uint32_t data)
{ puts (&quot;outl&quot;); return 0; }
static int my_pre_kvm_run(void *opaque, int vcpu)
{ return 0; }
static struct kvm_callbacks my_callbacks = {
.inb                 = my_inb,
.inw                 = my_inw,
.inl                 = my_inl,
.outb                = my_outb,
.outw                = my_outw,
.outl                = my_outl,
.pre_kvm_run         = my_pre_kvm_run,
};
void load_file(void *mem, const char *filename)
{
int  fd;
int  nr;
fd = open(filename, O_RDONLY);
if (fd == -1) {
fprintf(stderr, &quot;Cannot open %s&quot;, filename);
perror(&quot;open&quot;);
exit(1);
}
while ((nr = read(fd, mem, 4096)) != -1  &&  nr != 0)
mem += nr;
if (nr == -1) {
perror(&quot;read&quot;);
exit(1);
}
close(fd);
}
#define MEMORY_SIZE     (0x1000000)     /* 16 Mb */
#define FIRST_VCPU      (0)
int main(int argc, char *argv[])
{
kvm_context_t  kvm;
void           *memory_area;
/* Second argument is an opaque, we don't use it yet */
kvm = kvm_init(&my_callbacks, NULL);
if (!kvm) {
fprintf(stderr, &quot;KVM init failed&quot;);
exit(1);
}
if (kvm_create(kvm, MEMORY_SIZE, &memory_area) != 0) {
fprintf(stderr, &quot;VM creation failed&quot;);
exit(1);
}
#ifndef KVM_VERSION_LESS_THAN_65
if (kvm_create_vcpu(kvm, FIRST_VCPU)) {
fprintf(stderr, &quot;VCPU creation failed&quot;);
exit(1);
}
#endif
memory_area = kvm_create_phys_mem(kvm, 0, MEMORY_SIZE, 0, 1);
load_file(memory_area + 0xf0000, argv[1]);
kvm_run(kvm, FIRST_VCPU);
return 0;
}连接器代码

OUTPUT_FORMAT(binary)
SECTIONS {
. = 0;
.text : { *(.init) *(.text) }
. = ALIGN(4K);
.data : { *(.data) }
. = ALIGN(16);
.bss : { *(.bss) }
. = ALIGN(4K);
.edata = .;
}制作镜像代码:

#ifndef __RUNTIME_H__
#define __RUNTIME_H__
// port to use for general purpose output
#define IO_PORT_PSEUDO_SERIAL  0xf1
#endif /* __RUNTIME_H_ */
.code16
start:
mov    $0x48,%al    // H
outb   %al,$IO_PORT_PSEUDO_SERIAL
mov    $0x65,%al    // e
outb   %al,$IO_PORT_PSEUDO_SERIAL
mov    $0x6c,%al    // l
outb   %al,$IO_PORT_PSEUDO_SERIAL
mov    $0x6c,%al    // l
outb   %al,$IO_PORT_PSEUDO_SERIAL
mov    $0x6f,%al    // o
outb   %al,$IO_PORT_PSEUDO_SERIAL
mov    $0x0a,%al    // new_line
outb   %al,$IO_PORT_PSEUDO_SERIAL
hlt                 // halt the processor
. = 0xfff0
ljmp    $0xf000, $startMakefile

# If KVM was compiled from sources and you have errors about
# missing asm/kvm*.h files, copy them from
# kvm-XX/kernel/include/asm/* to {prefix}/include/asm/
CC=gcc
KERNEL16_CFLAGS=-nostdlib -ffreestanding -Wl,-T,kernel16.lds
all:    launcher kernel2
launcher: launcher.o
$(CC) launcher.o /usr/lib/libkvm.a -o launcher
launcher.o:
kernel2: kernel2.S
$(CC) $(KERNEL16_CFLAGS) kernel2.S -o kernel1
clean:
rm *.o launcher kernel1制作内核
gcc -nostdlib -Wl,-T,kernel16.lds kernel1.S -o kernel1执行
./launcher kernel1

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-124963-1-1.html 上篇帖子: KVM虚拟化技术浅析 下篇帖子: Xen 和 KVM的比较,那个更好呢?
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表