Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm into next
Pull KVM updates from Paolo Bonzini: "At over 200 commits, covering almost all supported architectures, this was a pretty active cycle for KVM. Changes include: - a lot of s390 changes: optimizations, support for migration, GDB support and more - ARM changes are pretty small: support for the PSCI 0.2 hypercall interface on both the guest and the host (the latter acked by Catalin) - initial POWER8 and little-endian host support - support for running u-boot on embedded POWER targets - pretty large changes to MIPS too, completing the userspace interface and improving the handling of virtualized timer hardware - for x86, a larger set of changes is scheduled for 3.17. Still, we have a few emulator bugfixes and support for running nested fully-virtualized Xen guests (para-virtualized Xen guests have always worked). And some optimizations too. The only missing architecture here is ia64. It's not a coincidence that support for KVM on ia64 is scheduled for removal in 3.17" * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (203 commits) KVM: add missing cleanup_srcu_struct KVM: PPC: Book3S PR: Rework SLB switching code KVM: PPC: Book3S PR: Use SLB entry 0 KVM: PPC: Book3S HV: Fix machine check delivery to guest KVM: PPC: Book3S HV: Work around POWER8 performance monitor bugs KVM: PPC: Book3S HV: Make sure we don't miss dirty pages KVM: PPC: Book3S HV: Fix dirty map for hugepages KVM: PPC: Book3S HV: Put huge-page HPTEs in rmap chain for base address KVM: PPC: Book3S HV: Fix check for running inside guest in global_invalidates() KVM: PPC: Book3S: Move KVM_REG_PPC_WORT to an unused register number KVM: PPC: Book3S: Add ONE_REG register names that were missed KVM: PPC: Add CAP to indicate hcall fixes KVM: PPC: MPIC: Reset IRQ source private members KVM: PPC: Graciously fail broken LE hypercalls PPC: ePAPR: Fix hypercall on LE guest KVM: PPC: BOOK3S: Remove open coded make_dsisr in alignment handler KVM: PPC: BOOK3S: Always use the saved DAR value PPC: KVM: Make NX bit available with magic page KVM: PPC: Disable NX for old magic page using guests KVM: PPC: BOOK3S: HV: Add mixed page-size support for guest ...
This commit is contained in:
@@ -354,6 +354,7 @@ struct vmcs02_list {
|
||||
struct nested_vmx {
|
||||
/* Has the level1 guest done vmxon? */
|
||||
bool vmxon;
|
||||
gpa_t vmxon_ptr;
|
||||
|
||||
/* The guest-physical address of the current VMCS L1 keeps for L2 */
|
||||
gpa_t current_vmptr;
|
||||
@@ -413,7 +414,6 @@ struct vcpu_vmx {
|
||||
struct kvm_vcpu vcpu;
|
||||
unsigned long host_rsp;
|
||||
u8 fail;
|
||||
u8 cpl;
|
||||
bool nmi_known_unmasked;
|
||||
u32 exit_intr_info;
|
||||
u32 idt_vectoring_info;
|
||||
@@ -2283,7 +2283,7 @@ static __init void nested_vmx_setup_ctls_msrs(void)
|
||||
rdmsr(MSR_IA32_VMX_EXIT_CTLS,
|
||||
nested_vmx_exit_ctls_low, nested_vmx_exit_ctls_high);
|
||||
nested_vmx_exit_ctls_low = VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR;
|
||||
/* Note that guest use of VM_EXIT_ACK_INTR_ON_EXIT is not supported. */
|
||||
|
||||
nested_vmx_exit_ctls_high &=
|
||||
#ifdef CONFIG_X86_64
|
||||
VM_EXIT_HOST_ADDR_SPACE_SIZE |
|
||||
@@ -2291,7 +2291,8 @@ static __init void nested_vmx_setup_ctls_msrs(void)
|
||||
VM_EXIT_LOAD_IA32_PAT | VM_EXIT_SAVE_IA32_PAT;
|
||||
nested_vmx_exit_ctls_high |= VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR |
|
||||
VM_EXIT_LOAD_IA32_EFER | VM_EXIT_SAVE_IA32_EFER |
|
||||
VM_EXIT_SAVE_VMX_PREEMPTION_TIMER;
|
||||
VM_EXIT_SAVE_VMX_PREEMPTION_TIMER | VM_EXIT_ACK_INTR_ON_EXIT;
|
||||
|
||||
if (vmx_mpx_supported())
|
||||
nested_vmx_exit_ctls_high |= VM_EXIT_CLEAR_BNDCFGS;
|
||||
|
||||
@@ -2353,12 +2354,11 @@ static __init void nested_vmx_setup_ctls_msrs(void)
|
||||
VMX_EPT_INVEPT_BIT;
|
||||
nested_vmx_ept_caps &= vmx_capability.ept;
|
||||
/*
|
||||
* Since invept is completely emulated we support both global
|
||||
* and context invalidation independent of what host cpu
|
||||
* supports
|
||||
* For nested guests, we don't do anything specific
|
||||
* for single context invalidation. Hence, only advertise
|
||||
* support for global context invalidation.
|
||||
*/
|
||||
nested_vmx_ept_caps |= VMX_EPT_EXTENT_GLOBAL_BIT |
|
||||
VMX_EPT_EXTENT_CONTEXT_BIT;
|
||||
nested_vmx_ept_caps |= VMX_EPT_EXTENT_GLOBAL_BIT;
|
||||
} else
|
||||
nested_vmx_ept_caps = 0;
|
||||
|
||||
@@ -3186,10 +3186,6 @@ static void enter_pmode(struct kvm_vcpu *vcpu)
|
||||
fix_pmode_seg(vcpu, VCPU_SREG_DS, &vmx->rmode.segs[VCPU_SREG_DS]);
|
||||
fix_pmode_seg(vcpu, VCPU_SREG_FS, &vmx->rmode.segs[VCPU_SREG_FS]);
|
||||
fix_pmode_seg(vcpu, VCPU_SREG_GS, &vmx->rmode.segs[VCPU_SREG_GS]);
|
||||
|
||||
/* CPL is always 0 when CPU enters protected mode */
|
||||
__set_bit(VCPU_EXREG_CPL, (ulong *)&vcpu->arch.regs_avail);
|
||||
vmx->cpl = 0;
|
||||
}
|
||||
|
||||
static void fix_rmode_seg(int seg, struct kvm_segment *save)
|
||||
@@ -3591,22 +3587,14 @@ static int vmx_get_cpl(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
|
||||
if (!is_protmode(vcpu))
|
||||
if (unlikely(vmx->rmode.vm86_active))
|
||||
return 0;
|
||||
|
||||
if (!is_long_mode(vcpu)
|
||||
&& (kvm_get_rflags(vcpu) & X86_EFLAGS_VM)) /* if virtual 8086 */
|
||||
return 3;
|
||||
|
||||
if (!test_bit(VCPU_EXREG_CPL, (ulong *)&vcpu->arch.regs_avail)) {
|
||||
__set_bit(VCPU_EXREG_CPL, (ulong *)&vcpu->arch.regs_avail);
|
||||
vmx->cpl = vmx_read_guest_seg_selector(vmx, VCPU_SREG_CS) & 3;
|
||||
else {
|
||||
int ar = vmx_read_guest_seg_ar(vmx, VCPU_SREG_SS);
|
||||
return AR_DPL(ar);
|
||||
}
|
||||
|
||||
return vmx->cpl;
|
||||
}
|
||||
|
||||
|
||||
static u32 vmx_segment_access_rights(struct kvm_segment *var)
|
||||
{
|
||||
u32 ar;
|
||||
@@ -3634,8 +3622,6 @@ static void vmx_set_segment(struct kvm_vcpu *vcpu,
|
||||
const struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
|
||||
|
||||
vmx_segment_cache_clear(vmx);
|
||||
if (seg == VCPU_SREG_CS)
|
||||
__clear_bit(VCPU_EXREG_CPL, (ulong *)&vcpu->arch.regs_avail);
|
||||
|
||||
if (vmx->rmode.vm86_active && seg != VCPU_SREG_LDTR) {
|
||||
vmx->rmode.segs[seg] = *var;
|
||||
@@ -4564,6 +4550,16 @@ static bool nested_exit_on_intr(struct kvm_vcpu *vcpu)
|
||||
PIN_BASED_EXT_INTR_MASK;
|
||||
}
|
||||
|
||||
/*
|
||||
* In nested virtualization, check if L1 has set
|
||||
* VM_EXIT_ACK_INTR_ON_EXIT
|
||||
*/
|
||||
static bool nested_exit_intr_ack_set(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return get_vmcs12(vcpu)->vm_exit_controls &
|
||||
VM_EXIT_ACK_INTR_ON_EXIT;
|
||||
}
|
||||
|
||||
static bool nested_exit_on_nmi(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return get_vmcs12(vcpu)->pin_based_vm_exec_control &
|
||||
@@ -4878,6 +4874,9 @@ static int handle_exception(struct kvm_vcpu *vcpu)
|
||||
(KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))) {
|
||||
vcpu->arch.dr6 &= ~15;
|
||||
vcpu->arch.dr6 |= dr6;
|
||||
if (!(dr6 & ~DR6_RESERVED)) /* icebp */
|
||||
skip_emulated_instruction(vcpu);
|
||||
|
||||
kvm_queue_exception(vcpu, DB_VECTOR);
|
||||
return 1;
|
||||
}
|
||||
@@ -5166,7 +5165,7 @@ static int handle_dr(struct kvm_vcpu *vcpu)
|
||||
return 1;
|
||||
kvm_register_write(vcpu, reg, val);
|
||||
} else
|
||||
if (kvm_set_dr(vcpu, dr, vcpu->arch.regs[reg]))
|
||||
if (kvm_set_dr(vcpu, dr, kvm_register_read(vcpu, reg)))
|
||||
return 1;
|
||||
|
||||
skip_emulated_instruction(vcpu);
|
||||
@@ -5439,7 +5438,7 @@ static int handle_task_switch(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
|
||||
/* clear all local breakpoint enable flags */
|
||||
vmcs_writel(GUEST_DR7, vmcs_readl(GUEST_DR7) & ~55);
|
||||
vmcs_writel(GUEST_DR7, vmcs_readl(GUEST_DR7) & ~0x55);
|
||||
|
||||
/*
|
||||
* TODO: What about debug traps on tss switch?
|
||||
@@ -5565,6 +5564,10 @@ static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
|
||||
gpa_t gpa;
|
||||
|
||||
gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
|
||||
if (!kvm_io_bus_write(vcpu->kvm, KVM_FAST_MMIO_BUS, gpa, 0, NULL)) {
|
||||
skip_emulated_instruction(vcpu);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = handle_mmio_page_fault_common(vcpu, gpa, true);
|
||||
if (likely(ret == RET_MMIO_PF_EMULATE))
|
||||
@@ -5669,12 +5672,24 @@ static int handle_pause(struct kvm_vcpu *vcpu)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int handle_invalid_op(struct kvm_vcpu *vcpu)
|
||||
static int handle_nop(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
kvm_queue_exception(vcpu, UD_VECTOR);
|
||||
skip_emulated_instruction(vcpu);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int handle_mwait(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
printk_once(KERN_WARNING "kvm: MWAIT instruction emulated as NOP!\n");
|
||||
return handle_nop(vcpu);
|
||||
}
|
||||
|
||||
static int handle_monitor(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
printk_once(KERN_WARNING "kvm: MONITOR instruction emulated as NOP!\n");
|
||||
return handle_nop(vcpu);
|
||||
}
|
||||
|
||||
/*
|
||||
* To run an L2 guest, we need a vmcs02 based on the L1-specified vmcs12.
|
||||
* We could reuse a single VMCS for all the L2 guests, but we also want the
|
||||
@@ -5811,6 +5826,154 @@ static enum hrtimer_restart vmx_preemption_timer_fn(struct hrtimer *timer)
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode the memory-address operand of a vmx instruction, as recorded on an
|
||||
* exit caused by such an instruction (run by a guest hypervisor).
|
||||
* On success, returns 0. When the operand is invalid, returns 1 and throws
|
||||
* #UD or #GP.
|
||||
*/
|
||||
static int get_vmx_mem_address(struct kvm_vcpu *vcpu,
|
||||
unsigned long exit_qualification,
|
||||
u32 vmx_instruction_info, gva_t *ret)
|
||||
{
|
||||
/*
|
||||
* According to Vol. 3B, "Information for VM Exits Due to Instruction
|
||||
* Execution", on an exit, vmx_instruction_info holds most of the
|
||||
* addressing components of the operand. Only the displacement part
|
||||
* is put in exit_qualification (see 3B, "Basic VM-Exit Information").
|
||||
* For how an actual address is calculated from all these components,
|
||||
* refer to Vol. 1, "Operand Addressing".
|
||||
*/
|
||||
int scaling = vmx_instruction_info & 3;
|
||||
int addr_size = (vmx_instruction_info >> 7) & 7;
|
||||
bool is_reg = vmx_instruction_info & (1u << 10);
|
||||
int seg_reg = (vmx_instruction_info >> 15) & 7;
|
||||
int index_reg = (vmx_instruction_info >> 18) & 0xf;
|
||||
bool index_is_valid = !(vmx_instruction_info & (1u << 22));
|
||||
int base_reg = (vmx_instruction_info >> 23) & 0xf;
|
||||
bool base_is_valid = !(vmx_instruction_info & (1u << 27));
|
||||
|
||||
if (is_reg) {
|
||||
kvm_queue_exception(vcpu, UD_VECTOR);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Addr = segment_base + offset */
|
||||
/* offset = base + [index * scale] + displacement */
|
||||
*ret = vmx_get_segment_base(vcpu, seg_reg);
|
||||
if (base_is_valid)
|
||||
*ret += kvm_register_read(vcpu, base_reg);
|
||||
if (index_is_valid)
|
||||
*ret += kvm_register_read(vcpu, index_reg)<<scaling;
|
||||
*ret += exit_qualification; /* holds the displacement */
|
||||
|
||||
if (addr_size == 1) /* 32 bit */
|
||||
*ret &= 0xffffffff;
|
||||
|
||||
/*
|
||||
* TODO: throw #GP (and return 1) in various cases that the VM*
|
||||
* instructions require it - e.g., offset beyond segment limit,
|
||||
* unusable or unreadable/unwritable segment, non-canonical 64-bit
|
||||
* address, and so on. Currently these are not checked.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function performs the various checks including
|
||||
* - if it's 4KB aligned
|
||||
* - No bits beyond the physical address width are set
|
||||
* - Returns 0 on success or else 1
|
||||
* (Intel SDM Section 30.3)
|
||||
*/
|
||||
static int nested_vmx_check_vmptr(struct kvm_vcpu *vcpu, int exit_reason,
|
||||
gpa_t *vmpointer)
|
||||
{
|
||||
gva_t gva;
|
||||
gpa_t vmptr;
|
||||
struct x86_exception e;
|
||||
struct page *page;
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
int maxphyaddr = cpuid_maxphyaddr(vcpu);
|
||||
|
||||
if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
|
||||
vmcs_read32(VMX_INSTRUCTION_INFO), &gva))
|
||||
return 1;
|
||||
|
||||
if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &vmptr,
|
||||
sizeof(vmptr), &e)) {
|
||||
kvm_inject_page_fault(vcpu, &e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (exit_reason) {
|
||||
case EXIT_REASON_VMON:
|
||||
/*
|
||||
* SDM 3: 24.11.5
|
||||
* The first 4 bytes of VMXON region contain the supported
|
||||
* VMCS revision identifier
|
||||
*
|
||||
* Note - IA32_VMX_BASIC[48] will never be 1
|
||||
* for the nested case;
|
||||
* which replaces physical address width with 32
|
||||
*
|
||||
*/
|
||||
if (!IS_ALIGNED(vmptr, PAGE_SIZE) || (vmptr >> maxphyaddr)) {
|
||||
nested_vmx_failInvalid(vcpu);
|
||||
skip_emulated_instruction(vcpu);
|
||||
return 1;
|
||||
}
|
||||
|
||||
page = nested_get_page(vcpu, vmptr);
|
||||
if (page == NULL ||
|
||||
*(u32 *)kmap(page) != VMCS12_REVISION) {
|
||||
nested_vmx_failInvalid(vcpu);
|
||||
kunmap(page);
|
||||
skip_emulated_instruction(vcpu);
|
||||
return 1;
|
||||
}
|
||||
kunmap(page);
|
||||
vmx->nested.vmxon_ptr = vmptr;
|
||||
break;
|
||||
case EXIT_REASON_VMCLEAR:
|
||||
if (!IS_ALIGNED(vmptr, PAGE_SIZE) || (vmptr >> maxphyaddr)) {
|
||||
nested_vmx_failValid(vcpu,
|
||||
VMXERR_VMCLEAR_INVALID_ADDRESS);
|
||||
skip_emulated_instruction(vcpu);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (vmptr == vmx->nested.vmxon_ptr) {
|
||||
nested_vmx_failValid(vcpu,
|
||||
VMXERR_VMCLEAR_VMXON_POINTER);
|
||||
skip_emulated_instruction(vcpu);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case EXIT_REASON_VMPTRLD:
|
||||
if (!IS_ALIGNED(vmptr, PAGE_SIZE) || (vmptr >> maxphyaddr)) {
|
||||
nested_vmx_failValid(vcpu,
|
||||
VMXERR_VMPTRLD_INVALID_ADDRESS);
|
||||
skip_emulated_instruction(vcpu);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (vmptr == vmx->nested.vmxon_ptr) {
|
||||
nested_vmx_failValid(vcpu,
|
||||
VMXERR_VMCLEAR_VMXON_POINTER);
|
||||
skip_emulated_instruction(vcpu);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 1; /* shouldn't happen */
|
||||
}
|
||||
|
||||
if (vmpointer)
|
||||
*vmpointer = vmptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Emulate the VMXON instruction.
|
||||
* Currently, we just remember that VMX is active, and do not save or even
|
||||
@@ -5849,6 +6012,10 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
|
||||
kvm_inject_gp(vcpu, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (nested_vmx_check_vmptr(vcpu, EXIT_REASON_VMON, NULL))
|
||||
return 1;
|
||||
|
||||
if (vmx->nested.vmxon) {
|
||||
nested_vmx_failValid(vcpu, VMXERR_VMXON_IN_VMX_ROOT_OPERATION);
|
||||
skip_emulated_instruction(vcpu);
|
||||
@@ -5971,88 +6138,20 @@ static int handle_vmoff(struct kvm_vcpu *vcpu)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode the memory-address operand of a vmx instruction, as recorded on an
|
||||
* exit caused by such an instruction (run by a guest hypervisor).
|
||||
* On success, returns 0. When the operand is invalid, returns 1 and throws
|
||||
* #UD or #GP.
|
||||
*/
|
||||
static int get_vmx_mem_address(struct kvm_vcpu *vcpu,
|
||||
unsigned long exit_qualification,
|
||||
u32 vmx_instruction_info, gva_t *ret)
|
||||
{
|
||||
/*
|
||||
* According to Vol. 3B, "Information for VM Exits Due to Instruction
|
||||
* Execution", on an exit, vmx_instruction_info holds most of the
|
||||
* addressing components of the operand. Only the displacement part
|
||||
* is put in exit_qualification (see 3B, "Basic VM-Exit Information").
|
||||
* For how an actual address is calculated from all these components,
|
||||
* refer to Vol. 1, "Operand Addressing".
|
||||
*/
|
||||
int scaling = vmx_instruction_info & 3;
|
||||
int addr_size = (vmx_instruction_info >> 7) & 7;
|
||||
bool is_reg = vmx_instruction_info & (1u << 10);
|
||||
int seg_reg = (vmx_instruction_info >> 15) & 7;
|
||||
int index_reg = (vmx_instruction_info >> 18) & 0xf;
|
||||
bool index_is_valid = !(vmx_instruction_info & (1u << 22));
|
||||
int base_reg = (vmx_instruction_info >> 23) & 0xf;
|
||||
bool base_is_valid = !(vmx_instruction_info & (1u << 27));
|
||||
|
||||
if (is_reg) {
|
||||
kvm_queue_exception(vcpu, UD_VECTOR);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Addr = segment_base + offset */
|
||||
/* offset = base + [index * scale] + displacement */
|
||||
*ret = vmx_get_segment_base(vcpu, seg_reg);
|
||||
if (base_is_valid)
|
||||
*ret += kvm_register_read(vcpu, base_reg);
|
||||
if (index_is_valid)
|
||||
*ret += kvm_register_read(vcpu, index_reg)<<scaling;
|
||||
*ret += exit_qualification; /* holds the displacement */
|
||||
|
||||
if (addr_size == 1) /* 32 bit */
|
||||
*ret &= 0xffffffff;
|
||||
|
||||
/*
|
||||
* TODO: throw #GP (and return 1) in various cases that the VM*
|
||||
* instructions require it - e.g., offset beyond segment limit,
|
||||
* unusable or unreadable/unwritable segment, non-canonical 64-bit
|
||||
* address, and so on. Currently these are not checked.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Emulate the VMCLEAR instruction */
|
||||
static int handle_vmclear(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
gva_t gva;
|
||||
gpa_t vmptr;
|
||||
struct vmcs12 *vmcs12;
|
||||
struct page *page;
|
||||
struct x86_exception e;
|
||||
|
||||
if (!nested_vmx_check_permission(vcpu))
|
||||
return 1;
|
||||
|
||||
if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
|
||||
vmcs_read32(VMX_INSTRUCTION_INFO), &gva))
|
||||
if (nested_vmx_check_vmptr(vcpu, EXIT_REASON_VMCLEAR, &vmptr))
|
||||
return 1;
|
||||
|
||||
if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &vmptr,
|
||||
sizeof(vmptr), &e)) {
|
||||
kvm_inject_page_fault(vcpu, &e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!IS_ALIGNED(vmptr, PAGE_SIZE)) {
|
||||
nested_vmx_failValid(vcpu, VMXERR_VMCLEAR_INVALID_ADDRESS);
|
||||
skip_emulated_instruction(vcpu);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (vmptr == vmx->nested.current_vmptr) {
|
||||
nested_release_vmcs12(vmx);
|
||||
vmx->nested.current_vmptr = -1ull;
|
||||
@@ -6372,30 +6471,15 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu)
|
||||
static int handle_vmptrld(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
gva_t gva;
|
||||
gpa_t vmptr;
|
||||
struct x86_exception e;
|
||||
u32 exec_control;
|
||||
|
||||
if (!nested_vmx_check_permission(vcpu))
|
||||
return 1;
|
||||
|
||||
if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
|
||||
vmcs_read32(VMX_INSTRUCTION_INFO), &gva))
|
||||
if (nested_vmx_check_vmptr(vcpu, EXIT_REASON_VMPTRLD, &vmptr))
|
||||
return 1;
|
||||
|
||||
if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &vmptr,
|
||||
sizeof(vmptr), &e)) {
|
||||
kvm_inject_page_fault(vcpu, &e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!IS_ALIGNED(vmptr, PAGE_SIZE)) {
|
||||
nested_vmx_failValid(vcpu, VMXERR_VMPTRLD_INVALID_ADDRESS);
|
||||
skip_emulated_instruction(vcpu);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (vmx->nested.current_vmptr != vmptr) {
|
||||
struct vmcs12 *new_vmcs12;
|
||||
struct page *page;
|
||||
@@ -6471,7 +6555,6 @@ static int handle_invept(struct kvm_vcpu *vcpu)
|
||||
struct {
|
||||
u64 eptp, gpa;
|
||||
} operand;
|
||||
u64 eptp_mask = ((1ull << 51) - 1) & PAGE_MASK;
|
||||
|
||||
if (!(nested_vmx_secondary_ctls_high & SECONDARY_EXEC_ENABLE_EPT) ||
|
||||
!(nested_vmx_ept_caps & VMX_EPT_INVEPT_BIT)) {
|
||||
@@ -6511,16 +6594,13 @@ static int handle_invept(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case VMX_EPT_EXTENT_CONTEXT:
|
||||
if ((operand.eptp & eptp_mask) !=
|
||||
(nested_ept_get_cr3(vcpu) & eptp_mask))
|
||||
break;
|
||||
case VMX_EPT_EXTENT_GLOBAL:
|
||||
kvm_mmu_sync_roots(vcpu);
|
||||
kvm_mmu_flush_tlb(vcpu);
|
||||
nested_vmx_succeed(vcpu);
|
||||
break;
|
||||
default:
|
||||
/* Trap single context invalidation invept calls */
|
||||
BUG_ON(1);
|
||||
break;
|
||||
}
|
||||
@@ -6571,8 +6651,8 @@ static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
|
||||
[EXIT_REASON_EPT_VIOLATION] = handle_ept_violation,
|
||||
[EXIT_REASON_EPT_MISCONFIG] = handle_ept_misconfig,
|
||||
[EXIT_REASON_PAUSE_INSTRUCTION] = handle_pause,
|
||||
[EXIT_REASON_MWAIT_INSTRUCTION] = handle_invalid_op,
|
||||
[EXIT_REASON_MONITOR_INSTRUCTION] = handle_invalid_op,
|
||||
[EXIT_REASON_MWAIT_INSTRUCTION] = handle_mwait,
|
||||
[EXIT_REASON_MONITOR_INSTRUCTION] = handle_monitor,
|
||||
[EXIT_REASON_INVEPT] = handle_invept,
|
||||
};
|
||||
|
||||
@@ -7413,7 +7493,6 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
|
||||
|
||||
vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP)
|
||||
| (1 << VCPU_EXREG_RFLAGS)
|
||||
| (1 << VCPU_EXREG_CPL)
|
||||
| (1 << VCPU_EXREG_PDPTR)
|
||||
| (1 << VCPU_EXREG_SEGMENTS)
|
||||
| (1 << VCPU_EXREG_CR3));
|
||||
@@ -8601,6 +8680,14 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
|
||||
prepare_vmcs12(vcpu, vmcs12, exit_reason, exit_intr_info,
|
||||
exit_qualification);
|
||||
|
||||
if ((exit_reason == EXIT_REASON_EXTERNAL_INTERRUPT)
|
||||
&& nested_exit_intr_ack_set(vcpu)) {
|
||||
int irq = kvm_cpu_get_interrupt(vcpu);
|
||||
WARN_ON(irq < 0);
|
||||
vmcs12->vm_exit_intr_info = irq |
|
||||
INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR;
|
||||
}
|
||||
|
||||
trace_kvm_nested_vmexit_inject(vmcs12->vm_exit_reason,
|
||||
vmcs12->exit_qualification,
|
||||
vmcs12->idt_vectoring_info_field,
|
||||
|
Reference in New Issue
Block a user