Commit f526d6a8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull kvm fixes from Paolo Bonzini:
 "x86:

   - fix lock initialization race in gfn-to-pfn cache (+selftests)

   - fix two refcounting errors

   - emulator fixes

   - mask off reserved bits in CPUID

   - fix bug with disabling SGX

  RISC-V:

   - update MAINTAINERS"

* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
  KVM: x86/xen: Fix eventfd error handling in kvm_xen_eventfd_assign()
  KVM: x86: smm: number of GPRs in the SMRAM image depends on the image format
  KVM: x86: emulator: update the emulation mode after CR0 write
  KVM: x86: emulator: update the emulation mode after rsm
  KVM: x86: emulator: introduce emulator_recalc_and_set_mode
  KVM: x86: emulator: em_sysexit should update ctxt->mode
  KVM: selftests: Mark "guest_saw_irq" as volatile in xen_shinfo_test
  KVM: selftests: Add tests in xen_shinfo_test to detect lock races
  KVM: Reject attempts to consume or refresh inactive gfn_to_pfn_cache
  KVM: Initialize gfn_to_pfn_cache locks in dedicated helper
  KVM: VMX: fully disable SGX if SECONDARY_EXEC_ENCLS_EXITING unavailable
  KVM: x86: Exempt pending triple fault from event injection sanity check
  MAINTAINERS: git://github -> https://github.com for kvm-riscv
  KVM: debugfs: Return retval of simple_attr_open() if it fails
  KVM: x86: Reduce refcount if single_open() fails in kvm_mmu_rmaps_stat_open()
  KVM: x86: Mask off reserved bits in CPUID.8000001FH
  KVM: x86: Mask off reserved bits in CPUID.8000001AH
  KVM: x86: Mask off reserved bits in CPUID.80000008H
  KVM: x86: Mask off reserved bits in CPUID.80000006H
  KVM: x86: Mask off reserved bits in CPUID.80000001H
parents d79dcde0 73536338
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -11248,7 +11248,7 @@ L: kvm@vger.kernel.org
L:	kvm-riscv@lists.infradead.org
L:	linux-riscv@lists.infradead.org
S:	Maintained
T:	git git://github.com/kvm-riscv/linux.git
T:	git https://github.com/kvm-riscv/linux.git
F:	arch/riscv/include/asm/kvm*
F:	arch/riscv/include/uapi/asm/kvm*
F:	arch/riscv/kvm/
+9 −2
Original line number Diff line number Diff line
@@ -1133,11 +1133,13 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
			entry->eax = max(entry->eax, 0x80000021);
		break;
	case 0x80000001:
		entry->ebx &= ~GENMASK(27, 16);
		cpuid_entry_override(entry, CPUID_8000_0001_EDX);
		cpuid_entry_override(entry, CPUID_8000_0001_ECX);
		break;
	case 0x80000006:
		/* L2 cache and TLB: pass through host info. */
		/* Drop reserved bits, pass host L2 cache and TLB info. */
		entry->edx &= ~GENMASK(17, 16);
		break;
	case 0x80000007: /* Advanced power management */
		/* invariant TSC is CPUID.80000007H:EDX[8] */
@@ -1167,6 +1169,7 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
			g_phys_as = phys_as;

		entry->eax = g_phys_as | (virt_as << 8);
		entry->ecx &= ~(GENMASK(31, 16) | GENMASK(11, 8));
		entry->edx = 0;
		cpuid_entry_override(entry, CPUID_8000_0008_EBX);
		break;
@@ -1186,6 +1189,9 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
		entry->ecx = entry->edx = 0;
		break;
	case 0x8000001a:
		entry->eax &= GENMASK(2, 0);
		entry->ebx = entry->ecx = entry->edx = 0;
		break;
	case 0x8000001e:
		break;
	case 0x8000001F:
