From: Zhang Yi <yi.z.zhang@linux.intel.com>
To: xen-devel@lists.xenproject.org
Cc: kevin.tian@intel.com, tamas@tklengyel.com, wei.liu2@citrix.com,
jun.nakajima@intel.com, rcojocaru@bitdefender.com,
george.dunlap@eu.citrix.com, andrew.cooper3@citrix.com,
ian.jackson@eu.citrix.com,
Zhang Yi Z <yi.z.zhang@linux.intel.com>,
jbeulich@suse.com
Subject: [PATCH RFC 08/14] xen: vmx: Added setup spp page structure.
Date: Thu, 19 Oct 2017 16:12:33 +0800 [thread overview]
Message-ID: <d505ccd98f0e9f4faf1b10088b1edf53130ce8db.1508397860.git.yi.z.zhang@linux.intel.com> (raw)
In-Reply-To: <cover.1508397860.git.yi.z.zhang@linux.intel.com>
From: Zhang Yi Z <yi.z.zhang@linux.intel.com>
The hardware uses the guest-physical address and bits 11:7 of the
address accessed to lookup the SPPT to fetch a write permission bit for
the 128 byte wide sub-page region being accessed within the 4K
guest-physical page. If the sub-page region write permission bit is set,
the write is allowed; otherwise the write is disallowed and results in
an EPT violation.
Guest-physical pages mapped via leaf EPT-paging-structures for which the
accumulated write-access bit and the SPP bits are both clear (0)
generate
EPT violations on memory writes accesses. Guest-physical pages mapped
via EPT-paging-structure for which the accumulated write-access bit is
set (1) allow writes, effectively ignoring the SPP bit on the leaf
EPT-paging structure.
Software will setup the spp page table level4,3,2 as well as EPT page
structure, and fill the level1 via the 32 bit bitmap per a single 4K
page.
Now it could be divided to 32 x 128 sub-pages.
Signed-off-by: Zhang Yi Z <yi.z.zhang@linux.intel.com>
---
xen/arch/x86/mm/mem_access.c | 35 +++++++++++++++
xen/arch/x86/mm/p2m-ept.c | 94 +++++++++++++++++++++++++++++++++++++++
xen/include/asm-x86/hvm/vmx/vmx.h | 10 +++++
xen/include/asm-x86/p2m.h | 3 ++
4 files changed, 142 insertions(+)
diff --git a/xen/arch/x86/mm/mem_access.c b/xen/arch/x86/mm/mem_access.c
index a471c74..1b97469 100644
--- a/xen/arch/x86/mm/mem_access.c
+++ b/xen/arch/x86/mm/mem_access.c
@@ -490,6 +490,41 @@ unlock_exit:
return rc;
}
+static u64 format_spp_spte(u32 spp_wp_bitmap)
+{
+ u64 new_spte = 0;
+ int i = 0;
+
+ /*
+ * One 4K page contains 32 sub-pages, in SPP table L4E, old bits
+ * are reserved, so we need to transfer u32 subpage write
+ * protect bitmap to u64 SPP L4E format.
+ */
+ while ( i < 32 ) {
+ if ( spp_wp_bitmap & (1ULL << i) )
+ new_spte |= 1ULL << (i * 2);
+
+ i++;
+ }
+
+ return new_spte;
+}
+
+int p2m_set_spp_page_st(struct domain *d, gfn_t gfn, uint32_t access_map)
+{
+ struct p2m_domain *p2m = p2m_get_hostp2m(d);
+ u64 access = format_spp_spte(access_map);
+ unsigned long gfn_l = gfn_x(gfn);
+ int ret = -1;
+
+ p2m_lock(p2m);
+ if ( p2m->spp_set_entry )
+ ret = p2m->spp_set_entry(p2m, gfn_l, access);
+ p2m_unlock(p2m);
+
+ return ret;
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c
index c249286..c9dc29c 100644
--- a/xen/arch/x86/mm/p2m-ept.c
+++ b/xen/arch/x86/mm/p2m-ept.c
@@ -38,6 +38,8 @@
#define is_epte_present(ept_entry) ((ept_entry)->epte & 0x7)
#define is_epte_superpage(ept_entry) ((ept_entry)->sp)
+#define is_sppt_present(spp_entry) ((spp_entry)->spp & 0x1)
+
static inline bool_t is_epte_valid(ept_entry_t *e)
{
/* suppress_ve alone is not considered valid, so mask it off */
@@ -253,6 +255,22 @@ static int ept_set_middle_entry(struct p2m_domain *p2m, ept_entry_t *ept_entry)
return 1;
}
+static int spp_set_middle_entry(struct p2m_domain *p2m, spp_entry_t *spp_entry)
+{
+ struct page_info *pg;
+
+ pg = p2m_alloc_ptp(p2m, 0);
+ if ( pg == NULL )
+ return 0;
+
+ spp_entry->spp = 0;
+ spp_entry->mfn = page_to_mfn(pg);
+
+ spp_entry->present = 1;
+
+ return 1;
+}
+
/* free ept sub tree behind an entry */
static void ept_free_entry(struct p2m_domain *p2m, ept_entry_t *ept_entry, int level)
{
@@ -323,6 +341,44 @@ static bool_t ept_split_super_page(struct p2m_domain *p2m,
return rv;
}
+static int spp_next_level(struct p2m_domain *p2m,
+ spp_entry_t **table, unsigned long *gfn_remainder,
+ int next_level)
+{
+ unsigned long mfn;
+ spp_entry_t *spp_entry, e;
+ u32 shift, index;
+
+ shift = next_level * EPT_TABLE_ORDER;
+
+ index = *gfn_remainder >> shift;
+
+ /* index must be falling into the page */
+ ASSERT(index < EPT_PAGETABLE_ENTRIES);
+
+ spp_entry = (*table) + index;
+
+ /* ept_next_level() is called (sometimes) without a lock. Read
+ * the entry once, and act on the "cached" entry after that to
+ * avoid races. */
+ e.spp = read_atomic(&(spp_entry->spp));
+
+ if ( !is_sppt_present(&e) )
+ {
+ if ( !spp_set_middle_entry(p2m, spp_entry) )
+ return GUEST_TABLE_MAP_FAILED;
+ else
+ e.spp = read_atomic(&(spp_entry->spp)); /* Refresh */
+ }
+
+ mfn = e.mfn;
+ unmap_domain_page(*table);
+ *table = map_domain_page(_mfn(mfn));
+ *gfn_remainder &= (1UL << shift) - 1;
+ return GUEST_TABLE_NORMAL_PAGE;
+}
+
+
/* Take the currently mapped table, find the corresponding gfn entry,
* and map the next table, if available. If the entry is empty
* and read_only is set,
@@ -709,6 +765,43 @@ out:
return rc;
}
+static int
+spp_set_entry(struct p2m_domain *p2m, unsigned long gfn, u64 access)
+{
+ struct spp_data *spp = &p2m->spptp;
+ unsigned long gfn_remainder = gfn;
+ spp_entry_t *table;
+ u64 *pspp_bitmap;
+ u64 old_spp_bitmap;
+ unsigned int i;
+ int ret, rc = 0;
+
+ ASSERT(spp);
+ table = map_domain_page(_mfn(pagetable_get_pfn(p2m_get_spp_pagetable(p2m))));
+
+ for ( i = 3; i > 0; i-- )
+ {
+ ret = spp_next_level(p2m, &table, &gfn_remainder, i);
+ if ( ret != GUEST_TABLE_NORMAL_PAGE )
+ {
+ printk("dazhang1 error oc ret = %x\n", ret);
+ rc = -1;
+ goto out;
+ }
+ }
+
+ pspp_bitmap = (u64 *) (table + gfn_remainder);
+ old_spp_bitmap = read_atomic(pspp_bitmap);
+ if( old_spp_bitmap != access )
+ {
+ write_atomic(pspp_bitmap, access);
+ }
+
+out:
+ unmap_domain_page(table);
+ return rc;
+}
+
/*
* ept_set_entry() computes 'need_modify_vtd_table' for itself,
* by observing whether any gfn->mfn translations are modified.
@@ -1309,6 +1402,7 @@ int ept_p2m_init(struct p2m_domain *p2m)
if ( cpu_has_vmx_ept_spp )
{
p2m->update_ept_spp_wp = ept_spp_update_wp;
+ p2m->spp_set_entry = spp_set_entry;
}
if ( !zalloc_cpumask_var(&ept->invalidate) )
diff --git a/xen/include/asm-x86/hvm/vmx/vmx.h b/xen/include/asm-x86/hvm/vmx/vmx.h
index 18383b8..655ce80 100644
--- a/xen/include/asm-x86/hvm/vmx/vmx.h
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h
@@ -52,6 +52,16 @@ typedef union {
u64 epte;
} ept_entry_t;
+typedef union {
+ struct {
+ u64 present : 1, /* bit 0 - spp middle table is present */
+ reserved : 11, /* bit 1:11 - reserved */
+ mfn : 40, /* bit 12:51 - Machine physical frame number */
+ reserved2 : 12; /* bit 52:63 - reserved */
+ };
+ u64 spp;
+} spp_entry_t;
+
typedef struct {
/*use lxe[0] to save result */
ept_entry_t lxe[5];
diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
index adbc1c6..b94ebb2 100644
--- a/xen/include/asm-x86/p2m.h
+++ b/xen/include/asm-x86/p2m.h
@@ -268,6 +268,9 @@ struct p2m_domain {
long (*audit_p2m)(struct p2m_domain *p2m);
int (*update_ept_spp_wp)(struct p2m_domain *p2m,
unsigned long gfn);
+ int (*spp_set_entry)(struct p2m_domain *p2m,
+ unsigned long gfn,
+ u64 access);
/*
* P2M updates may require TLBs to be flushed (invalidated).
--
2.7.4
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
next prev parent reply other threads:[~2017-10-19 8:12 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-10-19 8:04 [PATCH RFC 00/14] Intel EPT-Based Sub-page Write Protection Support Zhang Yi
2017-10-19 8:08 ` [PATCH RFC 01/14] xen: vmx: Added EPT based Subpage Write Protection Doc Zhang Yi
2017-10-19 8:08 ` [PATCH RFC 02/14] xen: vmx: Added VMX SPP feature flags and VM-Execution Controls Zhang Yi
2017-10-19 8:09 ` [PATCH RFC 03/14] xen: vmx: Introduce the SPPTP and SPP page table Zhang Yi
2017-10-19 8:10 ` [PATCH RFC 04/14] xen: vmx: Introduce SPP-Induced vm exit and it's handle Zhang Yi
2017-10-19 8:11 ` [PATCH RFC 05/14] xen: vmx: Disable the 2M/1G superpage when SPP enabled Zhang Yi
2017-10-19 18:17 ` Tamas K Lengyel
2017-10-20 8:44 ` Yi Zhang
2017-10-24 17:43 ` Tamas K Lengyel
2017-10-25 15:32 ` Yi Zhang
2017-10-25 15:12 ` Tamas K Lengyel
2017-10-19 8:11 ` [PATCH RFC 06/14] xen: vmx: Added SPP flags in EPT leaf entry Zhang Yi
2017-10-19 8:12 ` [PATCH RFC 07/14] xen: vmx: Update the EPT leaf entry indicated with the SPP enable bit Zhang Yi
2017-10-19 8:12 ` Zhang Yi [this message]
2017-10-19 18:26 ` [PATCH RFC 08/14] xen: vmx: Added setup spp page structure Tamas K Lengyel
2017-10-20 8:43 ` Yi Zhang
2017-10-19 8:13 ` [PATCH RFC 09/14] xen: vmx: Introduce a Hyper call to set subpage Zhang Yi
2017-10-19 18:34 ` Tamas K Lengyel
2017-10-20 8:41 ` Yi Zhang
2017-10-19 8:13 ` [PATCH RFC 10/14] xen: vmx: Implement the Hypercall p2m_set_subpage Zhang Yi
2017-10-19 8:14 ` [PATCH RFC 11/14] xen: vmx: Added handle of SPP write protection fault Zhang Yi
2017-10-19 8:15 ` [PATCH RFC 12/14] xen: vmx: Support for clear EPT SPP write Protect bit Zhang Yi
2017-10-19 8:15 ` [PATCH RFC 13/14] xen: tools: Introduce the set-subpage into xenctrl Zhang Yi
2017-10-19 8:37 ` Razvan Cojocaru
2017-10-20 8:40 ` Yi Zhang
2017-10-19 8:16 ` [PATCH RFC 14/14] xen: tools: Added xen-subpage tool Zhang Yi
2017-10-19 8:42 ` Razvan Cojocaru
2017-10-20 8:39 ` Yi Zhang
2017-10-19 9:07 ` [PATCH RFC 00/14] Intel EPT-Based Sub-page Write Protection Support Razvan Cojocaru
2017-10-20 8:37 ` Yi Zhang
2017-10-20 8:39 ` Razvan Cojocaru
2017-10-20 8:39 ` Razvan Cojocaru
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=d505ccd98f0e9f4faf1b10088b1edf53130ce8db.1508397860.git.yi.z.zhang@linux.intel.com \
--to=yi.z.zhang@linux.intel.com \
--cc=andrew.cooper3@citrix.com \
--cc=george.dunlap@eu.citrix.com \
--cc=ian.jackson@eu.citrix.com \
--cc=jbeulich@suse.com \
--cc=jun.nakajima@intel.com \
--cc=kevin.tian@intel.com \
--cc=rcojocaru@bitdefender.com \
--cc=tamas@tklengyel.com \
--cc=wei.liu2@citrix.com \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).