Commit 2f673816 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull kvm fixes from Paolo Bonzini:
 "Bugfixes, including a TLB flush fix that affects processors without
  nested page tables"

* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
  kvm: fix previous commit for 32-bit builds
  kvm: avoid speculation-based attacks from out-of-range memslot accesses
  KVM: x86: Unload MMU on guest TLB flush if TDP disabled to force MMU sync
  KVM: x86: Ensure liveliness of nested VM-Enter fail tracepoint message
  selftests: kvm: Add support for customized slot0 memory size
  KVM: selftests: introduce P47V64 for s390x
  KVM: x86: Ensure PV TLB flush tracepoint reflects KVM behavior
  KVM: X86: MMU: Use the correct inherited permissions to get shadow page
  KVM: LAPIC: Write 0 to TMICT should also cancel vmx-preemption timer
  KVM: SVM: Fix SEV SEND_START session length & SEND_UPDATE_DATA query length after commit 238eca82
parents 368094df 4422829e
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -171,8 +171,8 @@ Shadow pages contain the following information:
    shadow pages) so role.quadrant takes values in the range 0..3.  Each
    quadrant maps 1GB virtual address space.
  role.access:
    Inherited guest access permissions in the form uwx.  Note execute
    permission is positive, not negative.
    Inherited guest access permissions from the parent ptes in the form uwx.
    Note execute permission is positive, not negative.
  role.invalid:
    The page is invalid and should not be used.  It is a root page that is
    currently pinned (by a cpu hardware register pointing to it); once it is
+11 −6
Original line number Diff line number Diff line
@@ -1494,6 +1494,15 @@ static void limit_periodic_timer_frequency(struct kvm_lapic *apic)

static void cancel_hv_timer(struct kvm_lapic *apic);

static void cancel_apic_timer(struct kvm_lapic *apic)
{
	hrtimer_cancel(&apic->lapic_timer.timer);
	preempt_disable();
	if (apic->lapic_timer.hv_timer_in_use)
		cancel_hv_timer(apic);
	preempt_enable();
}

static void apic_update_lvtt(struct kvm_lapic *apic)
{
	u32 timer_mode = kvm_lapic_get_reg(apic, APIC_LVTT) &
@@ -1502,11 +1511,7 @@ static void apic_update_lvtt(struct kvm_lapic *apic)
	if (apic->lapic_timer.timer_mode != timer_mode) {
		if (apic_lvtt_tscdeadline(apic) != (timer_mode ==
				APIC_LVT_TIMER_TSCDEADLINE)) {
			hrtimer_cancel(&apic->lapic_timer.timer);
			preempt_disable();
			if (apic->lapic_timer.hv_timer_in_use)
				cancel_hv_timer(apic);
			preempt_enable();
			cancel_apic_timer(apic);
			kvm_lapic_set_reg(apic, APIC_TMICT, 0);
			apic->lapic_timer.period = 0;
			apic->lapic_timer.tscdeadline = 0;
@@ -2092,7 +2097,7 @@ int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
		if (apic_lvtt_tscdeadline(apic))
			break;

		hrtimer_cancel(&apic->lapic_timer.timer);
		cancel_apic_timer(apic);
		kvm_lapic_set_reg(apic, APIC_TMICT, val);
		start_apic_timer(apic);
		break;
+9 −5
Original line number Diff line number Diff line
@@ -90,8 +90,8 @@ struct guest_walker {
	gpa_t pte_gpa[PT_MAX_FULL_LEVELS];
	pt_element_t __user *ptep_user[PT_MAX_FULL_LEVELS];
	bool pte_writable[PT_MAX_FULL_LEVELS];
	unsigned pt_access;
	unsigned pte_access;
	unsigned int pt_access[PT_MAX_FULL_LEVELS];
	unsigned int pte_access;
	gfn_t gfn;
	struct x86_exception fault;
};
@@ -418,13 +418,15 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
		}

		walker->ptes[walker->level - 1] = pte;

		/* Convert to ACC_*_MASK flags for struct guest_walker.  */
		walker->pt_access[walker->level - 1] = FNAME(gpte_access)(pt_access ^ walk_nx_mask);
	} while (!is_last_gpte(mmu, walker->level, pte));

	pte_pkey = FNAME(gpte_pkeys)(vcpu, pte);
	accessed_dirty = have_ad ? pte_access & PT_GUEST_ACCESSED_MASK : 0;

	/* Convert to ACC_*_MASK flags for struct guest_walker.  */
	walker->pt_access = FNAME(gpte_access)(pt_access ^ walk_nx_mask);
	walker->pte_access = FNAME(gpte_access)(pte_access ^ walk_nx_mask);
	errcode = permission_fault(vcpu, mmu, walker->pte_access, pte_pkey, access);
	if (unlikely(errcode))
@@ -463,7 +465,8 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
	}

	pgprintk("%s: pte %llx pte_access %x pt_access %x\n",
		 __func__, (u64)pte, walker->pte_access, walker->pt_access);
		 __func__, (u64)pte, walker->pte_access,
		 walker->pt_access[walker->level - 1]);
	return 1;

error:
@@ -643,7 +646,7 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gpa_t addr,
	bool huge_page_disallowed = exec && nx_huge_page_workaround_enabled;
	struct kvm_mmu_page *sp = NULL;
	struct kvm_shadow_walk_iterator it;
	unsigned direct_access, access = gw->pt_access;
	unsigned int direct_access, access;
	int top_level, level, req_level, ret;
	gfn_t base_gfn = gw->gfn;

@@ -675,6 +678,7 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gpa_t addr,
		sp = NULL;
		if (!is_shadow_present_pte(*it.sptep)) {
			table_gfn = gw->table_gfn[it.level - 2];
			access = gw->pt_access[it.level - 2];
			sp = kvm_mmu_get_page(vcpu, table_gfn, addr, it.level-1,
					      false, access);
		}
+2 −4
Original line number Diff line number Diff line
@@ -1103,10 +1103,9 @@ __sev_send_start_query_session_length(struct kvm *kvm, struct kvm_sev_cmd *argp,
	struct sev_data_send_start data;
	int ret;

	memset(&data, 0, sizeof(data));
	data.handle = sev->handle;
	ret = sev_issue_cmd(kvm, SEV_CMD_SEND_START, &data, &argp->error);
	if (ret < 0)
		return ret;

	params->session_len = data.session_len;
	if (copy_to_user((void __user *)(uintptr_t)argp->data, params,
@@ -1215,10 +1214,9 @@ __sev_send_update_data_query_lengths(struct kvm *kvm, struct kvm_sev_cmd *argp,
	struct sev_data_send_update_data data;
	int ret;

	memset(&data, 0, sizeof(data));
	data.handle = sev->handle;
	ret = sev_issue_cmd(kvm, SEV_CMD_SEND_UPDATE_DATA, &data, &argp->error);
	if (ret < 0)
		return ret;

	params->hdr_len = data.hdr_len;
	params->trans_len = data.trans_len;
+3 −3
Original line number Diff line number Diff line
@@ -1550,16 +1550,16 @@ TRACE_EVENT(kvm_nested_vmenter_failed,
	TP_ARGS(msg, err),

	TP_STRUCT__entry(
		__field(const char *, msg)
		__string(msg, msg)
		__field(u32, err)
	),

	TP_fast_assign(
		__entry->msg = msg;
		__assign_str(msg, msg);
		__entry->err = err;
	),

	TP_printk("%s%s", __entry->msg, !__entry->err ? "" :
	TP_printk("%s%s", __get_str(msg), !__entry->err ? "" :
		__print_symbolic(__entry->err, VMX_VMENTER_INSTRUCTION_ERRORS))
);

Loading