Skip to content

Commit

Permalink
Merge tag 'for-linus-6.1-rc1-tag' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/kernel/git/xen/tip

Pull xen updates from Juergen Gross:

 - Some minor typo fixes

 - A fix of the Xen pcifront driver for supporting the device model to
   run in a Linux stub domain

 - A cleanup of the pcifront driver

 - A series to enable grant-based virtio with Xen on x86

 - A cleanup of Xen PV guests to distinguish between safe and faulting
   MSR accesses

 - Two fixes of the Xen gntdev driver

 - Two fixes of the new xen grant DMA driver

* tag 'for-linus-6.1-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/xen/tip:
  xen: Kconfig: Fix spelling mistake "Maxmium" -> "Maximum"
  xen/pv: support selecting safe/unsafe msr accesses
  xen/pv: refactor msr access functions to support safe and unsafe accesses
  xen/pv: fix vendor checks for pmu emulation
  xen/pv: add fault recovery control to pmu msr accesses
  xen/virtio: enable grant based virtio on x86
  xen/virtio: use dom0 as default backend for CONFIG_XEN_VIRTIO_FORCE_GRANT
  xen/virtio: restructure xen grant dma setup
  xen/pcifront: move xenstore config scanning into sub-function
  xen/gntdev: Accommodate VMA splitting
  xen/gntdev: Prevent leaking grants
  xen/virtio: Fix potential deadlock when accessing xen_grant_dma_devices
  xen/virtio: Fix n_pages calculation in xen_grant_dma_map(unmap)_page()
  xen/xenbus: Fix spelling mistake "hardward" -> "hardware"
  xen-pcifront: Handle missed Connected state
  • Loading branch information
Linus Torvalds committed Oct 12, 2022
2 parents 1440f57 + 7880672 commit 778ce72
Show file tree
Hide file tree
Showing 12 changed files with 313 additions and 242 deletions.
6 changes: 6 additions & 0 deletions Documentation/admin-guide/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6851,6 +6851,12 @@
Crash from Xen panic notifier, without executing late
panic() code such as dumping handler.

xen_msr_safe= [X86,XEN]
Format: <bool>
Select whether to always use non-faulting (safe) MSR
access functions when running as Xen PV guest. The
default value is controlled by CONFIG_XEN_PV_MSR_SAFE.

xen_nopvspin [X86,XEN]
Disables the qspinlock slowpath using Xen PV optimizations.
This parameter is obsoleted by "nopvspin" parameter, which
Expand Down
9 changes: 9 additions & 0 deletions arch/x86/xen/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,12 @@ config XEN_DOM0
select X86_X2APIC if XEN_PVH && X86_64
help
Support running as a Xen Dom0 guest.

config XEN_PV_MSR_SAFE
bool "Always use safe MSR accesses in PV guests"
default y
depends on XEN_PV
help
Use safe (not faulting) MSR access functions even if the MSR access
should not fault anyway.
The default can be changed by using the "xen_msr_safe" boot parameter.
2 changes: 1 addition & 1 deletion arch/x86/xen/enlighten_hvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ static void __init xen_hvm_guest_init(void)
return;

if (IS_ENABLED(CONFIG_XEN_VIRTIO_FORCE_GRANT))
virtio_set_mem_acc_cb(virtio_require_restricted_mem_acc);
virtio_set_mem_acc_cb(xen_virtio_restricted_mem_acc);

init_hvm_pv_info();

