diff mbox

[05/15] xen: p2m: new 'p2m_epc' type for EPC mapping

Message ID b92cd8efa7f45dc4f17a66228137aa0b3174abef.1499586046.git.kai.huang@linux.intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Kai Huang July 9, 2017, 8:12 a.m. UTC
A new 'p2m_epc' type is added for EPC mapping type. Two wrapper functions
set_epc_p2m_entry and clear_epc_p2m_entry are also added for further use.

Signed-off-by: Kai Huang <kai.huang@linux.intel.com>
---
 xen/arch/x86/mm/p2m-ept.c |  3 +++
 xen/arch/x86/mm/p2m.c     | 41 +++++++++++++++++++++++++++++++++++++++++
 xen/include/asm-x86/p2m.h | 12 ++++++++++--
 3 files changed, 54 insertions(+), 2 deletions(-)

Comments

Andrew Cooper July 12, 2017, 11:01 a.m. UTC | #1
On 09/07/17 10:12, Kai Huang wrote:
> A new 'p2m_epc' type is added for EPC mapping type. Two wrapper functions
> set_epc_p2m_entry and clear_epc_p2m_entry are also added for further use.

Other groups in Intel have been looking to reduce the number of p2m 
types we have, so we can use more hardware defined bits in the EPT 
pagetable entries.

If we need a new type then we will certainly add one, but it is not 
clear why this type is needed.

~Andrew
George Dunlap July 12, 2017, 12:21 p.m. UTC | #2
> On Jul 12, 2017, at 1:01 PM, Andrew Cooper <andrew.cooper3@citrix.com> wrote:

> 

> On 09/07/17 10:12, Kai Huang wrote:

>> A new 'p2m_epc' type is added for EPC mapping type. Two wrapper functions

>> set_epc_p2m_entry and clear_epc_p2m_entry are also added for further use.

> 

> Other groups in Intel have been looking to reduce the number of p2m types we have, so we can use more hardware defined bits in the EPT pagetable entries.

> 

> If we need a new type then we will certainly add one, but it is not clear why this type is needed.


Does the hypervisor need to know which pages of a domain’s p2m 1) have valid config set up, but 2) aren’t accessible to itself or any other domain?

 -George
Kai Huang July 13, 2017, 5:56 a.m. UTC | #3
On 7/13/2017 12:21 AM, George Dunlap wrote:
> 
>> On Jul 12, 2017, at 1:01 PM, Andrew Cooper <andrew.cooper3@citrix.com> wrote:
>>
>> On 09/07/17 10:12, Kai Huang wrote:
>>> A new 'p2m_epc' type is added for EPC mapping type. Two wrapper functions
>>> set_epc_p2m_entry and clear_epc_p2m_entry are also added for further use.
>>
>> Other groups in Intel have been looking to reduce the number of p2m types we have, so we can use more hardware defined bits in the EPT pagetable entries.
>>
>> If we need a new type then we will certainly add one, but it is not clear why this type is needed.
> 
> Does the hypervisor need to know which pages of a domain’s p2m 1) have valid config set up, but 2) aren’t accessible to itself or any other domain?

Hi Andrew, George,

Actually I haven't thought this thoroughly, but my first glance is 
there's no existing p2m_type that can be reasonably used for EPC. 
Probably p2m_ram_rw or p2m_mmio_direct are two potential candidates. For 
EPC, for *static partitioning* Xen hypervisor just needs to setup 
mappings and then leave it until guest is destroyed. But for p2m_ram_rw 
and p2m_mmio_direct there are additional logic when Xen learns about the 
two types. To me adding 'p2m_epc' is more straightforward and safe. 
Maybe we can change to a more generic name such as 'p2m_ram_encrypted'? 
But again I am not sure other encryption technology can also be applied 
to EPC.

> 
>   -George
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> https://lists.xen.org/xen-devel
>
diff mbox

Patch

diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c
index ecab56fbec..95929868dc 100644
--- a/xen/arch/x86/mm/p2m-ept.c
+++ b/xen/arch/x86/mm/p2m-ept.c
@@ -182,6 +182,9 @@  static void ept_p2m_type_to_flags(struct p2m_domain *p2m, ept_entry_t *entry,
             entry->a = !!cpu_has_vmx_ept_ad;
             entry->d = 0;
             break;
+        case p2m_epc:
+            entry->r = entry->w = entry->x = 1;
+            break;
     }
 
 
diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index bee733dc46..29f42cb96d 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -1176,6 +1176,12 @@  int set_identity_p2m_entry(struct domain *d, unsigned long gfn,
     return ret;
 }
 
