Skip to content

Commit 3ecf162

Browse files
committed
Merge tag 'kvm-x86-xen-6.15' of https://github.com/kvm-x86/linux into HEAD
KVM Xen changes for 6.15 - Don't write to the Xen hypercall page on MSR writes that are initiated by the host (userspace or KVM) to fix a class of bugs where KVM can write to guest memory at unexpected times, e.g. during vCPU creation if userspace has set the Xen hypercall MSR index to collide with an MSR that KVM emulates. - Restrict the Xen hypercall MSR indx to the unofficial synthetic range to reduce the set of possible collisions with MSRs that are emulated by KVM (collisions can still happen as KVM emulates Hyper-V MSRs, which also reside in the synthetic range). - Clean up and optimize KVM's handling of Xen MSR writes and xen_hvm_config. - Update Xen TSC leaves during CPUID emulation instead of modifying the CPUID entries when updating PV clocks, as there is no guarantee PV clocks will be updated between TSC frequency changes and CPUID emulation, and guest reads of Xen TSC should be rare, i.e. are not a hot path.
2 parents fcce7c1 + a2b00f8 commit 3ecf162

File tree

8 files changed

+80
-43
lines changed

8 files changed

+80
-43
lines changed

Documentation/virt/kvm/api.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,10 @@ blobs in userspace. When the guest writes the MSR, kvm copies one
10001000
page of a blob (32- or 64-bit, depending on the vcpu mode) to guest
10011001
memory.
10021002

1003+
The MSR index must be in the range [0x40000000, 0x4fffffff], i.e. must reside
1004+
in the range that is unofficially reserved for use by hypervisors. The min/max
1005+
values are enumerated via KVM_XEN_MSR_MIN_INDEX and KVM_XEN_MSR_MAX_INDEX.
1006+
10031007
::
10041008