Expand Down
101 changes: 71 additions & 30 deletions arch/x86/xen/enlighten_pv.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,21 @@ struct tls_descs {
*/
static DEFINE_PER_CPU(struct tls_descs, shadow_tls_desc);

static __read_mostly bool xen_msr_safe = IS_ENABLED(CONFIG_XEN_PV_MSR_SAFE);

static int __init parse_xen_msr_safe(char *str)
{
if (str)
return strtobool(str, &xen_msr_safe);
return -EINVAL;
}
early_param("xen_msr_safe", parse_xen_msr_safe);

static void __init xen_pv_init_platform(void)
{
/* PV guests can't operate virtio devices without grants. */
if (IS_ENABLED(CONFIG_XEN_VIRTIO))
virtio_set_mem_acc_cb(virtio_require_restricted_mem_acc);
virtio_set_mem_acc_cb(xen_virtio_restricted_mem_acc);

populate_extra_pte(fix_to_virt(FIX_PARAVIRT_BOOTMAP));

Expand Down Expand Up @@ -917,14 +927,18 @@ static void xen_write_cr4(unsigned long cr4)
native_write_cr4(cr4);
}

static u64 xen_read_msr_safe(unsigned int msr, int *err)
static u64 xen_do_read_msr(unsigned int msr, int *err)
{
u64 val;
u64 val = 0; /* Avoid uninitialized value for safe variant. */

if (pmu_msr_read(msr, &val, err))
return val;

val = native_read_msr_safe(msr, err);
if (err)
val = native_read_msr_safe(msr, err);
else
val = native_read_msr(msr);

switch (msr) {
case MSR_IA32_APICBASE:
val &= ~X2APIC_ENABLE;
Expand All @@ -933,23 +947,39 @@ static u64 xen_read_msr_safe(unsigned int msr, int *err)
return val;
}

static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
static void set_seg(unsigned int which, unsigned int low, unsigned int high,
int *err)
{
int ret;
unsigned int which;
u64 base;
u64 base = ((u64)high << 32) | low;

ret = 0;
if (HYPERVISOR_set_segment_base(which, base) == 0)
return;

if (err)
*err = -EIO;
else
WARN(1, "Xen set_segment_base(%u, %llx) failed\n", which, base);
}

/*
* Support write_msr_safe() and write_msr() semantics.
* With err == NULL write_msr() semantics are selected.
* Supplying an err pointer requires err to be pre-initialized with 0.
*/
static void xen_do_write_msr(unsigned int msr, unsigned int low,
unsigned int high, int *err)
{
switch (msr) {
case MSR_FS_BASE: which = SEGBASE_FS; goto set;
case MSR_KERNEL_GS_BASE: which = SEGBASE_GS_USER; goto set;
case MSR_GS_BASE: which = SEGBASE_GS_KERNEL; goto set;

set:
base = ((u64)high << 32) | low;
if (HYPERVISOR_set_segment_base(which, base) != 0)
ret = -EIO;
case MSR_FS_BASE:
set_seg(SEGBASE_FS, low, high, err);
break;

case MSR_KERNEL_GS_BASE:
set_seg(SEGBASE_GS_USER, low, high, err);
break;

case MSR_GS_BASE:
set_seg(SEGBASE_GS_KERNEL, low, high, err);
break;

case MSR_STAR:
Expand All @@ -965,31 +995,42 @@ static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
break;

default:
if (!pmu_msr_write(msr, low, high, &ret))
ret = native_write_msr_safe(msr, low, high);
if (!pmu_msr_write(msr, low, high, err)) {
if (err)
*err = native_write_msr_safe(msr, low, high);
else
native_write_msr(msr, low, high);
}
}
}

return ret;
static u64 xen_read_msr_safe(unsigned int msr, int *err)
{
return xen_do_read_msr(msr, err);
}

static int xen_write_msr_safe(unsigned int msr, unsigned int low,
unsigned int high)
{
int err = 0;

xen_do_write_msr(msr, low, high, &err);

return err;
}

static u64 xen_read_msr(unsigned int msr)
{
/*
* This will silently swallow a #GP from RDMSR. It may be worth
* changing that.
*/
int err;

return xen_read_msr_safe(msr, &err);
return xen_do_read_msr(msr, xen_msr_safe ? &err : NULL);
}

static void xen_write_msr(unsigned int msr, unsigned low, unsigned high)
{
/*
* This will silently swallow a #GP from WRMSR. It may be worth
* changing that.
*/
xen_write_msr_safe(msr, low, high);
int err;

xen_do_write_msr(msr, low, high, xen_msr_safe ? &err : NULL);
}

/* This is called once we have the cpu_possible_mask */
Expand Down
71 changes: 42 additions & 29 deletions arch/x86/xen/pmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ static inline uint32_t get_fam15h_addr(u32 addr)

static inline bool is_amd_pmu_msr(unsigned int msr)
{
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
return false;

if ((msr >= MSR_F15H_PERF_CTL &&
msr < MSR_F15H_PERF_CTR + (amd_num_counters * 2)) ||
(msr >= MSR_K7_EVNTSEL0 &&
Expand All @@ -140,10 +144,15 @@ static inline bool is_amd_pmu_msr(unsigned int msr)
return false;
}

static int is_intel_pmu_msr(u32 msr_index, int *type, int *index)
static bool is_intel_pmu_msr(u32 msr_index, int *type, int *index)
{
u32 msr_index_pmc;

if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL &&
boot_cpu_data.x86_vendor != X86_VENDOR_CENTAUR &&
boot_cpu_data.x86_vendor != X86_VENDOR_ZHAOXIN)
return false;

switch (msr_index) {
case MSR_CORE_PERF_FIXED_CTR_CTRL:
case MSR_IA32_DS_AREA:
Expand Down Expand Up @@ -290,48 +299,52 @@ static bool xen_amd_pmu_emulate(unsigned int msr, u64 *val, bool is_read)
return false;
}

static bool pmu_msr_chk_emulated(unsigned int msr, uint64_t *val, bool is_read,
bool *emul)
{
int type, index;

if (is_amd_pmu_msr(msr))
*emul = xen_amd_pmu_emulate(msr, val, is_read);
else if (is_intel_pmu_msr(msr, &type, &index))
*emul = xen_intel_pmu_emulate(msr, val, type, index, is_read);
else
return false;

return true;
}

bool pmu_msr_read(unsigned int msr, uint64_t *val, int *err)
{
if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) {
if (is_amd_pmu_msr(msr)) {
if (!xen_amd_pmu_emulate(msr, val, 1))
*val = native_read_msr_safe(msr, err);
return true;
}
} else {
int type, index;
bool emulated;

if (is_intel_pmu_msr(msr, &type, &index)) {
if (!xen_intel_pmu_emulate(msr, val, type, index, 1))
*val = native_read_msr_safe(msr, err);
return true;
}
if (!pmu_msr_chk_emulated(msr, val, true, &emulated))
return false;

if (!emulated) {
*val = err ? native_read_msr_safe(msr, err)
: native_read_msr(msr);
}

return false;
return true;
}

bool pmu_msr_write(unsigned int msr, uint32_t low, uint32_t high, int *err)
{
uint64_t val = ((uint64_t)high << 32) | low;
bool emulated;

if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) {
if (is_amd_pmu_msr(msr)) {
if (!xen_amd_pmu_emulate(msr, &val, 0))
*err = native_write_msr_safe(msr, low, high);
return true;
}
} else {
int type, index;
if (!pmu_msr_chk_emulated(msr, &val, false, &emulated))
return false;

if (is_intel_pmu_msr(msr, &type, &index)) {
if (!xen_intel_pmu_emulate(msr, &val, type, index, 0))
*err = native_write_msr_safe(msr, low, high);
return true;
}
if (!emulated) {
if (err)
*err = native_write_msr_safe(msr, low, high);
else
native_write_msr(msr, low, high);
}

return false;
return true;
}

static unsigned long long xen_amd_read_pmc(int counter)
Expand Down
Loading

0 comments on commit 778ce72

Please sign in to comment.