@@ -1193,7 +1199,8 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
			entry->eax = entry->ebx = entry->ecx = entry->edx = 0;
		} else {
			cpuid_entry_override(entry, CPUID_8000_001F_EAX);

			/* Clear NumVMPL since KVM does not support VMPL.  */
			entry->ebx &= ~GENMASK(31, 12);
			/*
			 * Enumerate '0' for "PA bits reduction", the adjusted
			 * MAXPHYADDR is enumerated directly (see 0x80000008).
+6 −1
Original line number Diff line number Diff line
@@ -158,11 +158,16 @@ static int kvm_mmu_rmaps_stat_show(struct seq_file *m, void *v)
static int kvm_mmu_rmaps_stat_open(struct inode *inode, struct file *file)
{
	struct kvm *kvm = inode->i_private;
	int r;

	if (!kvm_get_kvm_safe(kvm))
		return -ENOENT;

	return single_open(file, kvm_mmu_rmaps_stat_show, kvm);
	r = single_open(file, kvm_mmu_rmaps_stat_show, kvm);
	if (r < 0)
		kvm_put_kvm(kvm);

	return r;
}

static int kvm_mmu_rmaps_stat_release(struct inode *inode, struct file *file)
+76 −32
Original line number Diff line number Diff line
@@ -791,8 +791,7 @@ static int linearize(struct x86_emulate_ctxt *ctxt,
			   ctxt->mode, linear);
}

static inline int assign_eip(struct x86_emulate_ctxt *ctxt, ulong dst,
			     enum x86emul_mode mode)
static inline int assign_eip(struct x86_emulate_ctxt *ctxt, ulong dst)
{
	ulong linear;
	int rc;
@@ -802,41 +801,71 @@ static inline int assign_eip(struct x86_emulate_ctxt *ctxt, ulong dst,

	if (ctxt->op_bytes != sizeof(unsigned long))
		addr.ea = dst & ((1UL << (ctxt->op_bytes << 3)) - 1);
	rc = __linearize(ctxt, addr, &max_size, 1, false, true, mode, &linear);
	rc = __linearize(ctxt, addr, &max_size, 1, false, true, ctxt->mode, &linear);
	if (rc == X86EMUL_CONTINUE)
		ctxt->_eip = addr.ea;
	return rc;
}

static inline int assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst)
static inline int emulator_recalc_and_set_mode(struct x86_emulate_ctxt *ctxt)
{
	return assign_eip(ctxt, dst, ctxt->mode);
}
	u64 efer;
	struct desc_struct cs;
	u16 selector;
	u32 base3;

static int assign_eip_far(struct x86_emulate_ctxt *ctxt, ulong dst,
			  const struct desc_struct *cs_desc)
{
	enum x86emul_mode mode = ctxt->mode;
	int rc;
	ctxt->ops->get_msr(ctxt, MSR_EFER, &efer);

#ifdef CONFIG_X86_64
	if (ctxt->mode >= X86EMUL_MODE_PROT16) {
		if (cs_desc->l) {
			u64 efer = 0;
	if (!(ctxt->ops->get_cr(ctxt, 0) & X86_CR0_PE)) {
		/* Real mode. cpu must not have long mode active */
		if (efer & EFER_LMA)
			return X86EMUL_UNHANDLEABLE;
		ctxt->mode = X86EMUL_MODE_REAL;
		return X86EMUL_CONTINUE;
	}

			ctxt->ops->get_msr(ctxt, MSR_EFER, &efer);
	if (ctxt->eflags & X86_EFLAGS_VM) {
		/* Protected/VM86 mode. cpu must not have long mode active */
		if (efer & EFER_LMA)
				mode = X86EMUL_MODE_PROT64;
		} else
			mode = X86EMUL_MODE_PROT32; /* temporary value */
			return X86EMUL_UNHANDLEABLE;
		ctxt->mode = X86EMUL_MODE_VM86;
		return X86EMUL_CONTINUE;
	}
#endif
	if (mode == X86EMUL_MODE_PROT16 || mode == X86EMUL_MODE_PROT32)
		mode = cs_desc->d ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
	rc = assign_eip(ctxt, dst, mode);
	if (rc == X86EMUL_CONTINUE)
		ctxt->mode = mode;

	if (!ctxt->ops->get_segment(ctxt, &selector, &cs, &base3, VCPU_SREG_CS))
		return X86EMUL_UNHANDLEABLE;

	if (efer & EFER_LMA) {
		if (cs.l) {
			/* Proper long mode */
			ctxt->mode = X86EMUL_MODE_PROT64;
		} else if (cs.d) {
			/* 32 bit compatibility mode*/
			ctxt->mode = X86EMUL_MODE_PROT32;
		} else {
			ctxt->mode = X86EMUL_MODE_PROT16;
		}
	} else {
		/* Legacy 32 bit / 16 bit mode */
		ctxt->mode = cs.d ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
	}

	return X86EMUL_CONTINUE;
}

static inline int assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst)
{
	return assign_eip(ctxt, dst);
}

static int assign_eip_far(struct x86_emulate_ctxt *ctxt, ulong dst)
{
	int rc = emulator_recalc_and_set_mode(ctxt);

	if (rc != X86EMUL_CONTINUE)
		return rc;

	return assign_eip(ctxt, dst);
}