10051009
struct kvm_xen_hvm_config {

arch/x86/include/asm/kvm_host.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,6 +1192,8 @@ struct kvm_xen {
11921192
struct gfn_to_pfn_cache shinfo_cache;
11931193
struct idr evtchn_ports;
11941194
unsigned long poll_mask[BITS_TO_LONGS(KVM_MAX_VCPUS)];
1195+
1196+
struct kvm_xen_hvm_config hvm_config;
11951197
};
11961198
#endif
11971199

@@ -1412,8 +1414,6 @@ struct kvm_arch {
14121414
struct delayed_work kvmclock_update_work;
14131415
struct delayed_work kvmclock_sync_work;
14141416

1415-
struct kvm_xen_hvm_config xen_hvm_config;
1416-
14171417
/* reads protected by irq_srcu, writes by irq_lock */
14181418
struct hlist_head mask_notifier_list;
14191419

arch/x86/include/uapi/asm/kvm.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,9 @@ struct kvm_x86_mce {
559559
#define KVM_XEN_HVM_CONFIG_PVCLOCK_TSC_UNSTABLE (1 << 7)
560560
#define KVM_XEN_HVM_CONFIG_SHARED_INFO_HVA (1 << 8)
561561

562+
#define KVM_XEN_MSR_MIN_INDEX 0x40000000u
563+
#define KVM_XEN_MSR_MAX_INDEX 0x4fffffffu
564+
562565
struct kvm_xen_hvm_config {
563566
__u32 flags;
564567
__u32 msr;

arch/x86/kvm/cpuid.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2008,6 +2008,22 @@ bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx,
20082008
} else if (function == 0x80000007) {
20092009
if (kvm_hv_invtsc_suppressed(vcpu))
20102010
*edx &= ~feature_bit(CONSTANT_TSC);
2011+
} else if (IS_ENABLED(CONFIG_KVM_XEN) &&
2012+
kvm_xen_is_tsc_leaf(vcpu, function)) {
2013+
/*
2014+
* Update guest TSC frequency information if necessary.
2015+
* Ignore failures, there is no sane value that can be
2016+
* provided if KVM can't get the TSC frequency.
2017+
*/
2018+
if (kvm_check_request(KVM_REQ_CLOCK_UPDATE, vcpu))
2019+
kvm_guest_time_update(vcpu);
2020+
2021+
if (index == 1) {
2022+
*ecx = vcpu->arch.pvclock_tsc_mul;
2023+
*edx = vcpu->arch.pvclock_tsc_shift;
2024+
} else if (index == 2) {
2025+
*eax = vcpu->arch.hw_tsc_khz;
2026+
}
20112027
}
20122028
} else {
20132029
*eax = *ebx = *ecx = *edx = 0;

arch/x86/kvm/x86.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3169,7 +3169,7 @@ static void kvm_setup_guest_pvclock(struct pvclock_vcpu_time_info *ref_hv_clock,
31693169
trace_kvm_pvclock_update(vcpu->vcpu_id, &hv_clock);
31703170
}
31713171

3172-
static int kvm_guest_time_update(struct kvm_vcpu *v)
3172+
int kvm_guest_time_update(struct kvm_vcpu *v)
31733173
{
31743174
struct pvclock_vcpu_time_info hv_clock = {};
31753175
unsigned long flags, tgt_tsc_khz;
@@ -3242,7 +3242,6 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
32423242
&vcpu->pvclock_tsc_shift,
32433243
&vcpu->pvclock_tsc_mul);
32443244
vcpu->hw_tsc_khz = tgt_tsc_khz;
3245-
kvm_xen_update_tsc_info(v);
32463245
}
32473246

32483247
hv_clock.tsc_shift = vcpu->pvclock_tsc_shift;
@@ -3282,7 +3281,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
32823281
*
32833282
* Note! Clear TSC_STABLE only for Xen clocks, i.e. the order matters!
32843283
*/
3285-
if (ka->xen_hvm_config.flags & KVM_XEN_HVM_CONFIG_PVCLOCK_TSC_UNSTABLE)
3284+
if (ka->xen.hvm_config.flags & KVM_XEN_HVM_CONFIG_PVCLOCK_TSC_UNSTABLE)
32863285
hv_clock.flags &= ~PVCLOCK_TSC_STABLE_BIT;
32873286

32883287
if (vcpu->xen.vcpu_info_cache.active)
@@ -3745,7 +3744,13 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
37453744
u32 msr = msr_info->index;
37463745
u64 data = msr_info->data;
37473746

3748-
if (msr && msr == vcpu->kvm->arch.xen_hvm_config.msr)
3747+
/*
3748+
* Do not allow host-initiated writes to trigger the Xen hypercall
3749+
* page setup; it could incur locking paths which are not expected
3750+
* if userspace sets the MSR in an unusual location.
3751+
*/
3752+
if (kvm_xen_is_hypercall_page_msr(vcpu->kvm, msr) &&
3753+
!msr_info->host_initiated)
37493754
return kvm_xen_write_hypercall_page(vcpu, data);
37503755

37513756
switch (msr) {

arch/x86/kvm/x86.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,7 @@ void kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip);
369369
u64 get_kvmclock_ns(struct kvm *kvm);
370370
uint64_t kvm_get_wall_clock_epoch(struct kvm *kvm);
371371
bool kvm_get_monotonic_and_clockread(s64 *kernel_ns, u64 *tsc_timestamp);
372+
int kvm_guest_time_update(struct kvm_vcpu *v);
372373

373374
int kvm_read_guest_virt(struct kvm_vcpu *vcpu,
374375
gva_t addr, void *val, unsigned int bytes,

arch/x86/kvm/xen.c

Lines changed: 19 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,10 +1335,10 @@ int kvm_xen_write_hypercall_page(struct kvm_vcpu *vcpu, u64 data)
13351335
* Note, truncation is a non-issue as 'lm' is guaranteed to be
13361336
* false for a 32-bit kernel, i.e. when hva_t is only 4 bytes.
13371337
*/
1338-
hva_t blob_addr = lm ? kvm->arch.xen_hvm_config.blob_addr_64
1339-
: kvm->arch.xen_hvm_config.blob_addr_32;
1340-
u8 blob_size = lm ? kvm->arch.xen_hvm_config.blob_size_64
1341-
: kvm->arch.xen_hvm_config.blob_size_32;
1338+
hva_t blob_addr = lm ? kvm->arch.xen.hvm_config.blob_addr_64
1339+
: kvm->arch.xen.hvm_config.blob_addr_32;
1340+
u8 blob_size = lm ? kvm->arch.xen.hvm_config.blob_size_64
1341+
: kvm->arch.xen.hvm_config.blob_size_32;
13421342
u8 *page;
13431343
int ret;
13441344

@@ -1379,15 +1379,24 @@ int kvm_xen_hvm_config(struct kvm *kvm, struct kvm_xen_hvm_config *xhc)
13791379
xhc->blob_size_32 || xhc->blob_size_64))
13801380
return -EINVAL;
13811381

1382+
/*
1383+
* Restrict the MSR to the range that is unofficially reserved for
1384+
* synthetic, virtualization-defined MSRs, e.g. to prevent confusing
1385+
* KVM by colliding with a real MSR that requires special handling.
1386+
*/
1387+
if (xhc->msr &&
1388+
(xhc->msr < KVM_XEN_MSR_MIN_INDEX || xhc->msr > KVM_XEN_MSR_MAX_INDEX))
1389+
return -EINVAL;
1390+
13821391
mutex_lock(&kvm->arch.xen.xen_lock);
13831392

1384-
if (xhc->msr && !kvm->arch.xen_hvm_config.msr)
1393+
if (xhc->msr && !kvm->arch.xen.hvm_config.msr)
13851394
static_branch_inc(&kvm_xen_enabled.key);
1386-
else if (!xhc->msr && kvm->arch.xen_hvm_config.msr)
1395+
else if (!xhc->msr && kvm->arch.xen.hvm_config.msr)
13871396
static_branch_slow_dec_deferred(&kvm_xen_enabled);
13881397

1389-
old_flags = kvm->arch.xen_hvm_config.flags;
1390-
memcpy(&kvm->arch.xen_hvm_config, xhc, sizeof(*xhc));
1398+
old_flags = kvm->arch.xen.hvm_config.flags;
1399+
memcpy(&kvm->arch.xen.hvm_config, xhc, sizeof(*xhc));
13911400

13921401
mutex_unlock(&kvm->arch.xen.xen_lock);
13931402

@@ -1468,7 +1477,7 @@ static bool kvm_xen_schedop_poll(struct kvm_vcpu *vcpu, bool longmode,
14681477
int i;
14691478

14701479
if (!lapic_in_kernel(vcpu) ||
1471-
!(vcpu->kvm->arch.xen_hvm_config.flags & KVM_XEN_HVM_CONFIG_EVTCHN_SEND))
1480+
!(vcpu->kvm->arch.xen.hvm_config.flags & KVM_XEN_HVM_CONFIG_EVTCHN_SEND))
14721481
return false;
14731482

14741483
if (IS_ENABLED(CONFIG_64BIT) && !longmode) {
@@ -2302,29 +2311,6 @@ void kvm_xen_destroy_vcpu(struct kvm_vcpu *vcpu)
23022311
del_timer_sync(&vcpu->arch.xen.poll_timer);
23032312
}
23042313

2305-
void kvm_xen_update_tsc_info(struct kvm_vcpu *vcpu)
2306-
{
2307-
struct kvm_cpuid_entry2 *entry;
2308-
u32 function;
2309-
2310-
if (!vcpu->arch.xen.cpuid.base)
2311-
return;
2312-
2313-
function = vcpu->arch.xen.cpuid.base | XEN_CPUID_LEAF(3);
2314-
if (function > vcpu->arch.xen.cpuid.limit)
2315-
return;
2316-
2317-
entry = kvm_find_cpuid_entry_index(vcpu, function, 1);
2318-
if (entry) {
2319-
entry->ecx = vcpu->arch.pvclock_tsc_mul;
2320-
entry->edx = vcpu->arch.pvclock_tsc_shift;
2321-
}
2322-
2323-
entry = kvm_find_cpuid_entry_index(vcpu, function, 2);
2324-
if (entry)
2325-
entry->eax = vcpu->arch.hw_tsc_khz;
2326-
}
2327-
23282314
void kvm_xen_init_vm(struct kvm *kvm)
23292315
{
23302316
mutex_init(&kvm->arch.xen.xen_lock);
@@ -2346,6 +2332,6 @@ void kvm_xen_destroy_vm(struct kvm *kvm)
23462332
}
23472333
idr_destroy(&kvm->arch.xen.evtchn_ports);
23482334

2349-
if (kvm->arch.xen_hvm_config.msr)
2335+
if (kvm->arch.xen.hvm_config.msr)
23502336
static_branch_slow_dec_deferred(&kvm_xen_enabled);
23512337
}