+int set_epc_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn)
+{
+    return set_typed_p2m_entry(d, gfn, mfn, PAGE_ORDER_4K, p2m_epc,
+            p2m_get_hostp2m(d)->default_access);
+}
+
 /*
  * Returns:
  *    0        for success
@@ -1260,6 +1266,41 @@  int clear_identity_p2m_entry(struct domain *d, unsigned long gfn)
     return ret;
 }
 
+int clear_epc_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn)
+{
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
+    mfn_t omfn;
+    p2m_type_t ot;
+    p2m_access_t oa;
+    int ret = 0;
+
+    gfn_lock(p2m, gfn, 0);
+
+    omfn = p2m->get_entry(p2m, gfn, &ot, &oa, 0, NULL, NULL);
+    if ( mfn_eq(omfn, INVALID_MFN) || !p2m_is_epc(ot) )
+    {
+        printk(XENLOG_G_WARNING
+                "d%d: invalid EPC map to clear: gfn 0x%lx, type %d.\n",
+                d->domain_id, gfn, ot);
+        goto out;
+    }
+    if ( !mfn_eq(mfn, omfn) )
+    {
+        printk(XENLOG_G_WARNING
+                "d%d: mistaken EPC mfn to clear: gfn 0x%lx, "
+                "omfn 0x%lx, mfn 0x%lx.\n",
+                d->domain_id, gfn, mfn_x(omfn), mfn_x(mfn));
+    }
+
+    ret = p2m_set_entry(p2m, gfn, INVALID_MFN, PAGE_ORDER_4K, p2m_invalid,
+            p2m->default_access);
+
+out:
+    gfn_unlock(p2m, gfn, 0);
+
+    return ret;
+}
+
 /* Returns: 0 for success, -errno for failure */
 int set_shared_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn)
 {
diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
index e736609241..a9e330dd3c 100644
--- a/xen/include/asm-x86/p2m.h
+++ b/xen/include/asm-x86/p2m.h
@@ -72,6 +72,7 @@  typedef enum {
     p2m_ram_broken = 13,          /* Broken page, access cause domain crash */
     p2m_map_foreign  = 14,        /* ram pages from foreign domain */
     p2m_ioreq_server = 15,
+    p2m_epc = 16,                 /* EPC */
 } p2m_type_t;
 
 /* Modifiers to the query */
@@ -142,10 +143,13 @@  typedef unsigned int p2m_query_t;
                             | p2m_to_mask(p2m_ram_logdirty) )
 #define P2M_SHARED_TYPES   (p2m_to_mask(p2m_ram_shared))
 
+#define P2M_EPC_TYPES   (p2m_to_mask(p2m_epc))
+
 /* Valid types not necessarily associated with a (valid) MFN. */
 #define P2M_INVALID_MFN_TYPES (P2M_POD_TYPES                  \
                                | p2m_to_mask(p2m_mmio_direct) \
-                               | P2M_PAGING_TYPES)
+                               | P2M_PAGING_TYPES             \
+                               | P2M_EPC_TYPES)
 
 /* Broken type: the frame backing this pfn has failed in hardware
  * and must not be touched. */
@@ -153,6 +157,7 @@  typedef unsigned int p2m_query_t;
 
 /* Useful predicates */
 #define p2m_is_ram(_t) (p2m_to_mask(_t) & P2M_RAM_TYPES)
+#define p2m_is_epc(_t) (p2m_to_mask(_t) & P2M_EPC_TYPES)
 #define p2m_is_hole(_t) (p2m_to_mask(_t) & P2M_HOLE_TYPES)
 #define p2m_is_mmio(_t) (p2m_to_mask(_t) & P2M_MMIO_TYPES)
 #define p2m_is_readonly(_t) (p2m_to_mask(_t) & P2M_RO_TYPES)
@@ -163,7 +168,7 @@  typedef unsigned int p2m_query_t;
 /* Grant types are *not* considered valid, because they can be
    unmapped at any time and, unless you happen to be the shadow or p2m
    implementations, there's no way of synchronising against that. */
-#define p2m_is_valid(_t) (p2m_to_mask(_t) & (P2M_RAM_TYPES | P2M_MMIO_TYPES))
+#define p2m_is_valid(_t) (p2m_to_mask(_t) & (P2M_RAM_TYPES | P2M_MMIO_TYPES | P2M_EPC_TYPES))
 #define p2m_has_emt(_t)  (p2m_to_mask(_t) & (P2M_RAM_TYPES | p2m_to_mask(p2m_mmio_direct)))
 #define p2m_is_pageable(_t) (p2m_to_mask(_t) & P2M_PAGEABLE_TYPES)
 #define p2m_is_paging(_t)   (p2m_to_mask(_t) & P2M_PAGING_TYPES)
@@ -634,6 +639,9 @@  int clear_identity_p2m_entry(struct domain *d, unsigned long gfn);
 int p2m_add_foreign(struct domain *tdom, unsigned long fgfn,
                     unsigned long gpfn, domid_t foreign_domid);
 
+int set_epc_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn);
+int clear_epc_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn);
+
 /* 
  * Populate-on-demand
  */