|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v7 2/4] x86/mm: Reject invalid cacheability in PV guests by default
Setting cacheability flags that are not ones specified by Xen is a bug
in the guest. By default, return -EINVAL if a guests attempts to do
this. The invalid-cacheability= Xen command-line flag allows the
administrator to allow such attempts or to produce
Suggested-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Signed-off-by: Demi Marie Obenour <demi@xxxxxxxxxxxxxxxxxxxxxx>
---
Changes since v6:
- Make invalid-cacheability= a subflag of pv=.
- Move check for invalid cacheability to get_page_from_l1e().
Changes since v5:
- Make parameters static and __ro_after_init.
- Replace boolean parameter allow_invalid_cacheability with string
parameter invalid-cacheability.
- Move parameter definitions to near where they are used.
- Add documentation.
Changes since v4:
- Remove pointless BUILD_BUG_ON().
- Add comment explaining why an exception is being injected.
Changes since v3:
- Add Andrew Cooper’s Suggested-by
---
docs/misc/xen-command-line.pandoc | 11 ++++++
xen/arch/x86/include/asm/pv/domain.h | 7 ++++
xen/arch/x86/mm.c | 53 +++++++++++++++++++++++++++-
xen/arch/x86/pv/domain.c | 18 ++++++++--
4 files changed, 85 insertions(+), 4 deletions(-)
diff --git a/docs/misc/xen-command-line.pandoc
b/docs/misc/xen-command-line.pandoc
index
424b12cfb27d6ade2ec63eacb8afe5df82465451..0230a7bc17cbd4362a42ea64cea695f31f5e0f86
100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -1417,6 +1417,17 @@ detection of systems known to misbehave upon accesses to
that port.
### idle_latency_factor (x86)
> `= <integer>`
+### invalid-cacheability (x86)
+> `= allow | deny | trap`
+
+> Default: `deny` in release builds, otherwise `trap`
+
+Specify what happens when a PV guest tries to use one of the reserved entries
in
+the PAT. `deny` causes the attempt to be rejected with -EINVAL, `allow` allows
+the attempt, and `trap` causes a general protection fault to be raised.
+Currently, the reserved entries are marked as uncacheable in Xen's PAT, but
this
+will change if new memory types are added, so guests must not rely on it.
+
### ioapic_ack (x86)
> `= old | new`
diff --git a/xen/arch/x86/include/asm/pv/domain.h
b/xen/arch/x86/include/asm/pv/domain.h
index
924508bbb4f0c199b3cd2306d9d8f0bd0ef399f9..1c9ce259ab4ee23ea5d057f5dfa964effb169032
100644
--- a/xen/arch/x86/include/asm/pv/domain.h
+++ b/xen/arch/x86/include/asm/pv/domain.h
@@ -71,6 +71,13 @@ void pv_vcpu_destroy(struct vcpu *v);
int pv_vcpu_initialise(struct vcpu *v);
void pv_domain_destroy(struct domain *d);
int pv_domain_initialise(struct domain *d);
+extern __ro_after_init uint8_t invalid_cacheability;
+
+enum {
+ INVALID_CACHEABILITY_ALLOW,
+ INVALID_CACHEABILITY_DENY,
+ INVALID_CACHEABILITY_TRAP,
+};
/*
* Bits which a PV guest can toggle in its view of cr4. Some are loaded into
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index
3558ca215b02a517d55d75329d645ae5905424e4..a8f137925cba1846b97aee9321df6427f4dd1a94
100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -879,6 +879,30 @@ get_page_from_l1e(
return -EINVAL;
}
+ if ( invalid_cacheability != INVALID_CACHEABILITY_ALLOW )
+ {
+ switch ( l1e.l1 & PAGE_CACHE_ATTRS )
+ {
+ case _PAGE_WB:
+ case _PAGE_UC:
+ case _PAGE_UCM:
+ case _PAGE_WC:
+ case _PAGE_WT:
+ case _PAGE_WP:
+ break;
+ default:
+ /*
+ * If we get here, a PV guest tried to use one of the
+ * reserved values in Xen's PAT. This indicates a bug
+ * in the guest. If requested by the user, inject #GP
+ * to cause the guest to log a stack trace.
+ */
+ if ( invalid_cacheability == INVALID_CACHEABILITY_TRAP )
+ pv_inject_hw_exception(TRAP_gp_fault, 0);
+ return -EINVAL;
+ }
+ }
+
valid = mfn_valid(_mfn(mfn));
if ( !valid ||
@@ -1324,6 +1348,31 @@ static int put_page_from_l4e(l4_pgentry_t l4e, mfn_t
l4mfn, unsigned int flags)
return put_pt_page(l4e_get_page(l4e), mfn_to_page(l4mfn), flags);
}
+#ifdef NDEBUG
+#define INVALID_CACHEABILITY_DEFAULT INVALID_CACHEABILITY_DENY
+#else
+#define INVALID_CACHEABILITY_DEFAULT INVALID_CACHEABILITY_TRAP
+#endif
+
+__ro_after_init uint8_t invalid_cacheability =
+ INVALID_CACHEABILITY_DEFAULT;
+
+static int __init cf_check set_invalid_cacheability(const char *str)
+{
+ if (strcmp("allow", str) == 0)
+ invalid_cacheability = INVALID_CACHEABILITY_ALLOW;
+ else if (strcmp("deny", str) == 0)
+ invalid_cacheability = INVALID_CACHEABILITY_DENY;
+ else if (strcmp("trap", str) == 0)
+ invalid_cacheability = INVALID_CACHEABILITY_TRAP;
+ else
+ return -EINVAL;
+
+ return 0;
+}
+
+custom_param("invalid-cacheability", set_invalid_cacheability);
+
static int promote_l1_table(struct page_info *page)
{
struct domain *d = page_get_owner(page);
@@ -1343,7 +1392,9 @@ static int promote_l1_table(struct page_info *page)
}
else
{
- switch ( ret = get_page_from_l1e(pl1e[i], d, d) )
+ l1_pgentry_t l1e = pl1e[i];
+
+ switch ( ret = get_page_from_l1e(l1e, d, d) )
{
default:
goto fail;
diff --git a/xen/arch/x86/pv/domain.c b/xen/arch/x86/pv/domain.c
index
f94f28c8e271549acb449ef2e129b928751f765d..40b424351fd99fe1fb0a5faa5b20bf4070bb1d4a
100644
--- a/xen/arch/x86/pv/domain.c
+++ b/xen/arch/x86/pv/domain.c
@@ -28,9 +28,21 @@ static int __init cf_check parse_pv(const char *s)
do {
ss = strchr(s, ',');
if ( !ss )
- ss = strchr(s, '\0');
-
- if ( (val = parse_boolean("32", s, ss)) >= 0 )
+ ss += strlen(s);
+ if ( !strncmp("invalid-cacheability=", s,
+ sizeof("invalid-cacheability=") - 1) )
+ {
+ const char *p = s + (sizeof("invalid-cacheability=") - 1);
+ if (ss - p == 5 && !memcmp(p, "allow", 5))
+ invalid_cacheability = INVALID_CACHEABILITY_ALLOW;
+ else if (ss - p == 4 && !memcmp(p, "deny", 4))
+ invalid_cacheability = INVALID_CACHEABILITY_DENY;
+ else if (ss - p == 4 && !memcmp(p, "trap", 4))
+ invalid_cacheability = INVALID_CACHEABILITY_TRAP;
+ else
+ rc = -EINVAL;
+ }
+ else if ( (val = parse_boolean("32", s, ss)) >= 0 )
{
#ifdef CONFIG_PV32
opt_pv32 = val;
--
Sincerely,
Demi Marie Obenour (she/her/hers)
Invisible Things Lab
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |