Skip to content

Commit 255006a

Browse files
committed
Merge tag 'kvm-x86-vmx-6.5' of https://github.com/kvm-x86/linux into HEAD
KVM VMX changes for 6.5: - Fix missing/incorrect #GP checks on ENCLS - Use standard mmu_notifier hooks for handling APIC access page - Misc cleanups
2 parents 24975ce + 0a3869e commit 255006a

10 files changed

Lines changed: 73 additions & 58 deletions

File tree

arch/x86/kvm/mmu/mmu.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1603,6 +1603,10 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
16031603
if (tdp_mmu_enabled)
16041604
flush = kvm_tdp_mmu_unmap_gfn_range(kvm, range, flush);
16051605

1606+
if (kvm_x86_ops.set_apic_access_page_addr &&
1607+
range->slot->id == APIC_ACCESS_PAGE_PRIVATE_MEMSLOT)
1608+
kvm_make_all_cpus_request(kvm, KVM_REQ_APIC_PAGE_RELOAD);
1609+
16061610
return flush;
16071611
}
16081612

arch/x86/kvm/vmx/capabilities.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,8 @@ static inline bool cpu_has_vmx_ept(void)
152152

153153
static inline bool vmx_umip_emulated(void)
154154
{
155-
return vmcs_config.cpu_based_2nd_exec_ctrl &
156-
SECONDARY_EXEC_DESC;
155+
return !boot_cpu_has(X86_FEATURE_UMIP) &&
156+
(vmcs_config.cpu_based_2nd_exec_ctrl & SECONDARY_EXEC_DESC);
157157
}
158158

159159
static inline bool cpu_has_vmx_rdtscp(void)

arch/x86/kvm/vmx/nested.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2328,8 +2328,7 @@ static void prepare_vmcs02_early(struct vcpu_vmx *vmx, struct loaded_vmcs *vmcs0
23282328
* Preset *DT exiting when emulating UMIP, so that vmx_set_cr4()
23292329
* will not have to rewrite the controls just for this bit.
23302330
*/
2331-
if (!boot_cpu_has(X86_FEATURE_UMIP) && vmx_umip_emulated() &&
2332-
(vmcs12->guest_cr4 & X86_CR4_UMIP))
2331+
if (vmx_umip_emulated() && (vmcs12->guest_cr4 & X86_CR4_UMIP))
23332332
exec_control |= SECONDARY_EXEC_DESC;
23342333

23352334
if (exec_control & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY)

arch/x86/kvm/vmx/pmu_intel.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,6 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
385385
}
386386
break;
387387
case MSR_IA32_DS_AREA:
388-
if (msr_info->host_initiated && data && !guest_cpuid_has(vcpu, X86_FEATURE_DS))
389-
return 1;
390388
if (is_noncanonical_address(data, vcpu))
391389
return 1;
392390

arch/x86/kvm/vmx/sgx.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -357,11 +357,12 @@ static int handle_encls_einit(struct kvm_vcpu *vcpu)
357357

358358
static inline bool encls_leaf_enabled_in_guest(struct kvm_vcpu *vcpu, u32 leaf)
359359
{
360-
if (!enable_sgx || !guest_cpuid_has(vcpu, X86_FEATURE_SGX))
361-
return false;
362-
360+
/*
361+
* ENCLS generates a #UD if SGX1 isn't supported, i.e. this point will
362+
* be reached if and only if the SGX1 leafs are enabled.
363+
*/
363364
if (leaf >= ECREATE && leaf <= ETRACK)
364-
return guest_cpuid_has(vcpu, X86_FEATURE_SGX1);
365+
return true;
365366

366367
if (leaf >= EAUG && leaf <= EMODT)
367368
return guest_cpuid_has(vcpu, X86_FEATURE_SGX2);
@@ -380,9 +381,11 @@ int handle_encls(struct kvm_vcpu *vcpu)
380381
{
381382
u32 leaf = (u32)kvm_rax_read(vcpu);
382383

383-
if (!encls_leaf_enabled_in_guest(vcpu, leaf)) {
384+
if (!enable_sgx || !guest_cpuid_has(vcpu, X86_FEATURE_SGX) ||
385+
!guest_cpuid_has(vcpu, X86_FEATURE_SGX1)) {
384386
kvm_queue_exception(vcpu, UD_VECTOR);
385-
} else if (!sgx_enabled_in_guest_bios(vcpu)) {
387+
} else if (!encls_leaf_enabled_in_guest(vcpu, leaf) ||
388+
!sgx_enabled_in_guest_bios(vcpu) || !is_paging(vcpu)) {
386389
kvm_inject_gp(vcpu, 0);
387390
} else {
388391
if (leaf == ECREATE)

arch/x86/kvm/vmx/vmenter.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ SYM_FUNC_START(__vmx_vcpu_run)
187187
_ASM_EXTABLE(.Lvmresume, .Lfixup)
188188
_ASM_EXTABLE(.Lvmlaunch, .Lfixup)
189189

190-
SYM_INNER_LABEL(vmx_vmexit, SYM_L_GLOBAL)
190+
SYM_INNER_LABEL_ALIGN(vmx_vmexit, SYM_L_GLOBAL)
191191

192192
/* Restore unwind state from before the VMRESUME/VMLAUNCH. */
193193
UNWIND_HINT_RESTORE

arch/x86/kvm/vmx/vmx.c

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3384,15 +3384,15 @@ static bool vmx_is_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
33843384

33853385
void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
33863386
{
3387-
unsigned long old_cr4 = vcpu->arch.cr4;
3387+
unsigned long old_cr4 = kvm_read_cr4(vcpu);
33883388
struct vcpu_vmx *vmx = to_vmx(vcpu);
3389+
unsigned long hw_cr4;
3390+
33893391
/*
33903392
* Pass through host's Machine Check Enable value to hw_cr4, which
33913393
* is in force while we are in guest mode. Do not let guests control
33923394
* this bit, even if host CR4.MCE == 0.
33933395
*/
3394-
unsigned long hw_cr4;
3395-
33963396
hw_cr4 = (cr4_read_shadow() & X86_CR4_MCE) | (cr4 & ~X86_CR4_MCE);
33973397
if (is_unrestricted_guest(vcpu))
33983398
hw_cr4 |= KVM_VM_CR4_ALWAYS_ON_UNRESTRICTED_GUEST;
@@ -3401,7 +3401,7 @@ void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
34013401
else
34023402
hw_cr4 |= KVM_PMODE_VM_CR4_ALWAYS_ON;
34033403

3404-
if (!boot_cpu_has(X86_FEATURE_UMIP) && vmx_umip_emulated()) {
3404+
if (vmx_umip_emulated()) {
34053405
if (cr4 & X86_CR4_UMIP) {
34063406
secondary_exec_controls_setbit(vmx, SECONDARY_EXEC_DESC);
34073407
hw_cr4 &= ~X86_CR4_UMIP;
@@ -5399,7 +5399,13 @@ static int handle_set_cr4(struct kvm_vcpu *vcpu, unsigned long val)
53995399

54005400
static int handle_desc(struct kvm_vcpu *vcpu)
54015401
{
5402-
WARN_ON(!(vcpu->arch.cr4 & X86_CR4_UMIP));
5402+
/*
5403+
* UMIP emulation relies on intercepting writes to CR4.UMIP, i.e. this
5404+
* and other code needs to be updated if UMIP can be guest owned.
5405+
*/
5406+
BUILD_BUG_ON(KVM_POSSIBLE_CR4_GUEST_BITS & X86_CR4_UMIP);
5407+
5408+
WARN_ON_ONCE(!kvm_is_cr4_bit_set(vcpu, X86_CR4_UMIP));
54035409
return kvm_emulate_instruction(vcpu, 0);
54045410
}
54055411

@@ -6705,7 +6711,12 @@ void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
67056711

67066712
static void vmx_set_apic_access_page_addr(struct kvm_vcpu *vcpu)
67076713
{
6708-
struct page *page;
6714+
const gfn_t gfn = APIC_DEFAULT_PHYS_BASE >> PAGE_SHIFT;
6715+
struct kvm *kvm = vcpu->kvm;
6716+
struct kvm_memslots *slots = kvm_memslots(kvm);
6717+
struct kvm_memory_slot *slot;
6718+
unsigned long mmu_seq;
6719+
kvm_pfn_t pfn;
67096720

67106721
/* Defer reload until vmcs01 is the current VMCS. */
67116722
if (is_guest_mode(vcpu)) {
@@ -6717,18 +6728,53 @@ static void vmx_set_apic_access_page_addr(struct kvm_vcpu *vcpu)
67176728
SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES))
67186729
return;
67196730

6720-
page = gfn_to_page(vcpu->kvm, APIC_DEFAULT_PHYS_BASE >> PAGE_SHIFT);
6721-
if (is_error_page(page))
6731+
/*
6732+
* Grab the memslot so that the hva lookup for the mmu_notifier retry
6733+
* is guaranteed to use the same memslot as the pfn lookup, i.e. rely
6734+
* on the pfn lookup's validation of the memslot to ensure a valid hva
6735+
* is used for the retry check.
6736+
*/
6737+
slot = id_to_memslot(slots, APIC_ACCESS_PAGE_PRIVATE_MEMSLOT);
6738+
if (!slot || slot->flags & KVM_MEMSLOT_INVALID)
67226739
return;
67236740

6724-
vmcs_write64(APIC_ACCESS_ADDR, page_to_phys(page));
6741+
/*
6742+
* Ensure that the mmu_notifier sequence count is read before KVM
6743+
* retrieves the pfn from the primary MMU. Note, the memslot is
6744+
* protected by SRCU, not the mmu_notifier. Pairs with the smp_wmb()
6745+
* in kvm_mmu_invalidate_end().
6746+
*/
6747+
mmu_seq = kvm->mmu_invalidate_seq;
6748+
smp_rmb();
6749+
6750+
/*
6751+
* No need to retry if the memslot does not exist or is invalid. KVM
6752+
* controls the APIC-access page memslot, and only deletes the memslot
6753+
* if APICv is permanently inhibited, i.e. the memslot won't reappear.
6754+
*/
6755+
pfn = gfn_to_pfn_memslot(slot, gfn);
6756+
if (is_error_noslot_pfn(pfn))
6757+
return;
6758+
6759+
read_lock(&vcpu->kvm->mmu_lock);
6760+
if (mmu_invalidate_retry_hva(kvm, mmu_seq,
6761+
gfn_to_hva_memslot(slot, gfn))) {
6762+
kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu);
6763+
read_unlock(&vcpu->kvm->mmu_lock);
6764+
goto out;
6765+
}
6766+
6767+
vmcs_write64(APIC_ACCESS_ADDR, pfn_to_hpa(pfn));
6768+
read_unlock(&vcpu->kvm->mmu_lock);
6769+
67256770
vmx_flush_tlb_current(vcpu);
67266771

6772+
out:
67276773
/*
67286774
* Do not pin apic access page in memory, the MMU notifier
67296775
* will call us again if it is migrated or swapped out.
67306776
*/
6731-
put_page(page);
6777+
kvm_release_pfn_clean(pfn);
67326778
}
67336779

67346780
static void vmx_hwapic_isr_update(int max_isr)

arch/x86/kvm/x86.c

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10449,20 +10449,6 @@ static void vcpu_load_eoi_exitmap(struct kvm_vcpu *vcpu)
1044910449
vcpu, (u64 *)vcpu->arch.ioapic_handled_vectors);
1045010450
}
1045110451

10452-
void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
10453-
unsigned long start, unsigned long end)
10454-
{
10455-
unsigned long apic_address;
10456-
10457-
/*
10458-
* The physical address of apic access page is stored in the VMCS.
10459-
* Update it when it becomes invalid.
10460-
*/
10461-
apic_address = gfn_to_hva(kvm, APIC_DEFAULT_PHYS_BASE >> PAGE_SHIFT);
10462-
if (start <= apic_address && apic_address < end)
10463-
kvm_make_all_cpus_request(kvm, KVM_REQ_APIC_PAGE_RELOAD);
10464-
}
10465-
1046610452
void kvm_arch_guest_memory_reclaimed(struct kvm *kvm)
1046710453
{
1046810454
static_call_cond(kvm_x86_guest_memory_reclaimed)(kvm);

include/linux/kvm_host.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2239,9 +2239,6 @@ static inline long kvm_arch_vcpu_async_ioctl(struct file *filp,
22392239
}
22402240
#endif /* CONFIG_HAVE_KVM_VCPU_ASYNC_IOCTL */
22412241

2242-
void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
2243-
unsigned long start, unsigned long end);
2244-
22452242
void kvm_arch_guest_memory_reclaimed(struct kvm *kvm);
22462243

22472244
#ifdef CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE

virt/kvm/kvm_main.c

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -154,11 +154,6 @@ static unsigned long long kvm_active_vms;
154154

155155
static DEFINE_PER_CPU(cpumask_var_t, cpu_kick_mask);
156156

157-
__weak void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
158-
unsigned long start, unsigned long end)
159-
{
160-
}
161-
162157
__weak void kvm_arch_guest_memory_reclaimed(struct kvm *kvm)
163158
{
164159
}
@@ -521,18 +516,6 @@ static inline struct kvm *mmu_notifier_to_kvm(struct mmu_notifier *mn)
521516
return container_of(mn, struct kvm, mmu_notifier);
522517
}
523518

524-
static void kvm_mmu_notifier_invalidate_range(struct mmu_notifier *mn,
525-
struct mm_struct *mm,
526-
unsigned long start, unsigned long end)
527-
{
528-
struct kvm *kvm = mmu_notifier_to_kvm(mn);
529-
int idx;
530-
531-
idx = srcu_read_lock(&kvm->srcu);
532-
kvm_arch_mmu_notifier_invalidate_range(kvm, start, end);
533-
srcu_read_unlock(&kvm->srcu, idx);
534-
}
535-
536519
typedef bool (*hva_handler_t)(struct kvm *kvm, struct kvm_gfn_range *range);
537520

538521
typedef void (*on_lock_fn_t)(struct kvm *kvm, unsigned long start,
@@ -910,7 +893,6 @@ static void kvm_mmu_notifier_release(struct mmu_notifier *mn,
910893
}
911894

912895
static const struct mmu_notifier_ops kvm_mmu_notifier_ops = {
913-
.invalidate_range = kvm_mmu_notifier_invalidate_range,
914896
.invalidate_range_start = kvm_mmu_notifier_invalidate_range_start,
915897
.invalidate_range_end = kvm_mmu_notifier_invalidate_range_end,
916898
.clear_flush_young = kvm_mmu_notifier_clear_flush_young,

0 commit comments

Comments
 (0)