Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/xen/xen Restore (again) support for grant tables v1...
details: https://anonhg.NetBSD.org/src/rev/12685d43dde4
branches: trunk
changeset: 366628:12685d43dde4
user: bouyer <bouyer%NetBSD.org@localhost>
date: Fri Jun 03 10:42:17 2022 +0000
description:
Restore (again) support for grant tables v1: pvshim doesn't support
v2 (it doesn't even support GNTTABOP_set_version) some setups will
likely require pvshim in the future.
diffstat:
sys/arch/xen/xen/xengnt.c | 183 ++++++++++++++++++++++++++++++++++-----------
1 files changed, 136 insertions(+), 47 deletions(-)
diffs (truncated from 305 to 300 lines):
diff -r a1e83d420454 -r 12685d43dde4 sys/arch/xen/xen/xengnt.c
--- a/sys/arch/xen/xen/xengnt.c Fri Jun 03 00:21:44 2022 +0000
+++ b/sys/arch/xen/xen/xengnt.c Fri Jun 03 10:42:17 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: xengnt.c,v 1.38 2020/05/13 16:13:14 jdolecek Exp $ */
+/* $NetBSD: xengnt.c,v 1.39 2022/06/03 10:42:17 bouyer Exp $ */
/*
* Copyright (c) 2006 Manuel Bouyer.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xengnt.c,v 1.38 2020/05/13 16:13:14 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xengnt.c,v 1.39 2022/06/03 10:42:17 bouyer Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -54,6 +54,10 @@
/* External tools reserve first few grant table entries. */
#define NR_RESERVED_ENTRIES 8
+/* current supported version */
+int gnt_v = 0;
+#define GNT_ISV1 (gnt_v == 1)
+#define GNT_ISV2 (gnt_v == 2)
/* Current number of frames making up the grant table */
int gnt_nr_grant_frames;
/* Maximum number of frames that can make up the grant table */
@@ -67,11 +71,19 @@
#define XENGNT_NO_ENTRY 0xffffffff
/* VM address of the grant table */
-#define NR_GRANT_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(grant_entry_v2_t))
+#define NR_GRANT_ENTRIES_PER_PAGE_V1 (PAGE_SIZE / sizeof(grant_entry_v1_t))
+#define NR_GRANT_ENTRIES_PER_PAGE_V2 (PAGE_SIZE / sizeof(grant_entry_v2_t))
+#define NR_GRANT_ENTRIES_PER_PAGE \
+ ((gnt_v == 1) ? NR_GRANT_ENTRIES_PER_PAGE_V1 : NR_GRANT_ENTRIES_PER_PAGE_V2)
#define NR_GRANT_STATUS_PER_PAGE (PAGE_SIZE / sizeof(grant_status_t))
-grant_entry_v2_t *grant_table;
-/* Number of grant status frames */
+union {
+ grant_entry_v1_t *gntt_v1;
+ grant_entry_v2_t *gntt_v2;
+ void *gntt;
+} grant_table;
+
+/* Number of grant status frames (v2 only)*/
int gnt_status_frames;
grant_status_t *grant_status;
@@ -81,6 +93,7 @@
static void xengnt_free_entry(grant_ref_t);
static int xengnt_more_entries(void);
static int xengnt_map_status(void);
+static bool xengnt_finish_init(void);
void
xengnt_init(void)
@@ -90,6 +103,16 @@
int nr_grant_entries;
int i;
+ /* first try to see which version we support */
+ struct gnttab_set_version gntversion;
+ gnt_v = gntversion.version = 2;
+ rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gntversion, 1);
+ if (rc < 0 || gntversion.version != 2) {
+ aprint_debug("GNTTABOP_set_version 2 failed (%d), "
+ "fall back to version 1\n", rc);
+ gnt_v = 1;
+ }
+
query.dom = DOMID_SELF;
rc = HYPERVISOR_grant_table_op(GNTTABOP_query_size, &query, 1);
if ((rc < 0) || (query.status != GNTST_okay))
@@ -105,9 +128,9 @@
nr_grant_entries =
gnt_max_grant_frames * NR_GRANT_ENTRIES_PER_PAGE;
- grant_table = (void *)uvm_km_alloc(kernel_map,
+ grant_table.gntt = (void *)uvm_km_alloc(kernel_map,
gnt_max_grant_frames * PAGE_SIZE, 0, UVM_KMF_VAONLY);
- if (grant_table == NULL)
+ if (grant_table.gntt == NULL)
panic("xengnt_init() table no VM space");
gnt_entries = kmem_alloc((nr_grant_entries + 1) * sizeof(grant_ref_t),
@@ -115,16 +138,18 @@
for (i = 0; i <= nr_grant_entries; i++)
gnt_entries[i] = XENGNT_NO_ENTRY;
- gnt_status_frames =
- round_page(nr_grant_entries * sizeof(grant_status_t)) / PAGE_SIZE;
- grant_status = (void *)uvm_km_alloc(kernel_map,
- gnt_status_frames * PAGE_SIZE, 0, UVM_KMF_VAONLY);
- if (grant_status == NULL)
- panic("xengnt_init() status no VM space");
+ if (GNT_ISV2) {
+ gnt_status_frames =
+ round_page(nr_grant_entries * sizeof(grant_status_t)) / PAGE_SIZE;
+ grant_status = (void *)uvm_km_alloc(kernel_map,
+ gnt_status_frames * PAGE_SIZE, 0, UVM_KMF_VAONLY);
+ if (grant_status == NULL)
+ panic("xengnt_init() status no VM space");
+ }
mutex_init(&grant_lock, MUTEX_DEFAULT, IPL_VM);
- xengnt_resume();
+ xengnt_finish_init();
}
/*
@@ -134,13 +159,29 @@
xengnt_resume(void)
{
int rc;
- int previous_nr_grant_frames = gnt_nr_grant_frames;
struct gnttab_set_version gntversion;
- gntversion.version = 2;
+ KASSERT(gnt_v == 1 || gnt_v == 2);
+ gntversion.version = gnt_v;
rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gntversion, 1);
- if (rc < 0 || gntversion.version != 2)
- panic("GNTTABOP_set_version 2 failed %d", rc);
+
+ if (GNT_ISV2) {
+ if (rc < 0 || gntversion.version != 2) {
+ panic("GNTTABOP_set_version 2 failed %d", rc);
+ }
+ } else {
+ if (rc == 0 && gntversion.version != 1) {
+ panic("GNTTABOP_set_version 1 failed");
+ }
+ }
+
+ return xengnt_finish_init();
+}
+
+static bool
+xengnt_finish_init(void)
+{
+ int previous_nr_grant_frames = gnt_nr_grant_frames;
last_gnt_entry = 0;
gnt_nr_grant_frames = 0;
@@ -150,7 +191,8 @@
if (xengnt_more_entries() != 0)
panic("xengnt_resume: can't restore grant frames");
}
- xengnt_map_status();
+ if (GNT_ISV2)
+ xengnt_map_status();
mutex_exit(&grant_lock);
return true;
}
@@ -172,10 +214,12 @@
}
/* Remove virtual => machine mapping for grant table */
- pmap_kremove((vaddr_t)grant_table, gnt_nr_grant_frames * PAGE_SIZE);
+ pmap_kremove((vaddr_t)grant_table.gntt, gnt_nr_grant_frames * PAGE_SIZE);
- /* Remove virtual => machine mapping for status table */
- pmap_kremove((vaddr_t)grant_status, gnt_status_frames * PAGE_SIZE);
+ if (GNT_ISV2) {
+ /* Remove virtual => machine mapping for status table */
+ pmap_kremove((vaddr_t)grant_status, gnt_status_frames * PAGE_SIZE);
+ }
pmap_update(pmap_kernel());
mutex_exit(&grant_lock);
@@ -191,6 +235,7 @@
uint64_t *pages;
size_t sz;
KASSERT(mutex_owned(&grant_lock));
+ KASSERT(GNT_ISV2);
sz = gnt_status_frames * sizeof(*pages);
pages = kmem_alloc(sz, KM_NOSLEEP);
@@ -320,7 +365,7 @@
* map between grant_table addresses and the machine addresses of
* the grant table frames
*/
- pmap_kenter_ma(((vaddr_t)grant_table) + gnt_nr_grant_frames * PAGE_SIZE,
+ pmap_kenter_ma(((vaddr_t)grant_table.gntt) + gnt_nr_grant_frames * PAGE_SIZE,
((paddr_t)pages[gnt_nr_grant_frames]) << PAGE_SHIFT,
VM_PROT_WRITE, 0);
pmap_update(pmap_kernel());
@@ -401,38 +446,79 @@
return ENOMEM;
}
- grant_table[*entryp].full_page.frame = ma >> PAGE_SHIFT;
- grant_table[*entryp].hdr.domid = dom;
- /*
- * ensure that the above values reach global visibility
- * before permitting frame's access (done when we set flags)
- */
- xen_rmb();
- grant_table[*entryp].hdr.flags =
- GTF_permit_access | (ro ? GTF_readonly : 0);
+ if (GNT_ISV2) {
+ grant_table.gntt_v2[*entryp].full_page.frame = ma >> PAGE_SHIFT;
+ grant_table.gntt_v2[*entryp].hdr.domid = dom;
+ /*
+ * ensure that the above values reach global visibility
+ * before permitting frame's access (done when we set flags)
+ */
+ xen_rmb();
+ grant_table.gntt_v2[*entryp].hdr.flags =
+ GTF_permit_access | (ro ? GTF_readonly : 0);
+ } else {
+ grant_table.gntt_v1[*entryp].frame = ma >> PAGE_SHIFT;
+ grant_table.gntt_v1[*entryp].domid = dom;
+ /*
+ * ensure that the above values reach global visibility
+ * before permitting frame's access (done when we set flags)
+ */
+ xen_rmb();
+ grant_table.gntt_v1[*entryp].flags =
+ GTF_permit_access | (ro ? GTF_readonly : 0);
+ }
mutex_exit(&grant_lock);
return 0;
}
+static inline uint16_t
+xen_atomic_cmpxchg16(volatile uint16_t *ptr, uint16_t val, uint16_t newval)
+{
+ unsigned long result;
+
+ __asm volatile(__LOCK_PREFIX
+ "cmpxchgw %w1,%2"
+ :"=a" (result)
+ :"q"(newval), "m" (*ptr), "0" (val)
+ :"memory");
+
+ return result;
+}
+
void
xengnt_revoke_access(grant_ref_t entry)
{
- grant_table[entry].hdr.flags = 0;
- xen_mb(); /* Concurrent access by hypervisor */
+ if (GNT_ISV2) {
+ grant_table.gntt_v2[entry].hdr.flags = 0;
+ xen_mb(); /* Concurrent access by hypervisor */
+
+ if (__predict_false(
+ (grant_status[entry] & (GTF_reading|GTF_writing)) != 0)) {
+ printf("xengnt_revoke_access(%u): still in use\n",
+ entry);
+ } else {
- if (__predict_false((grant_status[entry] & (GTF_reading|GTF_writing))
- != 0))
- printf("xengnt_revoke_access(%u): still in use\n",
- entry);
- else {
+ /*
+ * The read of grant_status needs to have acquire
+ * semantics.
+ * Reads already have that on x86, so need only protect
+ * against compiler reordering. May need full barrier
+ * on other architectures.
+ */
+ __insn_barrier();
+ }
+ } else {
+ uint16_t flags, nflags;
- /*
- * The read of grant_status needs to have acquire semantics.
- * Reads already have that on x86, so need only protect
- * against compiler reordering. May need full barrier
- * on other architectures.
- */
- __insn_barrier();
+ nflags = grant_table.gntt_v1[entry].flags;
+
+ do {
+ if ((flags = nflags) & (GTF_reading|GTF_writing))
+ panic("xengnt_revoke_access: still in use");
+ nflags = xen_atomic_cmpxchg16(
+ &grant_table.gntt_v1[entry].flags, flags, 0);
+ } while (nflags != flags);
+
}
xengnt_free_entry(entry);
}
@@ -440,5 +526,8 @@
int
xengnt_status(grant_ref_t entry)
{
- return grant_status[entry] & (GTF_reading|GTF_writing);
Home |
Main Index |
Thread Index |
Old Index