vmcs.c
来自「xen虚拟机源代码安装包」· C语言 代码 · 共 1,066 行 · 第 1/3 页
C
1,066 行
{ struct list_head *active_vmcs_list = &this_cpu(active_vmcs_list); unsigned long flags; local_irq_save(flags); while ( !list_empty(active_vmcs_list) ) __vmx_clear_vmcs(list_entry(active_vmcs_list->next, struct vcpu, arch.hvm_vmx.active_list)); BUG_ON(!(read_cr4() & X86_CR4_VMXE)); __vmxoff(); local_irq_restore(flags);}struct foreign_vmcs { struct vcpu *v; unsigned int count;};static DEFINE_PER_CPU(struct foreign_vmcs, foreign_vmcs);void vmx_vmcs_enter(struct vcpu *v){ struct foreign_vmcs *fv; /* * NB. We must *always* run an HVM VCPU on its own VMCS, except for * vmx_vmcs_enter/exit critical regions. */ if ( likely(v == current) ) return; fv = &this_cpu(foreign_vmcs); if ( fv->v == v ) { BUG_ON(fv->count == 0); } else { BUG_ON(fv->v != NULL); BUG_ON(fv->count != 0); vcpu_pause(v); spin_lock(&v->arch.hvm_vmx.vmcs_lock); vmx_clear_vmcs(v); vmx_load_vmcs(v); fv->v = v; } fv->count++;}void vmx_vmcs_exit(struct vcpu *v){ struct foreign_vmcs *fv; if ( likely(v == current) ) return; fv = &this_cpu(foreign_vmcs); BUG_ON(fv->v != v); BUG_ON(fv->count == 0); if ( --fv->count == 0 ) { /* Don't confuse vmx_do_resume (for @v or @current!) */ vmx_clear_vmcs(v); if ( is_hvm_vcpu(current) ) vmx_load_vmcs(current); spin_unlock(&v->arch.hvm_vmx.vmcs_lock); vcpu_unpause(v); fv->v = NULL; }}struct xgt_desc { unsigned short size; unsigned long address __attribute__((packed));};static void vmx_set_host_env(struct vcpu *v){ unsigned int cpu = smp_processor_id(); __vmwrite(HOST_IDTR_BASE, (unsigned long)idt_tables[cpu]); __vmwrite(HOST_TR_SELECTOR, __TSS(cpu) << 3); __vmwrite(HOST_TR_BASE, (unsigned long)&init_tss[cpu]); __vmwrite(HOST_SYSENTER_ESP, get_stack_bottom()); /* * Skip end of cpu_user_regs when entering the hypervisor because the * CPU does not save context onto the stack. SS,RSP,CS,RIP,RFLAGS,etc * all get saved into the VMCS instead. */ __vmwrite(HOST_RSP, (unsigned long)&get_cpu_info()->guest_cpu_user_regs.error_code);}void vmx_disable_intercept_for_msr(struct vcpu *v, u32 msr){ unsigned long *msr_bitmap = v->arch.hvm_vmx.msr_bitmap; /* VMX MSR bitmap supported? */ if ( msr_bitmap == NULL ) return; /* * See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals * have the write-low and read-high bitmap offsets the wrong way round. * We can control MSRs 0x00000000-0x00001fff and 0xc0000000-0xc0001fff. */ if ( msr <= 0x1fff ) { __clear_bit(msr, msr_bitmap + 0x000/BYTES_PER_LONG); /* read-low */ __clear_bit(msr, msr_bitmap + 0x800/BYTES_PER_LONG); /* write-low */ } else if ( (msr >= 0xc0000000) && (msr <= 0xc0001fff) ) { msr &= 0x1fff; __clear_bit(msr, msr_bitmap + 0x400/BYTES_PER_LONG); /* read-high */ __clear_bit(msr, msr_bitmap + 0xc00/BYTES_PER_LONG); /* write-high */ }}static int construct_vmcs(struct vcpu *v){ struct domain *d = v->domain; uint16_t sysenter_cs; unsigned long sysenter_eip; vmx_vmcs_enter(v); /* VMCS controls. */ __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control); __vmwrite(VM_EXIT_CONTROLS, vmx_vmexit_control); __vmwrite(VM_ENTRY_CONTROLS, vmx_vmentry_control); v->arch.hvm_vmx.exec_control = vmx_cpu_based_exec_control; v->arch.hvm_vmx.secondary_exec_control = vmx_secondary_exec_control; if ( paging_mode_hap(d) ) { v->arch.hvm_vmx.exec_control &= ~(CPU_BASED_INVLPG_EXITING | CPU_BASED_CR3_LOAD_EXITING | CPU_BASED_CR3_STORE_EXITING); } else { v->arch.hvm_vmx.secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_EPT; } __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vmx.exec_control); if ( cpu_has_vmx_secondary_exec_control ) __vmwrite(SECONDARY_VM_EXEC_CONTROL, v->arch.hvm_vmx.secondary_exec_control); /* MSR access bitmap. */ if ( cpu_has_vmx_msr_bitmap ) { unsigned long *msr_bitmap = alloc_xenheap_page(); if ( msr_bitmap == NULL ) return -ENOMEM; memset(msr_bitmap, ~0, PAGE_SIZE); v->arch.hvm_vmx.msr_bitmap = msr_bitmap; __vmwrite(MSR_BITMAP, virt_to_maddr(msr_bitmap)); vmx_disable_intercept_for_msr(v, MSR_FS_BASE); vmx_disable_intercept_for_msr(v, MSR_GS_BASE); vmx_disable_intercept_for_msr(v, MSR_IA32_SYSENTER_CS); vmx_disable_intercept_for_msr(v, MSR_IA32_SYSENTER_ESP); vmx_disable_intercept_for_msr(v, MSR_IA32_SYSENTER_EIP); } /* I/O access bitmap. */ __vmwrite(IO_BITMAP_A, virt_to_maddr((char *)hvm_io_bitmap + 0)); __vmwrite(IO_BITMAP_B, virt_to_maddr((char *)hvm_io_bitmap + PAGE_SIZE)); /* Host GDTR base. */ __vmwrite(HOST_GDTR_BASE, GDT_VIRT_START(v)); /* Host data selectors. */ __vmwrite(HOST_SS_SELECTOR, __HYPERVISOR_DS); __vmwrite(HOST_DS_SELECTOR, __HYPERVISOR_DS); __vmwrite(HOST_ES_SELECTOR, __HYPERVISOR_DS); __vmwrite(HOST_FS_SELECTOR, 0); __vmwrite(HOST_GS_SELECTOR, 0); __vmwrite(HOST_FS_BASE, 0); __vmwrite(HOST_GS_BASE, 0); /* Host control registers. */ v->arch.hvm_vmx.host_cr0 = read_cr0() | X86_CR0_TS; __vmwrite(HOST_CR0, v->arch.hvm_vmx.host_cr0); __vmwrite(HOST_CR4, mmu_cr4_features); /* Host CS:RIP. */ __vmwrite(HOST_CS_SELECTOR, __HYPERVISOR_CS); __vmwrite(HOST_RIP, (unsigned long)vmx_asm_vmexit_handler); /* Host SYSENTER CS:RIP. */ rdmsrl(MSR_IA32_SYSENTER_CS, sysenter_cs); __vmwrite(HOST_SYSENTER_CS, sysenter_cs); rdmsrl(MSR_IA32_SYSENTER_EIP, sysenter_eip); __vmwrite(HOST_SYSENTER_EIP, sysenter_eip); /* MSR intercepts. */ __vmwrite(VM_EXIT_MSR_LOAD_COUNT, 0); __vmwrite(VM_EXIT_MSR_STORE_COUNT, 0); __vmwrite(VM_ENTRY_MSR_LOAD_COUNT, 0); __vmwrite(VM_ENTRY_INTR_INFO, 0); __vmwrite(CR0_GUEST_HOST_MASK, ~0UL); __vmwrite(CR4_GUEST_HOST_MASK, ~0UL); __vmwrite(PAGE_FAULT_ERROR_CODE_MASK, 0); __vmwrite(PAGE_FAULT_ERROR_CODE_MATCH, 0); __vmwrite(CR3_TARGET_COUNT, 0); __vmwrite(GUEST_ACTIVITY_STATE, 0); /* Guest segment bases. */ __vmwrite(GUEST_ES_BASE, 0); __vmwrite(GUEST_SS_BASE, 0); __vmwrite(GUEST_DS_BASE, 0); __vmwrite(GUEST_FS_BASE, 0); __vmwrite(GUEST_GS_BASE, 0); __vmwrite(GUEST_CS_BASE, 0); /* Guest segment limits. */ __vmwrite(GUEST_ES_LIMIT, ~0u); __vmwrite(GUEST_SS_LIMIT, ~0u); __vmwrite(GUEST_DS_LIMIT, ~0u); __vmwrite(GUEST_FS_LIMIT, ~0u); __vmwrite(GUEST_GS_LIMIT, ~0u); __vmwrite(GUEST_CS_LIMIT, ~0u); /* Guest segment AR bytes. */ __vmwrite(GUEST_ES_AR_BYTES, 0xc093); /* read/write, accessed */ __vmwrite(GUEST_SS_AR_BYTES, 0xc093); __vmwrite(GUEST_DS_AR_BYTES, 0xc093); __vmwrite(GUEST_FS_AR_BYTES, 0xc093); __vmwrite(GUEST_GS_AR_BYTES, 0xc093); __vmwrite(GUEST_CS_AR_BYTES, 0xc09b); /* exec/read, accessed */ /* Guest IDT. */ __vmwrite(GUEST_IDTR_BASE, 0); __vmwrite(GUEST_IDTR_LIMIT, 0); /* Guest GDT. */ __vmwrite(GUEST_GDTR_BASE, 0); __vmwrite(GUEST_GDTR_LIMIT, 0); /* Guest LDT. */ __vmwrite(GUEST_LDTR_AR_BYTES, 0x0082); /* LDT */ __vmwrite(GUEST_LDTR_SELECTOR, 0); __vmwrite(GUEST_LDTR_BASE, 0); __vmwrite(GUEST_LDTR_LIMIT, 0); /* Guest TSS. */ __vmwrite(GUEST_TR_AR_BYTES, 0x008b); /* 32-bit TSS (busy) */ __vmwrite(GUEST_TR_BASE, 0); __vmwrite(GUEST_TR_LIMIT, 0xff); __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0); __vmwrite(GUEST_DR7, 0); __vmwrite(VMCS_LINK_POINTER, ~0UL);#if defined(__i386__) __vmwrite(VMCS_LINK_POINTER_HIGH, ~0UL);#endif __vmwrite(EXCEPTION_BITMAP, HVM_TRAP_MASK | (paging_mode_hap(d) ? 0 : (1U << TRAP_page_fault)) | (1U << TRAP_no_device)); v->arch.hvm_vcpu.guest_cr[0] = X86_CR0_PE | X86_CR0_ET; hvm_update_guest_cr(v, 0); v->arch.hvm_vcpu.guest_cr[4] = 0; hvm_update_guest_cr(v, 4); if ( cpu_has_vmx_tpr_shadow ) { __vmwrite(VIRTUAL_APIC_PAGE_ADDR, page_to_maddr(vcpu_vlapic(v)->regs_page)); __vmwrite(TPR_THRESHOLD, 0); } if ( paging_mode_hap(d) ) { __vmwrite(EPT_POINTER, d->arch.hvm_domain.vmx.ept_control.eptp);#ifdef __i386__ __vmwrite(EPT_POINTER_HIGH, d->arch.hvm_domain.vmx.ept_control.eptp >> 32);#endif } if ( cpu_has_vmx_vpid ) { v->arch.hvm_vmx.vpid = v->domain->arch.hvm_domain.vmx.vpid_base + v->vcpu_id; __vmwrite(VIRTUAL_PROCESSOR_ID, v->arch.hvm_vmx.vpid); } vmx_vmcs_exit(v); paging_update_paging_modes(v); /* will update HOST & GUEST_CR3 as reqd */ vmx_vlapic_msr_changed(v); return 0;}int vmx_read_guest_msr(u32 msr, u64 *val){ struct vcpu *curr = current; unsigned int i, msr_count = curr->arch.hvm_vmx.msr_count; const struct vmx_msr_entry *msr_area = curr->arch.hvm_vmx.msr_area; for ( i = 0; i < msr_count; i++ ) { if ( msr_area[i].index == msr ) { *val = msr_area[i].data; return 0; } } return -ESRCH;}int vmx_write_guest_msr(u32 msr, u64 val){ struct vcpu *curr = current; unsigned int i, msr_count = curr->arch.hvm_vmx.msr_count; struct vmx_msr_entry *msr_area = curr->arch.hvm_vmx.msr_area; for ( i = 0; i < msr_count; i++ ) { if ( msr_area[i].index == msr ) { msr_area[i].data = val; return 0; } }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?