在kvm-all.c里面的kvm_init()函数,
会调用kvm_arch_init()函数,
- kvm_get_supported_msrs();
- kvm_get_supported_feature_msrs();
在kvm-all.c里面的kvm_init()函数,
会调用kvm_arch_init()函数,
The scope of an MSR defines the set of processors that access the same MSR with RDMSR and WRMSR.
Thread-scope MSRs are unique to every logical processor; Core-scope MSRs are shared by the threads in the same core; similarly for module-scope, die-scope, and package-scope.
When a processor package contains a single die, die-scope and package-scope are synonymous. When a package contains multiple die, they are distinct。
MSR寄存器的作用域可以是thread,即单个超线程,可以是每个core有单独的,也可以是一个die共用,还是是整个package。
本文为kvm操作MSR寄存器的第四部分,主要介绍kvm trap guest中的wrmsr指令的处理过程。
当guest中因为执行wrmsr指令产生vm exit时,其exit reason为32,相应地最后会调用KVM中的handle_wrmsr()函数。
其函数实现如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19static int handle_wrmsr(struct kvm_vcpu *vcpu)
{
struct msr_data msr;
u32 ecx = vcpu->arch.regs[VCPU_REGS_RCX];
u64 data = (vcpu->arch.regs[VCPU_REGS_RAX] & -1u)
| ((u64)(vcpu->arch.regs[VCPU_REGS_RDX] & -1u) << 32);
msr.data = data;
msr.index = ecx;
msr.host_initiated = false;
if (kvm_set_msr(vcpu, &msr) != 0) {
trace_kvm_msr_write_ex(ecx, data);
kvm_inject_gp(vcpu, 0);
return 1;
}
trace_kvm_msr_write(ecx, data);
return kvm_skip_emulated_instruction(vcpu);
}
在x86.c文件中定一个了msrs_to_save[], emulated_msrs[], msr_based_features[]三个保存MSR寄存器index的数组,
以及num_msrs_to_save, num_emulated_msrs, num_msr_based_features三个静态全局变量来表示以上三个数组的大小。
其中msrs_to_save[]和emulated_msrs[]数组合起来为暴露给userspace的MSRs: userspace(QEMU)通过KVM_GET_MSR_INDEX_LIST ioctl获取,并且之后就可以调用KVM_GET_MSRS, KVM_SET_MSRS对这些MSRs进行读写
msr_based_features[]数组向userspace传递KVM支持的feature-based MSRs.
注意
msr_based_features[]数组和前面2个数组不是互斥的。
即msr_based_features[]数组中的MSR可以同时属于前面两个数组,但msr_to_save[]和emulated_msrs[]是互斥的。
本文为kvm操作MSR寄存器的第二部分,介绍guest中rdmsr指令的处理过程。
之前在(一)中有介绍,如果对guest设置了Use MSR bitmaps VM-execution control bit,那么Read bitmap for low MSRs(0000 0000H - 0000 1FFFH)和Read bitmap for high MSRs(C000 0000H - C000 1FFFH)范围中的为0的bit对应的地址的MSR在执行rdmsr的时候不会产生VM EXIT。
其他情况,运行rdmsr均会触发VM exit,最后会进入vmx.c中的handle_rdmsr()函数。
本文介绍KVM中percpu变量shared_msrs,以及其相关的一些的数据结构。
其最终是为了在VM entry和VM exit的时候切换host和guest之间几个重要的MSR的值。
CPL,DPL,RPL的取值为0,1,2,3.数值越大,特权级越低。
当要访问数据段中的操作数的时候,数据段(data segment)对应的段选择符(segment selector)必须加载到对应的数据段寄存器(data segment registers, DS, ES, FS or GS)或者堆栈段(stack-segment register,SS)。
在加载的时候,需要进行特权级检查,需要对比当前正在运行的程序的CPL,目标操作数所在段的段选择符的RPL,以及目标操作数所在段的段描述符的DPL
只有当CPL <= DPL && RPL <= DPL,目标操作数所在的段才会加载成功,否则产生一个GP,general protection.
kvm_main.c中的init函数首先会调用,kvm_arch_init(opaque);