static inline int jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
@@ -2172,7 +2201,7 @@ static int em_jmp_far(struct x86_emulate_ctxt *ctxt)
	if (rc != X86EMUL_CONTINUE)
		return rc;

	rc = assign_eip_far(ctxt, ctxt->src.val, &new_desc);
	rc = assign_eip_far(ctxt, ctxt->src.val);
	/* Error handling is not implemented. */
	if (rc != X86EMUL_CONTINUE)
		return X86EMUL_UNHANDLEABLE;
@@ -2250,7 +2279,7 @@ static int em_ret_far(struct x86_emulate_ctxt *ctxt)
				       &new_desc);
	if (rc != X86EMUL_CONTINUE)
		return rc;
	rc = assign_eip_far(ctxt, eip, &new_desc);
	rc = assign_eip_far(ctxt, eip);
	/* Error handling is not implemented. */
	if (rc != X86EMUL_CONTINUE)
		return X86EMUL_UNHANDLEABLE;
@@ -2432,7 +2461,7 @@ static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt,
	ctxt->eflags =             GET_SMSTATE(u32, smstate, 0x7ff4) | X86_EFLAGS_FIXED;
	ctxt->_eip =               GET_SMSTATE(u32, smstate, 0x7ff0);

	for (i = 0; i < NR_EMULATOR_GPRS; i++)
	for (i = 0; i < 8; i++)
		*reg_write(ctxt, i) = GET_SMSTATE(u32, smstate, 0x7fd0 + i * 4);

	val = GET_SMSTATE(u32, smstate, 0x7fcc);
@@ -2489,7 +2518,7 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt,
	u16 selector;
	int i, r;

	for (i = 0; i < NR_EMULATOR_GPRS; i++)
	for (i = 0; i < 16; i++)
		*reg_write(ctxt, i) = GET_SMSTATE(u64, smstate, 0x7ff8 - i * 8);

	ctxt->_eip   = GET_SMSTATE(u64, smstate, 0x7f78);
@@ -2633,7 +2662,7 @@ static int em_rsm(struct x86_emulate_ctxt *ctxt)
	 * those side effects need to be explicitly handled for both success
	 * and shutdown.
	 */
	return X86EMUL_CONTINUE;
	return emulator_recalc_and_set_mode(ctxt);

emulate_shutdown:
	ctxt->ops->triple_fault(ctxt);
@@ -2876,6 +2905,7 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
	ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);

	ctxt->_eip = rdx;
	ctxt->mode = usermode;
	*reg_write(ctxt, VCPU_REGS_RSP) = rcx;

	return X86EMUL_CONTINUE;
@@ -3469,7 +3499,7 @@ static int em_call_far(struct x86_emulate_ctxt *ctxt)
	if (rc != X86EMUL_CONTINUE)
		return rc;

	rc = assign_eip_far(ctxt, ctxt->src.val, &new_desc);
	rc = assign_eip_far(ctxt, ctxt->src.val);
	if (rc != X86EMUL_CONTINUE)
		goto fail;

@@ -3611,11 +3641,25 @@ static int em_movbe(struct x86_emulate_ctxt *ctxt)

static int em_cr_write(struct x86_emulate_ctxt *ctxt)
{
	if (ctxt->ops->set_cr(ctxt, ctxt->modrm_reg, ctxt->src.val))
	int cr_num = ctxt->modrm_reg;
	int r;

	if (ctxt->ops->set_cr(ctxt, cr_num, ctxt->src.val))
		return emulate_gp(ctxt, 0);

	/* Disable writeback. */
	ctxt->dst.type = OP_NONE;

	if (cr_num == 0) {
		/*
		 * CR0 write might have updated CR0.PE and/or CR0.PG
		 * which can affect the cpu's execution mode.
		 */
		r = emulator_recalc_and_set_mode(ctxt);
		if (r != X86EMUL_CONTINUE)
			return r;
	}

	return X86EMUL_CONTINUE;
}

+5 −0
Original line number Diff line number Diff line
@@ -8263,6 +8263,11 @@ static __init int hardware_setup(void)
	if (!cpu_has_virtual_nmis())
		enable_vnmi = 0;

#ifdef CONFIG_X86_SGX_KVM
	if (!cpu_has_vmx_encls_vmexit())
		enable_sgx = false;
#endif

	/*
	 * set_apic_access_page_addr() is used to reload apic access
	 * page upon invalidation.  No need to do anything if not
Loading