arch/x86/kvm/xen.h

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef __ARCH_X86_KVM_XEN_H__
1010
#define __ARCH_X86_KVM_XEN_H__
1111

12+
#include <asm/xen/cpuid.h>
1213
#include <asm/xen/hypervisor.h>
1314

1415
#ifdef CONFIG_KVM_XEN
@@ -35,7 +36,6 @@ int kvm_xen_set_evtchn_fast(struct kvm_xen_evtchn *xe,
3536
int kvm_xen_setup_evtchn(struct kvm *kvm,
3637
struct kvm_kernel_irq_routing_entry *e,
3738
const struct kvm_irq_routing_entry *ue);
38-
void kvm_xen_update_tsc_info(struct kvm_vcpu *vcpu);
3939

4040
static inline void kvm_xen_sw_enable_lapic(struct kvm_vcpu *vcpu)
4141
{
@@ -50,16 +50,32 @@ static inline void kvm_xen_sw_enable_lapic(struct kvm_vcpu *vcpu)
5050
kvm_xen_inject_vcpu_vector(vcpu);
5151
}
5252

53+
static inline bool kvm_xen_is_tsc_leaf(struct kvm_vcpu *vcpu, u32 function)
54+
{
55+
return static_branch_unlikely(&kvm_xen_enabled.key) &&
56+
vcpu->arch.xen.cpuid.base &&
57+
function <= vcpu->arch.xen.cpuid.limit &&
58+
function == (vcpu->arch.xen.cpuid.base | XEN_CPUID_LEAF(3));
59+
}
60+
5361
static inline bool kvm_xen_msr_enabled(struct kvm *kvm)
5462
{
5563
return static_branch_unlikely(&kvm_xen_enabled.key) &&
56-
kvm->arch.xen_hvm_config.msr;
64+
kvm->arch.xen.hvm_config.msr;
65+
}
66+
67+
static inline bool kvm_xen_is_hypercall_page_msr(struct kvm *kvm, u32 msr)
68+
{
69+
if (!static_branch_unlikely(&kvm_xen_enabled.key))
70+
return false;
71+
72+
return msr && msr == kvm->arch.xen.hvm_config.msr;
5773
}
5874

5975
static inline bool kvm_xen_hypercall_enabled(struct kvm *kvm)
6076
{
6177
return static_branch_unlikely(&kvm_xen_enabled.key) &&
62-
(kvm->arch.xen_hvm_config.flags &
78+
(kvm->arch.xen.hvm_config.flags &
6379
KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL);
6480
}
6581

@@ -124,6 +140,11 @@ static inline bool kvm_xen_msr_enabled(struct kvm *kvm)
124140
return false;
125141
}
126142

143+
static inline bool kvm_xen_is_hypercall_page_msr(struct kvm *kvm, u32 msr)
144+
{
145+
return false;
146+
}
147+
127148
static inline bool kvm_xen_hypercall_enabled(struct kvm *kvm)
128149
{
129150
return false;
@@ -157,8 +178,9 @@ static inline bool kvm_xen_timer_enabled(struct kvm_vcpu *vcpu)
157178
return false;
158179
}
159180

160-
static inline void kvm_xen_update_tsc_info(struct kvm_vcpu *vcpu)
181+
static inline bool kvm_xen_is_tsc_leaf(struct kvm_vcpu *vcpu, u32 function)
161182
{
183+
return false;
162184
}
163185
#endif
164186

0 commit comments

Comments
 (0)