硬件虚拟化之vmm接管异常中断

本文深入探讨了KVM虚拟机中VMM如何接管VCPU的中断和异常行为,详细介绍了VCPU退出状态记录的过程,以及如何通过设置VMCS配置来实现中断接管。

上一篇讲到了虚拟cpu的构建过程,接下来就要利用vmm接管vcpu的中断,异常等行为。

一、vcpu退出状态记录

struct kvm_vcpu *vcpu_k;
kvm_run->exit_reason


/* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
struct kvm_run {
	/* in */
	__u8 request_interrupt_window;
	__u8 padding1[7];

	/* out */
	__u32 exit_reason;
.......



#define KVM_EXIT_UNKNOWN          0
#define KVM_EXIT_EXCEPTION        1
#define KVM_EXIT_IO               2
#define KVM_EXIT_HYPERCALL        3
#define KVM_EXIT_DEBUG            4
#define KVM_EXIT_HLT              5
#define KVM_EXIT_MMIO             6
#define KVM_EXIT_IRQ_WINDOW_OPEN  7
#define KVM_EXIT_SHUTDOWN         8
#define KVM_EXIT_FAIL_ENTRY       9
#define KVM_EXIT_INTR             10
#define KVM_EXIT_SET_TPR          11
#define KVM_EXIT_TPR_ACCESS       12
vcpu_init
    kvm_vm_create_vcpu
        vmx_create_vcpu
            kvm_vcpu_init_vt

void vcpu_init(struct vm *vm, struct vcpu *vcpu)
{
	int vcpu_mmap_size;
    long r = 0;
	if(vm->kvm)
		r= kvm_vm_create_vcpu(vm->kvm, 0);
	vcpu->vcpu_k = vm->kvm->vcpus[0];
	vcpu->kvm_run = vcpu->vcpu_k->run;

kvm_run 记录了vcpu 运行的各种状态,并且在create_vcpu的时候进行了初始化,分配了page。

int run_vm(struct vm *vm, struct vcpu *vcpu, size_t sz)
{
    struct kvm_vcpu *vcpu_k;
	struct kvm_regs regs;
	uint64_t memval = 0;
    //long r =0;
    vcpu_k = vcpu->vcpu_k;
	for (;;) {
		if (kvm_vcpu_ioctl_s(vcpu_k, (unsigned int)KVM_RUN, 0) < 0) {
			printk("KVM_RUN error \n");
			return -1;
		}
		printk("exit_reason %lx\n", vcpu->kvm_run);
		switch (vcpu->kvm_run->exit_reason) {
		case KVM_EXIT_HLT:
		 	goto check;

		case KVM_EXIT_IO:
		// 	if (vcpu->kvm_run->io.direction == KVM_EXIT_IO_OUT
		// 	    && vcpu->kvm_run->io.port == 0xE9) {
		// 		//char *p = (char *)vcpu->kvm_run;
		// 		// fwrite(p + vcpu->kvm_run->io.data_offset,
		// 		//        vcpu->kvm_run->io.size, 1, stdout);
		// 		// fflush(stdout);
		// 		continue;
		// 	}

			/* fall through */
		default:
			//printk(	"Got exit_reason %d,"
			//	" expected KVM_EXIT_HLT (%d)\n",
			//	vcpu->kvm_run->exit_reason, KVM_EXIT_HLT);
			return 0;
		}
	}

 check:
	if (kvm_vcpu_ioctl_s(vcpu_k,(unsigned int)KVM_GET_REGS, (unsigned long)&regs) < 0) {
		printk("KVM_GET_REGS error \n");
		return 0;
	}
	printk("excute success \n");
	return 1;
}

由于虚拟机和VMM存在同一份代码,vcpu运行的的逻辑需要区别于VMM。我们需要标记vcpu的状态,处于vcpu将不运行VMM的vm_run逻辑,而跟模式将会进行中断检测处理。

 

二、kvm中的vm_exit逻辑

int kvm_emulate_halt(struct kvm_vcpu *vcpu)
{
	++vcpu->stat.halt_exits;
	if (irqchip_in_kernel(vcpu->kvm)) {
		vcpu->arch.mp_state = VCPU_MP_STATE_HALTED;
		kvm_vcpu_block(vcpu);
		if (vcpu->arch.mp_state != VCPU_MP_STATE_RUNNABLE)
			return -EINTR;
		return 1;
	} else {
		vcpu->run->exit_reason = KVM_EXIT_HLT;
		return 0;
	}
}

static int handle_halt(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
	skip_emulated_instruction(vcpu);
	return kvm_emulate_halt(vcpu);
}

handle_exception
    kvm_emulate_halt(vcpu);


static int halt_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
{
	svm->next_rip = svm->vmcb->save.rip + 1;
	skip_emulated_instruction(&svm->vcpu);
	return kvm_emulate_halt(&svm->vcpu);
}

 

__vcpu_run
    kvm_x86_ops_vt->prepare_guest_switch(vcpu);
    kvm_x86_ops_vt->run(vcpu, kvm_run);

但是,中断这里还没反应。

 

三、判断代码运行状态

首先我们的代码会运行在两种状态下,跟模式状态,非根模式状态。


static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigne
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值