Commit 8b35c359 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'fixes' of git://git.kernel.org/pub/scm/virt/kvm/kvm

Pull kvm bugfixes from Gleb Natapov:
 "The bulk of the fixes is in MIPS KVM kernel<->userspace ABI.  MIPS KVM
  is new for 3.10 and some problems were found with current ABI.  It is
  better to fix them now and do not have a kernel with broken one"

* 'fixes' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
  KVM: Fix race in apic->pending_events processing
  KVM: fix sil/dil/bpl/spl in the mod/rm fields
  KVM: Emulate multibyte NOP
  ARM: KVM: be more thorough when invalidating TLBs
  ARM: KVM: prevent NULL pointer dereferences with KVM VCPU ioctl
  mips/kvm: Use ENOIOCTLCMD to indicate unimplemented ioctls.
  mips/kvm: Fix ABI by moving manipulation of CP0 registers to KVM_{G,S}ET_ONE_REG
  mips/kvm: Use ARRAY_SIZE() instead of hardcoded constants in kvm_arch_vcpu_ioctl_{s,g}et_regs
  mips/kvm: Fix name of gpr field in struct kvm_regs.
  mips/kvm: Fix ABI for use of 64-bit registers.
  mips/kvm: Fix ABI for use of FPU.
parents 6f66f900 299018f4
...@@ -492,6 +492,11 @@ static void vcpu_pause(struct kvm_vcpu *vcpu) ...@@ -492,6 +492,11 @@ static void vcpu_pause(struct kvm_vcpu *vcpu)
wait_event_interruptible(*wq, !vcpu->arch.pause); wait_event_interruptible(*wq, !vcpu->arch.pause);
} }
static int kvm_vcpu_initialized(struct kvm_vcpu *vcpu)
{
return vcpu->arch.target >= 0;
}
/** /**
* kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code * kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code
* @vcpu: The VCPU pointer * @vcpu: The VCPU pointer
...@@ -508,8 +513,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) ...@@ -508,8 +513,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
int ret; int ret;
sigset_t sigsaved; sigset_t sigsaved;
/* Make sure they initialize the vcpu with KVM_ARM_VCPU_INIT */ if (unlikely(!kvm_vcpu_initialized(vcpu)))
if (unlikely(vcpu->arch.target < 0))
return -ENOEXEC; return -ENOEXEC;
ret = kvm_vcpu_first_run_init(vcpu); ret = kvm_vcpu_first_run_init(vcpu);
...@@ -710,6 +714,10 @@ long kvm_arch_vcpu_ioctl(struct file *filp, ...@@ -710,6 +714,10 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
case KVM_SET_ONE_REG: case KVM_SET_ONE_REG:
case KVM_GET_ONE_REG: { case KVM_GET_ONE_REG: {
struct kvm_one_reg reg; struct kvm_one_reg reg;
if (unlikely(!kvm_vcpu_initialized(vcpu)))
return -ENOEXEC;
if (copy_from_user(&reg, argp, sizeof(reg))) if (copy_from_user(&reg, argp, sizeof(reg)))
return -EFAULT; return -EFAULT;
if (ioctl == KVM_SET_ONE_REG) if (ioctl == KVM_SET_ONE_REG)
...@@ -722,6 +730,9 @@ long kvm_arch_vcpu_ioctl(struct file *filp, ...@@ -722,6 +730,9 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
struct kvm_reg_list reg_list; struct kvm_reg_list reg_list;
unsigned n; unsigned n;
if (unlikely(!kvm_vcpu_initialized(vcpu)))
return -ENOEXEC;
if (copy_from_user(&reg_list, user_list, sizeof(reg_list))) if (copy_from_user(&reg_list, user_list, sizeof(reg_list)))
return -EFAULT; return -EFAULT;
n = reg_list.n; n = reg_list.n;
......
...@@ -43,7 +43,14 @@ static phys_addr_t hyp_idmap_vector; ...@@ -43,7 +43,14 @@ static phys_addr_t hyp_idmap_vector;
static void kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa) static void kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
{ {
kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, kvm, ipa); /*
* This function also gets called when dealing with HYP page
* tables. As HYP doesn't have an associated struct kvm (and
* the HYP page tables are fairly static), we don't do
* anything there.
*/
if (kvm)
kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, kvm, ipa);
} }
static int mmu_topup_memory_cache(struct kvm_mmu_memory_cache *cache, static int mmu_topup_memory_cache(struct kvm_mmu_memory_cache *cache,
...@@ -78,18 +85,20 @@ static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc) ...@@ -78,18 +85,20 @@ static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc)
return p; return p;
} }
static void clear_pud_entry(pud_t *pud) static void clear_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr)
{ {
pmd_t *pmd_table = pmd_offset(pud, 0); pmd_t *pmd_table = pmd_offset(pud, 0);
pud_clear(pud); pud_clear(pud);
kvm_tlb_flush_vmid_ipa(kvm, addr);
pmd_free(NULL, pmd_table); pmd_free(NULL, pmd_table);
put_page(virt_to_page(pud)); put_page(virt_to_page(pud));
} }
static void clear_pmd_entry(pmd_t *pmd) static void clear_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr)
{ {
pte_t *pte_table = pte_offset_kernel(pmd, 0); pte_t *pte_table = pte_offset_kernel(pmd, 0);
pmd_clear(pmd); pmd_clear(pmd);
kvm_tlb_flush_vmid_ipa(kvm, addr);
pte_free_kernel(NULL, pte_table); pte_free_kernel(NULL, pte_table);
put_page(virt_to_page(pmd)); put_page(virt_to_page(pmd));
} }
...@@ -100,11 +109,12 @@ static bool pmd_empty(pmd_t *pmd) ...@@ -100,11 +109,12 @@ static bool pmd_empty(pmd_t *pmd)
return page_count(pmd_page) == 1; return page_count(pmd_page) == 1;
} }
static void clear_pte_entry(pte_t *pte) static void clear_pte_entry(struct kvm *kvm, pte_t *pte, phys_addr_t addr)
{ {
if (pte_present(*pte)) { if (pte_present(*pte)) {
kvm_set_pte(pte, __pte(0)); kvm_set_pte(pte, __pte(0));
put_page(virt_to_page(pte)); put_page(virt_to_page(pte));
kvm_tlb_flush_vmid_ipa(kvm, addr);
} }
} }
...@@ -114,7 +124,8 @@ static bool pte_empty(pte_t *pte) ...@@ -114,7 +124,8 @@ static bool pte_empty(pte_t *pte)
return page_count(pte_page) == 1; return page_count(pte_page) == 1;
} }
static void unmap_range(pgd_t *pgdp, unsigned long long start, u64 size) static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
unsigned long long start, u64 size)
{ {
pgd_t *pgd; pgd_t *pgd;
pud_t *pud; pud_t *pud;
...@@ -138,15 +149,15 @@ static void unmap_range(pgd_t *pgdp, unsigned long long start, u64 size) ...@@ -138,15 +149,15 @@ static void unmap_range(pgd_t *pgdp, unsigned long long start, u64 size)
} }
pte = pte_offset_kernel(pmd, addr); pte = pte_offset_kernel(pmd, addr);
clear_pte_entry(pte); clear_pte_entry(kvm, pte, addr);
range = PAGE_SIZE; range = PAGE_SIZE;
/* If we emptied the pte, walk back up the ladder */ /* If we emptied the pte, walk back up the ladder */
if (pte_empty(pte)) { if (pte_empty(pte)) {
clear_pmd_entry(pmd); clear_pmd_entry(kvm, pmd, addr);
range = PMD_SIZE; range = PMD_SIZE;
if (pmd_empty(pmd)) { if (pmd_empty(pmd)) {
clear_pud_entry(pud); clear_pud_entry(kvm, pud, addr);
range = PUD_SIZE; range = PUD_SIZE;
} }
} }
...@@ -165,14 +176,14 @@ void free_boot_hyp_pgd(void) ...@@ -165,14 +176,14 @@ void free_boot_hyp_pgd(void)
mutex_lock(&kvm_hyp_pgd_mutex); mutex_lock(&kvm_hyp_pgd_mutex);
if (boot_hyp_pgd) { if (boot_hyp_pgd) {
unmap_range(boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE); unmap_range(NULL, boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE);
unmap_range(boot_hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE); unmap_range(NULL, boot_hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
kfree(boot_hyp_pgd); kfree(boot_hyp_pgd);
boot_hyp_pgd = NULL; boot_hyp_pgd = NULL;
} }
if (hyp_pgd) if (hyp_pgd)
unmap_range(hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE); unmap_range(NULL, hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
kfree(init_bounce_page); kfree(init_bounce_page);
init_bounce_page = NULL; init_bounce_page = NULL;
...@@ -200,9 +211,10 @@ void free_hyp_pgds(void) ...@@ -200,9 +211,10 @@ void free_hyp_pgds(void)
if (hyp_pgd) { if (hyp_pgd) {
for (addr = PAGE_OFFSET; virt_addr_valid(addr); addr += PGDIR_SIZE) for (addr = PAGE_OFFSET; virt_addr_valid(addr); addr += PGDIR_SIZE)
unmap_range(hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE); unmap_range(NULL, hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);
for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE) for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE)
unmap_range(hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE); unmap_range(NULL, hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);
kfree(hyp_pgd); kfree(hyp_pgd);
hyp_pgd = NULL; hyp_pgd = NULL;
} }
...@@ -393,7 +405,7 @@ int kvm_alloc_stage2_pgd(struct kvm *kvm) ...@@ -393,7 +405,7 @@ int kvm_alloc_stage2_pgd(struct kvm *kvm)
*/ */
static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size) static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
{ {
unmap_range(kvm->arch.pgd, start, size); unmap_range(kvm, kvm->arch.pgd, start, size);
} }
/** /**
...@@ -675,7 +687,6 @@ static void handle_hva_to_gpa(struct kvm *kvm, ...@@ -675,7 +687,6 @@ static void handle_hva_to_gpa(struct kvm *kvm,
static void kvm_unmap_hva_handler(struct kvm *kvm, gpa_t gpa, void *data) static void kvm_unmap_hva_handler(struct kvm *kvm, gpa_t gpa, void *data)
{ {
unmap_stage2_range(kvm, gpa, PAGE_SIZE); unmap_stage2_range(kvm, gpa, PAGE_SIZE);
kvm_tlb_flush_vmid_ipa(kvm, gpa);
} }
int kvm_unmap_hva(struct kvm *kvm, unsigned long hva) int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
......
...@@ -496,10 +496,6 @@ struct kvm_mips_callbacks { ...@@ -496,10 +496,6 @@ struct kvm_mips_callbacks {
uint32_t cause); uint32_t cause);
int (*irq_clear) (struct kvm_vcpu *vcpu, unsigned int priority, int (*irq_clear) (struct kvm_vcpu *vcpu, unsigned int priority,
uint32_t cause); uint32_t cause);
int (*vcpu_ioctl_get_regs) (struct kvm_vcpu *vcpu,
struct kvm_regs *regs);
int (*vcpu_ioctl_set_regs) (struct kvm_vcpu *vcpu,
struct kvm_regs *regs);
}; };
extern struct kvm_mips_callbacks *kvm_mips_callbacks; extern struct kvm_mips_callbacks *kvm_mips_callbacks;
int kvm_mips_emulation_init(struct kvm_mips_callbacks **install_callbacks); int kvm_mips_emulation_init(struct kvm_mips_callbacks **install_callbacks);
......
/* /*
* This file is subject to the terms and conditions of the GNU General Public * This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive * License. See the file "COPYING" in the main directory of this archive
* for more details. * for more details.
* *
* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
* Authors: Sanjay Lal <sanjayl@kymasys.com> * Copyright (C) 2013 Cavium, Inc.
*/ * Authors: Sanjay Lal <sanjayl@kymasys.com>
*/
#ifndef __LINUX_KVM_MIPS_H #ifndef __LINUX_KVM_MIPS_H
#define __LINUX_KVM_MIPS_H #define __LINUX_KVM_MIPS_H
#include <linux/types.h> #include <linux/types.h>
#define __KVM_MIPS /*
* KVM MIPS specific structures and definitions.
#define N_MIPS_COPROC_REGS 32 *
#define N_MIPS_COPROC_SEL 8 * Some parts derived from the x86 version of this file.
*/
/* for KVM_GET_REGS and KVM_SET_REGS */ /*
* for KVM_GET_REGS and KVM_SET_REGS
*
* If Config[AT] is zero (32-bit CPU), the register contents are
* stored in the lower 32-bits of the struct kvm_regs fields and sign
* extended to 64-bits.
*/
struct kvm_regs { struct kvm_regs {
__u32 gprs[32]; /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
__u32 hi; __u64 gpr[32];
__u32 lo; __u64 hi;
__u32 pc; __u64 lo;
__u64 pc;
__u32 cp0reg[N_MIPS_COPROC_REGS][N_MIPS_COPROC_SEL];
};
/* for KVM_GET_SREGS and KVM_SET_SREGS */
struct kvm_sregs {
}; };
/* for KVM_GET_FPU and KVM_SET_FPU */ /*
* for KVM_GET_FPU and KVM_SET_FPU
*
* If Status[FR] is zero (32-bit FPU), the upper 32-bits of the FPRs
* are zero filled.
*/
struct kvm_fpu { struct kvm_fpu {
__u64 fpr[32];
__u32 fir;
__u32 fccr;
__u32 fexr;
__u32 fenr;
__u32 fcsr;
__u32 pad;
}; };
/*
* For MIPS, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access CP0
* registers. The id field is broken down as follows:
*
* bits[2..0] - Register 'sel' index.
* bits[7..3] - Register 'rd' index.
* bits[15..8] - Must be zero.
* bits[63..16] - 1 -> CP0 registers.
*
* Other sets registers may be added in the future. Each set would
* have its own identifier in bits[63..16].
*
* The addr field of struct kvm_one_reg must point to an aligned
* 64-bit wide location. For registers that are narrower than
* 64-bits, the value is stored in the low order bits of the location,
* and sign extended to 64-bits.
*
* The registers defined in struct kvm_regs are also accessible, the
* id values for these are below.
*/
#define KVM_REG_MIPS_R0 0
#define KVM_REG_MIPS_R1 1
#define KVM_REG_MIPS_R2 2
#define KVM_REG_MIPS_R3 3
#define KVM_REG_MIPS_R4 4
#define KVM_REG_MIPS_R5 5
#define KVM_REG_MIPS_R6 6
#define KVM_REG_MIPS_R7 7
#define KVM_REG_MIPS_R8 8
#define KVM_REG_MIPS_R9 9
#define KVM_REG_MIPS_R10 10
#define KVM_REG_MIPS_R11 11
#define KVM_REG_MIPS_R12 12
#define KVM_REG_MIPS_R13 13
#define KVM_REG_MIPS_R14 14
#define KVM_REG_MIPS_R15 15
#define KVM_REG_MIPS_R16 16
#define KVM_REG_MIPS_R17 17
#define KVM_REG_MIPS_R18 18
#define KVM_REG_MIPS_R19 19
#define KVM_REG_MIPS_R20 20
#define KVM_REG_MIPS_R21 21
#define KVM_REG_MIPS_R22 22
#define KVM_REG_MIPS_R23 23
#define KVM_REG_MIPS_R24 24
#define KVM_REG_MIPS_R25 25
#define KVM_REG_MIPS_R26 26
#define KVM_REG_MIPS_R27 27
#define KVM_REG_MIPS_R28 28
#define KVM_REG_MIPS_R29 29
#define KVM_REG_MIPS_R30 30
#define KVM_REG_MIPS_R31 31
#define KVM_REG_MIPS_HI 32
#define KVM_REG_MIPS_LO 33
#define KVM_REG_MIPS_PC 34
/*
* KVM MIPS specific structures and definitions
*
*/
struct kvm_debug_exit_arch { struct kvm_debug_exit_arch {
__u64 epc;
}; };
/* for KVM_SET_GUEST_DEBUG */ /* for KVM_SET_GUEST_DEBUG */
struct kvm_guest_debug_arch { struct kvm_guest_debug_arch {
}; };
/* definition of registers in kvm_run */
struct kvm_sync_regs {
};
/* dummy definition */
struct kvm_sregs {
};
struct kvm_mips_interrupt { struct kvm_mips_interrupt {
/* in */ /* in */
__u32 cpu; __u32 cpu;
__u32 irq; __u32 irq;
}; };
/* definition of registers in kvm_run */
struct kvm_sync_regs {
};
#endif /* __LINUX_KVM_MIPS_H */ #endif /* __LINUX_KVM_MIPS_H */
This diff is collapsed.
...@@ -345,54 +345,6 @@ static int kvm_trap_emul_handle_break(struct kvm_vcpu *vcpu) ...@@ -345,54 +345,6 @@ static int kvm_trap_emul_handle_break(struct kvm_vcpu *vcpu)
return ret; return ret;
} }
static int
kvm_trap_emul_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
kvm_write_c0_guest_index(cop0, regs->cp0reg[MIPS_CP0_TLB_INDEX][0]);
kvm_write_c0_guest_context(cop0, regs->cp0reg[MIPS_CP0_TLB_CONTEXT][0]);
kvm_write_c0_guest_badvaddr(cop0, regs->cp0reg[MIPS_CP0_BAD_VADDR][0]);
kvm_write_c0_guest_entryhi(cop0, regs->cp0reg[MIPS_CP0_TLB_HI][0]);
kvm_write_c0_guest_epc(cop0, regs->cp0reg[MIPS_CP0_EXC_PC][0]);
kvm_write_c0_guest_status(cop0, regs->cp0reg[MIPS_CP0_STATUS][0]);
kvm_write_c0_guest_cause(cop0, regs->cp0reg[MIPS_CP0_CAUSE][0]);
kvm_write_c0_guest_pagemask(cop0,
regs->cp0reg[MIPS_CP0_TLB_PG_MASK][0]);
kvm_write_c0_guest_wired(cop0, regs->cp0reg[MIPS_CP0_TLB_WIRED][0]);
kvm_write_c0_guest_errorepc(cop0, regs->cp0reg[MIPS_CP0_ERROR_PC][0]);
return 0;
}
static int
kvm_trap_emul_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
regs->cp0reg[MIPS_CP0_TLB_INDEX][0] = kvm_read_c0_guest_index(cop0);
regs->cp0reg[MIPS_CP0_TLB_CONTEXT][0] = kvm_read_c0_guest_context(cop0);
regs->cp0reg[MIPS_CP0_BAD_VADDR][0] = kvm_read_c0_guest_badvaddr(cop0);
regs->cp0reg[MIPS_CP0_TLB_HI][0] = kvm_read_c0_guest_entryhi(cop0);
regs->cp0reg[MIPS_CP0_EXC_PC][0] = kvm_read_c0_guest_epc(cop0);
regs->cp0reg[MIPS_CP0_STATUS][0] = kvm_read_c0_guest_status(cop0);
regs->cp0reg[MIPS_CP0_CAUSE][0] = kvm_read_c0_guest_cause(cop0);
regs->cp0reg[MIPS_CP0_TLB_PG_MASK][0] =
kvm_read_c0_guest_pagemask(cop0);
regs->cp0reg[MIPS_CP0_TLB_WIRED][0] = kvm_read_c0_guest_wired(cop0);
regs->cp0reg[MIPS_CP0_ERROR_PC][0] = kvm_read_c0_guest_errorepc(cop0);
regs->cp0reg[MIPS_CP0_CONFIG][0] = kvm_read_c0_guest_config(cop0);
regs->cp0reg[MIPS_CP0_CONFIG][1] = kvm_read_c0_guest_config1(cop0);
regs->cp0reg[MIPS_CP0_CONFIG][2] = kvm_read_c0_guest_config2(cop0);
regs->cp0reg[MIPS_CP0_CONFIG][3] = kvm_read_c0_guest_config3(cop0);
regs->cp0reg[MIPS_CP0_CONFIG][7] = kvm_read_c0_guest_config7(cop0);
return 0;
}
static int kvm_trap_emul_vm_init(struct kvm *kvm) static int kvm_trap_emul_vm_init(struct kvm *kvm)
{ {
return 0; return 0;
...@@ -471,8 +423,6 @@ static struct kvm_mips_callbacks kvm_trap_emul_callbacks = { ...@@ -471,8 +423,6 @@ static struct kvm_mips_callbacks kvm_trap_emul_callbacks = {
.dequeue_io_int = kvm_mips_dequeue_io_int_cb, .dequeue_io_int = kvm_mips_dequeue_io_int_cb,
.irq_deliver = kvm_mips_irq_deliver_cb, .irq_deliver = kvm_mips_irq_deliver_cb,
.irq_clear = kvm_mips_irq_clear_cb, .irq_clear = kvm_mips_irq_clear_cb,
.vcpu_ioctl_get_regs = kvm_trap_emul_ioctl_get_regs,
.vcpu_ioctl_set_regs = kvm_trap_emul_ioctl_set_regs,
}; };
int kvm_mips_emulation_init(struct kvm_mips_callbacks **install_callbacks) int kvm_mips_emulation_init(struct kvm_mips_callbacks **install_callbacks)
......
...@@ -1240,9 +1240,12 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt, ...@@ -1240,9 +1240,12 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
ctxt->modrm_seg = VCPU_SREG_DS; ctxt->modrm_seg = VCPU_SREG_DS;
if (ctxt->modrm_mod == 3) { if (ctxt->modrm_mod == 3) {
int highbyte_regs = ctxt->rex_prefix == 0;
op->type = OP_REG; op->type = OP_REG;
op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes; op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
op->addr.reg = decode_register(ctxt, ctxt->modrm_rm, ctxt->d & ByteOp); op->addr.reg = decode_register(ctxt, ctxt->modrm_rm,
highbyte_regs && (ctxt->d & ByteOp));
if (ctxt->d & Sse) { if (ctxt->d & Sse) {
op->type = OP_XMM; op->type = OP_XMM;
op->bytes = 16; op->bytes = 16;
...@@ -3997,7 +4000,8 @@ static const struct opcode twobyte_table[256] = { ...@@ -3997,7 +4000,8 @@ static const struct opcode twobyte_table[256] = {
DI(ImplicitOps | Priv, invd), DI(ImplicitOps | Priv, wbinvd), N, N, DI(ImplicitOps | Priv, invd), DI(ImplicitOps | Priv, wbinvd), N, N,
N, D(ImplicitOps | ModRM), N, N, N, D(ImplicitOps | ModRM), N, N,
/* 0x10 - 0x1F */ /* 0x10 - 0x1F */
N, N, N, N, N, N, N, N, D(ImplicitOps | ModRM), N, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
D(ImplicitOps | ModRM), N, N, N, N, N, N, D(ImplicitOps | ModRM),
/* 0x20 - 0x2F */ /* 0x20 - 0x2F */
DIP(ModRM | DstMem | Priv | Op3264, cr_read, check_cr_read), DIP(ModRM | DstMem | Priv | Op3264, cr_read, check_cr_read),
DIP(ModRM | DstMem | Priv | Op3264, dr_read, check_dr_read), DIP(ModRM | DstMem | Priv | Op3264, dr_read, check_dr_read),
...@@ -4836,6 +4840,7 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) ...@@ -4836,6 +4840,7 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
case 0x08: /* invd */ case 0x08: /* invd */
case 0x0d: /* GrpP (prefetch) */ case 0x0d: /* GrpP (prefetch) */
case 0x18: /* Grp16 (prefetch/nop) */ case 0x18: /* Grp16 (prefetch/nop) */
case 0x1f: /* nop */
break; break;
case 0x20: /* mov cr, reg */ case 0x20: /* mov cr, reg */
ctxt->dst.val = ops->get_cr(ctxt, ctxt->modrm_reg); ctxt->dst.val = ops->get_cr(ctxt, ctxt->modrm_reg);
......
...@@ -1861,11 +1861,14 @@ void kvm_apic_accept_events(struct kvm_vcpu *vcpu) ...@@ -1861,11 +1861,14 @@ void kvm_apic_accept_events(struct kvm_vcpu *vcpu)
{ {
struct kvm_lapic *apic = vcpu->arch.apic; struct kvm_lapic *apic = vcpu->arch.apic;
unsigned int sipi_vector; unsigned int sipi_vector;
unsigned long pe;
if (!kvm_vcpu_has_lapic(vcpu)) if (!kvm_vcpu_has_lapic(vcpu) || !apic->pending_events)
return; return;
if (test_and_clear_bit(KVM_APIC_INIT, &apic->pending_events)) { pe = xchg(&apic->pending_events, 0);
if (test_bit(KVM_APIC_INIT, &pe)) {
kvm_lapic_reset(vcpu); kvm_lapic_reset(vcpu);
kvm_vcpu_reset(vcpu); kvm_vcpu_reset(vcpu);
if (kvm_vcpu_is_bsp(apic->vcpu)) if (kvm_vcpu_is_bsp(apic->vcpu))
...@@ -1873,7 +1876,7 @@ void kvm_apic_accept_events(struct kvm_vcpu *vcpu) ...@@ -1873,7 +1876,7 @@ void kvm_apic_accept_events(struct kvm_vcpu *vcpu)
else else
vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED; vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
} }
if (test_and_clear_bit(KVM_APIC_SIPI, &apic->pending_events) && if (test_bit(KVM_APIC_SIPI, &pe) &&
vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) { vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
/* evaluate pending_events before reading the vector */ /* evaluate pending_events before reading the vector */
smp_rmb(); smp_rmb();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment