Skip to content

Commit f340d73

Browse files
committed
Merge: Preparatory patches for TDX support in KVM
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/209 This pull request backsports few KVM commits that are relevant to TDX to RHEL10 kernel JIRA: https://issues.redhat.com/browse/RHEL-71725 Tested: kvm unit tests and selftests were run on intel and amd machine Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> Approved-by: Vitaly Kuznetsov <vkuznets@redhat.com> Approved-by: Paolo Bonzini <bonzini@gnu.org> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Jan Stancek <jstancek@redhat.com>
2 parents f406c9d + ac22ee7 commit f340d73

File tree

17 files changed

+142
-82
lines changed

17 files changed

+142
-82
lines changed

arch/powerpc/kvm/book3s_pr.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,7 @@ static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte)
645645
int i;
646646

647647
hpage = gfn_to_page(vcpu->kvm, pte->raddr >> PAGE_SHIFT);
648-
if (is_error_page(hpage))
648+
if (!hpage)
649649
return;
650650

651651
hpage_offset = pte->raddr & ~PAGE_MASK;

arch/powerpc/kvm/book3s_xive_native.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,7 @@ static int kvmppc_xive_native_set_queue_config(struct kvmppc_xive *xive,
654654
}
655655

656656
page = gfn_to_page(kvm, gfn);
657-
if (is_error_page(page)) {
657+
if (!page) {
658658
srcu_read_unlock(&kvm->srcu, srcu_idx);
659659
pr_err("Couldn't get queue page %llx!\n", kvm_eq.qaddr);
660660
return -EINVAL;

arch/s390/kvm/vsie.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,7 @@ static int pin_guest_page(struct kvm *kvm, gpa_t gpa, hpa_t *hpa)
662662
struct page *page;
663663

664664
page = gfn_to_page(kvm, gpa_to_gfn(gpa));
665-
if (is_error_page(page))
665+
if (!page)
666666
return -EINVAL;
667667
*hpa = (hpa_t)page_to_phys(page) + (gpa & ~PAGE_MASK);
668668
return 0;

arch/x86/include/asm/kvm-x86-ops.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ KVM_X86_OP(set_msr)
3434
KVM_X86_OP(get_segment_base)
3535
KVM_X86_OP(get_segment)
3636
KVM_X86_OP(get_cpl)
37+
KVM_X86_OP(get_cpl_no_cache)
3738
KVM_X86_OP(set_segment)
3839
KVM_X86_OP(get_cs_db_l_bits)
3940
KVM_X86_OP(is_valid_cr0)

arch/x86/include/asm/kvm_host.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,6 +1656,7 @@ struct kvm_x86_ops {
16561656
void (*get_segment)(struct kvm_vcpu *vcpu,
16571657
struct kvm_segment *var, int seg);
16581658
int (*get_cpl)(struct kvm_vcpu *vcpu);
1659+
int (*get_cpl_no_cache)(struct kvm_vcpu *vcpu);
16591660
void (*set_segment)(struct kvm_vcpu *vcpu,
16601661
struct kvm_segment *var, int seg);
16611662
void (*get_cs_db_l_bits)(struct kvm_vcpu *vcpu, int *db, int *l);

arch/x86/kvm/cpuid.c

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,26 @@
3636
u32 kvm_cpu_caps[NR_KVM_CPU_CAPS] __read_mostly;
3737
EXPORT_SYMBOL_GPL(kvm_cpu_caps);
3838

39+
struct cpuid_xstate_sizes {
40+
u32 eax;
41+
u32 ebx;
42+
u32 ecx;
43+
};
44+
45+
static struct cpuid_xstate_sizes xstate_sizes[XFEATURE_MAX] __ro_after_init;
46+
47+
void __init kvm_init_xstate_sizes(void)
48+
{
49+
u32 ign;
50+
int i;
51+
52+
for (i = XFEATURE_YMM; i < ARRAY_SIZE(xstate_sizes); i++) {
53+
struct cpuid_xstate_sizes *xs = &xstate_sizes[i];
54+
55+
cpuid_count(0xD, i, &xs->eax, &xs->ebx, &xs->ecx, &ign);
56+
}
57+
}
58+
3959
u32 xstate_required_size(u64 xstate_bv, bool compacted)
4060
{
4161
int feature_bit = 0;
@@ -44,14 +64,15 @@ u32 xstate_required_size(u64 xstate_bv, bool compacted)
4464
xstate_bv &= XFEATURE_MASK_EXTEND;
4565
while (xstate_bv) {
4666
if (xstate_bv & 0x1) {
47-
u32 eax, ebx, ecx, edx, offset;
48-
cpuid_count(0xD, feature_bit, &eax, &ebx, &ecx, &edx);
67+
struct cpuid_xstate_sizes *xs = &xstate_sizes[feature_bit];
68+
u32 offset;
69+
4970
/* ECX[1]: 64B alignment in compacted form */
5071
if (compacted)
51-
offset = (ecx & 0x2) ? ALIGN(ret, 64) : ret;
72+
offset = (xs->ecx & 0x2) ? ALIGN(ret, 64) : ret;
5273
else
53-
offset = ebx;
54-
ret = max(ret, offset + eax);
74+
offset = xs->ebx;
75+
ret = max(ret, offset + xs->eax);
5576
}
5677

5778
xstate_bv >>= 1;

arch/x86/kvm/cpuid.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu,
3232
bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx,
3333
u32 *ecx, u32 *edx, bool exact_only);
3434

35+
void __init kvm_init_xstate_sizes(void);
3536
u32 xstate_required_size(u64 xstate_bv, bool compacted);
3637

3738
int cpuid_query_maxphyaddr(struct kvm_vcpu *vcpu);

arch/x86/kvm/kvm_cache_regs.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,18 @@ BUILD_KVM_GPR_ACCESSORS(r14, R14)
4343
BUILD_KVM_GPR_ACCESSORS(r15, R15)
4444
#endif
4545

46+
/*
47+
* Using the register cache from interrupt context is generally not allowed, as
48+
* caching a register and marking it available/dirty can't be done atomically,
49+
* i.e. accesses from interrupt context may clobber state or read stale data if
50+
* the vCPU task is in the process of updating the cache. The exception is if
51+
* KVM is handling a PMI IRQ/NMI VM-Exit, as that bound code sequence doesn't
52+
* touch the cache, it runs after the cache is reset (post VM-Exit), and PMIs
53+
* need to access several registers that are cacheable.
54+
*/
55+
#define kvm_assert_register_caching_allowed(vcpu) \
56+
lockdep_assert_once(in_task() || kvm_arch_pmi_in_guest(vcpu))
57+
4658
/*
4759
* avail dirty
4860
* 0 0 register in VMCS/VMCB
@@ -53,24 +65,28 @@ BUILD_KVM_GPR_ACCESSORS(r15, R15)
5365
static inline bool kvm_register_is_available(struct kvm_vcpu *vcpu,
5466
enum kvm_reg reg)
5567
{
68+
kvm_assert_register_caching_allowed(vcpu);
5669
return test_bit(reg, (unsigned long *)&vcpu->arch.regs_avail);
5770
}
5871

5972
static inline bool kvm_register_is_dirty(struct kvm_vcpu *vcpu,
6073
enum kvm_reg reg)
6174
{
75+
kvm_assert_register_caching_allowed(vcpu);
6276
return test_bit(reg, (unsigned long *)&vcpu->arch.regs_dirty);
6377
}
6478

6579
static inline void kvm_register_mark_available(struct kvm_vcpu *vcpu,
6680
enum kvm_reg reg)
6781
{
82+
kvm_assert_register_caching_allowed(vcpu);
6883
__set_bit(reg, (unsigned long *)&vcpu->arch.regs_avail);
6984
}
7085

7186
static inline void kvm_register_mark_dirty(struct kvm_vcpu *vcpu,
7287
enum kvm_reg reg)
7388
{
89+
kvm_assert_register_caching_allowed(vcpu);
7490
__set_bit(reg, (unsigned long *)&vcpu->arch.regs_avail);
7591
__set_bit(reg, (unsigned long *)&vcpu->arch.regs_dirty);
7692
}
@@ -84,6 +100,7 @@ static inline void kvm_register_mark_dirty(struct kvm_vcpu *vcpu,
84100
static __always_inline bool kvm_register_test_and_mark_available(struct kvm_vcpu *vcpu,
85101
enum kvm_reg reg)
86102
{
103+
kvm_assert_register_caching_allowed(vcpu);
87104
return arch___test_and_set_bit(reg, (unsigned long *)&vcpu->arch.regs_avail);
88105
}
89106

arch/x86/kvm/lapic.c

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ enum {
382382
DIRTY
383383
};
384384

385-
void kvm_recalculate_apic_map(struct kvm *kvm)
385+
static void kvm_recalculate_apic_map(struct kvm *kvm)
386386
{
387387
struct kvm_apic_map *new, *old = NULL;
388388
struct kvm_vcpu *vcpu;
@@ -2577,7 +2577,7 @@ u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu)
25772577
return (tpr & 0xf0) >> 4;
25782578
}
25792579

2580-
void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
2580+
static void __kvm_apic_set_base(struct kvm_vcpu *vcpu, u64 value)
25812581
{
25822582
u64 old_value = vcpu->arch.apic_base;
25832583
struct kvm_lapic *apic = vcpu->arch.apic;
@@ -2625,6 +2625,31 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
26252625
}
26262626
}
26272627

2628+
int kvm_apic_set_base(struct kvm_vcpu *vcpu, u64 value, bool host_initiated)
2629+
{
2630+
enum lapic_mode old_mode = kvm_get_apic_mode(vcpu);
2631+
enum lapic_mode new_mode = kvm_apic_mode(value);
2632+
2633+
if (vcpu->arch.apic_base == value)
2634+
return 0;
2635+
2636+
u64 reserved_bits = kvm_vcpu_reserved_gpa_bits_raw(vcpu) | 0x2ff |
2637+
(guest_cpuid_has(vcpu, X86_FEATURE_X2APIC) ? 0 : X2APIC_ENABLE);
2638+
2639+
if ((value & reserved_bits) != 0 || new_mode == LAPIC_MODE_INVALID)
2640+
return 1;
2641+
if (!host_initiated) {
2642+
if (old_mode == LAPIC_MODE_X2APIC && new_mode == LAPIC_MODE_XAPIC)
2643+
return 1;
2644+
if (old_mode == LAPIC_MODE_DISABLED && new_mode == LAPIC_MODE_X2APIC)
2645+
return 1;
2646+
}
2647+
2648+
__kvm_apic_set_base(vcpu, value);
2649+
kvm_recalculate_apic_map(vcpu->kvm);
2650+
return 0;
2651+
}
2652+
26282653
void kvm_apic_update_apicv(struct kvm_vcpu *vcpu)
26292654
{
26302655
struct kvm_lapic *apic = vcpu->arch.apic;
@@ -2671,7 +2696,7 @@ int kvm_alloc_apic_access_page(struct kvm *kvm)
26712696
}
26722697

26732698
page = gfn_to_page(kvm, APIC_DEFAULT_PHYS_BASE >> PAGE_SHIFT);
2674-
if (is_error_page(page)) {
2699+
if (!page) {
26752700
ret = -EFAULT;
26762701
goto out;
26772702
}
@@ -2735,7 +2760,14 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
27352760
msr_val = APIC_DEFAULT_PHYS_BASE | MSR_IA32_APICBASE_ENABLE;
27362761
if (kvm_vcpu_is_reset_bsp(vcpu))
27372762
msr_val |= MSR_IA32_APICBASE_BSP;
2738-
kvm_lapic_set_base(vcpu, msr_val);
2763+
2764+
/*
2765+
* Use the inner helper to avoid an extra recalcuation of the
2766+
* optimized APIC map if some other task has dirtied the map.
2767+
* The recalculation needed for this vCPU will be done after
2768+
* all APIC state has been initialized (see below).
2769+
*/
2770+
__kvm_apic_set_base(vcpu, msr_val);
27392771
}
27402772

27412773
if (!apic)
@@ -3076,7 +3108,6 @@ int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
30763108

30773109
kvm_x86_call(apicv_pre_state_restore)(vcpu);
30783110

3079-
kvm_lapic_set_base(vcpu, vcpu->arch.apic_base);
30803111
/* set SPIV separately to get count of SW disabled APICs right */
30813112
apic_set_spiv(apic, *((u32 *)(s->regs + APIC_SPIV)));
30823113

arch/x86/kvm/lapic.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,6 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event);
9595
u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu);
9696
void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8);
9797
void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu);
98-
void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value);
99-
void kvm_recalculate_apic_map(struct kvm *kvm);
10098
void kvm_apic_set_version(struct kvm_vcpu *vcpu);
10199
void kvm_apic_after_set_mcg_cap(struct kvm_vcpu *vcpu);
102100
bool kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
@@ -117,11 +115,9 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
117115
struct kvm_lapic_irq *irq, int *r, struct dest_map *dest_map);
118116
void kvm_apic_send_ipi(struct kvm_lapic *apic, u32 icr_low, u32 icr_high);
119117

120-
u64 kvm_get_apic_base(struct kvm_vcpu *vcpu);
121-
int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
118+
int kvm_apic_set_base(struct kvm_vcpu *vcpu, u64 value, bool host_initiated);
122119
int kvm_apic_get_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
123120
int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
124-
enum lapic_mode kvm_get_apic_mode(struct kvm_vcpu *vcpu);
125121
int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
126122

127123
u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu);
@@ -271,6 +267,11 @@ static inline enum lapic_mode kvm_apic_mode(u64 apic_base)
271267
return apic_base & (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE);
272268
}
273269

270+
static inline enum lapic_mode kvm_get_apic_mode(struct kvm_vcpu *vcpu)
271+
{
272+
return kvm_apic_mode(vcpu->arch.apic_base);
273+
}
274+
274275
static inline u8 kvm_xapic_id(struct kvm_lapic *apic)
275276
{
276277
return kvm_lapic_get_reg(apic, APIC_ID) >> 24;

0 commit comments

Comments
 (0)