All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM
@ 2016-08-16 22:16 Sergej Proskurin
  2016-08-16 22:16 ` [PATCH v3 01/38] arm/p2m: Cosmetic fixes - apply p2m_get_hostp2m Sergej Proskurin
                   ` (37 more replies)
  0 siblings, 38 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin

Hello all,

The following patch series can be found on Github[0] and is part of my
contribution to this year's Google Summer of Code (GSoC)[1]. My project is
managed by the organization The Honeynet Project. As part of GSoC, I am being
supervised by the Xen developer Tamas K. Lengyel <tamas@tklengyel.com>, George
D. Webster, and Steven Maresca.

In this patch series, we provide an implementation of the altp2m subsystem for
ARM. Our implementation is based on the altp2m subsystem for x86, providing
additional --alternate-- views on the guest's physical memory by means of the
ARM 2nd stage translation mechanism. The patches introduce new HVMOPs and
extend the p2m subsystem. Also, we extend libxl to support altp2m on ARM and
modify xen-access to test the suggested functionality.

To be more precise, altp2m allows to create and switch to additional p2m views
(i.e. gfn to mfn mappings). These views can be manipulated and activated as
will through the provided HVMOPs. In this way, the active guest instance in
question can seamlessly proceed execution without noticing that anything has
changed. The prime scope of application of altp2m is Virtual Machine
Introspection, where guest systems are analyzed from the outside of the VM.

Altp2m can be activated by means of the guest control parameter "altp2m" on x86
and ARM architectures. For use-cases requiring purely external access to
altp2m, this patch allows to specify if the altp2m interface should be external
only.

The current code-base is based on Julien Grall's branch p2m-rfc[2].

Please note: To work properly, the provided patch must include the fix that has
been presented in [3]. The fix makes sure that the flag p2m->mem_access_enabled
is considered during the manipulation of (alt)p2m entries.

Best regards,
~Sergej

[0] https://github.com/sergej-proskurin/xen (branch arm-altp2m-v3)
[1] https://summerofcode.withgoogle.com/projects/#4970052843470848
[2] git://xenbits.xen.org/people/julieng/xen-unstable.git (branch p2m-rfc)
[3] https://lists.xenproject.org/archives/html/xen-devel/2016-08/msg01870.html

Sergej Proskurin (37):
  arm/p2m: Cosmetic fixes - apply p2m_get_hostp2m
  arm/p2m: Expose p2m_*lock helpers
  arm/p2m: Introduce p2m_(switch|restore)_vttbr_and_(g|s)et_flags
  arm/p2m: Add first altp2m HVMOP stubs
  arm/p2m: Add hvm_allow_(set|get)_param
  arm/p2m: Add HVMOP_altp2m_get_domain_state
  arm/p2m: Introduce p2m_is_(hostp2m|altp2m)
  arm/p2m: Free p2m entries only in the hostp2m
  arm/p2m: Add backpointer to the domain in p2m_domain
  arm/p2m: Move hostp2m init/teardown to individual functions
  arm/p2m: Cosmetic fix - function prototype of p2m_alloc_table
  arm/p2m: Rename parameter in p2m_alloc_vmid
  arm/p2m: Change func prototype and impl of p2m_(alloc|free)_vmid
  arm/p2m: Add altp2m init/teardown routines
  arm/p2m: Add altp2m table flushing routine
  arm/p2m: Add HVMOP_altp2m_set_domain_state
  arm/p2m: Add HVMOP_altp2m_create_p2m
  arm/p2m: Add HVMOP_altp2m_destroy_p2m
  arm/p2m: Add HVMOP_altp2m_switch_p2m
  arm/p2m: Add p2m_get_active_p2m macro
  arm/p2m: Make p2m_restore_state ready for altp2m
  arm/p2m: Make get_page_from_gva ready for altp2m
  arm/p2m: Cosmetic fixes -- __p2m_get_mem_access
  arm/p2m: Make p2m_mem_access_check ready for altp2m
  arm/p2m: Cosmetic fixes - function prototypes
  arm/p2m: Introduce helpers managing altp2m entries
  arm/p2m: Introduce p2m_lookup_attr
  arm/p2m: Modify reference count only if hostp2m active
  arm/p2m: Add HVMOP_altp2m_set_mem_access
  arm/p2m: Add altp2m_propagate_change
  altp2m: Introduce altp2m_switch_vcpu_altp2m_by_id
  arm/p2m: Code movement in instr/data abort handlers
  arm/p2m: Add altp2m paging mechanism
  arm/p2m: Add HVMOP_altp2m_change_gfn
  arm/p2m: Adjust debug information to altp2m
  arm/p2m: Extend xen-access for altp2m on ARM
  arm/p2m: Add test of xc_altp2m_change_gfn

Tamas K Lengyel (1):
  altp2m: Allow specifying external-only use-case

 docs/man/xl.cfg.pod.5.in            |  37 ++-
 tools/libxl/libxl.h                 |  10 +-
 tools/libxl/libxl_create.c          |   7 +-
 tools/libxl/libxl_dom.c             |  30 +-
 tools/libxl/libxl_types.idl         |  13 +
 tools/libxl/xl_cmdimpl.c            |  25 +-
 tools/tests/xen-access/xen-access.c | 183 ++++++++++-
 xen/arch/arm/Makefile               |   1 +
 xen/arch/arm/altp2m.c               | 627 ++++++++++++++++++++++++++++++++++++
 xen/arch/arm/hvm.c                  | 210 +++++++++++-
 xen/arch/arm/p2m.c                  | 452 +++++++++++++++++++-------
 xen/arch/arm/traps.c                |  65 +++-
 xen/arch/x86/hvm/hvm.c              |  20 +-
 xen/arch/x86/mm/altp2m.c            |   6 +
 xen/arch/x86/mm/p2m.c               |   6 -
 xen/common/vm_event.c               |   3 +-
 xen/include/asm-arm/altp2m.h        |  77 ++++-
 xen/include/asm-arm/domain.h        |  16 +
 xen/include/asm-arm/p2m.h           |  85 ++++-
 xen/include/asm-x86/altp2m.h        |   3 +
 xen/include/asm-x86/p2m.h           |   3 -
 xen/include/public/hvm/params.h     |  10 +-
 xen/include/xsm/dummy.h             |  14 +-
 xen/include/xsm/xsm.h               |   6 +-
 xen/xsm/flask/hooks.c               |   2 +-
 25 files changed, 1718 insertions(+), 193 deletions(-)
 create mode 100644 xen/arch/arm/altp2m.c

--
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* [PATCH v3 01/38] arm/p2m: Cosmetic fixes - apply p2m_get_hostp2m
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-09-01 15:46   ` Julien Grall
  2016-08-16 22:16 ` [PATCH v3 02/38] arm/p2m: Expose p2m_*lock helpers Sergej Proskurin
                   ` (36 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

This commit substitutes the direct access of the host's p2m
(&d->arch.p2m) for the macro "p2m_get_hostp2m". This macro simplifies
the differentiation between the host's p2m and introduced alternative
p2m's, in the following commits.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
 xen/arch/arm/p2m.c | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index beaaf43..da6c7d4 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -107,7 +107,7 @@ static inline int p2m_is_write_locked(struct p2m_domain *p2m)
 
 void p2m_dump_info(struct domain *d)
 {
-    struct p2m_domain *p2m = &d->arch.p2m;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
 
     p2m_read_lock(p2m);
     printk("p2m mappings for domain %d (vmid %d):\n",
@@ -127,7 +127,7 @@ void memory_type_changed(struct domain *d)
 
 void dump_p2m_lookup(struct domain *d, paddr_t addr)
 {
-    struct p2m_domain *p2m = &d->arch.p2m;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
 
     printk("dom%d IPA 0x%"PRIpaddr"\n", d->domain_id, addr);
 
@@ -146,7 +146,7 @@ void p2m_save_state(struct vcpu *p)
 void p2m_restore_state(struct vcpu *n)
 {
     register_t hcr;
-    struct p2m_domain *p2m = &n->domain->arch.p2m;
+    struct p2m_domain *p2m = p2m_get_hostp2m(n->domain);
 
     if ( is_idle_vcpu(n) )
         return;
@@ -405,7 +405,7 @@ out:
 mfn_t p2m_lookup(struct domain *d, gfn_t gfn, p2m_type_t *t)
 {
     mfn_t ret;
-    struct p2m_domain *p2m = &d->arch.p2m;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
 
     p2m_read_lock(p2m);
     ret = p2m_get_entry(p2m, gfn, t, NULL, NULL);
@@ -1052,7 +1052,7 @@ static inline int p2m_insert_mapping(struct domain *d,
                                      mfn_t mfn,
                                      p2m_type_t t)
 {
-    struct p2m_domain *p2m = &d->arch.p2m;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     int rc;
 
     p2m_write_lock(p2m);
@@ -1071,7 +1071,7 @@ static inline int p2m_remove_mapping(struct domain *d,
                                      unsigned long nr,
                                      mfn_t mfn)
 {
-    struct p2m_domain *p2m = &d->arch.p2m;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     int rc;
 
     p2m_write_lock(p2m);
@@ -1153,7 +1153,7 @@ void guest_physmap_remove_page(struct domain *d,
 
 static int p2m_alloc_table(struct domain *d)
 {
-    struct p2m_domain *p2m = &d->arch.p2m;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     struct page_info *page;
     unsigned int i;
 
@@ -1196,7 +1196,7 @@ void p2m_vmid_allocator_init(void)
 
 static int p2m_alloc_vmid(struct domain *d)
 {
-    struct p2m_domain *p2m = &d->arch.p2m;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
 
     int rc, nr;
 
@@ -1226,7 +1226,7 @@ out:
 
 static void p2m_free_vmid(struct domain *d)
 {
-    struct p2m_domain *p2m = &d->arch.p2m;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     spin_lock(&vmid_alloc_lock);
     if ( p2m->vmid != INVALID_VMID )
         clear_bit(p2m->vmid, vmid_mask);
@@ -1236,7 +1236,7 @@ static void p2m_free_vmid(struct domain *d)
 
 void p2m_teardown(struct domain *d)
 {
-    struct p2m_domain *p2m = &d->arch.p2m;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     struct page_info *pg;
 
     while ( (pg = page_list_remove_head(&p2m->pages)) )
@@ -1254,7 +1254,7 @@ void p2m_teardown(struct domain *d)
 
 int p2m_init(struct domain *d)
 {
-    struct p2m_domain *p2m = &d->arch.p2m;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     int rc = 0;
 
     rwlock_init(&p2m->lock);
@@ -1296,7 +1296,7 @@ int p2m_init(struct domain *d)
  */
 int relinquish_p2m_mapping(struct domain *d)
 {
-    struct p2m_domain *p2m = &d->arch.p2m;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     unsigned long count = 0;
     p2m_type_t t;
     int rc = 0;
@@ -1347,7 +1347,7 @@ int relinquish_p2m_mapping(struct domain *d)
 
 int p2m_cache_flush(struct domain *d, gfn_t start, unsigned long nr)
 {
-    struct p2m_domain *p2m = &d->arch.p2m;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     gfn_t end = gfn_add(start, nr);
     p2m_type_t t;
     unsigned int order;
@@ -1410,7 +1410,7 @@ p2m_mem_access_check_and_get_page(vaddr_t gva, unsigned long flag)
     xenmem_access_t xma;
     p2m_type_t t;
     struct page_info *page = NULL;
-    struct p2m_domain *p2m = &current->domain->arch.p2m;
+    struct p2m_domain *p2m = p2m_get_hostp2m(current->domain);
 
     rc = gva_to_ipa(gva, &ipa, flag);
     if ( rc < 0 )
@@ -1497,7 +1497,7 @@ struct page_info *get_page_from_gva(struct vcpu *v, vaddr_t va,
                                     unsigned long flags)
 {
     struct domain *d = v->domain;
-    struct p2m_domain *p2m = &d->arch.p2m;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     struct page_info *page = NULL;
     paddr_t maddr = 0;
     int rc;
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 02/38] arm/p2m: Expose p2m_*lock helpers
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
  2016-08-16 22:16 ` [PATCH v3 01/38] arm/p2m: Cosmetic fixes - apply p2m_get_hostp2m Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-09-01 15:48   ` Julien Grall
  2016-08-16 22:16 ` [PATCH v3 03/38] arm/p2m: Introduce p2m_(switch|restore)_vttbr_and_(g|s)et_flags Sergej Proskurin
                   ` (35 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

This commit exposes the "p2m_*lock" helpers, as they will be used within
the file ./xen/arch/arm/altp2m.c, as will be shown in the following
commits.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
 xen/arch/arm/p2m.c        | 12 ++++++------
 xen/include/asm-arm/p2m.h | 16 ++++++++++++++++
 2 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index da6c7d4..08114d8 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -62,14 +62,14 @@ static inline bool_t p2m_is_superpage(lpae_t pte, unsigned int level)
     return (level < 3) && p2m_mapping(pte);
 }
 
-static inline void p2m_write_lock(struct p2m_domain *p2m)
+void p2m_write_lock(struct p2m_domain *p2m)
 {
     write_lock(&p2m->lock);
 }
 
 static void p2m_flush_tlb(struct p2m_domain *p2m);
 
-static inline void p2m_write_unlock(struct p2m_domain *p2m)
+void p2m_write_unlock(struct p2m_domain *p2m)
 {
     if ( p2m->need_flush )
     {
@@ -85,22 +85,22 @@ static inline void p2m_write_unlock(struct p2m_domain *p2m)
     write_unlock(&p2m->lock);
 }
 
-static inline void p2m_read_lock(struct p2m_domain *p2m)
+void p2m_read_lock(struct p2m_domain *p2m)
 {
     read_lock(&p2m->lock);
 }
 
-static inline void p2m_read_unlock(struct p2m_domain *p2m)
+void p2m_read_unlock(struct p2m_domain *p2m)
 {
     read_unlock(&p2m->lock);
 }
 
-static inline int p2m_is_locked(struct p2m_domain *p2m)
+int p2m_is_locked(struct p2m_domain *p2m)
 {
     return rw_is_locked(&p2m->lock);
 }
 
-static inline int p2m_is_write_locked(struct p2m_domain *p2m)
+int p2m_is_write_locked(struct p2m_domain *p2m)
 {
     return rw_is_write_locked(&p2m->lock);
 }
diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
index e6be3ea..eae31c1 100644
--- a/xen/include/asm-arm/p2m.h
+++ b/xen/include/asm-arm/p2m.h
@@ -216,6 +216,22 @@ void guest_physmap_remove_page(struct domain *d,
 mfn_t gfn_to_mfn(struct domain *d, gfn_t gfn);
 
 /*
+ * P2M rwlock helpers.
+ */
+
+void p2m_write_lock(struct p2m_domain *p2m);
+
+void p2m_write_unlock(struct p2m_domain *p2m);
+
+void p2m_read_lock(struct p2m_domain *p2m);
+
+void p2m_read_unlock(struct p2m_domain *p2m);
+
+int p2m_is_locked(struct p2m_domain *p2m);
+
+int p2m_is_write_locked(struct p2m_domain *p2m);
+
+/*
  * Populate-on-demand
  */
 
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 03/38] arm/p2m: Introduce p2m_(switch|restore)_vttbr_and_(g|s)et_flags
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
  2016-08-16 22:16 ` [PATCH v3 01/38] arm/p2m: Cosmetic fixes - apply p2m_get_hostp2m Sergej Proskurin
  2016-08-16 22:16 ` [PATCH v3 02/38] arm/p2m: Expose p2m_*lock helpers Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-09-01 15:51   ` Julien Grall
  2016-08-16 22:16 ` [PATCH v3 04/38] arm/p2m: Add first altp2m HVMOP stubs Sergej Proskurin
                   ` (34 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

This commit introduces macros for switching and restoring the vttbr
considering the currently set irq flags. We define these macros, as the
following commits will use the associated functionality multiple times
throughout the file ./xen/arch/arm/p2m.c.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
 xen/arch/arm/p2m.c | 37 +++++++++++++++++++++++--------------
 1 file changed, 23 insertions(+), 14 deletions(-)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 08114d8..02e9ee7 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -27,6 +27,26 @@ static unsigned int __read_mostly p2m_root_level;
 
 #define P2M_ROOT_PAGES    (1<<P2M_ROOT_ORDER)
 
+#define p2m_switch_vttbr_and_get_flags(ovttbr, nvttbr, flags)       \
+({                                                                  \
+    if ( ovttbr != nvttbr )                                         \
+    {                                                               \
+        local_irq_save(flags);                                      \
+        WRITE_SYSREG64(nvttbr, VTTBR_EL2);                          \
+        isb();                                                      \
+    }                                                               \
+})
+
+#define p2m_restore_vttbr_and_set_flags(ovttbr, flags)              \
+({                                                                  \
+    if ( ovttbr != READ_SYSREG64(VTTBR_EL2) )                       \
+    {                                                               \
+        WRITE_SYSREG64(ovttbr, VTTBR_EL2);                          \
+        isb();                                                      \
+        local_irq_restore(flags);                                   \
+    }                                                               \
+})
+
 unsigned int __read_mostly p2m_ipa_bits;
 
 /* Helpers to lookup the properties of each level */
@@ -173,28 +193,17 @@ void p2m_restore_state(struct vcpu *n)
 static void p2m_flush_tlb(struct p2m_domain *p2m)
 {
     unsigned long flags = 0;
-    uint64_t ovttbr;
+    uint64_t ovttbr = READ_SYSREG64(VTTBR_EL2);
 
     /*
      * ARM only provides an instruction to flush TLBs for the current
      * VMID. So switch to the VTTBR of a given P2M if different.
      */
-    ovttbr = READ_SYSREG64(VTTBR_EL2);
-    if ( ovttbr != p2m->vttbr )
-    {
-        local_irq_save(flags);
-        WRITE_SYSREG64(p2m->vttbr, VTTBR_EL2);
-        isb();
-    }
+    p2m_switch_vttbr_and_get_flags(ovttbr, p2m->vttbr, flags);
 
     flush_tlb();
 
-    if ( ovttbr != READ_SYSREG64(VTTBR_EL2) )
-    {
-        WRITE_SYSREG64(ovttbr, VTTBR_EL2);
-        isb();
-        local_irq_restore(flags);
-    }
+    p2m_restore_vttbr_and_set_flags(ovttbr, flags);
 }
 
 /*
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 04/38] arm/p2m: Add first altp2m HVMOP stubs
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (2 preceding siblings ...)
  2016-08-16 22:16 ` [PATCH v3 03/38] arm/p2m: Introduce p2m_(switch|restore)_vttbr_and_(g|s)et_flags Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-09-01 16:09   ` Julien Grall
  2016-08-16 22:16 ` [PATCH v3 05/38] arm/p2m: Add hvm_allow_(set|get)_param Sergej Proskurin
                   ` (33 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

This commit moves the altp2m-related code from x86 to ARM. Functions
that are no yet supported notify the caller or print a BUG message
stating their absence.

Also, the struct arch_domain is extended with the altp2m_active
attribute, representing the current altp2m activity configuration of the
domain.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v2: Removed altp2m command-line option: Guard through HVM_PARAM_ALTP2M.
    Removed not used altp2m helper stubs in altp2m.h.

v3: Cosmetic fixes.

    Added domain lock in "do_altp2m_op" to avoid concurrent execution of
    altp2m-related HVMOPs.

    Added check making sure that HVM_PARAM_ALTP2M is set before
    execution of altp2m-related HVMOPs.
---
 xen/arch/arm/hvm.c           | 89 ++++++++++++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/altp2m.h |  4 +-
 xen/include/asm-arm/domain.h |  3 ++
 3 files changed, 94 insertions(+), 2 deletions(-)

diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
index d999bde..45d51c6 100644
--- a/xen/arch/arm/hvm.c
+++ b/xen/arch/arm/hvm.c
@@ -32,6 +32,91 @@
 
 #include <asm/hypercall.h>
 
+#include <asm/altp2m.h>
+
+static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
+{
+    struct xen_hvm_altp2m_op a;
+    struct domain *d = NULL;
+    int rc = 0;
+
+    if ( copy_from_guest(&a, arg, 1) )
+        return -EFAULT;
+
+    if ( a.pad1 || a.pad2 ||
+         (a.version != HVMOP_ALTP2M_INTERFACE_VERSION) ||
+         (a.cmd < HVMOP_altp2m_get_domain_state) ||
+         (a.cmd > HVMOP_altp2m_change_gfn) )
+        return -EINVAL;
+
+    d = (a.cmd != HVMOP_altp2m_vcpu_enable_notify) ?
+        rcu_lock_domain_by_any_id(a.domain) : rcu_lock_current_domain();
+
+    if ( d == NULL )
+        return -ESRCH;
+
+    /* Prevent concurrent execution of the following HVMOPs. */
+    domain_lock(d);
+
+    if ( (a.cmd != HVMOP_altp2m_get_domain_state) &&
+         (a.cmd != HVMOP_altp2m_set_domain_state) &&
+         !altp2m_active(d) )
+    {
+        rc = -EOPNOTSUPP;
+        goto out;
+    }
+
+    if ( !(d)->arch.hvm_domain.params[HVM_PARAM_ALTP2M] )
+    {
+        rc = -EINVAL;
+        goto out;
+    }
+
+    if ( (rc = xsm_hvm_altp2mhvm_op(XSM_TARGET, d)) )
+        goto out;
+
+    switch ( a.cmd )
+    {
+    case HVMOP_altp2m_get_domain_state:
+        rc = -EOPNOTSUPP;
+        break;
+
+    case HVMOP_altp2m_set_domain_state:
+        rc = -EOPNOTSUPP;
+        break;
+
+    case HVMOP_altp2m_vcpu_enable_notify:
+        rc = -EOPNOTSUPP;
+        break;
+
+    case HVMOP_altp2m_create_p2m:
+        rc = -EOPNOTSUPP;
+        break;
+
+    case HVMOP_altp2m_destroy_p2m:
+        rc = -EOPNOTSUPP;
+        break;
+
+    case HVMOP_altp2m_switch_p2m:
+        rc = -EOPNOTSUPP;
+        break;
+
+    case HVMOP_altp2m_set_mem_access:
+        rc = -EOPNOTSUPP;
+        break;
+
+    case HVMOP_altp2m_change_gfn:
+        rc = -EOPNOTSUPP;
+        break;
+    }
+
+out:
+    domain_unlock(d);
+    rcu_unlock_domain(d);
+
+    return rc;
+}
+
 long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
 {
     long rc = 0;
@@ -80,6 +165,10 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
             rc = -EINVAL;
         break;
 
+    case HVMOP_altp2m:
+        rc = do_altp2m_op(arg);
+        break;
+
     default:
     {
         gdprintk(XENLOG_DEBUG, "HVMOP op=%lu: not implemented\n", op);
diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
index a87747a..0711796 100644
--- a/xen/include/asm-arm/altp2m.h
+++ b/xen/include/asm-arm/altp2m.h
@@ -2,6 +2,7 @@
  * Alternate p2m
  *
  * Copyright (c) 2014, Intel Corporation.
+ * Copyright (c) 2016, Sergej Proskurin <proskurin@sec.in.tum.de>.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -24,8 +25,7 @@
 /* Alternate p2m on/off per domain */
 static inline bool_t altp2m_active(const struct domain *d)
 {
-    /* Not implemented on ARM. */
-    return 0;
+    return d->arch.altp2m_active;
 }
 
 /* Alternate p2m VCPU */
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index 9452fcd..cc4bda0 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -126,6 +126,9 @@ struct arch_domain
     paddr_t efi_acpi_gpa;
     paddr_t efi_acpi_len;
 #endif
+
+    /* altp2m: allow multiple copies of host p2m */
+    bool_t altp2m_active;
 }  __cacheline_aligned;
 
 struct arch_vcpu
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 05/38] arm/p2m: Add hvm_allow_(set|get)_param
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (3 preceding siblings ...)
  2016-08-16 22:16 ` [PATCH v3 04/38] arm/p2m: Add first altp2m HVMOP stubs Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-08-16 22:16 ` [PATCH v3 06/38] arm/p2m: Add HVMOP_altp2m_get_domain_state Sergej Proskurin
                   ` (32 subsequent siblings)
  37 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

This commit introduces the functions hvm_allow_(set|get)_param. These
can be used as a filter controlling access to HVM params. This
functionality has been inspired by the x86 implementation.

The introduced filter ensures that the HVM param HVM_PARAM_ALTP2M is set
once and not altered by guest domains.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
 xen/arch/arm/hvm.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 56 insertions(+), 9 deletions(-)

diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
index 45d51c6..ce6a436 100644
--- a/xen/arch/arm/hvm.c
+++ b/xen/arch/arm/hvm.c
@@ -117,6 +117,48 @@ out:
     return rc;
 }
 
+static int hvm_allow_set_param(struct domain *d, const struct xen_hvm_param *a)
+{
+    uint64_t value = d->arch.hvm_domain.params[a->index];
+    int rc;
+
+    rc = xsm_hvm_param(XSM_TARGET, d, HVMOP_set_param);
+    if ( rc )
+        return rc;
+
+    switch ( a->index )
+    {
+    /* The following parameters should only be changed once. */
+    case HVM_PARAM_ALTP2M:
+        if ( value != 0 && a->value != value )
+            rc = -EEXIST;
+        break;
+    default:
+        break;
+    }
+
+    return rc;
+}
+
+static int hvm_allow_get_param(struct domain *d, const struct xen_hvm_param *a)
+{
+    int rc;
+
+    rc = xsm_hvm_param(XSM_TARGET, d, HVMOP_get_param);
+    if ( rc )
+        return rc;
+
+    switch ( a->index )
+    {
+        /* This switch statement can be used to control/limit guest access to
+         * certain HVM params. */
+    default:
+        break;
+    }
+
+    return rc;
+}
+
 long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
 {
     long rc = 0;
@@ -139,21 +181,26 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
         if ( d == NULL )
             return -ESRCH;
 
-        rc = xsm_hvm_param(XSM_TARGET, d, op);
-        if ( rc )
-            goto param_fail;
-
-        if ( op == HVMOP_set_param )
+        switch ( op )
         {
+        case HVMOP_set_param:
+            rc = hvm_allow_set_param(d, &a);
+            if ( rc )
+                break;
+
             d->arch.hvm_domain.params[a.index] = a.value;
-        }
-        else
-        {
+            break;
+
+        case HVMOP_get_param:
+            rc = hvm_allow_get_param(d, &a);
+            if ( rc )
+                break;
+
             a.value = d->arch.hvm_domain.params[a.index];
             rc = copy_to_guest(arg, &a, 1) ? -EFAULT : 0;
+            break;
         }
 
-    param_fail:
         rcu_unlock_domain(d);
         break;
     }
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 06/38] arm/p2m: Add HVMOP_altp2m_get_domain_state
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (4 preceding siblings ...)
  2016-08-16 22:16 ` [PATCH v3 05/38] arm/p2m: Add hvm_allow_(set|get)_param Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-09-01 17:06   ` Julien Grall
  2016-08-16 22:16 ` [PATCH v3 07/38] arm/p2m: Introduce p2m_is_(hostp2m|altp2m) Sergej Proskurin
                   ` (31 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

This commit adopts the x86 HVMOP_altp2m_get_domain_state implementation.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v3: Removed the "altp2m_enabled" check in HVMOP_altp2m_get_domain_state
    case as it has been moved in front of the switch statement in
    "do_altp2m_op".

    Removed the macro "altp2m_enabled". Instead, check directly for the
    HVM_PARAM_ALTP2M param in d->arch.hvm_domain.
---
 xen/arch/arm/hvm.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
index ce6a436..180154e 100644
--- a/xen/arch/arm/hvm.c
+++ b/xen/arch/arm/hvm.c
@@ -66,7 +66,7 @@ static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
         goto out;
     }
 
-    if ( !(d)->arch.hvm_domain.params[HVM_PARAM_ALTP2M] )
+    if ( !d->arch.hvm_domain.params[HVM_PARAM_ALTP2M] )
     {
         rc = -EINVAL;
         goto out;
@@ -78,7 +78,8 @@ static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
     switch ( a.cmd )
     {
     case HVMOP_altp2m_get_domain_state:
-        rc = -EOPNOTSUPP;
+        a.u.domain_state.state = altp2m_active(d);
+        rc = __copy_to_guest(arg, &a, 1) ? -EFAULT : 0;
         break;
 
     case HVMOP_altp2m_set_domain_state:
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 07/38] arm/p2m: Introduce p2m_is_(hostp2m|altp2m)
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (5 preceding siblings ...)
  2016-08-16 22:16 ` [PATCH v3 06/38] arm/p2m: Add HVMOP_altp2m_get_domain_state Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-08-16 22:16 ` [PATCH v3 08/38] arm/p2m: Free p2m entries only in the hostp2m Sergej Proskurin
                   ` (30 subsequent siblings)
  37 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

This commit adds a p2m class to the struct p2m_domain to distinguish
between the host's original p2m and alternate p2m's. The need for this
functionality will be shown in the following commits.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
 xen/include/asm-arm/p2m.h | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
index eae31c1..040ca13 100644
--- a/xen/include/asm-arm/p2m.h
+++ b/xen/include/asm-arm/p2m.h
@@ -18,6 +18,11 @@ struct domain;
 
 extern void memory_type_changed(struct domain *);
 
+typedef enum {
+    p2m_host,
+    p2m_alternate,
+} p2m_class_t;
+
 /* Per-p2m-table state */
 struct p2m_domain {
     /* Lock that protects updates to the p2m */
@@ -92,6 +97,9 @@ struct p2m_domain {
      * enough available bits to store this information.
      */
     struct radix_tree_root mem_access_settings;
+
+    /* Choose between: host/alternate. */
+    p2m_class_t p2m_class;
 };
 
 /*
@@ -303,6 +311,16 @@ static inline int get_page_and_type(struct page_info *page,
 /* get host p2m table */
 #define p2m_get_hostp2m(d) (&(d)->arch.p2m)
 
+static inline bool_t p2m_is_hostp2m(const struct p2m_domain *p2m)
+{
+    return p2m->p2m_class == p2m_host;
+}
+
+static inline bool_t p2m_is_altp2m(const struct p2m_domain *p2m)
+{
+    return p2m->p2m_class == p2m_alternate;
+}
+
 /* vm_event and mem_access are supported on any ARM guest */
 static inline bool_t p2m_mem_access_sanity_check(struct domain *d)
 {
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 08/38] arm/p2m: Free p2m entries only in the hostp2m
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (6 preceding siblings ...)
  2016-08-16 22:16 ` [PATCH v3 07/38] arm/p2m: Introduce p2m_is_(hostp2m|altp2m) Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-09-01 17:08   ` Julien Grall
  2016-08-16 22:16 ` [PATCH v3 09/38] arm/p2m: Add backpointer to the domain in p2m_domain Sergej Proskurin
                   ` (29 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

Freeing p2m entries of arbitrary p2m's (in particular in alternate
p2m's) will lead to unpredicted behavior as the entries might still be
used within the host's p2m. The host's p2m should, however, free the
entries, as it is the main instance responsible for their management. If
entries were freed in the host's p2m, but still reside in one or more of
the alternate p2m's, the change will be propagated to these functions as
will be shown in the following commits.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
 xen/arch/arm/p2m.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 02e9ee7..bfbccca 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -1004,7 +1004,9 @@ static int __p2m_set_entry(struct p2m_domain *p2m,
      * Free the entry only if the original pte was valid and the base
      * is different (to avoid freeing when permission is changed).
      */
-    if ( p2m_valid(orig_pte) && entry->p2m.base != orig_pte.p2m.base )
+    if ( p2m_valid(orig_pte) &&
+         entry->p2m.base != orig_pte.p2m.base &&
+         p2m_is_hostp2m(p2m) )
         p2m_free_entry(p2m, orig_pte, level);
 
     /* XXX: Flush iommu */
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 09/38] arm/p2m: Add backpointer to the domain in p2m_domain
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (7 preceding siblings ...)
  2016-08-16 22:16 ` [PATCH v3 08/38] arm/p2m: Free p2m entries only in the hostp2m Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-08-16 22:16 ` [PATCH v3 10/38] arm/p2m: Move hostp2m init/teardown to individual functions Sergej Proskurin
                   ` (28 subsequent siblings)
  37 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

With the introduction of altp2m, many functions have been adapted to
receive an argument of type "struct p2m_domain*" instead of "struct
domain*". A backpointer to the associated domain within the "struct
p2m_domain*" reduces the number of function parameters without losing
the accessibility of the "struct domain". The need for this pointer is
shown in the following commits.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
 xen/arch/arm/p2m.c        | 1 +
 xen/include/asm-arm/p2m.h | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index bfbccca..e859fca 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -1280,6 +1280,7 @@ int p2m_init(struct domain *d)
     p2m->max_mapped_gfn = _gfn(0);
     p2m->lowest_mapped_gfn = _gfn(ULONG_MAX);
 
+    p2m->domain = d;
     p2m->default_access = p2m_access_rwx;
     p2m->mem_access_enabled = false;
     radix_tree_init(&p2m->mem_access_settings);
diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
index 040ca13..fa07e19 100644
--- a/xen/include/asm-arm/p2m.h
+++ b/xen/include/asm-arm/p2m.h
@@ -100,6 +100,9 @@ struct p2m_domain {
 
     /* Choose between: host/alternate. */
     p2m_class_t p2m_class;
+
+    /* Back pointer to struct domain. */
+    struct domain *domain;
 };
 
 /*
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 10/38] arm/p2m: Move hostp2m init/teardown to individual functions
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (8 preceding siblings ...)
  2016-08-16 22:16 ` [PATCH v3 09/38] arm/p2m: Add backpointer to the domain in p2m_domain Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-09-01 17:36   ` Julien Grall
  2016-08-16 22:16 ` [PATCH v3 11/38] arm/p2m: Cosmetic fix - function prototype of p2m_alloc_table Sergej Proskurin
                   ` (27 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

This commit pulls out generic init/teardown functionality out of
"p2m_init" and "p2m_teardown" into "p2m_init_one", "p2m_teardown_one",
and "p2m_flush_table" functions.  This allows our future implementation
to reuse existing code for the initialization/teardown of altp2m views.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v2: Added the function p2m_flush_table to the previous version.

v3: Removed struct vttbr.

    Moved define INVALID_VTTBR to p2m.h.

    Exported function prototypes of "p2m_flush_table", "p2m_init_one",
    and "p2m_teardown_one" in p2m.h.

    Extended the function "p2m_flush_table" by additionally resetting
    the fields lowest_mapped_gfn and max_mapped_gfn.

    Added a "p2m_flush_tlb" call in "p2m_flush_table". On altp2m reset
    in function "altp2m_reset", it is important to flush the TLBs after
    clearing the root table pages and before clearing the intermediate
    altp2m page tables to prevent illegal access to stalled TLB entries
    on currently active VCPUs.

    Added a check checking whether p2m->root is NULL in p2m_flush_table.

    Renamed the function "p2m_free_one" to "p2m_teardown_one".

    Removed resetting p2m->vttbr in "p2m_teardown_one", as it the p2m
    will be destroyed afterwards.

    Moved call to "p2m_alloc_table" back to "p2m_init_one".

    Moved the introduction of the type p2m_class_t out of this patch.

    Moved the backpointer to the struct domain out of the struct
    p2m_domain.
---
 xen/arch/arm/p2m.c        | 71 +++++++++++++++++++++++++++++++++++++++++------
 xen/include/asm-arm/p2m.h | 11 ++++++++
 2 files changed, 73 insertions(+), 9 deletions(-)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index e859fca..9ef19d4 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -1245,27 +1245,53 @@ static void p2m_free_vmid(struct domain *d)
     spin_unlock(&vmid_alloc_lock);
 }
 
-void p2m_teardown(struct domain *d)
+/* Reset this p2m table to be empty. */
+void p2m_flush_table(struct p2m_domain *p2m)
 {
-    struct p2m_domain *p2m = p2m_get_hostp2m(d);
-    struct page_info *pg;
+    struct page_info *page, *pg;
+    unsigned int i;
+
+    if ( p2m->root )
+    {
+        page = p2m->root;
+
+        /* Clear all concatenated first level pages. */
+        for ( i = 0; i < P2M_ROOT_PAGES; i++ )
+            clear_and_clean_page(page + i);
+    }
+
+    /*
+     * Flush TLBs before releasing remaining intermediate p2m page tables to
+     * prevent illegal access to stalled TLB entries.
+     */
+    p2m_flush_tlb(p2m);
 
+    /* Free the rest of the trie pages back to the paging pool. */
     while ( (pg = page_list_remove_head(&p2m->pages)) )
         free_domheap_page(pg);
 
+    p2m->lowest_mapped_gfn = INVALID_GFN;
+    p2m->max_mapped_gfn = _gfn(0);
+}
+
+void p2m_teardown_one(struct p2m_domain *p2m)
+{
+    p2m_flush_table(p2m);
+
     if ( p2m->root )
         free_domheap_pages(p2m->root, P2M_ROOT_ORDER);
 
     p2m->root = NULL;
 
-    p2m_free_vmid(d);
+    p2m_free_vmid(p2m->domain);
+
+    p2m->vttbr = INVALID_VTTBR;
 
     radix_tree_destroy(&p2m->mem_access_settings, NULL);
 }
 
-int p2m_init(struct domain *d)
+int p2m_init_one(struct domain *d, struct p2m_domain *p2m)
 {
-    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     int rc = 0;
 
     rwlock_init(&p2m->lock);
@@ -1278,11 +1304,14 @@ int p2m_init(struct domain *d)
         return rc;
 
     p2m->max_mapped_gfn = _gfn(0);
-    p2m->lowest_mapped_gfn = _gfn(ULONG_MAX);
+    p2m->lowest_mapped_gfn = INVALID_GFN;
 
     p2m->domain = d;
+    p2m->access_required = false;
     p2m->default_access = p2m_access_rwx;
     p2m->mem_access_enabled = false;
+    p2m->root = NULL;
+    p2m->vttbr = INVALID_VTTBR;
     radix_tree_init(&p2m->mem_access_settings);
 
     /*
@@ -1293,9 +1322,33 @@ int p2m_init(struct domain *d)
     p2m->clean_pte = iommu_enabled &&
         !iommu_has_feature(d, IOMMU_FEAT_COHERENT_WALK);
 
-    rc = p2m_alloc_table(d);
+    return p2m_alloc_table(d);
+}
 
-    return rc;
+static void p2m_teardown_hostp2m(struct domain *d)
+{
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
+
+    p2m_teardown_one(p2m);
+}
+
+void p2m_teardown(struct domain *d)
+{
+    p2m_teardown_hostp2m(d);
+}
+
+static int p2m_init_hostp2m(struct domain *d)
+{
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
+
+    p2m->p2m_class = p2m_host;
+
+    return p2m_init_one(d, p2m);
+}
+
+int p2m_init(struct domain *d)
+{
+    return p2m_init_hostp2m(d);
 }
 
 /*
diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
index fa07e19..1a004ed 100644
--- a/xen/include/asm-arm/p2m.h
+++ b/xen/include/asm-arm/p2m.h
@@ -11,6 +11,8 @@
 
 #define paddr_bits PADDR_BITS
 
+#define INVALID_VTTBR (0UL)
+
 /* Holds the bit size of IPAs in p2m tables.  */
 extern unsigned int p2m_ipa_bits;
 
@@ -226,6 +228,15 @@ void guest_physmap_remove_page(struct domain *d,
 
 mfn_t gfn_to_mfn(struct domain *d, gfn_t gfn);
 
+/* Flushes the page table held by the p2m. */
+void p2m_flush_table(struct p2m_domain *p2m);
+
+/* Initialize the p2m structure. */
+int p2m_init_one(struct domain *d, struct p2m_domain *p2m);
+
+/* Release resources held by the p2m structure. */
+void p2m_teardown_one(struct p2m_domain *p2m);
+
 /*
  * P2M rwlock helpers.
  */
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 11/38] arm/p2m: Cosmetic fix - function prototype of p2m_alloc_table
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (9 preceding siblings ...)
  2016-08-16 22:16 ` [PATCH v3 10/38] arm/p2m: Move hostp2m init/teardown to individual functions Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-09-09 16:45   ` Julien Grall
  2016-08-16 22:16 ` [PATCH v3 12/38] arm/p2m: Rename parameter in p2m_alloc_vmid Sergej Proskurin
                   ` (26 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

The function "p2m_alloc_table" should be able to allocate 2nd stage
translation tables not only for the host's p2m but also for alternate
p2m's.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v2: Removed altp2m table initialization from "p2m_table_init".

v3: Removed initialization of the field d->arch.altp2m_active in
    "p2m_table_init" to avoid altp2m initialization throughout different
    files.

    Merged the function "p2m_alloc_table" and "p2m_table_init".
---
 xen/arch/arm/p2m.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 9ef19d4..dd5d700 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -1162,9 +1162,8 @@ void guest_physmap_remove_page(struct domain *d,
     p2m_remove_mapping(d, gfn, (1 << page_order), mfn);
 }
 
-static int p2m_alloc_table(struct domain *d)
+static int p2m_alloc_table(struct p2m_domain *p2m)
 {
-    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     struct page_info *page;
     unsigned int i;
 
@@ -1322,7 +1321,7 @@ int p2m_init_one(struct domain *d, struct p2m_domain *p2m)
     p2m->clean_pte = iommu_enabled &&
         !iommu_has_feature(d, IOMMU_FEAT_COHERENT_WALK);
 
-    return p2m_alloc_table(d);
+    return p2m_alloc_table(p2m);
 }
 
 static void p2m_teardown_hostp2m(struct domain *d)
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 12/38] arm/p2m: Rename parameter in p2m_alloc_vmid
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (10 preceding siblings ...)
  2016-08-16 22:16 ` [PATCH v3 11/38] arm/p2m: Cosmetic fix - function prototype of p2m_alloc_table Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-08-16 22:16 ` [PATCH v3 13/38] arm/p2m: Change func prototype and impl of p2m_(alloc|free)_vmid Sergej Proskurin
                   ` (25 subsequent siblings)
  37 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

This commit does not change or introduce any additional functionality
but rather is a part of the following commit that alters the
functionality of the function "p2m_alloc_vmid".

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
 xen/arch/arm/p2m.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index dd5d700..a295fdc 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -1208,24 +1208,24 @@ static int p2m_alloc_vmid(struct domain *d)
 {
     struct p2m_domain *p2m = p2m_get_hostp2m(d);
 
-    int rc, nr;
+    int rc, vmid;
 
     spin_lock(&vmid_alloc_lock);
 
-    nr = find_first_zero_bit(vmid_mask, MAX_VMID);
+    vmid = find_first_zero_bit(vmid_mask, MAX_VMID);
 
-    ASSERT(nr != INVALID_VMID);
+    ASSERT(vmid != INVALID_VMID);
 
-    if ( nr == MAX_VMID )
+    if ( vmid == MAX_VMID )
     {
         rc = -EBUSY;
         printk(XENLOG_ERR "p2m.c: dom%d: VMID pool exhausted\n", d->domain_id);
         goto out;
     }
 
-    set_bit(nr, vmid_mask);
+    set_bit(vmid, vmid_mask);
 
-    p2m->vmid = nr;
+    p2m->vmid = vmid;
 
     rc = 0;
 
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 13/38] arm/p2m: Change func prototype and impl of p2m_(alloc|free)_vmid
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (11 preceding siblings ...)
  2016-08-16 22:16 ` [PATCH v3 12/38] arm/p2m: Rename parameter in p2m_alloc_vmid Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-08-16 22:16 ` [PATCH v3 14/38] arm/p2m: Add altp2m init/teardown routines Sergej Proskurin
                   ` (24 subsequent siblings)
  37 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

This commit changes the prototype and implementation of the functions
"p2m_alloc_vmid" and "p2m_free_vmid". The function "p2m_alloc_vmid" does
not expect the struct domain as argument anymore and returns an
allocated vmid. The function "p2m_free_vmid" takes only the vmid that is
to be freed as argument.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v3: Changed function prototypes and implementation of the functions
    "p2m_alloc_vmid" and "p2m_free_vmid".

    Changes in "p2m_alloc_vmid":
    This function does not expect any arguments. Also, in this commit,
    the function "p2m_alloc_vmid" returns either the successfully
    allocated vmid or the value INVALID_VMID. Thus, it is now the
    responsibility of the caller to set the returned vmid in the
    associated fields.

    Changes in "p2m_free_vmid":
    This function expects now only the vmid of type uint8_t.
---
 xen/arch/arm/p2m.c | 35 ++++++++++++-----------------------
 1 file changed, 12 insertions(+), 23 deletions(-)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index a295fdc..23ceb96 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -1204,11 +1204,9 @@ void p2m_vmid_allocator_init(void)
     set_bit(INVALID_VMID, vmid_mask);
 }
 
-static int p2m_alloc_vmid(struct domain *d)
+static uint8_t p2m_alloc_vmid(void)
 {
-    struct p2m_domain *p2m = p2m_get_hostp2m(d);
-
-    int rc, vmid;
+    uint8_t vmid;
 
     spin_lock(&vmid_alloc_lock);
 
@@ -1218,28 +1216,23 @@ static int p2m_alloc_vmid(struct domain *d)
 
     if ( vmid == MAX_VMID )
     {
-        rc = -EBUSY;
-        printk(XENLOG_ERR "p2m.c: dom%d: VMID pool exhausted\n", d->domain_id);
+        vmid = INVALID_VMID;
+        printk(XENLOG_ERR "p2m.c: VMID pool exhausted\n");
         goto out;
     }
 
     set_bit(vmid, vmid_mask);
 
-    p2m->vmid = vmid;
-
-    rc = 0;
-
 out:
     spin_unlock(&vmid_alloc_lock);
-    return rc;
+    return vmid;
 }
 
-static void p2m_free_vmid(struct domain *d)
+static void p2m_free_vmid(uint8_t vmid)
 {
-    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     spin_lock(&vmid_alloc_lock);
-    if ( p2m->vmid != INVALID_VMID )
-        clear_bit(p2m->vmid, vmid_mask);
+    if ( vmid != INVALID_VMID )
+        clear_bit(vmid, vmid_mask);
 
     spin_unlock(&vmid_alloc_lock);
 }
@@ -1282,7 +1275,7 @@ void p2m_teardown_one(struct p2m_domain *p2m)
 
     p2m->root = NULL;
 
-    p2m_free_vmid(p2m->domain);
+    p2m_free_vmid(p2m->vmid);
 
     p2m->vttbr = INVALID_VTTBR;
 
@@ -1291,16 +1284,12 @@ void p2m_teardown_one(struct p2m_domain *p2m)
 
 int p2m_init_one(struct domain *d, struct p2m_domain *p2m)
 {
-    int rc = 0;
-
     rwlock_init(&p2m->lock);
     INIT_PAGE_LIST_HEAD(&p2m->pages);
 
-    p2m->vmid = INVALID_VMID;
-
-    rc = p2m_alloc_vmid(d);
-    if ( rc != 0 )
-        return rc;
+    p2m->vmid = p2m_alloc_vmid();
+    if ( p2m->vmid == INVALID_VMID )
+        return -EBUSY;
 
     p2m->max_mapped_gfn = _gfn(0);
     p2m->lowest_mapped_gfn = INVALID_GFN;
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 14/38] arm/p2m: Add altp2m init/teardown routines
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (12 preceding siblings ...)
  2016-08-16 22:16 ` [PATCH v3 13/38] arm/p2m: Change func prototype and impl of p2m_(alloc|free)_vmid Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-09-09 16:56   ` Julien Grall
  2016-08-16 22:16 ` [PATCH v3 15/38] arm/p2m: Add altp2m table flushing routine Sergej Proskurin
                   ` (23 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

The p2m initialization now invokes initialization routines responsible
for the allocation and initialization of altp2m structures. The same
applies to teardown routines. The functionality has been adopted from
the x86 altp2m implementation.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v2: Shared code between host/altp2m init/teardown functions.
    Added conditional init/teardown of altp2m.
    Altp2m related functions are moved to altp2m.c

v3: Removed locking the altp2m_lock in altp2m_teardown. Locking this
    lock at this point is unnecessary.

    Removed re-setting altp2m_vttbr, altp2m_p2m, and altp2m_active
    values in the function "altp2m_teardown". Re-setting these values is
    unnecessary as the entire domain will be destroyed right afterwards.

    Removed check for "altp2m_enabled" in "p2m_init" as altp2m has not yet
    been enabled by libxl at this point.

    Removed check for "altp2m_enabled" before tearing down altp2m within
    the function "p2m_teardown" so that altp2m gets destroyed even if
    the HVM_PARAM_ALTP2M gets reset before "p2m_teardown" is called.

    Added initialization of the field d->arch.altp2m_active in
    "altp2m_init".

    Removed check for already initialized vmid's in "altp2m_init_one",
    as "altp2m_init_one" is now called always with an uninitialized p2m.

    Removed the array altp2m_vttbr[] in struct arch_domain.
---
 xen/arch/arm/Makefile        |  1 +
 xen/arch/arm/altp2m.c        | 61 ++++++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/p2m.c           | 16 +++++++++++-
 xen/include/asm-arm/altp2m.h |  6 +++++
 xen/include/asm-arm/domain.h |  6 +++++
 xen/include/asm-arm/p2m.h    |  2 ++
 6 files changed, 91 insertions(+), 1 deletion(-)
 create mode 100644 xen/arch/arm/altp2m.c

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 23aaf52..4a7f660 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -5,6 +5,7 @@ subdir-$(CONFIG_ARM_64) += efi
 subdir-$(CONFIG_ACPI) += acpi
 
 obj-$(CONFIG_ALTERNATIVE) += alternative.o
+obj-y += altp2m.o
 obj-y += bootfdt.o
 obj-y += cpu.o
 obj-y += cpuerrata.o
diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
new file mode 100644
index 0000000..66a373a
--- /dev/null
+++ b/xen/arch/arm/altp2m.c
@@ -0,0 +1,61 @@
+/*
+ * arch/arm/altp2m.c
+ *
+ * Alternate p2m
+ * Copyright (c) 2016 Sergej Proskurin <proskurin@sec.in.tum.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <asm/p2m.h>
+#include <asm/altp2m.h>
+
+int altp2m_init(struct domain *d)
+{
+    unsigned int i;
+
+    spin_lock_init(&d->arch.altp2m_lock);
+
+    for ( i = 0; i < MAX_ALTP2M; i++ )
+        d->arch.altp2m_p2m[i] = NULL;
+
+    d->arch.altp2m_active = false;
+
+    return 0;
+}
+
+void altp2m_teardown(struct domain *d)
+{
+    unsigned int i;
+    struct p2m_domain *p2m;
+
+    for ( i = 0; i < MAX_ALTP2M; i++ )
+    {
+        if ( !d->arch.altp2m_p2m[i] )
+            continue;
+
+        p2m = d->arch.altp2m_p2m[i];
+        p2m_teardown_one(p2m);
+        xfree(p2m);
+    }
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 23ceb96..63c0df0 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -14,6 +14,8 @@
 #include <asm/hardirq.h>
 #include <asm/page.h>
 
+#include <asm/altp2m.h>
+
 #ifdef CONFIG_ARM_64
 static unsigned int __read_mostly p2m_root_order;
 static unsigned int __read_mostly p2m_root_level;
@@ -1322,6 +1324,12 @@ static void p2m_teardown_hostp2m(struct domain *d)
 
 void p2m_teardown(struct domain *d)
 {
+    /*
+     * Teardown altp2m unconditionally so that altp2m gets always destroyed --
+     * even if HVM_PARAM_ALTP2M gets reset before teardown.
+     */
+    altp2m_teardown(d);
+
     p2m_teardown_hostp2m(d);
 }
 
@@ -1336,7 +1344,13 @@ static int p2m_init_hostp2m(struct domain *d)
 
 int p2m_init(struct domain *d)
 {
-    return p2m_init_hostp2m(d);
+    int rc;
+
+    rc = p2m_init_hostp2m(d);
+    if ( rc )
+        return rc;
+
+    return altp2m_init(d);
 }
 
 /*
diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
index 0711796..a156109 100644
--- a/xen/include/asm-arm/altp2m.h
+++ b/xen/include/asm-arm/altp2m.h
@@ -22,6 +22,9 @@
 
 #include <xen/sched.h>
 
+#define altp2m_lock(d)    spin_lock(&(d)->arch.altp2m_lock)
+#define altp2m_unlock(d)  spin_unlock(&(d)->arch.altp2m_lock)
+
 /* Alternate p2m on/off per domain */
 static inline bool_t altp2m_active(const struct domain *d)
 {
@@ -36,4 +39,7 @@ static inline uint16_t altp2m_vcpu_idx(const struct vcpu *v)
     return 0;
 }
 
+int altp2m_init(struct domain *d);
+void altp2m_teardown(struct domain *d);
+
 #endif /* __ASM_ARM_ALTP2M_H */
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index cc4bda0..a4e4762 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -127,8 +127,14 @@ struct arch_domain
     paddr_t efi_acpi_len;
 #endif
 
+    /*
+     * Lock that protects access to altp2m related fields in both struct
+     * arch_domain and struct p2m_domain.
+     */
+    spinlock_t altp2m_lock;
     /* altp2m: allow multiple copies of host p2m */
     bool_t altp2m_active;
+    struct p2m_domain *altp2m_p2m[MAX_ALTP2M];
 }  __cacheline_aligned;
 
 struct arch_vcpu
diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
index 1a004ed..de0c90a 100644
--- a/xen/include/asm-arm/p2m.h
+++ b/xen/include/asm-arm/p2m.h
@@ -9,6 +9,8 @@
 #include <xen/p2m-common.h>
 #include <public/memory.h>
 
+#define MAX_ALTP2M 10           /* ARM might contain an arbitrary number of
+                                   altp2m views. */
 #define paddr_bits PADDR_BITS
 
 #define INVALID_VTTBR (0UL)
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 15/38] arm/p2m: Add altp2m table flushing routine
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (13 preceding siblings ...)
  2016-08-16 22:16 ` [PATCH v3 14/38] arm/p2m: Add altp2m init/teardown routines Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-09-09 17:02   ` Julien Grall
  2016-08-16 22:16 ` [PATCH v3 16/38] arm/p2m: Add HVMOP_altp2m_set_domain_state Sergej Proskurin
                   ` (22 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

The current implementation differentiates between flushing and
destroying altp2m views. This commit adds the function altp2m_flush,
which allows to release all of the alternate p2m views.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v2: Pages in p2m->pages are not cleared in p2m_flush_table anymore.
    VMID is freed in p2m_free_one.
    Cosmetic fixes.

v3: Changed the locking mechanism to "p2m_write_lock" inside the
    function "altp2m_flush".

    Do not flush but rather teardown the altp2m in the function
    "altp2m_flush".

    Exchanged the check "altp2m_vttbr[idx] == INVALID_VTTBR" for
    "altp2m_p2m[idx] == NULL" in "altp2m_flush".
---
 xen/arch/arm/altp2m.c        | 31 +++++++++++++++++++++++++++++++
 xen/include/asm-arm/altp2m.h |  3 +++
 2 files changed, 34 insertions(+)

diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
index 66a373a..02cffd7 100644
--- a/xen/arch/arm/altp2m.c
+++ b/xen/arch/arm/altp2m.c
@@ -34,6 +34,37 @@ int altp2m_init(struct domain *d)
     return 0;
 }
 
+void altp2m_flush(struct domain *d)
+{
+    unsigned int i;
+    struct p2m_domain *p2m;
+
+    /*
+     * If altp2m is active, we are not allowed to flush altp2m[0]. This special
+     * view is considered as the hostp2m as long as altp2m is active.
+     */
+    ASSERT(!altp2m_active(d));
+
+    altp2m_lock(d);
+
+    for ( i = 0; i < MAX_ALTP2M; i++ )
+    {
+        if ( d->arch.altp2m_p2m[i] == NULL )
+            continue;
+
+        p2m = d->arch.altp2m_p2m[i];
+
+        p2m_write_lock(p2m);
+        p2m_teardown_one(p2m);
+        p2m_write_unlock(p2m);
+
+        xfree(p2m);
+        d->arch.altp2m_p2m[i] = NULL;
+    }
+
+    altp2m_unlock(d);
+}
+
 void altp2m_teardown(struct domain *d)
 {
     unsigned int i;
diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
index a156109..4c15b75 100644
--- a/xen/include/asm-arm/altp2m.h
+++ b/xen/include/asm-arm/altp2m.h
@@ -42,4 +42,7 @@ static inline uint16_t altp2m_vcpu_idx(const struct vcpu *v)
 int altp2m_init(struct domain *d);
 void altp2m_teardown(struct domain *d);
 
+/* Flush all the alternate p2m's for a domain. */
+void altp2m_flush(struct domain *d);
+
 #endif /* __ASM_ARM_ALTP2M_H */
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 16/38] arm/p2m: Add HVMOP_altp2m_set_domain_state
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (14 preceding siblings ...)
  2016-08-16 22:16 ` [PATCH v3 15/38] arm/p2m: Add altp2m table flushing routine Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-09-09 17:14   ` Julien Grall
  2016-09-14 11:07   ` Julien Grall
  2016-08-16 22:16 ` [PATCH v3 17/38] arm/p2m: Add HVMOP_altp2m_create_p2m Sergej Proskurin
                   ` (21 subsequent siblings)
  37 siblings, 2 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

The HVMOP_altp2m_set_domain_state allows to activate altp2m on a
specific domain. This commit adopts the x86
HVMOP_altp2m_set_domain_state implementation.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v2: Dynamically allocate memory for altp2m views only when needed.
    Move altp2m related helpers to altp2m.c.
    p2m_flush_tlb is made publicly accessible.

v3: Cosmetic fixes.

    Removed call to "p2m_alloc_table" in "altp2m_init_helper" as the
    entire p2m allocation is now done within the function
    "p2m_init_one". The same applies to the call of the function
    "p2m_flush_tlb" from "p2m_init_one".

    Removed the "altp2m_enabled" check in HVMOP_altp2m_set_domain_state
    case as it has been moved in front of the switch statement in
    "do_altp2m_op".

    Changed the order of setting the new altp2m state (depending on
    setting/resetting the state) in HVMOP_altp2m_set_domain_state case.

    Removed the call to altp2m_vcpu_reset from altp2m_vcpu_initialise,
    as the p2midx is set right after the call to 0, representing the
    default view.

    Moved the define "vcpu_altp2m" from domain.h to altp2m.h to avoid
    defining altp2m-related functionality in multiple files. Also renamed
    "vcpu_altp2m" to "altp2m_vcpu".

    Declared the function "p2m_flush_tlb" as static, as it is not called
    from altp2m.h anymore.

    Exported the function "altp2m_get_altp2m" in altp2m.h.

    Exchanged the check "altp2m_vttbr[idx] == INVALID_VTTBR" for
    "altp2m_p2m[idx] == NULL" in "altp2m_init_by_id".

    Set the field p2m->access_required to false by default.
---
 xen/arch/arm/altp2m.c        | 102 +++++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/hvm.c           |  34 ++++++++++++++-
 xen/include/asm-arm/altp2m.h |  14 ++++++
 xen/include/asm-arm/domain.h |   7 +++
 xen/include/asm-arm/p2m.h    |   5 +++
 5 files changed, 161 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
index 02cffd7..02a52ec 100644
--- a/xen/arch/arm/altp2m.c
+++ b/xen/arch/arm/altp2m.c
@@ -20,6 +20,108 @@
 #include <asm/p2m.h>
 #include <asm/altp2m.h>
 
+struct p2m_domain *altp2m_get_altp2m(struct vcpu *v)
+{
+    unsigned int index = altp2m_vcpu(v).p2midx;
+
+    if ( index == INVALID_ALTP2M )
+        return NULL;
+
+    BUG_ON(index >= MAX_ALTP2M);
+
+    return v->domain->arch.altp2m_p2m[index];
+}
+
+static void altp2m_vcpu_reset(struct vcpu *v)
+{
+    struct altp2mvcpu *av = &altp2m_vcpu(v);
+
+    av->p2midx = INVALID_ALTP2M;
+}
+
+void altp2m_vcpu_initialise(struct vcpu *v)
+{
+    if ( v != current )
+        vcpu_pause(v);
+
+    altp2m_vcpu(v).p2midx = 0;
+    atomic_inc(&altp2m_get_altp2m(v)->active_vcpus);
+
+    if ( v != current )
+        vcpu_unpause(v);
+}
+
+void altp2m_vcpu_destroy(struct vcpu *v)
+{
+    struct p2m_domain *p2m;
+
+    if ( v != current )
+        vcpu_pause(v);
+
+    if ( (p2m = altp2m_get_altp2m(v)) )
+        atomic_dec(&p2m->active_vcpus);
+
+    altp2m_vcpu_reset(v);
+
+    if ( v != current )
+        vcpu_unpause(v);
+}
+
+static int altp2m_init_helper(struct domain *d, unsigned int idx)
+{
+    int rc;
+    struct p2m_domain *p2m = d->arch.altp2m_p2m[idx];
+
+    ASSERT(p2m == NULL);
+
+    /* Allocate a new, zeroed altp2m view. */
+    p2m = xzalloc(struct p2m_domain);
+    if ( p2m == NULL)
+    {
+        rc = -ENOMEM;
+        goto err;
+    }
+
+    p2m->p2m_class = p2m_alternate;
+
+    /* Initialize the new altp2m view. */
+    rc = p2m_init_one(d, p2m);
+    if ( rc )
+        goto err;
+
+    p2m->access_required = false;
+    _atomic_set(&p2m->active_vcpus, 0);
+
+    d->arch.altp2m_p2m[idx] = p2m;
+
+    return rc;
+
+err:
+    if ( p2m )
+        xfree(p2m);
+
+    d->arch.altp2m_p2m[idx] = NULL;
+
+    return rc;
+}
+
+int altp2m_init_by_id(struct domain *d, unsigned int idx)
+{
+    int rc = -EINVAL;
+
+    if ( idx >= MAX_ALTP2M )
+        return rc;
+
+    altp2m_lock(d);
+
+    if ( d->arch.altp2m_p2m[idx] == NULL )
+        rc = altp2m_init_helper(d, idx);
+
+    altp2m_unlock(d);
+
+    return rc;
+}
+
 int altp2m_init(struct domain *d)
 {
     unsigned int i;
diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
index 180154e..c69da36 100644
--- a/xen/arch/arm/hvm.c
+++ b/xen/arch/arm/hvm.c
@@ -83,8 +83,40 @@ static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
         break;
 
     case HVMOP_altp2m_set_domain_state:
-        rc = -EOPNOTSUPP;
+    {
+        struct vcpu *v;
+        bool_t ostate, nstate;
+
+        ostate = d->arch.altp2m_active;
+        nstate = !!a.u.domain_state.state;
+
+        /* If the alternate p2m state has changed, handle appropriately */
+        if ( (nstate != ostate) &&
+             (ostate || !(rc = altp2m_init_by_id(d, 0))) )
+        {
+            for_each_vcpu( d, v )
+            {
+                if ( !ostate )
+                {
+                    altp2m_vcpu_initialise(v);
+                    d->arch.altp2m_active = nstate;
+                }
+                else
+                {
+                    d->arch.altp2m_active = nstate;
+                    altp2m_vcpu_destroy(v);
+                }
+            }
+
+            /*
+             * The altp2m_active state has been deactivated. It is now safe to
+             * flush all altp2m views -- including altp2m[0].
+             */
+            if ( ostate )
+                altp2m_flush(d);
+        }
         break;
+    }
 
     case HVMOP_altp2m_vcpu_enable_notify:
         rc = -EOPNOTSUPP;
diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
index 4c15b75..f604ffd 100644
--- a/xen/include/asm-arm/altp2m.h
+++ b/xen/include/asm-arm/altp2m.h
@@ -22,6 +22,10 @@
 
 #include <xen/sched.h>
 
+#define INVALID_ALTP2M    0xffff
+
+#define altp2m_vcpu(v)    ((v)->arch.avcpu)
+
 #define altp2m_lock(d)    spin_lock(&(d)->arch.altp2m_lock)
 #define altp2m_unlock(d)  spin_unlock(&(d)->arch.altp2m_lock)
 
@@ -42,6 +46,16 @@ static inline uint16_t altp2m_vcpu_idx(const struct vcpu *v)
 int altp2m_init(struct domain *d);
 void altp2m_teardown(struct domain *d);
 
+void altp2m_vcpu_initialise(struct vcpu *v);
+void altp2m_vcpu_destroy(struct vcpu *v);
+
+/* Get current alternate p2m table. */
+struct p2m_domain *altp2m_get_altp2m(struct vcpu *v);
+
+/* Make a specific alternate p2m valid. */
+int altp2m_init_by_id(struct domain *d,
+                      unsigned int idx);
+
 /* Flush all the alternate p2m's for a domain. */
 void altp2m_flush(struct domain *d);
 
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index a4e4762..99aa3bc 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -137,6 +137,10 @@ struct arch_domain
     struct p2m_domain *altp2m_p2m[MAX_ALTP2M];
 }  __cacheline_aligned;
 
+struct altp2mvcpu {
+    uint16_t p2midx; /* alternate p2m index */
+};
+
 struct arch_vcpu
 {
     struct {
@@ -266,6 +270,9 @@ struct arch_vcpu
     struct vtimer phys_timer;
     struct vtimer virt_timer;
     bool_t vtimer_initialized;
+
+    /* Alternate p2m context */
+    struct altp2mvcpu avcpu;
 }  __cacheline_aligned;
 
 void vcpu_show_execution_state(struct vcpu *);
diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
index de0c90a..978125a 100644
--- a/xen/include/asm-arm/p2m.h
+++ b/xen/include/asm-arm/p2m.h
@@ -9,6 +9,8 @@
 #include <xen/p2m-common.h>
 #include <public/memory.h>
 
+#include <asm/atomic.h>
+
 #define MAX_ALTP2M 10           /* ARM might contain an arbitrary number of
                                    altp2m views. */
 #define paddr_bits PADDR_BITS
@@ -102,6 +104,9 @@ struct p2m_domain {
      */
     struct radix_tree_root mem_access_settings;
 
+    /* Alternate p2m: count of vcpu's currently using this p2m. */
+    atomic_t active_vcpus;
+
     /* Choose between: host/alternate. */
     p2m_class_t p2m_class;
 
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 17/38] arm/p2m: Add HVMOP_altp2m_create_p2m
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (15 preceding siblings ...)
  2016-08-16 22:16 ` [PATCH v3 16/38] arm/p2m: Add HVMOP_altp2m_set_domain_state Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-09-12  8:38   ` Julien Grall
  2016-08-16 22:16 ` [PATCH v3 18/38] arm/p2m: Add HVMOP_altp2m_destroy_p2m Sergej Proskurin
                   ` (20 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v2: Cosmetic fixes.

v3: Cosmetic fixes.

    Renamed the function "altp2m_init_next" to
    "altp2m_init_next_available".

    Exchanged the check "altp2m_vttbr[idx] == INVALID_VTTBR" for
    "altp2m_p2m[idx] == NULL" in "altp2m_init_next_available".
---
 xen/arch/arm/altp2m.c        | 23 +++++++++++++++++++++++
 xen/arch/arm/hvm.c           |  3 ++-
 xen/include/asm-arm/altp2m.h |  4 ++++
 3 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
index 02a52ec..b5d1951 100644
--- a/xen/arch/arm/altp2m.c
+++ b/xen/arch/arm/altp2m.c
@@ -122,6 +122,29 @@ int altp2m_init_by_id(struct domain *d, unsigned int idx)
     return rc;
 }
 
+int altp2m_init_next_available(struct domain *d, uint16_t *idx)
+{
+    int rc = -EINVAL;
+    uint16_t i;
+
+    altp2m_lock(d);
+
+    for ( i = 0; i < MAX_ALTP2M; i++ )
+    {
+        if ( d->arch.altp2m_p2m[i] != NULL )
+            continue;
+
+        rc = altp2m_init_helper(d, i);
+        *idx = i;
+
+        break;
+    }
+
+    altp2m_unlock(d);
+
+    return rc;
+}
+
 int altp2m_init(struct domain *d)
 {
     unsigned int i;
diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
index c69da36..a504dfd 100644
--- a/xen/arch/arm/hvm.c
+++ b/xen/arch/arm/hvm.c
@@ -123,7 +123,8 @@ static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
         break;
 
     case HVMOP_altp2m_create_p2m:
-        rc = -EOPNOTSUPP;
+        if ( !(rc = altp2m_init_next_available(d, &a.u.view.view)) )
+            rc = __copy_to_guest(arg, &a, 1) ? -EFAULT : 0;
         break;
 
     case HVMOP_altp2m_destroy_p2m:
diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
index f604ffd..5701012 100644
--- a/xen/include/asm-arm/altp2m.h
+++ b/xen/include/asm-arm/altp2m.h
@@ -56,6 +56,10 @@ struct p2m_domain *altp2m_get_altp2m(struct vcpu *v);
 int altp2m_init_by_id(struct domain *d,
                       unsigned int idx);
 
+/* Find and initialize the next available alternate p2m. */
+int altp2m_init_next_available(struct domain *d,
+                               uint16_t *idx);
+
 /* Flush all the alternate p2m's for a domain. */
 void altp2m_flush(struct domain *d);
 
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 18/38] arm/p2m: Add HVMOP_altp2m_destroy_p2m
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (16 preceding siblings ...)
  2016-08-16 22:16 ` [PATCH v3 17/38] arm/p2m: Add HVMOP_altp2m_create_p2m Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-09-12  8:41   ` Julien Grall
  2016-08-16 22:16 ` [PATCH v3 19/38] arm/p2m: Add HVMOP_altp2m_switch_p2m Sergej Proskurin
                   ` (19 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v2: Substituted the call to tlb_flush for p2m_flush_table.
    Added comments.
    Cosmetic fixes.

v3: Changed the locking mechanism to "p2m_write_lock" inside the
    function "altp2m_destroy_by_id".

    Do not flush but rather teardown the altp2m in the function
    "altp2m_destroy_by_id".

    Exchanged the check "altp2m_vttbr[idx] == INVALID_VTTBR" for
    "altp2m_p2m[idx] == NULL" in "altp2m_destroy_by_id".
---
 xen/arch/arm/altp2m.c        | 43 +++++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/hvm.c           |  2 +-
 xen/include/asm-arm/altp2m.h |  4 ++++
 3 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
index b5d1951..c14ab0b 100644
--- a/xen/arch/arm/altp2m.c
+++ b/xen/arch/arm/altp2m.c
@@ -190,6 +190,49 @@ void altp2m_flush(struct domain *d)
     altp2m_unlock(d);
 }
 
+int altp2m_destroy_by_id(struct domain *d, unsigned int idx)
+{
+    struct p2m_domain *p2m;
+    int rc = -EBUSY;
+
+    /*
+     * The altp2m[0] is considered as the hostp2m and is used as a safe harbor
+     * to which you can switch as long as altp2m is active. After deactivating
+     * altp2m, the system switches back to the original hostp2m view. That is,
+     * altp2m[0] should only be destroyed/flushed/freed, when altp2m is
+     * deactivated.
+     */
+    if ( !idx || idx >= MAX_ALTP2M )
+        return rc;
+
+    domain_pause_except_self(d);
+
+    altp2m_lock(d);
+
+    if ( d->arch.altp2m_p2m[idx] != NULL )
+    {
+        p2m = d->arch.altp2m_p2m[idx];
+
+        if ( !_atomic_read(p2m->active_vcpus) )
+        {
+            p2m_write_lock(p2m);
+            p2m_teardown_one(p2m);
+            p2m_write_unlock(p2m);
+
+            xfree(p2m);
+            d->arch.altp2m_p2m[idx] = NULL;
+
+            rc = 0;
+        }
+    }
+
+    altp2m_unlock(d);
+
+    domain_unpause_except_self(d);
+
+    return rc;
+}
+
 void altp2m_teardown(struct domain *d)
 {
     unsigned int i;
diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
index a504dfd..df973ef 100644
--- a/xen/arch/arm/hvm.c
+++ b/xen/arch/arm/hvm.c
@@ -128,7 +128,7 @@ static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
         break;
 
     case HVMOP_altp2m_destroy_p2m:
-        rc = -EOPNOTSUPP;
+        rc = altp2m_destroy_by_id(d, a.u.view.view);
         break;
 
     case HVMOP_altp2m_switch_p2m:
diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
index 5701012..6074079 100644
--- a/xen/include/asm-arm/altp2m.h
+++ b/xen/include/asm-arm/altp2m.h
@@ -63,4 +63,8 @@ int altp2m_init_next_available(struct domain *d,
 /* Flush all the alternate p2m's for a domain. */
 void altp2m_flush(struct domain *d);
 
+/* Make a specific alternate p2m invalid */
+int altp2m_destroy_by_id(struct domain *d,
+                         unsigned int idx);
+
 #endif /* __ASM_ARM_ALTP2M_H */
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 19/38] arm/p2m: Add HVMOP_altp2m_switch_p2m
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (17 preceding siblings ...)
  2016-08-16 22:16 ` [PATCH v3 18/38] arm/p2m: Add HVMOP_altp2m_destroy_p2m Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-09-12  8:47   ` Julien Grall
  2016-08-16 22:16 ` [PATCH v3 20/38] arm/p2m: Add p2m_get_active_p2m macro Sergej Proskurin
                   ` (18 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v3: Extended the function "altp2m_switch_domain_altp2m_by_id" so that if
    the guest domain indirectly calles this function, the current vcpu also
    changes the altp2m view without performing an explicit context switch.

    Exchanged the check "altp2m_vttbr[idx] == INVALID_VTTBR" for
    "altp2m_p2m[idx] == NULL" in "altp2m_switch_domain_altp2m_by_id".
---
 xen/arch/arm/altp2m.c        | 48 ++++++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/hvm.c           |  2 +-
 xen/include/asm-arm/altp2m.h |  4 ++++
 3 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
index c14ab0b..ba345b9 100644
--- a/xen/arch/arm/altp2m.c
+++ b/xen/arch/arm/altp2m.c
@@ -32,6 +32,54 @@ struct p2m_domain *altp2m_get_altp2m(struct vcpu *v)
     return v->domain->arch.altp2m_p2m[index];
 }
 
+int altp2m_switch_domain_altp2m_by_id(struct domain *d, unsigned int idx)
+{
+    struct vcpu *v;
+    int rc = -EINVAL;
+
+    if ( idx >= MAX_ALTP2M )
+        return rc;
+
+    domain_pause_except_self(d);
+
+    altp2m_lock(d);
+
+    if ( d->arch.altp2m_p2m[idx] != NULL )
+    {
+        for_each_vcpu( d, v )
+            if ( idx != altp2m_vcpu(v).p2midx )
+            {
+                atomic_dec(&altp2m_get_altp2m(v)->active_vcpus);
+                altp2m_vcpu(v).p2midx = idx;
+                atomic_inc(&altp2m_get_altp2m(v)->active_vcpus);
+
+                /*
+                 * In case it is the guest domain, which indirectly called this
+                 * function, the current vcpu will not switch its context
+                 * within the function "p2m_restore_state". That is, changing
+                 * the altp2m_vcpu(v).p2midx will not lead to the requested
+                 * altp2m switch on that specific vcpu. To achieve the desired
+                 * behavior, we write to VTTBR_EL2 directly.
+                 */
+                if ( v->domain == d && v == current )
+                {
+                    struct p2m_domain *ap2m = d->arch.altp2m_p2m[idx];
+
+                    WRITE_SYSREG64(ap2m->vttbr, VTTBR_EL2);
+                    isb();
+                }
+            }
+
+        rc = 0;
+    }
+
+    altp2m_unlock(d);
+
+    domain_unpause_except_self(d);
+
+    return rc;
+}
+
 static void altp2m_vcpu_reset(struct vcpu *v)
 {
     struct altp2mvcpu *av = &altp2m_vcpu(v);
diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
index df973ef..9ac3422 100644
--- a/xen/arch/arm/hvm.c
+++ b/xen/arch/arm/hvm.c
@@ -132,7 +132,7 @@ static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
         break;
 
     case HVMOP_altp2m_switch_p2m:
-        rc = -EOPNOTSUPP;
+        rc = altp2m_switch_domain_altp2m_by_id(d, a.u.view.view);
         break;
 
     case HVMOP_altp2m_set_mem_access:
diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
index 6074079..c2e44ab 100644
--- a/xen/include/asm-arm/altp2m.h
+++ b/xen/include/asm-arm/altp2m.h
@@ -52,6 +52,10 @@ void altp2m_vcpu_destroy(struct vcpu *v);
 /* Get current alternate p2m table. */
 struct p2m_domain *altp2m_get_altp2m(struct vcpu *v);
 
+/* Switch alternate p2m for entire domain */
+int altp2m_switch_domain_altp2m_by_id(struct domain *d,
+                                      unsigned int idx);
+
 /* Make a specific alternate p2m valid. */
 int altp2m_init_by_id(struct domain *d,
                       unsigned int idx);
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 20/38] arm/p2m: Add p2m_get_active_p2m macro
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (18 preceding siblings ...)
  2016-08-16 22:16 ` [PATCH v3 19/38] arm/p2m: Add HVMOP_altp2m_switch_p2m Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-09-12  8:50   ` Julien Grall
  2016-08-16 22:16 ` [PATCH v3 21/38] arm/p2m: Make p2m_restore_state ready for altp2m Sergej Proskurin
                   ` (17 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

This commit introduces the macro "p2m_get_active_p2m" returning the
currently active (alt)p2m. The need for this macro will be shown in the
following commits.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
 xen/arch/arm/p2m.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 63c0df0..12b3dcc 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -29,6 +29,9 @@ static unsigned int __read_mostly p2m_root_level;
 
 #define P2M_ROOT_PAGES    (1<<P2M_ROOT_ORDER)
 
+#define p2m_get_active_p2m(v) unlikely(altp2m_active(v->domain)) ?  \
+                              altp2m_get_altp2m(v) : p2m_get_hostp2m(v->domain);
+
 #define p2m_switch_vttbr_and_get_flags(ovttbr, nvttbr, flags)       \
 ({                                                                  \
     if ( ovttbr != nvttbr )                                         \
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 21/38] arm/p2m: Make p2m_restore_state ready for altp2m
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (19 preceding siblings ...)
  2016-08-16 22:16 ` [PATCH v3 20/38] arm/p2m: Add p2m_get_active_p2m macro Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-09-12  8:51   ` Julien Grall
  2016-08-16 22:16 ` [PATCH v3 22/38] arm/p2m: Make get_page_from_gva " Sergej Proskurin
                   ` (16 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

This commit adapts the function "p2m_restore_state" in a way that the
currently active altp2m table is considered during state restoration.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v3: Moved declaration of "altp2m_switch_domain_altp2m_by_id" out of this
    patch.
---
 xen/arch/arm/p2m.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 12b3dcc..15abd39 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -171,7 +171,7 @@ void p2m_save_state(struct vcpu *p)
 void p2m_restore_state(struct vcpu *n)
 {
     register_t hcr;
-    struct p2m_domain *p2m = p2m_get_hostp2m(n->domain);
+    struct p2m_domain *p2m = p2m_get_active_p2m(n);
 
     if ( is_idle_vcpu(n) )
         return;
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 22/38] arm/p2m: Make get_page_from_gva ready for altp2m
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (20 preceding siblings ...)
  2016-08-16 22:16 ` [PATCH v3 21/38] arm/p2m: Make p2m_restore_state ready for altp2m Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-08-16 22:16 ` [PATCH v3 23/38] arm/p2m: Cosmetic fixes -- __p2m_get_mem_access Sergej Proskurin
                   ` (15 subsequent siblings)
  37 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

The function get_page_from_gva uses ARM's hardware support to translate
gva's to machine addresses. This function is used, among others, for
memory regulation purposes, e.g, within the context of memory ballooning.
To ensure correct behavior while altp2m is in use, we use the host's p2m
table for the associated gva to ma translation. This is required at this
point, as altp2m lazily copies pages from the host's p2m and even might
be flushed because of changes to the host's p2m (as it is done within
the context of memory ballooning).

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v3: Cosmetic fixes.

    Make use of the p2m_(switch|restore)_vttbr_and_(g|s)et_flags macros
    to avoid code duplication.
---
 xen/arch/arm/p2m.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 15abd39..06f7eb8 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -1581,7 +1581,24 @@ struct page_info *get_page_from_gva(struct vcpu *v, vaddr_t va,
 
     p2m_read_lock(p2m);
 
-    rc = gvirt_to_maddr(va, &maddr, flags);
+    /*
+     * If altp2m is active, we need to translate the gva upon the hostp2m's
+     * vttbr, as it contains all valid mappings while the currently active
+     * altp2m view might not have the required gva mapping yet.
+     */
+    if ( unlikely(altp2m_active(d)) )
+    {
+        unsigned long flags = 0;
+        uint64_t ovttbr = READ_SYSREG64(VTTBR_EL2);
+
+        p2m_switch_vttbr_and_get_flags(ovttbr, p2m->vttbr, flags);
+
+        rc = gvirt_to_maddr(va, &maddr, flags);
+
+        p2m_restore_vttbr_and_set_flags(ovttbr, flags);
+    }
+    else
+        rc = gvirt_to_maddr(va, &maddr, flags);
 
     if ( rc )
         goto err;
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 23/38] arm/p2m: Cosmetic fixes -- __p2m_get_mem_access
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (21 preceding siblings ...)
  2016-08-16 22:16 ` [PATCH v3 22/38] arm/p2m: Make get_page_from_gva " Sergej Proskurin
@ 2016-08-16 22:16 ` Sergej Proskurin
  2016-09-12  8:53   ` Julien Grall
  2016-08-16 22:17 ` [PATCH v3 24/38] arm/p2m: Make p2m_mem_access_check ready for altp2m Sergej Proskurin
                   ` (14 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:16 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

This commit extends the function prototypes of the functions:
* __p2m_get_mem_access
* p2m_mem_access_check_and_get_page

We extend the function prototype of "__p2m_get_mem_access" to hold an
argument of type "struct p2m_domain*", as we need to distinguish between
the host's p2m and different altp2m views. While doing so, we needed to
extend the function's prototype of "p2m_mem_access_check_and_get_page"
to hold an argument of type "struct vcpu*".

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v3: Changed the parameter of "p2m_mem_access_check_and_get_page"
    from "struct p2m_domain*" to "struct vcpu*".
---
 xen/arch/arm/p2m.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 06f7eb8..5819ae0 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -606,10 +606,9 @@ static int p2m_create_table(struct p2m_domain *p2m, lpae_t *entry)
     return 0;
 }
 
-static int __p2m_get_mem_access(struct domain *d, gfn_t gfn,
+static int __p2m_get_mem_access(struct p2m_domain *p2m, gfn_t gfn,
                                 xenmem_access_t *access)
 {
-    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     void *i;
     unsigned int index;
 
@@ -1471,7 +1470,7 @@ mfn_t gfn_to_mfn(struct domain *d, gfn_t gfn)
  * we indeed found a conflicting mem_access setting.
  */
 static struct page_info*
-p2m_mem_access_check_and_get_page(vaddr_t gva, unsigned long flag)
+p2m_mem_access_check_and_get_page(struct vcpu *v, vaddr_t gva, unsigned long flag)
 {
     long rc;
     paddr_t ipa;
@@ -1480,7 +1479,7 @@ p2m_mem_access_check_and_get_page(vaddr_t gva, unsigned long flag)
     xenmem_access_t xma;
     p2m_type_t t;
     struct page_info *page = NULL;
-    struct p2m_domain *p2m = p2m_get_hostp2m(current->domain);
+    struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
 
     rc = gva_to_ipa(gva, &ipa, flag);
     if ( rc < 0 )
@@ -1492,7 +1491,7 @@ p2m_mem_access_check_and_get_page(vaddr_t gva, unsigned long flag)
      * We do this first as this is faster in the default case when no
      * permission is set on the page.
      */
-    rc = __p2m_get_mem_access(current->domain, gfn, &xma);
+    rc = __p2m_get_mem_access(p2m, gfn, &xma);
     if ( rc < 0 )
         goto err;
 
@@ -1556,7 +1555,7 @@ p2m_mem_access_check_and_get_page(vaddr_t gva, unsigned long flag)
 
     page = mfn_to_page(mfn_x(mfn));
 
-    if ( unlikely(!get_page(page, current->domain)) )
+    if ( unlikely(!get_page(page, v->domain)) )
         page = NULL;
 
 err:
@@ -1614,7 +1613,7 @@ struct page_info *get_page_from_gva(struct vcpu *v, vaddr_t va,
 
 err:
     if ( !page && p2m->mem_access_enabled )
-        page = p2m_mem_access_check_and_get_page(va, flags);
+        page = p2m_mem_access_check_and_get_page(v, va, flags);
 
     p2m_read_unlock(p2m);
 
@@ -1927,7 +1926,7 @@ int p2m_get_mem_access(struct domain *d, gfn_t gfn,
     struct p2m_domain *p2m = p2m_get_hostp2m(d);
 
     p2m_read_lock(p2m);
-    ret = __p2m_get_mem_access(d, gfn, access);
+    ret = __p2m_get_mem_access(p2m, gfn, access);
     p2m_read_unlock(p2m);
 
     return ret;
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 24/38] arm/p2m: Make p2m_mem_access_check ready for altp2m
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (22 preceding siblings ...)
  2016-08-16 22:16 ` [PATCH v3 23/38] arm/p2m: Cosmetic fixes -- __p2m_get_mem_access Sergej Proskurin
@ 2016-08-16 22:17 ` Sergej Proskurin
  2016-09-12  9:02   ` Julien Grall
  2016-08-16 22:17 ` [PATCH v3 25/38] arm/p2m: Cosmetic fixes - function prototypes Sergej Proskurin
                   ` (13 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:17 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

This commit extends the function "p2m_mem_access_check" and
"p2m_mem_access_check_and_get_page" to consider altp2m. The function
"p2m_mem_access_check_and_get_page" needs to translate the gva upon the
hostp2m's vttbr, as it contains all valid mappings while the currently
active altp2m view might not have the required gva mapping yet.

Also, the new implementation fills the request buffer to hold
altp2m-related information.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v3: Extended the function "p2m_mem_access_check_and_get_page" to
    consider altp2m. Similar to "get_page_from_gva", the function
    "p2m_mem_access_check_and_get_page" needs to translate the gva upon
    the hostp2m's vttbr. Although, the function "gva_to_ipa" (called in
    "p2m_mem_access_check_and_get_page") performs a stage 1 table walk,
    it will access page tables residing in memory. Accesses to this
    memory are controlled by the underlying 2nd stage translation table
    and hence require the original mappings of the hostp2m.
---
 xen/arch/arm/p2m.c | 43 +++++++++++++++++++++++++++++++++++++++----
 1 file changed, 39 insertions(+), 4 deletions(-)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 5819ae0..ed9e0f0 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -14,6 +14,7 @@
 #include <asm/hardirq.h>
 #include <asm/page.h>
 
+#include <asm/vm_event.h>
 #include <asm/altp2m.h>
 
 #ifdef CONFIG_ARM_64
@@ -1479,9 +1480,32 @@ p2m_mem_access_check_and_get_page(struct vcpu *v, vaddr_t gva, unsigned long fla
     xenmem_access_t xma;
     p2m_type_t t;
     struct page_info *page = NULL;
-    struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
+    struct domain *d = v->domain;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
+
+    /*
+     * If altp2m is active, we need to translate the gva upon the hostp2m's
+     * vttbr, as it contains all valid mappings while the currently active
+     * altp2m view might not have the required gva mapping yet. Although, the
+     * function gva_to_ipa performs a stage 1 table walk, it will access page
+     * tables residing in memory. Accesses to this memory are controlled by the
+     * underlying 2nd stage translation table and hence require the original
+     * mappings of the hostp2m.
+     */
+    if ( unlikely(altp2m_active(d)) )
+    {
+        unsigned long flags = 0;
+        uint64_t ovttbr = READ_SYSREG64(VTTBR_EL2);
+
+        p2m_switch_vttbr_and_get_flags(ovttbr, p2m->vttbr, flags);
+
+        rc = gva_to_ipa(gva, &ipa, flag);
+
+        p2m_restore_vttbr_and_set_flags(ovttbr, flags);
+    }
+    else
+        rc = gva_to_ipa(gva, &ipa, flag);
 
-    rc = gva_to_ipa(gva, &ipa, flag);
     if ( rc < 0 )
         goto err;
 
@@ -1698,13 +1722,16 @@ bool_t p2m_mem_access_check(paddr_t gpa, vaddr_t gla, const struct npfec npfec)
     xenmem_access_t xma;
     vm_event_request_t *req;
     struct vcpu *v = current;
-    struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
+    struct domain *d = v->domain;
+    struct p2m_domain *p2m = p2m_get_active_p2m(v);
 
     /* Mem_access is not in use. */
     if ( !p2m->mem_access_enabled )
         return true;
 
-    rc = p2m_get_mem_access(v->domain, _gfn(paddr_to_pfn(gpa)), &xma);
+    p2m_read_lock(p2m);
+    rc = __p2m_get_mem_access(p2m, _gfn(paddr_to_pfn(gpa)), &xma);
+    p2m_read_unlock(p2m);
     if ( rc )
         return true;
 
@@ -1810,6 +1837,14 @@ bool_t p2m_mem_access_check(paddr_t gpa, vaddr_t gla, const struct npfec npfec)
         req->u.mem_access.flags |= npfec.insn_fetch     ? MEM_ACCESS_X : 0;
         req->vcpu_id = v->vcpu_id;
 
+        vm_event_fill_regs(req);
+
+        if ( unlikely(altp2m_active(d)) )
+        {
+            req->flags |= VM_EVENT_FLAG_ALTERNATE_P2M;
+            req->altp2m_idx = altp2m_vcpu(v).p2midx;
+        }
+
         mem_access_send_req(v->domain, req);
         xfree(req);
     }
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 25/38] arm/p2m: Cosmetic fixes - function prototypes
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (23 preceding siblings ...)
  2016-08-16 22:17 ` [PATCH v3 24/38] arm/p2m: Make p2m_mem_access_check ready for altp2m Sergej Proskurin
@ 2016-08-16 22:17 ` Sergej Proskurin
  2016-08-16 22:17 ` [PATCH v3 26/38] arm/p2m: Introduce helpers managing altp2m entries Sergej Proskurin
                   ` (12 subsequent siblings)
  37 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:17 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

This commit changes the prototypes of the following functions:
- p2m_insert_mapping
- p2m_remove_mapping

These changes are required as our implementation reuses most of the
existing ARM p2m implementation to set page table attributes of the
individual altp2m views. Therefore, exiting function prototypes have
been extended to hold another argument (of type struct p2m_domain *).
This allows to specify the p2m/altp2m domain that should be processed by
the individual function -- instead of accessing the host's default p2m
domain.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v2: Adoption of the functions "__p2m_lookup" and "__p2m_get_mem_access"
    have been moved out of this commit.
---
 xen/arch/arm/p2m.c | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index ed9e0f0..ca5ae97 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -1062,13 +1062,12 @@ static int p2m_set_entry(struct p2m_domain *p2m,
     return rc;
 }
 
-static inline int p2m_insert_mapping(struct domain *d,
+static inline int p2m_insert_mapping(struct p2m_domain *p2m,
                                      gfn_t start_gfn,
                                      unsigned long nr,
                                      mfn_t mfn,
                                      p2m_type_t t)
 {
-    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     int rc;
 
     p2m_write_lock(p2m);
@@ -1082,12 +1081,11 @@ static inline int p2m_insert_mapping(struct domain *d,
     return rc;
 }
 
-static inline int p2m_remove_mapping(struct domain *d,
+static inline int p2m_remove_mapping(struct p2m_domain *p2m,
                                      gfn_t start_gfn,
                                      unsigned long nr,
                                      mfn_t mfn)
 {
-    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     int rc;
 
     p2m_write_lock(p2m);
@@ -1103,7 +1101,7 @@ int map_regions_rw_cache(struct domain *d,
                          unsigned long nr,
                          mfn_t mfn)
 {
-    return p2m_insert_mapping(d, gfn, nr, mfn, p2m_mmio_direct_c);
+    return p2m_insert_mapping(p2m_get_hostp2m(d), gfn, nr, mfn, p2m_mmio_direct_c);
 }
 
 int unmap_regions_rw_cache(struct domain *d,
@@ -1111,7 +1109,7 @@ int unmap_regions_rw_cache(struct domain *d,
                            unsigned long nr,
                            mfn_t mfn)
 {
-    return p2m_remove_mapping(d, gfn, nr, mfn);
+    return p2m_remove_mapping(p2m_get_hostp2m(d), gfn, nr, mfn);
 }
 
 int map_mmio_regions(struct domain *d,
@@ -1119,7 +1117,7 @@ int map_mmio_regions(struct domain *d,
                      unsigned long nr,
                      mfn_t mfn)
 {
-    return p2m_insert_mapping(d, start_gfn, nr, mfn, p2m_mmio_direct_nc);
+    return p2m_insert_mapping(p2m_get_hostp2m(d), start_gfn, nr, mfn, p2m_mmio_direct_nc);
 }
 
 int unmap_mmio_regions(struct domain *d,
@@ -1127,7 +1125,7 @@ int unmap_mmio_regions(struct domain *d,
                        unsigned long nr,
                        mfn_t mfn)
 {
-    return p2m_remove_mapping(d, start_gfn, nr, mfn);
+    return p2m_remove_mapping(p2m_get_hostp2m(d), start_gfn, nr, mfn);
 }
 
 int map_dev_mmio_region(struct domain *d,
@@ -1157,14 +1155,14 @@ int guest_physmap_add_entry(struct domain *d,
                             unsigned long page_order,
                             p2m_type_t t)
 {
-    return p2m_insert_mapping(d, gfn, (1 << page_order), mfn, t);
+    return p2m_insert_mapping(p2m_get_hostp2m(d), gfn, (1 << page_order), mfn, t);
 }
 
 void guest_physmap_remove_page(struct domain *d,
                                gfn_t gfn,
                                mfn_t mfn, unsigned int page_order)
 {
-    p2m_remove_mapping(d, gfn, (1 << page_order), mfn);
+    p2m_remove_mapping(p2m_get_hostp2m(d), gfn, (1 << page_order), mfn);
 }
 
 static int p2m_alloc_table(struct p2m_domain *p2m)
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 26/38] arm/p2m: Introduce helpers managing altp2m entries
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (24 preceding siblings ...)
  2016-08-16 22:17 ` [PATCH v3 25/38] arm/p2m: Cosmetic fixes - function prototypes Sergej Proskurin
@ 2016-08-16 22:17 ` Sergej Proskurin
  2016-09-12  9:04   ` Julien Grall
  2016-08-16 22:17 ` [PATCH v3 27/38] arm/p2m: Introduce p2m_lookup_attr Sergej Proskurin
                   ` (11 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:17 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

This commit introduces the following functions:
* remove_altp2m_entry
* modify_altp2m_entry

These functions are responsible to manage an altp2m view's entries and
their attributes.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v3: Changed the function prototype of "modify_altp2m_entry" and
    "remove_altp2m_entry" to hold arguments of type gfn_t/mfn_t instead
    of addresses.

    Remove the argument of type "struct domain*" from the function's
    prototypes.

    Remove the function "modify_altp2m_range".
---
 xen/arch/arm/p2m.c        | 36 ++++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/p2m.h | 14 ++++++++++++++
 2 files changed, 50 insertions(+)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index ca5ae97..1d3df0f 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -1165,6 +1165,42 @@ void guest_physmap_remove_page(struct domain *d,
     p2m_remove_mapping(p2m_get_hostp2m(d), gfn, (1 << page_order), mfn);
 }
 
+int remove_altp2m_entry(struct p2m_domain *ap2m,
+                        gfn_t gfn,
+                        mfn_t mfn,
+                        unsigned int page_order)
+{
+    ASSERT(p2m_is_altp2m(ap2m));
+
+    /* Align the gfn and mfn to the given pager order. */
+    gfn = _gfn(gfn_x(gfn) & ~((1UL << page_order)-1));
+    mfn = _mfn(mfn_x(mfn) & ~((1UL << page_order)-1));
+
+    return p2m_remove_mapping(ap2m, gfn, (1UL << page_order), mfn);
+}
+
+int modify_altp2m_entry(struct p2m_domain *ap2m,
+                        gfn_t gfn,
+                        mfn_t mfn,
+                        p2m_type_t t,
+                        p2m_access_t a,
+                        unsigned int page_order)
+{
+    int rc;
+
+    ASSERT(p2m_is_altp2m(ap2m));
+
+    /* Align the gfn and mfn to the given pager order. */
+    gfn = _gfn(gfn_x(gfn) & ~((1UL << page_order)-1));
+    mfn = _mfn(mfn_x(mfn) & ~((1UL << page_order)-1));
+
+    p2m_write_lock(ap2m);
+    rc = p2m_set_entry(ap2m, gfn, (1UL << page_order), mfn, t, a);
+    p2m_write_unlock(ap2m);
+
+    return rc;
+}
+
 static int p2m_alloc_table(struct p2m_domain *p2m)
 {
     struct page_info *page;
diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
index 978125a..e02f69e 100644
--- a/xen/include/asm-arm/p2m.h
+++ b/xen/include/asm-arm/p2m.h
@@ -196,6 +196,20 @@ void p2m_dump_info(struct domain *d);
 /* Look up the MFN corresponding to a domain's GFN. */
 mfn_t p2m_lookup(struct domain *d, gfn_t gfn, p2m_type_t *t);
 
+/* Remove an altp2m view's entry. */
+int remove_altp2m_entry(struct p2m_domain *p2m,
+                        gfn_t gfn,
+                        mfn_t mfn,
+                        unsigned int page_order);
+
+/* Modify an altp2m view's entry or its attributes. */
+int modify_altp2m_entry(struct p2m_domain *p2m,
+                        gfn_t gfn,
+                        mfn_t mfn,
+                        p2m_type_t t,
+                        p2m_access_t a,
+                        unsigned int page_order);
+
 /* Clean & invalidate caches corresponding to a region of guest address space */
 int p2m_cache_flush(struct domain *d, gfn_t start, unsigned long nr);
 
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 27/38] arm/p2m: Introduce p2m_lookup_attr
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (25 preceding siblings ...)
  2016-08-16 22:17 ` [PATCH v3 26/38] arm/p2m: Introduce helpers managing altp2m entries Sergej Proskurin
@ 2016-08-16 22:17 ` Sergej Proskurin
  2016-09-12  9:15   ` Julien Grall
  2016-08-16 22:17 ` [PATCH v3 28/38] arm/p2m: Modify reference count only if hostp2m active Sergej Proskurin
                   ` (10 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:17 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

The function "p2m_lookup_attr" allows to lookup the mfn, memory type,
access rights, and page order corresponding to a domain's gfn.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v3: Change function prototype of "p2m_lookup_attr" by removing the
    function parameter "unsigned int *mattr", as it is not needed by the
    callers.

    Change function prototype of "p2m_lookup_attr" by changing the
    parameter of type xenmem_access_t to p2m_access_t.
---
 xen/arch/arm/p2m.c        | 15 +++++++++++++++
 xen/include/asm-arm/p2m.h | 10 ++++++++++
 2 files changed, 25 insertions(+)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 1d3df0f..cef05ed 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -429,6 +429,21 @@ mfn_t p2m_lookup(struct domain *d, gfn_t gfn, p2m_type_t *t)
     return ret;
 }
 
+mfn_t p2m_lookup_attr(struct p2m_domain *p2m,
+                      gfn_t gfn,
+                      p2m_type_t *t,
+                      p2m_access_t *a,
+                      unsigned int *page_order)
+{
+    mfn_t ret;
+
+    p2m_read_lock(p2m);
+    ret = p2m_get_entry(p2m, gfn, t, a, page_order);
+    p2m_read_unlock(p2m);
+
+    return ret;
+}
+
 int guest_physmap_mark_populate_on_demand(struct domain *d,
                                           unsigned long gfn,
                                           unsigned int order)
diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
index e02f69e..384ef3b 100644
--- a/xen/include/asm-arm/p2m.h
+++ b/xen/include/asm-arm/p2m.h
@@ -196,6 +196,16 @@ void p2m_dump_info(struct domain *d);
 /* Look up the MFN corresponding to a domain's GFN. */
 mfn_t p2m_lookup(struct domain *d, gfn_t gfn, p2m_type_t *t);
 
+/*
+ * Lookup the MFN, memory type, access rights, and page table level
+ * corresponding to a domain's GFN.
+ */
+mfn_t p2m_lookup_attr(struct p2m_domain *p2m,
+                      gfn_t gfn,
+                      p2m_type_t *t,
+                      p2m_access_t *a,
+                      unsigned int *page_order);
+
 /* Remove an altp2m view's entry. */
 int remove_altp2m_entry(struct p2m_domain *p2m,
                         gfn_t gfn,
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 28/38] arm/p2m: Modify reference count only if hostp2m active
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (26 preceding siblings ...)
  2016-08-16 22:17 ` [PATCH v3 27/38] arm/p2m: Introduce p2m_lookup_attr Sergej Proskurin
@ 2016-08-16 22:17 ` Sergej Proskurin
  2016-09-12  9:17   ` Julien Grall
  2016-08-16 22:17 ` [PATCH v3 29/38] arm/p2m: Add HVMOP_altp2m_set_mem_access Sergej Proskurin
                   ` (9 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:17 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

This commit makes sure that the page reference count is updated through
the function "p2m_put_l3_page" only the entries have been freed from the
hosts's p2m.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
 xen/arch/arm/p2m.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index cef05ed..df2b85b 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -754,7 +754,7 @@ static void p2m_free_entry(struct p2m_domain *p2m,
     if ( !p2m_valid(entry) || p2m_is_superpage(entry, level) )
         return;
 
-    if ( level == 3 )
+    if ( level == 3 && p2m_is_hostp2m(p2m) )
     {
         p2m_put_l3_page(_mfn(entry.p2m.base), entry.p2m.type);
         return;
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 29/38] arm/p2m: Add HVMOP_altp2m_set_mem_access
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (27 preceding siblings ...)
  2016-08-16 22:17 ` [PATCH v3 28/38] arm/p2m: Modify reference count only if hostp2m active Sergej Proskurin
@ 2016-08-16 22:17 ` Sergej Proskurin
  2016-09-12 12:08   ` Julien Grall
  2016-08-16 22:17 ` [PATCH v3 30/38] arm/p2m: Add altp2m_propagate_change Sergej Proskurin
                   ` (8 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:17 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

The HVMOP_altp2m_set_mem_access allows to set gfn permissions of
(currently one page at a time) of a specific altp2m view. In case the
view does not hold the requested gfn entry, it will be first copied from
the host's p2m table and then modified as requested.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v2: Prevent the page reference count from being falsely updated on
    altp2m modification. Therefore, we add a check determining whether
    the target p2m is a hostp2m before p2m_put_l3_page is called.

v3: Cosmetic fixes.

    Added the functionality to set/get the default_access also in/from
    the requested altp2m view.

    Read-locked hp2m in "altp2m_set_mem_access".

    Moved the functions "p2m_is_(hostp2m|altp2m)" out of this commit.

    Moved the funtion "modify_altp2m_entry" out of this commit.

    Moved the function "p2m_lookup_attr" out of this commit.

    Moved guards for "p2m_put_l3_page" out of this commit.
---
 xen/arch/arm/altp2m.c        | 53 ++++++++++++++++++++++++++++
 xen/arch/arm/hvm.c           |  7 +++-
 xen/arch/arm/p2m.c           | 82 ++++++++++++++++++++++++++++++++------------
 xen/include/asm-arm/altp2m.h | 12 +++++++
 4 files changed, 131 insertions(+), 23 deletions(-)

diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
index ba345b9..03b8ce5 100644
--- a/xen/arch/arm/altp2m.c
+++ b/xen/arch/arm/altp2m.c
@@ -80,6 +80,59 @@ int altp2m_switch_domain_altp2m_by_id(struct domain *d, unsigned int idx)
     return rc;
 }
 
+int altp2m_set_mem_access(struct domain *d,
+                          struct p2m_domain *hp2m,
+                          struct p2m_domain *ap2m,
+                          p2m_access_t a,
+                          gfn_t gfn)
+{
+    p2m_type_t p2mt;
+    p2m_access_t old_a;
+    mfn_t mfn;
+    unsigned int page_order;
+    int rc;
+
+    altp2m_lock(d);
+    p2m_read_lock(hp2m);
+
+    /* Check if entry is part of the altp2m view. */
+    mfn = p2m_lookup_attr(ap2m, gfn, &p2mt, NULL, &page_order);
+
+    /* Check host p2m if no valid entry in ap2m. */
+    if ( mfn_eq(mfn, INVALID_MFN) )
+    {
+        /* Check if entry is part of the host p2m view. */
+        mfn = p2m_lookup_attr(hp2m, gfn, &p2mt, &old_a, &page_order);
+        if ( mfn_eq(mfn, INVALID_MFN) ||
+             ((p2mt != p2m_ram_rw) && (p2mt != p2m_ram_ro)) )
+        {
+            rc = -ESRCH;
+            goto out;
+        }
+
+        /* If this is a superpage, copy that first. */
+        if ( page_order != THIRD_ORDER )
+        {
+            rc = modify_altp2m_entry(ap2m, gfn, mfn, p2mt, old_a, page_order);
+            if ( rc < 0 )
+            {
+                rc = -ESRCH;
+                goto out;
+            }
+        }
+    }
+
+    /* Set mem access attributes - currently supporting only one (4K) page. */
+    page_order = THIRD_ORDER;
+    rc = modify_altp2m_entry(ap2m, gfn, mfn, p2mt, a, page_order);
+
+out:
+    p2m_read_unlock(hp2m);
+    altp2m_unlock(d);
+
+    return rc;
+}
+
 static void altp2m_vcpu_reset(struct vcpu *v)
 {
     struct altp2mvcpu *av = &altp2m_vcpu(v);
diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
index 9ac3422..df78893 100644
--- a/xen/arch/arm/hvm.c
+++ b/xen/arch/arm/hvm.c
@@ -136,7 +136,12 @@ static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
         break;
 
     case HVMOP_altp2m_set_mem_access:
-        rc = -EOPNOTSUPP;
+        if ( a.u.set_mem_access.pad )
+            rc = -EINVAL;
+        else
+            rc = p2m_set_mem_access(d, _gfn(a.u.set_mem_access.gfn), 1, 0, 0,
+                                    a.u.set_mem_access.hvmmem_access,
+                                    a.u.set_mem_access.view);
         break;
 
     case HVMOP_altp2m_change_gfn:
diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index df2b85b..8dee02187 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -1913,7 +1913,7 @@ long p2m_set_mem_access(struct domain *d, gfn_t gfn, uint32_t nr,
                         uint32_t start, uint32_t mask, xenmem_access_t access,
                         unsigned int altp2m_idx)
 {
-    struct p2m_domain *p2m = p2m_get_hostp2m(d);
+    struct p2m_domain *hp2m = p2m_get_hostp2m(d), *ap2m = NULL;
     p2m_access_t a;
     unsigned int order;
     long rc = 0;
@@ -1933,13 +1933,26 @@ long p2m_set_mem_access(struct domain *d, gfn_t gfn, uint32_t nr,
 #undef ACCESS
     };
 
+    /* altp2m view 0 is treated as the hostp2m */
+    if ( altp2m_idx )
+    {
+        if ( altp2m_idx >= MAX_ALTP2M ||
+             d->arch.altp2m_p2m[altp2m_idx] == NULL )
+            return -EINVAL;
+
+        ap2m = d->arch.altp2m_p2m[altp2m_idx];
+    }
+
     switch ( access )
     {
     case 0 ... ARRAY_SIZE(memaccess) - 1:
         a = memaccess[access];
         break;
     case XENMEM_access_default:
-        a = p2m->default_access;
+        if ( ap2m )
+            a = ap2m->default_access;
+        else
+            a = hp2m->default_access;
         break;
     default:
         return -EINVAL;
@@ -1949,39 +1962,66 @@ long p2m_set_mem_access(struct domain *d, gfn_t gfn, uint32_t nr,
      * Flip mem_access_enabled to true when a permission is set, as to prevent
      * allocating or inserting super-pages.
      */
-    p2m->mem_access_enabled = true;
+    if ( ap2m )
+        ap2m->mem_access_enabled = true;
+    else
+        hp2m->mem_access_enabled = true;
 
     /* If request to set default access. */
     if ( gfn_eq(gfn, INVALID_GFN) )
     {
-        p2m->default_access = a;
+        if ( ap2m )
+            ap2m->default_access = a;
+        else
+            hp2m->default_access = a;
+
         return 0;
     }
 
-    p2m_write_lock(p2m);
-
     for ( gfn = gfn_add(gfn, start); nr > start; gfn = gfn_add(gfn, 1UL << order) )
     {
-        p2m_type_t t;
-        mfn_t mfn = p2m_get_entry(p2m, gfn, &t, NULL, &order);
-
-        /* Skip hole */
-        if ( mfn_eq(mfn, INVALID_MFN) )
+        if ( ap2m )
         {
+            order = THIRD_ORDER;
+
             /*
-             * the order corresponds to the order of the mapping in the
-             * page table. so we need to align the gfn before
-             * incrementing.
+             * ARM altp2m currently supports only setting of memory access rights
+             * of only one (4K) page at a time.
              */
-            gfn = _gfn(gfn_x(gfn) & ~((1UL << order) - 1));
-            continue;
+            rc = altp2m_set_mem_access(d, hp2m, ap2m, a, gfn);
+            if ( rc && rc != -ESRCH )
+                break;
         }
         else
         {
-            order = 0;
-            rc = __p2m_set_entry(p2m, gfn, 0, mfn, t, a);
-            if ( rc )
-                break;
+            p2m_type_t t;
+            mfn_t mfn;
+
+            p2m_write_lock(hp2m);
+
+            mfn = p2m_get_entry(hp2m, gfn, &t, NULL, &order);
+
+            /* Skip hole */
+            if ( mfn_eq(mfn, INVALID_MFN) )
+            {
+                /*
+                 * the order corresponds to the order of the mapping in the
+                 * page table. so we need to align the gfn before
+                 * incrementing.
+                 */
+                gfn = _gfn(gfn_x(gfn) & ~((1UL << order) - 1));
+                continue;
+            }
+            else
+            {
+                order = 0;
+
+                rc = __p2m_set_entry(hp2m, gfn, 0, mfn, t, a);
+                if ( rc )
+                    break;
+            }
+
+            p2m_write_unlock(hp2m);
         }
 
         start += (1UL << order);
@@ -1993,8 +2033,6 @@ long p2m_set_mem_access(struct domain *d, gfn_t gfn, uint32_t nr,
         }
     }
 
-    p2m_write_unlock(p2m);
-
     if ( rc < 0 )
         return rc;
     else if ( rc > 0 )
diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
index c2e44ab..3e4c36d 100644
--- a/xen/include/asm-arm/altp2m.h
+++ b/xen/include/asm-arm/altp2m.h
@@ -71,4 +71,16 @@ void altp2m_flush(struct domain *d);
 int altp2m_destroy_by_id(struct domain *d,
                          unsigned int idx);
 
+/*
+ * Set memory access attributes of the gfn in the altp2m view. If the altp2m
+ * view does not contain the particular entry, copy it first from the hostp2m.
+ *
+ * Currently supports memory attribute adoptions of only one (4K) page.
+ */
+int altp2m_set_mem_access(struct domain *d,
+                          struct p2m_domain *hp2m,
+                          struct p2m_domain *ap2m,
+                          p2m_access_t a,
+                          gfn_t gfn);
+
 #endif /* __ASM_ARM_ALTP2M_H */
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 30/38] arm/p2m: Add altp2m_propagate_change
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (28 preceding siblings ...)
  2016-08-16 22:17 ` [PATCH v3 29/38] arm/p2m: Add HVMOP_altp2m_set_mem_access Sergej Proskurin
@ 2016-08-16 22:17 ` Sergej Proskurin
  2016-08-16 22:17 ` [PATCH v3 31/38] altp2m: Introduce altp2m_switch_vcpu_altp2m_by_id Sergej Proskurin
                   ` (7 subsequent siblings)
  37 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:17 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

This commit introduces the function "altp2m_propagate_change" that is
responsible to propagate changes applied to the host's p2m to a specific
or even all altp2m views. In this way, Xen can in-/decrease the guest's
physmem at run-time without leaving the altp2m views with
stalled/invalid entries.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v3: Cosmetic fixes.

    Changed the locking mechanism to "p2m_write_lock" inside the
    function "altp2m_reset".

    Removed TLB flushing and resetting of the max_mapped_gfn
    lowest_mapped_gfn fields within the function "altp2m_reset". These
    operations are performed in the function "p2m_flush_table".

    Protected altp2m_active(d) check in "altp2m_propagate_change".

    The function "altp2m_propagate_change" now decides whether an entry
    needs to be dropped out of the altp2m view only if the smfn value
    equals INVALID_MFN.

    Extended the function "altp2m_propagate_change" so that it returns
    an int value to the caller. Also, the function "apply_p2m_changes"
    checks the return value and fails the entire operation on error.

    Moved the funtion "modify_altp2m_range" out of this commit.
---
 xen/arch/arm/altp2m.c        | 74 ++++++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/p2m.c           |  4 +++
 xen/include/asm-arm/altp2m.h |  8 +++++
 3 files changed, 86 insertions(+)

diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
index 03b8ce5..b10711e 100644
--- a/xen/arch/arm/altp2m.c
+++ b/xen/arch/arm/altp2m.c
@@ -133,6 +133,80 @@ out:
     return rc;
 }
 
+static inline void altp2m_reset(struct p2m_domain *p2m)
+{
+    p2m_write_lock(p2m);
+    p2m_flush_table(p2m);
+    p2m_write_unlock(p2m);
+}
+
+int altp2m_propagate_change(struct domain *d,
+                            gfn_t sgfn,
+                            unsigned int page_order,
+                            mfn_t smfn,
+                            p2m_type_t p2mt,
+                            p2m_access_t p2ma)
+{
+    int rc = 0;
+    unsigned int i;
+    unsigned int reset_count = 0;
+    unsigned int last_reset_idx = ~0;
+    struct p2m_domain *p2m;
+    mfn_t m;
+
+    altp2m_lock(d);
+
+    if ( !altp2m_active(d) )
+        goto out;
+
+    for ( i = 0; i < MAX_ALTP2M; i++ )
+    {
+        if ( d->arch.altp2m_p2m[i] == NULL )
+            continue;
+
+        p2m = d->arch.altp2m_p2m[i];
+
+        /*
+         * Get the altp2m mapping. If the smfn has not been dropped, a valid
+         * altp2m mapping needs to be changed/modified accordingly.
+         */
+        m = p2m_lookup_attr(p2m, sgfn, NULL, NULL, NULL);
+
+        /* Check for a dropped page that may impact this altp2m. */
+        if ( mfn_eq(smfn, INVALID_MFN) &&
+             (gfn_x(sgfn) >= gfn_x(p2m->lowest_mapped_gfn)) &&
+             (gfn_x(sgfn) <= gfn_x(p2m->max_mapped_gfn)) )
+        {
+            if ( !reset_count++ )
+            {
+                altp2m_reset(p2m);
+                last_reset_idx = i;
+            }
+            else
+            {
+                /* At least 2 altp2m's impacted, so reset everything. */
+                for ( i = 0; i < MAX_ALTP2M; i++ )
+                {
+                    if ( i == last_reset_idx ||
+                         d->arch.altp2m_p2m[i] == NULL )
+                        continue;
+
+                    p2m = d->arch.altp2m_p2m[i];
+                    altp2m_reset(p2m);
+                }
+                goto out;
+            }
+        }
+        else if ( !mfn_eq(m, INVALID_MFN) )
+            rc = modify_altp2m_entry(p2m, sgfn, smfn, p2mt, p2ma, page_order);
+    }
+
+out:
+    altp2m_unlock(d);
+
+    return rc;
+}
+
 static void altp2m_vcpu_reset(struct vcpu *v)
 {
     struct altp2mvcpu *av = &altp2m_vcpu(v);
diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 8dee02187..dea3038 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -1033,6 +1033,10 @@ static int __p2m_set_entry(struct p2m_domain *p2m,
 
     rc = 0;
 
+    /* Update all affected altp2m views if necessary. */
+    if ( p2m_is_hostp2m(p2m) )
+        rc = altp2m_propagate_change(p2m->domain, sgfn, page_order, smfn, t, a);
+
 out:
     unmap_domain_page(table);
 
diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
index 3e4c36d..7f385d9 100644
--- a/xen/include/asm-arm/altp2m.h
+++ b/xen/include/asm-arm/altp2m.h
@@ -83,4 +83,12 @@ int altp2m_set_mem_access(struct domain *d,
                           p2m_access_t a,
                           gfn_t gfn);
 
+/* Propagates changes made to hostp2m to affected altp2m views. */
+int altp2m_propagate_change(struct domain *d,
+                            gfn_t sgfn,
+                            unsigned int page_order,
+                            mfn_t smfn,
+                            p2m_type_t p2mt,
+                            p2m_access_t p2ma);
+
 #endif /* __ASM_ARM_ALTP2M_H */
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 31/38] altp2m: Introduce altp2m_switch_vcpu_altp2m_by_id
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (29 preceding siblings ...)
  2016-08-16 22:17 ` [PATCH v3 30/38] arm/p2m: Add altp2m_propagate_change Sergej Proskurin
@ 2016-08-16 22:17 ` Sergej Proskurin
  2016-08-17 10:05   ` Jan Beulich
                     ` (2 more replies)
  2016-08-16 22:17 ` [PATCH v3 32/38] arm/p2m: Code movement in instr/data abort handlers Sergej Proskurin
                   ` (6 subsequent siblings)
  37 siblings, 3 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:17 UTC (permalink / raw)
  To: xen-devel
  Cc: Stefano Stabellini, Razvan Cojocaru, George Dunlap,
	Sergej Proskurin, Julien Grall, Tamas K Lengyel, Jan Beulich,
	Andrew Cooper

This commit adds the function "altp2m_switch_vcpu_altp2m_by_id" that is
executed after checking whether the vcpu should be switched to a
different altp2m within the function "altp2m_check".

Please note that in this commit, the function "p2m_altp2m_check" is
renamed to "altp2m_check" and moved from p2m.c to altp2m.c for the x86
architecuture. This change was perfomed in order to move altp2m related
functions to one spot (which is altp2m.c). The reason for modifying the
function's name is due the association of the function with the
associated .c file.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
Cc: George Dunlap <george.dunlap@eu.citrix.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: Razvan Cojocaru <rcojocaru@bitdefender.com>
Cc: Tamas K Lengyel <tamas@tklengyel.com>
---
v3: This commit has been moved out of the commit "arm/p2m: Add altp2m
    paging mechanism".

    Moved the function "p2m_altp2m_check" from p2m.c to altp2m.c and
    renamed it to "altp2m_check". This change required the adoption of
    the complementary function in the x86 architecture.
---
 xen/arch/arm/altp2m.c        | 32 ++++++++++++++++++++++++++++++++
 xen/arch/x86/mm/altp2m.c     |  6 ++++++
 xen/arch/x86/mm/p2m.c        |  6 ------
 xen/common/vm_event.c        |  3 ++-
 xen/include/asm-arm/altp2m.h |  7 ++++---
 xen/include/asm-arm/p2m.h    |  6 ------
 xen/include/asm-x86/altp2m.h |  3 +++
 xen/include/asm-x86/p2m.h    |  3 ---
 8 files changed, 47 insertions(+), 19 deletions(-)

diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
index b10711e..11272e9 100644
--- a/xen/arch/arm/altp2m.c
+++ b/xen/arch/arm/altp2m.c
@@ -32,6 +32,38 @@ struct p2m_domain *altp2m_get_altp2m(struct vcpu *v)
     return v->domain->arch.altp2m_p2m[index];
 }
 
+static bool_t altp2m_switch_vcpu_altp2m_by_id(struct vcpu *v, unsigned int idx)
+{
+    struct domain *d = v->domain;
+    bool_t rc = false;
+
+    if ( idx >= MAX_ALTP2M )
+        return rc;
+
+    altp2m_lock(d);
+
+    if ( d->arch.altp2m_p2m[idx] != NULL )
+    {
+        if ( idx != altp2m_vcpu(v).p2midx )
+        {
+            atomic_dec(&altp2m_get_altp2m(v)->active_vcpus);
+            altp2m_vcpu(v).p2midx = idx;
+            atomic_inc(&altp2m_get_altp2m(v)->active_vcpus);
+        }
+        rc = true;
+    }
+
+    altp2m_unlock(d);
+
+    return rc;
+}
+
+void altp2m_check(struct vcpu *v, uint16_t idx)
+{
+    if ( altp2m_active(v->domain) )
+        altp2m_switch_vcpu_altp2m_by_id(v, idx);
+}
+
 int altp2m_switch_domain_altp2m_by_id(struct domain *d, unsigned int idx)
 {
     struct vcpu *v;
diff --git a/xen/arch/x86/mm/altp2m.c b/xen/arch/x86/mm/altp2m.c
index 930bdc2..00abb5a 100644
--- a/xen/arch/x86/mm/altp2m.c
+++ b/xen/arch/x86/mm/altp2m.c
@@ -65,6 +65,12 @@ altp2m_vcpu_destroy(struct vcpu *v)
         vcpu_unpause(v);
 }
 
+void altp2m_check(struct vcpu *v, uint16_t idx)
+{
+    if ( altp2m_active(v->domain) )
+        p2m_switch_vcpu_altp2m_by_id(v, idx);
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index 812dbf6..cb28cc2 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -1646,12 +1646,6 @@ void p2m_mem_access_emulate_check(struct vcpu *v,
     }
 }
 
-void p2m_altp2m_check(struct vcpu *v, uint16_t idx)
-{
-    if ( altp2m_active(v->domain) )
-        p2m_switch_vcpu_altp2m_by_id(v, idx);
-}
-
 bool_t p2m_mem_access_check(paddr_t gpa, unsigned long gla,
                             struct npfec npfec,
                             vm_event_request_t **req_ptr)
diff --git a/xen/common/vm_event.c b/xen/common/vm_event.c
index 8398af7..e48d111 100644
--- a/xen/common/vm_event.c
+++ b/xen/common/vm_event.c
@@ -29,6 +29,7 @@
 #include <asm/monitor.h>
 #include <asm/vm_event.h>
 #include <xsm/xsm.h>
+#include <asm/altp2m.h>
 
 /* for public/io/ring.h macros */
 #define xen_mb()   mb()
@@ -423,7 +424,7 @@ void vm_event_resume(struct domain *d, struct vm_event_domain *ved)
 
         /* Check for altp2m switch */
         if ( rsp.flags & VM_EVENT_FLAG_ALTERNATE_P2M )
-            p2m_altp2m_check(v, rsp.altp2m_idx);
+            altp2m_check(v, rsp.altp2m_idx);
 
         /* Check flags which apply only when the vCPU is paused */
         if ( atomic_read(&v->vm_event_pause_count) )
diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
index 7f385d9..ef80829 100644
--- a/xen/include/asm-arm/altp2m.h
+++ b/xen/include/asm-arm/altp2m.h
@@ -38,9 +38,7 @@ static inline bool_t altp2m_active(const struct domain *d)
 /* Alternate p2m VCPU */
 static inline uint16_t altp2m_vcpu_idx(const struct vcpu *v)
 {
-    /* Not implemented on ARM, should not be reached. */
-    BUG();
-    return 0;
+    return altp2m_vcpu(v).p2midx;
 }
 
 int altp2m_init(struct domain *d);
@@ -52,6 +50,9 @@ void altp2m_vcpu_destroy(struct vcpu *v);
 /* Get current alternate p2m table. */
 struct p2m_domain *altp2m_get_altp2m(struct vcpu *v);
 
+/* Check to see if vcpu should be switched to a different p2m. */
+void altp2m_check(struct vcpu *v, uint16_t idx);
+
 /* Switch alternate p2m for entire domain */
 int altp2m_switch_domain_altp2m_by_id(struct domain *d,
                                       unsigned int idx);
diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
index 384ef3b..b01baec 100644
--- a/xen/include/asm-arm/p2m.h
+++ b/xen/include/asm-arm/p2m.h
@@ -161,12 +161,6 @@ void p2m_mem_access_emulate_check(struct vcpu *v,
     /* Not supported on ARM. */
 }
 
-static inline
-void p2m_altp2m_check(struct vcpu *v, uint16_t idx)
-{
-    /* Not supported on ARM. */
-}
-
 /* Initialise vmid allocator */
 void p2m_vmid_allocator_init(void);
 
diff --git a/xen/include/asm-x86/altp2m.h b/xen/include/asm-x86/altp2m.h
index 64c7618..67d0205 100644
--- a/xen/include/asm-x86/altp2m.h
+++ b/xen/include/asm-x86/altp2m.h
@@ -38,4 +38,7 @@ static inline uint16_t altp2m_vcpu_idx(const struct vcpu *v)
     return vcpu_altp2m(v).p2midx;
 }
 
+/* Check to see if vcpu should be switched to a different p2m. */
+void altp2m_check(struct vcpu *v, uint16_t idx);
+
 #endif /* __ASM_X86_ALTP2M_H */
diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
index d5fd546..438c676 100644
--- a/xen/include/asm-x86/p2m.h
+++ b/xen/include/asm-x86/p2m.h
@@ -787,9 +787,6 @@ unsigned int p2m_find_altp2m_by_eptp(struct domain *d, uint64_t eptp);
 /* Switch alternate p2m for a single vcpu */
 bool_t p2m_switch_vcpu_altp2m_by_id(struct vcpu *v, unsigned int idx);
 
-/* Check to see if vcpu should be switched to a different p2m. */
-void p2m_altp2m_check(struct vcpu *v, uint16_t idx);
-
 /* Flush all the alternate p2m's for a domain */
 void p2m_flush_altp2m(struct domain *d);
 
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 32/38] arm/p2m: Code movement in instr/data abort handlers
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (30 preceding siblings ...)
  2016-08-16 22:17 ` [PATCH v3 31/38] altp2m: Introduce altp2m_switch_vcpu_altp2m_by_id Sergej Proskurin
@ 2016-08-16 22:17 ` Sergej Proskurin
  2016-09-12 13:54   ` Julien Grall
  2016-08-16 22:17 ` [PATCH v3 33/38] arm/p2m: Add altp2m paging mechanism Sergej Proskurin
                   ` (5 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:17 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

This commit moves code in the functions
"do_trap_data_(instr|abort)_guest" without changing the original
functionality. The code movement is limited to moving the struct npfec
out of the switch statements in both functions. This commit acts as a
basis for the following commit implementing the altp2m paging mechanism.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
 xen/arch/arm/traps.c | 30 +++++++++++++-----------------
 1 file changed, 13 insertions(+), 17 deletions(-)

diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index da56cc0..0bf1653 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -2406,6 +2406,12 @@ static void do_trap_instr_abort_guest(struct cpu_user_regs *regs,
     paddr_t gpa;
     mfn_t mfn;
 
+    const struct npfec npfec = {
+        .insn_fetch = 1,
+        .gla_valid = 1,
+        .kind = hsr.iabt.s1ptw ? npfec_kind_in_gpt : npfec_kind_with_gla
+    };
+
     if ( hpfar_is_valid(hsr.iabt.s1ptw, fsc) )
         gpa = get_faulting_ipa(gva);
     else
@@ -2431,20 +2437,12 @@ static void do_trap_instr_abort_guest(struct cpu_user_regs *regs,
     switch ( fsc )
     {
     case FSC_FLT_PERM:
-    {
-        const struct npfec npfec = {
-            .insn_fetch = 1,
-            .gla_valid = 1,
-            .kind = hsr.iabt.s1ptw ? npfec_kind_in_gpt : npfec_kind_with_gla
-        };
-
         rc = p2m_mem_access_check(gpa, gva, npfec);
 
         /* Trap was triggered by mem_access, work here is done */
         if ( !rc )
             return;
         break;
-    }
     case FSC_FLT_TRANS:
         /*
          * The PT walk may have failed because someone was playing
@@ -2500,6 +2498,13 @@ static void do_trap_data_abort_guest(struct cpu_user_regs *regs,
     uint8_t fsc = hsr.dabt.dfsc & ~FSC_LL_MASK;
     mfn_t mfn;
 
+    const struct npfec npfec = {
+        .read_access = !dabt.write,
+        .write_access = dabt.write,
+        .gla_valid = 1,
+        .kind = dabt.s1ptw ? npfec_kind_in_gpt : npfec_kind_with_gla
+    };
+
     info.dabt = dabt;
 #ifdef CONFIG_ARM_32
     info.gva = READ_CP32(HDFAR);
@@ -2524,21 +2529,12 @@ static void do_trap_data_abort_guest(struct cpu_user_regs *regs,
     switch ( fsc )
     {
     case FSC_FLT_PERM:
-    {
-        const struct npfec npfec = {
-            .read_access = !dabt.write,
-            .write_access = dabt.write,
-            .gla_valid = 1,
-            .kind = dabt.s1ptw ? npfec_kind_in_gpt : npfec_kind_with_gla
-        };
-
         rc = p2m_mem_access_check(info.gpa, info.gva, npfec);
 
         /* Trap was triggered by mem_access, work here is done */
         if ( !rc )
             return;
         break;
-    }
     case FSC_FLT_TRANS:
         /*
          * Attempt first to emulate the MMIO has the data abort will
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 33/38] arm/p2m: Add altp2m paging mechanism
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (31 preceding siblings ...)
  2016-08-16 22:17 ` [PATCH v3 32/38] arm/p2m: Code movement in instr/data abort handlers Sergej Proskurin
@ 2016-08-16 22:17 ` Sergej Proskurin
  2016-09-12 14:18   ` Julien Grall
  2016-08-16 22:17 ` [PATCH v3 34/38] arm/p2m: Add HVMOP_altp2m_change_gfn Sergej Proskurin
                   ` (4 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:17 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

This commit adds the function "altp2m_lazy_copy" implementing the altp2m
paging mechanism. The function "altp2m_lazy_copy" lazily copies the
hostp2m's mapping into the currently active altp2m view on 2nd stage
translation faults on instruction or data access.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v3: Cosmetic fixes.

    Locked hostp2m in the function "altp2m_lazy_copy" to avoid a mapping
    being changed in hostp2m before it has been inserted into the
    valtp2m view.

    Removed unnecessary calls to "p2m_mem_access_check" in the functions
    "do_trap_instr_abort_guest" and "do_trap_data_abort_guest" after a
    translation fault has been handled by the function
    "altp2m_lazy_copy".

    Adapted "altp2m_lazy_copy" to return the value "true" if the
    encountered translation fault encounters a valid entry inside of the
    currently active altp2m view. If multiple vcpu's are using the same
    altp2m, it is likely that both generate a translation fault, whereas
    the first one will be already handled by "altp2m_lazy_copy". With
    this change the 2nd vcpu will retry accessing the faulting address.

    Changed order of altp2m checking and MMIO emulation within the
    function "do_trap_data_abort_guest".  Now, altp2m is checked and
    handled only if the MMIO does not have to be emulated.

    Changed the function prototype of "altp2m_lazy_copy".  This commit
    removes the unnecessary struct p2m_domain* from the previous
    function prototype.  Also, this commit removes the unnecessary
    argument gva.  Finally, this commit changes the address of the
    function parameter gpa from paddr_t to gfn_t and renames it to gfn.

    Moved the altp2m handling mechanism into a separate function
    "try_handle_altp2m".

    Moved the functions "p2m_altp2m_check" and
    "altp2m_switch_vcpu_altp2m_by_id" out of this patch.

    Moved applied code movement into a separate patch.
---
 xen/arch/arm/altp2m.c        | 62 ++++++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/traps.c         | 35 +++++++++++++++++++++++++
 xen/include/asm-arm/altp2m.h |  5 ++++
 3 files changed, 102 insertions(+)

diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
index 11272e9..2009bad 100644
--- a/xen/arch/arm/altp2m.c
+++ b/xen/arch/arm/altp2m.c
@@ -165,6 +165,68 @@ out:
     return rc;
 }
 
+/*
+ * The function altp2m_lazy_copy returns "false" on error.  The return value
+ * "true" signals that either the mapping has been successfully lazy-copied
+ * from the hostp2m to the currently active altp2m view or that the altp2m view
+ * holds already a valid mapping. The latter is the case if multiple vcpu's
+ * using the same altp2m view generate a translation fault that is led back in
+ * both cases to the same mapping and the first fault has been already handled.
+ */
+bool_t altp2m_lazy_copy(struct vcpu *v,
+                        gfn_t gfn,
+                        struct npfec npfec)
+{
+    struct domain *d = v->domain;
+    struct p2m_domain *hp2m = p2m_get_hostp2m(d), *ap2m = NULL;
+    p2m_type_t p2mt;
+    p2m_access_t p2ma;
+    mfn_t mfn;
+    unsigned int page_order;
+    int rc;
+
+    ap2m = altp2m_get_altp2m(v);
+    if ( ap2m == NULL)
+        return false;
+
+    /* Check if entry is part of the altp2m view. */
+    mfn = p2m_lookup_attr(ap2m, gfn, NULL, NULL, NULL);
+    if ( !mfn_eq(mfn, INVALID_MFN) )
+        /*
+         * If multiple vcpu's are using the same altp2m, it is likely that both
+         * generate a translation fault, whereas the first one will be handled
+         * successfully and the second will encounter a valid mapping that has
+         * already been added as a result of the previous translation fault.
+         * In this case, the 2nd vcpu need to retry accessing the faulting
+         * address.
+         */
+        return true;
+
+    /*
+     * Lock hp2m to prevent the hostp2m to change a mapping before it is added
+     * to the altp2m view.
+     */
+    p2m_read_lock(hp2m);
+
+    /* Check if entry is part of the host p2m view. */
+    mfn = p2m_lookup_attr(hp2m, gfn, &p2mt, &p2ma, &page_order);
+    if ( mfn_eq(mfn, INVALID_MFN) )
+        goto out;
+
+    rc = modify_altp2m_entry(ap2m, gfn, mfn, p2mt, p2ma, page_order);
+    if ( rc )
+    {
+        gdprintk(XENLOG_ERR, "altp2m[%d] failed to set entry for %#"PRI_gfn" -> %#"PRI_mfn"\n",
+                 altp2m_vcpu(v).p2midx, gfn_x(gfn), mfn_x(mfn));
+        domain_crash(hp2m->domain);
+    }
+
+out:
+    p2m_read_unlock(hp2m);
+
+    return true;
+}
+
 static inline void altp2m_reset(struct p2m_domain *p2m)
 {
     p2m_write_lock(p2m);
diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index 0bf1653..a4c923c 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -48,6 +48,8 @@
 #include <asm/vgic.h>
 #include <asm/cpuerrata.h>
 
+#include <asm/altp2m.h>
+
 /* The base of the stack must always be double-word aligned, which means
  * that both the kernel half of struct cpu_user_regs (which is pushed in
  * entry.S) and struct cpu_info (which lives at the bottom of a Xen
@@ -2397,6 +2399,24 @@ static inline bool hpfar_is_valid(bool s1ptw, uint8_t fsc)
     return s1ptw || (fsc == FSC_FLT_TRANS && !check_workaround_834220());
 }
 
+static bool_t try_handle_altp2m(struct vcpu *v,
+                                paddr_t gpa,
+                                struct npfec npfec)
+{
+    bool_t rc = false;
+
+    if ( altp2m_active(v->domain) )
+        /*
+         * Copy the mapping of the faulting address into the currently
+         * active altp2m view. Return true on success or if the particular
+         * mapping has already been lazily copied to the currently active
+         * altp2m view by another vcpu. Return false otherwise.
+         */
+        rc = altp2m_lazy_copy(v, _gfn(paddr_to_pfn(gpa)), npfec);
+
+    return rc;
+}
+
 static void do_trap_instr_abort_guest(struct cpu_user_regs *regs,
                                       const union hsr hsr)
 {
@@ -2445,6 +2465,14 @@ static void do_trap_instr_abort_guest(struct cpu_user_regs *regs,
         break;
     case FSC_FLT_TRANS:
         /*
+         * The guest shall retry accessing the page if the altp2m handler
+         * succeeds. Otherwise, we continue injecting an instruction abort
+         * exception.
+         */
+        if ( try_handle_altp2m(current, gpa, npfec) )
+            return;
+
+        /*
          * The PT walk may have failed because someone was playing
          * with the Stage-2 page table. Walk the Stage-2 PT to check
          * if the entry exists. If it's the case, return to the guest
@@ -2547,6 +2575,13 @@ static void do_trap_data_abort_guest(struct cpu_user_regs *regs,
         }
 
         /*
+         * The guest shall retry accessing the page if the altp2m handler
+         * succeeds. Otherwise, we continue injecting a data abort exception.
+         */
+        if ( try_handle_altp2m(current, info.gpa, npfec) )
+            return;
+
+        /*
          * The PT walk may have failed because someone was playing
          * with the Stage-2 page table. Walk the Stage-2 PT to check
          * if the entry exists. If it's the case, return to the guest
diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
index ef80829..8e40c45 100644
--- a/xen/include/asm-arm/altp2m.h
+++ b/xen/include/asm-arm/altp2m.h
@@ -84,6 +84,11 @@ int altp2m_set_mem_access(struct domain *d,
                           p2m_access_t a,
                           gfn_t gfn);
 
+/* Alternate p2m paging mechanism. */
+bool_t altp2m_lazy_copy(struct vcpu *v,
+                        gfn_t gfn,
+                        struct npfec npfec);
+
 /* Propagates changes made to hostp2m to affected altp2m views. */
 int altp2m_propagate_change(struct domain *d,
                             gfn_t sgfn,
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 34/38] arm/p2m: Add HVMOP_altp2m_change_gfn
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (32 preceding siblings ...)
  2016-08-16 22:17 ` [PATCH v3 33/38] arm/p2m: Add altp2m paging mechanism Sergej Proskurin
@ 2016-08-16 22:17 ` Sergej Proskurin
  2016-09-12 14:27   ` Julien Grall
  2016-08-16 22:17 ` [PATCH v3 35/38] arm/p2m: Adjust debug information to altp2m Sergej Proskurin
                   ` (3 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:17 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

This commit adds the functionality to change mfn mappings for specified
gfn's in altp2m views. This mechanism can be used within the context of
VMI, e.g., to establish stealthy debugging.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v3: Moved the altp2m_lock to guard access to d->arch.altp2m_vttbr[idx]
    in altp2m_change_gfn.

    Locked hp2m to prevent hp2m entries from being modified while the
    function "altp2m_change_gfn" is active.

    Removed setting ap2m->mem_access_enabled in "altp2m_change_gfn", as
    we do not need explicitly splitting pages at this point.

    Extended checks allowing to change gfn's in p2m_ram_(rw|ro) memory
    only.

    Moved the funtion "remove_altp2m_entry" out of this commit.
---
 xen/arch/arm/altp2m.c        | 98 ++++++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/hvm.c           |  7 +++-
 xen/include/asm-arm/altp2m.h |  6 +++
 3 files changed, 110 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
index 2009bad..fa8d526 100644
--- a/xen/arch/arm/altp2m.c
+++ b/xen/arch/arm/altp2m.c
@@ -301,6 +301,104 @@ out:
     return rc;
 }
 
+int altp2m_change_gfn(struct domain *d,
+                      unsigned int idx,
+                      gfn_t old_gfn,
+                      gfn_t new_gfn)
+{
+    struct p2m_domain *hp2m, *ap2m;
+    mfn_t mfn;
+    p2m_access_t p2ma;
+    p2m_type_t p2mt;
+    unsigned int page_order;
+    int rc = -EINVAL;
+
+    hp2m = p2m_get_hostp2m(d);
+    ap2m = d->arch.altp2m_p2m[idx];
+
+    altp2m_lock(d);
+    p2m_read_lock(hp2m);
+
+    if ( idx >= MAX_ALTP2M || d->arch.altp2m_p2m[idx] == NULL )
+        goto out;
+
+    mfn = p2m_lookup_attr(ap2m, old_gfn, &p2mt, NULL, &page_order);
+
+    /* Check whether the page needs to be reset. */
+    if ( gfn_eq(new_gfn, INVALID_GFN) )
+    {
+        /* If mfn is mapped by old_gfn, remove old_gfn from the altp2m table. */
+        if ( !mfn_eq(mfn, INVALID_MFN) )
+        {
+            rc = remove_altp2m_entry(ap2m, old_gfn, mfn, page_order);
+            if ( rc )
+            {
+                rc = -EINVAL;
+                goto out;
+            }
+        }
+
+        rc = 0;
+        goto out;
+    }
+
+    /* Check hostp2m if no valid entry in altp2m present. */
+    if ( mfn_eq(mfn, INVALID_MFN) )
+    {
+        mfn = p2m_lookup_attr(hp2m, old_gfn, &p2mt, &p2ma, &page_order);
+        if ( mfn_eq(mfn, INVALID_MFN) ||
+             /* Allow changing gfn's in p2m_ram_(rw|ro) memory only. */
+             ((p2mt != p2m_ram_rw) && (p2mt != p2m_ram_ro)) )
+        {
+            rc = -EINVAL;
+            goto out;
+        }
+
+        /* If this is a superpage, copy that first. */
+        if ( page_order != THIRD_ORDER )
+        {
+            rc = modify_altp2m_entry(ap2m, old_gfn, mfn, p2mt, p2ma, page_order);
+            if ( rc )
+            {
+                rc = -EINVAL;
+                goto out;
+            }
+        }
+    }
+
+    mfn = p2m_lookup_attr(ap2m, new_gfn, &p2mt, &p2ma, &page_order);
+
+    /* If new_gfn is not part of altp2m, get the mapping information from hp2m */
+    if ( mfn_eq(mfn, INVALID_MFN) )
+        mfn = p2m_lookup_attr(hp2m, new_gfn, &p2mt, &p2ma, &page_order);
+
+    if ( mfn_eq(mfn, INVALID_MFN) ||
+         /* Allow changing gfn's in p2m_ram_(rw|ro) memory only. */
+         ((p2mt != p2m_ram_rw) && (p2mt != p2m_ram_ro)) )
+    {
+        rc = -EINVAL;
+        goto out;
+    }
+
+    /* Set mem access attributes - currently supporting only one (4K) page. */
+    page_order = THIRD_ORDER;
+    rc = modify_altp2m_entry(ap2m, old_gfn, mfn, p2mt, p2ma, page_order);
+    if ( rc )
+    {
+        rc = -EINVAL;
+        goto out;
+    }
+
+    rc = 0;
+
+out:
+    p2m_read_unlock(hp2m);
+    altp2m_unlock(d);
+
+    return rc;
+}
+
+
 static void altp2m_vcpu_reset(struct vcpu *v)
 {
     struct altp2mvcpu *av = &altp2m_vcpu(v);
diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
index df78893..c754ad1 100644
--- a/xen/arch/arm/hvm.c
+++ b/xen/arch/arm/hvm.c
@@ -145,7 +145,12 @@ static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
         break;
 
     case HVMOP_altp2m_change_gfn:
-        rc = -EOPNOTSUPP;
+        if ( a.u.change_gfn.pad1 || a.u.change_gfn.pad2 )
+            rc = -EINVAL;
+        else
+            rc = altp2m_change_gfn(d, a.u.change_gfn.view,
+                                   _gfn(a.u.change_gfn.old_gfn),
+                                   _gfn(a.u.change_gfn.new_gfn));
         break;
     }
 
diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
index 8e40c45..8b459bf 100644
--- a/xen/include/asm-arm/altp2m.h
+++ b/xen/include/asm-arm/altp2m.h
@@ -97,4 +97,10 @@ int altp2m_propagate_change(struct domain *d,
                             p2m_type_t p2mt,
                             p2m_access_t p2ma);
 
+/* Change a gfn->mfn mapping */
+int altp2m_change_gfn(struct domain *d,
+                      unsigned int idx,
+                      gfn_t old_gfn,
+                      gfn_t new_gfn);
+
 #endif /* __ASM_ARM_ALTP2M_H */
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 35/38] arm/p2m: Adjust debug information to altp2m
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (33 preceding siblings ...)
  2016-08-16 22:17 ` [PATCH v3 34/38] arm/p2m: Add HVMOP_altp2m_change_gfn Sergej Proskurin
@ 2016-08-16 22:17 ` Sergej Proskurin
  2016-09-12 14:29   ` Julien Grall
  2016-08-16 22:17 ` [PATCH v3 36/38] altp2m: Allow specifying external-only use-case Sergej Proskurin
                   ` (2 subsequent siblings)
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:17 UTC (permalink / raw)
  To: xen-devel; +Cc: Sergej Proskurin, Julien Grall, Stefano Stabellini

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
v2: Dump p2m information of the hostp2m and all altp2m views.
---
 xen/arch/arm/p2m.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index dea3038..86e2a1d 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -162,6 +162,26 @@ void dump_p2m_lookup(struct domain *d, paddr_t addr)
 
     dump_pt_walk(page_to_maddr(p2m->root), addr,
                  P2M_ROOT_LEVEL, P2M_ROOT_PAGES);
+    printk("\n");
+
+    if ( altp2m_active(d) )
+    {
+        unsigned int i;
+
+        for ( i = 0; i < MAX_ALTP2M; i++ )
+        {
+            if ( d->arch.altp2m_p2m[i] == NULL )
+                continue;
+
+            p2m = d->arch.altp2m_p2m[i];
+
+            printk("AP2M[%d] @ %p mfn:0x%lx\n",
+                    i, p2m->root, page_to_mfn(p2m->root));
+
+            dump_pt_walk(page_to_maddr(p2m->root), addr, P2M_ROOT_LEVEL, P2M_ROOT_PAGES);
+            printk("\n");
+        }
+    }
 }
 
 void p2m_save_state(struct vcpu *p)
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 36/38] altp2m: Allow specifying external-only use-case
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (34 preceding siblings ...)
  2016-08-16 22:17 ` [PATCH v3 35/38] arm/p2m: Adjust debug information to altp2m Sergej Proskurin
@ 2016-08-16 22:17 ` Sergej Proskurin
  2016-08-17 10:08   ` Jan Beulich
                     ` (2 more replies)
  2016-08-16 22:17 ` [PATCH v3 37/38] arm/p2m: Extend xen-access for altp2m on ARM Sergej Proskurin
  2016-08-16 22:17 ` [PATCH v3 38/38] arm/p2m: Add test of xc_altp2m_change_gfn Sergej Proskurin
  37 siblings, 3 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:17 UTC (permalink / raw)
  To: xen-devel
  Cc: Wei Liu, Tamas K Lengyel, Ian Jackson, Sergej Proskurin,
	Jan Beulich, Andrew Cooper, Daniel De Graaf

From: Tamas K Lengyel <tamas.lengyel@zentific.com>

Currently setting altp2mhvm=1 in the domain configuration allows access to the
altp2m interface for both in-guest and external privileged tools. This poses
a problem for use-cases where only external access should be allowed, requiring
the user to compile Xen with XSM enabled to be able to appropriately restrict
access.

In this patch we deprecate the altp2mhvm domain configuration option and
introduce the altp2m option, which allows specifying if by default the altp2m
interface should be external-only. The information is stored in
HVM_PARAM_ALTP2M which we now define with specific XEN_ALTP2M_* modes.
If external_only mode is selected, the XSM check is shifted to use XSM_DM_PRIV
type check, thus restricting access to the interface by the guest itself. Note
that we keep the default XSM policy untouched. Users of XSM who wish to enforce
external_only mode for altp2m can do so by adjusting their XSM policy directly,
as this domain config option does not override an active XSM policy.

Also, as part of this patch we adjust the hvmop handler to require
HVM_PARAM_ALTP2M to be of a type other then disabled for all ops. This has been
previously only required for get/set altp2m domain state, all other options
were gated on altp2m_enabled. Since altp2m_enabled only gets set during set
altp2m domain state, this change introduces no new requirements to the other
ops but makes it more clear that it is required for all ops.

Signed-off-by: Tamas K Lengyel <tamas.lengyel@zentific.com>
Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: Daniel De Graaf <dgdegra@tycho.nsa.gov>

v2: Rename HVMALTP2M_* to XEN_ALTP2M_*
    Relax xsm check to XSM_DM_PRIV for external-only mode

v3: Introduce macro LIBXL_HAVE_ARM_ALTP2M in parallel to the former
    LIBXL_HAVE_ALTP2M to differentiate between altp2m for x86 and and
    altp2m for ARM architectures.

    Document the option "altp2m" in ./docs/man/xl.cfg.pod.5.in.

    Maintain the legacy info->u.hvm.altp2m field for x86 HVM domains in
    parallel to the introduced info->altp2m field for x86 HVM and ARM
    domains.
---
 docs/man/xl.cfg.pod.5.in        | 37 ++++++++++++++++++++++++++++++++++++-
 tools/libxl/libxl.h             | 10 +++++++++-
 tools/libxl/libxl_create.c      |  7 +++++--
 tools/libxl/libxl_dom.c         | 30 ++++++++++++++++++++++++++++--
 tools/libxl/libxl_types.idl     | 13 +++++++++++++
 tools/libxl/xl_cmdimpl.c        | 25 ++++++++++++++++++++++++-
 xen/arch/arm/hvm.c              | 14 +++++++++++++-
 xen/arch/x86/hvm/hvm.c          | 20 ++++++++++----------
 xen/include/public/hvm/params.h | 10 +++++++++-
 xen/include/xsm/dummy.h         | 14 +++++++++++---
 xen/include/xsm/xsm.h           |  6 +++---
 xen/xsm/flask/hooks.c           |  2 +-
 12 files changed, 162 insertions(+), 26 deletions(-)

diff --git a/docs/man/xl.cfg.pod.5.in b/docs/man/xl.cfg.pod.5.in
index 48c9c0d..bf9a48a 100644
--- a/docs/man/xl.cfg.pod.5.in
+++ b/docs/man/xl.cfg.pod.5.in
@@ -1268,6 +1268,37 @@ enabled by default and you should usually omit it. It may be necessary
 to disable the HPET in order to improve compatibility with guest
 Operating Systems (X86 only)
 
+=item B<altp2m=MODE>
+
+Specifies access mode to the alternate-p2m capability. Alternate-p2m allows a
+guest to manage multiple p2m guest physical "memory views" (as opposed to a
+single p2m). This option is disabled by default and is available to x86 hvm and
+ARM domains. You may want this option if you want to access-control/isolate
+access to specific guest physical memory pages accessed by the guest, e.g. for
+domain memory introspection or for isolation/access-control of memory between
+components within a single guest domain.
+
+The valid values are as follows:
+
+=over 4
+
+=item B<"disabled">
+
+Altp2m is disabled for the domain (default).
+
+=item B<"mixed">
+
+The mixed mode allows access to the altp2m interface for both in-guest
+and external tools as well.
+
+=item B<"external_only">
+
+Enables access to the alternate-p2m capability for hvm guests only
+by external privileged tools. Note: if XSM is enabled then the XSM policy
+should be used to specify external-only access to the interface.
+
+=back
+
 =item B<altp2mhvm=BOOLEAN>
 
 Enables or disables hvm guest access to alternate-p2m capability.
@@ -1278,7 +1309,11 @@ You may want this option if you want to access-control/isolate
 access to specific guest physical memory pages accessed by
 the guest, e.g. for HVM domain memory introspection or
 for isolation/access-control of memory between components within
-a single guest hvm domain.
+a single guest hvm domain. This option is deprecated, use the option
+"altp2m" instead.
+
+Note: While the option "altp2mhvm" is deprecated, legacy applications for
+x86 systems will continue to work using it.
 
 =item B<nestedhvm=BOOLEAN>
 
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index ae21302..f78d63e 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -847,11 +847,19 @@ typedef struct libxl__ctx libxl_ctx;
 
 /*
  * LIBXL_HAVE_ALTP2M
- * If this is defined, then libxl supports alternate p2m functionality.
+ * If this is defined, then libxl supports alternate p2m functionality for
+ * x86 HVM guests.
  */
 #define LIBXL_HAVE_ALTP2M 1
 
 /*
+ * LIBXL_HAVE_ARM_ALTP2M
+ * If this is defined, then libxl supports alternate p2m functionality for
+ * ARM guests.
+ */
+#define LIBXL_HAVE_ARM_ALTP2M 1
+
+/*
  * LIBXL_HAVE_REMUS
  * If this is defined, then libxl supports remus.
  */
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 04f8ae9..21e32c9 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -406,6 +406,7 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc,
             libxl_domain_type_to_string(b_info->type));
         return ERROR_INVAL;
     }
+
     return 0;
 }
 
@@ -918,8 +919,10 @@ static void initiate_domain_create(libxl__egc *egc,
 
     if (d_config->c_info.type == LIBXL_DOMAIN_TYPE_HVM &&
         (libxl_defbool_val(d_config->b_info.u.hvm.nested_hvm) &&
-         libxl_defbool_val(d_config->b_info.u.hvm.altp2m))) {
-        LOG(ERROR, "nestedhvm and altp2mhvm cannot be used together");
+        /* Cannot combine nested_hvm with altp2m or altp2mhvm params. */
+        (libxl_defbool_val(d_config->b_info.u.hvm.altp2m) ||
+        (d_config->b_info.altp2m != LIBXL_ALTP2M_MODE_DISABLED)))) {
+        LOG(ERROR, "nestedhvm and altp2m cannot be used together");
         goto error_out;
     }
 
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index eef5045..32af757 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -291,8 +291,6 @@ static void hvm_set_conf_params(xc_interface *handle, uint32_t domid,
                     libxl_defbool_val(info->u.hvm.vpt_align));
     xc_hvm_param_set(handle, domid, HVM_PARAM_NESTEDHVM,
                     libxl_defbool_val(info->u.hvm.nested_hvm));
-    xc_hvm_param_set(handle, domid, HVM_PARAM_ALTP2M,
-                    libxl_defbool_val(info->u.hvm.altp2m));
 }
 
 int libxl__build_pre(libxl__gc *gc, uint32_t domid,
@@ -301,6 +299,7 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid,
     libxl_domain_build_info *const info = &d_config->b_info;
     libxl_ctx *ctx = libxl__gc_owner(gc);
     char *xs_domid, *con_domid;
+    bool altp2m_support = false;
     int rc;
 
     if (xc_domain_max_vcpus(ctx->xch, domid, info->max_vcpus) != 0) {
@@ -434,6 +433,33 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid,
 #endif
     }
 
+#if defined(__i386__) || defined(__x86_64__)
+    /* Alternate p2m support on x86 is available only for HVM guests. */
+    if (info->type == LIBXL_DOMAIN_TYPE_HVM)
+        altp2m_support = true;
+#elif defined(__arm__) || defined(__aarch64__)
+    /* Alternate p2m support on ARM is available for all guests. */
+    altp2m_support = true;
+#endif
+
+    if (altp2m_support) {
+        /* The config parameter "altp2m" replaces the parameter "altp2mhvm". For
+         * legacy reasons, both parameters are accepted on x86 HVM guests (only
+         * "altp2m" is accepted on ARM guests).
+         *
+         * If the legacy field info->u.hvm.altp2m is set, activate altp2m.
+         * Otherwise set altp2m based on the field info->altp2m. */
+#if defined(__i386__) || defined(__x86_64__)
+        if (info->altp2m == LIBXL_ALTP2M_MODE_DISABLED &&
+            libxl_defbool_val(info->u.hvm.altp2m))
+            xc_hvm_param_set(ctx->xch, domid, HVM_PARAM_ALTP2M,
+                             libxl_defbool_val(info->u.hvm.altp2m));
+        else
+#endif
+            xc_hvm_param_set(ctx->xch, domid, HVM_PARAM_ALTP2M,
+                             info->altp2m);
+    }
+
     rc = libxl__arch_domain_create(gc, d_config, domid);
 
     return rc;
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index ef614be..878d5ae 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -439,6 +439,13 @@ libxl_rdm_reserve = Struct("rdm_reserve", [
     ("policy",      libxl_rdm_reserve_policy),
     ])
 
+# Consistent with the values defined for HVM_PARAM_ALTP2M
+libxl_altp2m_mode = Enumeration("altp2m_mode", [
+    (0, "disabled"),
+    (1, "mixed"),
+    (2, "external_only"),
+    ], init_val = "LIBXL_ALTP2M_MODE_DISABLED")
+
 libxl_domain_build_info = Struct("domain_build_info",[
     ("max_vcpus",       integer),
     ("avail_vcpus",     libxl_bitmap),
@@ -512,6 +519,9 @@ libxl_domain_build_info = Struct("domain_build_info",[
                                        ("mmio_hole_memkb",  MemKB),
                                        ("timer_mode",       libxl_timer_mode),
                                        ("nested_hvm",       libxl_defbool),
+                                       # The u.hvm.altp2m field is used solely
+                                       # for x86 HVM guests and is maintained
+                                       # for legacy purposes.
                                        ("altp2m",           libxl_defbool),
                                        ("smbios_firmware",  string),
                                        ("acpi_firmware",    string),
@@ -561,6 +571,9 @@ libxl_domain_build_info = Struct("domain_build_info",[
 
     ("arch_arm", Struct(None, [("gic_version", libxl_gic_version),
                               ])),
+    # Alternate p2m is not bound to any architecture or guest type, as it is
+    # supported by x86 HVM and ARM domains.
+    ("altp2m", libxl_altp2m_mode),
 
     ], dir=DIR_IN
 )
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 7f961e3..15f4ab6 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -1667,7 +1667,14 @@ static void parse_config_data(const char *config_source,
 
         xlu_cfg_get_defbool(config, "nestedhvm", &b_info->u.hvm.nested_hvm, 0);
 
-        xlu_cfg_get_defbool(config, "altp2mhvm", &b_info->u.hvm.altp2m, 0);
+        /*
+         * The config parameter "altp2mhvm" is considered deprecated, however
+         * further considered because of legacy reasons. The config parameter
+         * "altp2m" shall be used instead.
+         */
+        if (!xlu_cfg_get_defbool(config, "altp2mhvm", &b_info->u.hvm.altp2m, 0))
+            fprintf(stderr, "WARNING: Specifying \"altp2mhvm\" is deprecated. "
+                    "Please use \"altp2m\" instead.\n");
 
         xlu_cfg_replace_string(config, "smbios_firmware",
                                &b_info->u.hvm.smbios_firmware, 0);
@@ -1727,6 +1734,22 @@ static void parse_config_data(const char *config_source,
         abort();
     }
 
+    if (!xlu_cfg_get_long(config, "altp2m", &l, 0)) {
+        if (l < LIBXL_ALTP2M_MODE_DISABLED ||
+            l > LIBXL_ALTP2M_MODE_EXTERNAL_ONLY) {
+            fprintf(stderr, "ERROR: invalid value %ld for \"altp2m\"\n", l);
+            exit (1);
+        }
+
+        b_info->altp2m = l;
+    } else if (!xlu_cfg_get_string(config, "altp2m", &buf, 0)) {
+        if (libxl_altp2m_mode_from_string(buf, &b_info->altp2m)) {
+            fprintf(stderr, "ERROR: invalid value \"%s\" for \"altp2m\"\n",
+                    buf);
+            exit (1);
+        }
+    }
+
     if (!xlu_cfg_get_list(config, "ioports", &ioports, &num_ioports, 0)) {
         b_info->num_ioports = num_ioports;
         b_info->ioports = calloc(num_ioports, sizeof(*b_info->ioports));
diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
index c754ad1..4018e9a 100644
--- a/xen/arch/arm/hvm.c
+++ b/xen/arch/arm/hvm.c
@@ -72,7 +72,8 @@ static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
         goto out;
     }
 
-    if ( (rc = xsm_hvm_altp2mhvm_op(XSM_TARGET, d)) )
+    if ( (rc = xsm_hvm_altp2mhvm_op(XSM_OTHER, d,
+                d->arch.hvm_domain.params[HVM_PARAM_ALTP2M])) )
         goto out;
 
     switch ( a.cmd )
@@ -232,6 +233,17 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
             if ( rc )
                 break;
 
+            switch ( a.index )
+            {
+            case HVM_PARAM_ALTP2M:
+                rc = xsm_hvm_param_altp2mhvm(XSM_PRIV, d);
+                if ( rc )
+                    break;
+                if ( a.value > XEN_ALTP2M_external_only )
+                    rc = -EINVAL;
+                break;
+            }
+
             d->arch.hvm_domain.params[a.index] = a.value;
             break;
 
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 0180f26..ce48f8a 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -5042,7 +5042,7 @@ static int hvmop_set_param(
         rc = xsm_hvm_param_altp2mhvm(XSM_PRIV, d);
         if ( rc )
             break;
-        if ( a.value > 1 )
+        if ( a.value > XEN_ALTP2M_external_only )
             rc = -EINVAL;
         if ( a.value &&
              d->arch.hvm_domain.params[HVM_PARAM_NESTEDHVM] )
@@ -5238,18 +5238,19 @@ static int do_altp2m_op(
         goto out;
     }
 
-    if ( (rc = xsm_hvm_altp2mhvm_op(XSM_TARGET, d)) )
+    if ( !d->arch.hvm_domain.params[HVM_PARAM_ALTP2M] )
+    {
+        rc = -EINVAL;
+        goto out;
+    }
+
+    if ( (rc = xsm_hvm_altp2mhvm_op(XSM_OTHER, d,
+                d->arch.hvm_domain.params[HVM_PARAM_ALTP2M])) )
         goto out;
 
     switch ( a.cmd )
     {
     case HVMOP_altp2m_get_domain_state:
-        if ( !d->arch.hvm_domain.params[HVM_PARAM_ALTP2M] )
-        {
-            rc = -EINVAL;
-            break;
-        }
-
         a.u.domain_state.state = altp2m_active(d);
         rc = __copy_to_guest(arg, &a, 1) ? -EFAULT : 0;
         break;
@@ -5259,8 +5260,7 @@ static int do_altp2m_op(
         struct vcpu *v;
         bool_t ostate;
 
-        if ( !d->arch.hvm_domain.params[HVM_PARAM_ALTP2M] ||
-             nestedhvm_enabled(d) )
+        if ( nestedhvm_enabled(d) )
         {
             rc = -EINVAL;
             break;
diff --git a/xen/include/public/hvm/params.h b/xen/include/public/hvm/params.h
index f7338a3..3ffc33b 100644
--- a/xen/include/public/hvm/params.h
+++ b/xen/include/public/hvm/params.h
@@ -225,8 +225,16 @@
 /* Location of the VM Generation ID in guest physical address space. */
 #define HVM_PARAM_VM_GENERATION_ID_ADDR 34
 
-/* Boolean: Enable altp2m */
+/*
+ * Set mode for altp2m:
+ *  disabled: don't activate altp2m (default)
+ *  mixed: allow access to altp2m for both in-guest and external tools
+ *  external_only: allow access to external privileged tools only
+ */
 #define HVM_PARAM_ALTP2M       35
+#define XEN_ALTP2M_disabled      0
+#define XEN_ALTP2M_mixed         1
+#define XEN_ALTP2M_external_only 2
 
 /*
  * Size of the x87 FPU FIP/FDP registers that the hypervisor needs to
diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
index 406cd18..a0f6b70 100644
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -554,10 +554,18 @@ static XSM_INLINE int xsm_hvm_param_altp2mhvm(XSM_DEFAULT_ARG struct domain *d)
     return xsm_default_action(action, current->domain, d);
 }
 
-static XSM_INLINE int xsm_hvm_altp2mhvm_op(XSM_DEFAULT_ARG struct domain *d)
+static XSM_INLINE int xsm_hvm_altp2mhvm_op(XSM_DEFAULT_ARG struct domain *d, int mode)
 {
-    XSM_ASSERT_ACTION(XSM_TARGET);
-    return xsm_default_action(action, current->domain, d);
+    XSM_ASSERT_ACTION(XSM_OTHER);
+    switch ( mode )
+    {
+    case XEN_ALTP2M_mixed:
+        return xsm_default_action(XSM_TARGET, current->domain, d);
+    case XEN_ALTP2M_external_only:
+        return xsm_default_action(XSM_DM_PRIV, current->domain, d);
+    default:
+        return -EPERM;
+    };
 }
 
 static XSM_INLINE int xsm_vm_event_control(XSM_DEFAULT_ARG struct domain *d, int mode, int op)
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index 5dc59dd..4f53b27 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -140,7 +140,7 @@ struct xsm_operations {
     int (*hvm_control) (struct domain *d, unsigned long op);
     int (*hvm_param_nested) (struct domain *d);
     int (*hvm_param_altp2mhvm) (struct domain *d);
-    int (*hvm_altp2mhvm_op) (struct domain *d);
+    int (*hvm_altp2mhvm_op) (struct domain *d, int mode);
     int (*get_vnumainfo) (struct domain *d);
 
     int (*vm_event_control) (struct domain *d, int mode, int op);
@@ -583,9 +583,9 @@ static inline int xsm_hvm_param_altp2mhvm (xsm_default_t def, struct domain *d)
     return xsm_ops->hvm_param_altp2mhvm(d);
 }
 
-static inline int xsm_hvm_altp2mhvm_op (xsm_default_t def, struct domain *d)
+static inline int xsm_hvm_altp2mhvm_op (xsm_default_t def, struct domain *d, int mode)
 {
-    return xsm_ops->hvm_altp2mhvm_op(d);
+    return xsm_ops->hvm_altp2mhvm_op(d, mode);
 }
 
 static inline int xsm_get_vnumainfo (xsm_default_t def, struct domain *d)
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index ec6f5b4..b97396e 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -1197,7 +1197,7 @@ static int flask_hvm_param_altp2mhvm(struct domain *d)
     return current_has_perm(d, SECCLASS_HVM, HVM__ALTP2MHVM);
 }
 
-static int flask_hvm_altp2mhvm_op(struct domain *d)
+static int flask_hvm_altp2mhvm_op(struct domain *d, int mode)
 {
     return current_has_perm(d, SECCLASS_HVM, HVM__ALTP2MHVM_OP);
 }
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 37/38] arm/p2m: Extend xen-access for altp2m on ARM
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (35 preceding siblings ...)
  2016-08-16 22:17 ` [PATCH v3 36/38] altp2m: Allow specifying external-only use-case Sergej Proskurin
@ 2016-08-16 22:17 ` Sergej Proskurin
  2016-08-17 11:26   ` Razvan Cojocaru
  2016-08-16 22:17 ` [PATCH v3 38/38] arm/p2m: Add test of xc_altp2m_change_gfn Sergej Proskurin
  37 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:17 UTC (permalink / raw)
  To: xen-devel
  Cc: Sergej Proskurin, Tamas K Lengyel, Ian Jackson, Wei Liu, Razvan Cojocaru

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
Acked-by: Razvan Cojocaru <rcojocaru@bitdefender.com>
---
Cc: Razvan Cojocaru <rcojocaru@bitdefender.com>
Cc: Tamas K Lengyel <tamas@tklengyel.com>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>
---
 tools/tests/xen-access/xen-access.c | 27 +++++++++++++++++----------
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/tools/tests/xen-access/xen-access.c b/tools/tests/xen-access/xen-access.c
index ebb63b1..eafd7d6 100644
--- a/tools/tests/xen-access/xen-access.c
+++ b/tools/tests/xen-access/xen-access.c
@@ -337,8 +337,9 @@ void usage(char* progname)
 {
     fprintf(stderr, "Usage: %s [-m] <domain_id> write|exec", progname);
 #if defined(__i386__) || defined(__x86_64__)
-            fprintf(stderr, "|breakpoint|altp2m_write|altp2m_exec|debug|cpuid");
+            fprintf(stderr, "|breakpoint|debug|cpuid");
 #endif
+            fprintf(stderr, "|altp2m_write|altp2m_exec");
             fprintf(stderr,
             "\n"
             "Logs first page writes, execs, or breakpoint traps that occur on the domain.\n"
@@ -411,6 +412,15 @@ int main(int argc, char *argv[])
     {
         breakpoint = 1;
     }
+    else if ( !strcmp(argv[0], "debug") )
+    {
+        debug = 1;
+    }
+    else if ( !strcmp(argv[0], "cpuid") )
+    {
+        cpuid = 1;
+    }
+#endif
     else if ( !strcmp(argv[0], "altp2m_write") )
     {
         default_access = XENMEM_access_rx;
@@ -423,15 +433,6 @@ int main(int argc, char *argv[])
         altp2m = 1;
         memaccess = 1;
     }
-    else if ( !strcmp(argv[0], "debug") )
-    {
-        debug = 1;
-    }
-    else if ( !strcmp(argv[0], "cpuid") )
-    {
-        cpuid = 1;
-    }
-#endif
     else
     {
         usage(argv[0]);
@@ -504,12 +505,14 @@ int main(int argc, char *argv[])
             goto exit;
         }
 
+#if defined(__i386__) || defined(__x86_64__)
         rc = xc_monitor_singlestep( xch, domain_id, 1 );
         if ( rc < 0 )
         {
             ERROR("Error %d failed to enable singlestep monitoring!\n", rc);
             goto exit;
         }
+#endif
     }
 
     if ( memaccess && !altp2m )
@@ -583,7 +586,9 @@ int main(int argc, char *argv[])
                 rc = xc_altp2m_switch_to_view( xch, domain_id, 0 );
                 rc = xc_altp2m_destroy_view(xch, domain_id, altp2m_view_id);
                 rc = xc_altp2m_set_domain_state(xch, domain_id, 0);
+#if defined(__i386__) || defined(__x86_64__)
                 rc = xc_monitor_singlestep(xch, domain_id, 0);
+#endif
             } else {
                 rc = xc_set_mem_access(xch, domain_id, XENMEM_access_rwx, ~0ull, 0);
                 rc = xc_set_mem_access(xch, domain_id, XENMEM_access_rwx, START_PFN,
@@ -773,9 +778,11 @@ int main(int argc, char *argv[])
 exit:
     if ( altp2m )
     {
+#if defined(__i386__) || defined(__x86_64__)
         uint32_t vcpu_id;
         for ( vcpu_id = 0; vcpu_id<XEN_LEGACY_MAX_VCPUS; vcpu_id++)
             rc = control_singlestep(xch, domain_id, vcpu_id, 0);
+#endif
     }
 
     /* Tear down domain xenaccess */
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* [PATCH v3 38/38] arm/p2m: Add test of xc_altp2m_change_gfn
  2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
                   ` (36 preceding siblings ...)
  2016-08-16 22:17 ` [PATCH v3 37/38] arm/p2m: Extend xen-access for altp2m on ARM Sergej Proskurin
@ 2016-08-16 22:17 ` Sergej Proskurin
  2016-08-17 12:06   ` Razvan Cojocaru
  2016-08-24 12:27   ` Wei Liu
  37 siblings, 2 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-16 22:17 UTC (permalink / raw)
  To: xen-devel
  Cc: Sergej Proskurin, Tamas K Lengyel, Ian Jackson, Wei Liu, Razvan Cojocaru

This commit extends xen-access by a simple test of the functionality
provided by "xc_altp2m_change_gfn". The idea is to dynamically remap a
trapping gfn to another mfn, which holds the same content as the
original mfn. On success, the guest will continue to run. Subsequent
altp2m access violations will trap into Xen and be forced by xen-access
to switch to the default view (altp2m[0]) as before. The introduced test
can be invoked by providing the argument "altp2m_remap".

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Razvan Cojocaru <rcojocaru@bitdefender.com>
Cc: Tamas K Lengyel <tamas@tklengyel.com>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>
---
v3: Cosmetic fixes in "xenaccess_copy_gfn" and "xenaccess_change_gfn".

    Added munmap in "copy_gfn" in the second error case.

    Added option "altp2m_remap" selecting the altp2m-remap test.
---
 tools/tests/xen-access/xen-access.c | 162 +++++++++++++++++++++++++++++++++++-
 1 file changed, 158 insertions(+), 4 deletions(-)

diff --git a/tools/tests/xen-access/xen-access.c b/tools/tests/xen-access/xen-access.c
index eafd7d6..5909a8a 100644
--- a/tools/tests/xen-access/xen-access.c
+++ b/tools/tests/xen-access/xen-access.c
@@ -38,6 +38,7 @@
 #include <sys/mman.h>
 #include <sys/poll.h>
 
+#define XC_WANT_COMPAT_MAP_FOREIGN_API
 #include <xenctrl.h>
 #include <xenevtchn.h>
 #include <xen/vm_event.h>
@@ -49,6 +50,8 @@
 #define START_PFN 0ULL
 #endif
 
+#define INVALID_GFN ~(0UL)
+
 #define DPRINTF(a, b...) fprintf(stderr, a, ## b)
 #define ERROR(a, b...) fprintf(stderr, a "\n", ## b)
 #define PERROR(a, b...) fprintf(stderr, a ": %s\n", ## b, strerror(errno))
@@ -72,9 +75,14 @@ typedef struct xenaccess {
     xen_pfn_t max_gpfn;
 
     vm_event_t vm_event;
+
+    unsigned int ap2m_idx;
+    xen_pfn_t gfn_old;
+    xen_pfn_t gfn_new;
 } xenaccess_t;
 
 static int interrupted;
+static int gfn_changed = 0;
 bool evtchn_bind = 0, evtchn_open = 0, mem_access_enable = 0;
 
 static void close_handler(int sig)
@@ -82,6 +90,100 @@ static void close_handler(int sig)
     interrupted = sig;
 }
 
+static int xenaccess_copy_gfn(xc_interface *xch,
+                              domid_t domain_id,
+                              xen_pfn_t dst_gfn,
+                              xen_pfn_t src_gfn)
+{
+    void *src_vaddr = NULL;
+    void *dst_vaddr = NULL;
+
+    src_vaddr = xc_map_foreign_range(xch, domain_id, XC_PAGE_SIZE,
+                                     PROT_READ, src_gfn);
+    if ( src_vaddr == MAP_FAILED || src_vaddr == NULL)
+        return -1;
+
+    dst_vaddr = xc_map_foreign_range(xch, domain_id, XC_PAGE_SIZE,
+                                     PROT_WRITE, dst_gfn);
+    if ( dst_vaddr == MAP_FAILED || dst_vaddr == NULL)
+    {
+        munmap(src_vaddr, XC_PAGE_SIZE);
+        return -1;
+    }
+
+    memcpy(dst_vaddr, src_vaddr, XC_PAGE_SIZE);
+
+    munmap(src_vaddr, XC_PAGE_SIZE);
+    munmap(dst_vaddr, XC_PAGE_SIZE);
+
+    return 0;
+}
+
+/*
+ * This function allocates and populates a page in the guest's physmap that is
+ * subsequently filled with contents of the trapping address. Finally, through
+ * the invocation of xc_altp2m_change_gfn, the altp2m subsystem changes the gfn
+ * to mfn mapping of the target altp2m view.
+ */
+static int xenaccess_change_gfn(xc_interface *xch,
+                                domid_t domain_id,
+                                unsigned int ap2m_idx,
+                                xen_pfn_t gfn_old,
+                                xen_pfn_t *gfn_new)
+{
+    int rc;
+
+    /*
+     * We perform this function only once as it is intended to be used for
+     * testing and demonstration purposes. Thus, we signalize that further
+     * altp2m-related traps will not change trapping gfn's.
+     */
+    gfn_changed = 1;
+
+    rc = xc_domain_increase_reservation_exact(xch, domain_id, 1, 0, 0, gfn_new);
+    if ( rc < 0 )
+        return -1;
+
+    rc = xc_domain_populate_physmap_exact(xch, domain_id, 1, 0, 0, gfn_new);
+    if ( rc < 0 )
+        goto err;
+
+    /* Copy content of the old gfn into the newly allocated gfn */
+    rc = xenaccess_copy_gfn(xch, domain_id, *gfn_new, gfn_old);
+    if ( rc < 0 )
+        goto err;
+
+    xc_altp2m_change_gfn(xch, domain_id, ap2m_idx, gfn_old, *gfn_new);
+
+    return 0;
+
+err:
+    xc_domain_decrease_reservation_exact(xch, domain_id, 1, 0, gfn_new);
+
+    return -1;
+}
+
+static int xenaccess_reset_gfn(xc_interface *xch,
+                               domid_t domain_id,
+                               unsigned int ap2m_idx,
+                               xen_pfn_t gfn_old,
+                               xen_pfn_t gfn_new)
+{
+    int rc;
+
+    /* Reset previous state */
+    xc_altp2m_change_gfn(xch, domain_id, ap2m_idx, gfn_old, INVALID_GFN);
+
+    /* Invalidate the new gfn */
+    xc_altp2m_change_gfn(xch, domain_id, ap2m_idx, gfn_new, INVALID_GFN);
+
+    rc = xc_domain_decrease_reservation_exact(xch, domain_id, 1, 0, &gfn_new);
+    if ( rc < 0 )
+        return -1;
+
+    return 0;
+}
+
 int xc_wait_for_event_or_timeout(xc_interface *xch, xenevtchn_handle *xce, unsigned long ms)
 {
     struct pollfd fd = { .fd = xenevtchn_fd(xce), .events = POLLIN | POLLERR };
@@ -227,6 +329,10 @@ xenaccess_t *xenaccess_init(xc_interface **xch_r, domid_t domain_id)
     }
     mem_access_enable = 1;
 
+    xenaccess->ap2m_idx = ~(0);
+    xenaccess->gfn_old = INVALID_GFN;
+    xenaccess->gfn_new = INVALID_GFN;
+
     /* Open event channel */
     xenaccess->vm_event.xce_handle = xenevtchn_open(NULL, 0);
     if ( xenaccess->vm_event.xce_handle == NULL )
@@ -339,7 +445,7 @@ void usage(char* progname)
 #if defined(__i386__) || defined(__x86_64__)
             fprintf(stderr, "|breakpoint|debug|cpuid");
 #endif
-            fprintf(stderr, "|altp2m_write|altp2m_exec");
+            fprintf(stderr, "|altp2m_write|altp2m_exec|altp2m_remap");
             fprintf(stderr,
             "\n"
             "Logs first page writes, execs, or breakpoint traps that occur on the domain.\n"
@@ -364,6 +470,7 @@ int main(int argc, char *argv[])
     int breakpoint = 0;
     int shutting_down = 0;
     int altp2m = 0;
+    int altp2m_remap = 0;
     int debug = 0;
     int cpuid = 0;
     uint16_t altp2m_view_id = 0;
@@ -433,6 +540,13 @@ int main(int argc, char *argv[])
         altp2m = 1;
         memaccess = 1;
     }
+    else if ( !strcmp(argv[0], "altp2m_remap") )
+    {
+        default_access = XENMEM_access_rw;
+        altp2m = 1;
+        altp2m_remap = 1;
+        memaccess = 1;
+    }
     else
     {
         usage(argv[0]);
@@ -589,6 +703,14 @@ int main(int argc, char *argv[])
 #if defined(__i386__) || defined(__x86_64__)
                 rc = xc_monitor_singlestep(xch, domain_id, 0);
 #endif
+
+                /* Reset remapped gfn. */
+                if ( altp2m_remap && xenaccess->gfn_new != INVALID_GFN )
+                    rc = xenaccess_reset_gfn(xenaccess->xc_handle,
+                                             xenaccess->vm_event.domain_id,
+                                             xenaccess->ap2m_idx,
+                                             xenaccess->gfn_old,
+                                             xenaccess->gfn_new);
             } else {
                 rc = xc_set_mem_access(xch, domain_id, XENMEM_access_rwx, ~0ull, 0);
                 rc = xc_set_mem_access(xch, domain_id, XENMEM_access_rwx, START_PFN,
@@ -662,10 +784,42 @@ int main(int argc, char *argv[])
 
                 if ( altp2m && req.flags & VM_EVENT_FLAG_ALTERNATE_P2M)
                 {
-                    DPRINTF("\tSwitching back to default view!\n");
-
                     rsp.flags |= (VM_EVENT_FLAG_ALTERNATE_P2M | VM_EVENT_FLAG_TOGGLE_SINGLESTEP);
-                    rsp.altp2m_idx = 0;
+
+                    if ( altp2m_remap )
+                    {
+                        if ( !gfn_changed )
+                        {
+                            /* Store trapping gfn and ap2m index for cleanup. */
+                            xenaccess->gfn_old = req.u.mem_access.gfn;
+                            xenaccess->ap2m_idx = req.altp2m_idx;
+
+                            /* Note that this function is called only once. */
+                            rc = xenaccess_change_gfn(xenaccess->xc_handle, domain_id, req.altp2m_idx,
+                                                      xenaccess->gfn_old, &xenaccess->gfn_new);
+                            if (rc < 0)
+                            {
+                                ERROR("Error remapping gfn=%"PRIx64"\n", xenaccess->gfn_old);
+                                interrupted = -1;
+                                continue;
+                            }
+
+                            /* Do not change the currently active altp2m view, yet. */
+                            rsp.altp2m_idx = req.altp2m_idx;
+                        }
+                        else
+                        {
+                            DPRINTF("\tSwitching back to default view!\n");
+
+                            rsp.altp2m_idx = 0;
+                        }
+                    }
+                    else
+                    {
+                        DPRINTF("\tSwitching back to default view!\n");
+
+                        rsp.altp2m_idx = 0;
+                    }
                 }
                 else if ( default_access != after_first_access )
                 {
-- 
2.9.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 31/38] altp2m: Introduce altp2m_switch_vcpu_altp2m_by_id
  2016-08-16 22:17 ` [PATCH v3 31/38] altp2m: Introduce altp2m_switch_vcpu_altp2m_by_id Sergej Proskurin
@ 2016-08-17 10:05   ` Jan Beulich
  2016-08-17 12:37     ` Sergej Proskurin
  2016-08-17 12:08   ` Razvan Cojocaru
  2016-08-18 10:35   ` George Dunlap
  2 siblings, 1 reply; 116+ messages in thread
From: Jan Beulich @ 2016-08-17 10:05 UTC (permalink / raw)
  To: Sergej Proskurin
  Cc: Stefano Stabellini, Razvan Cojocaru, George Dunlap,
	Andrew Cooper, Julien Grall, Tamas K Lengyel, xen-devel

>>> On 17.08.16 at 00:17, <proskurin@sec.in.tum.de> wrote:
>  xen/arch/arm/altp2m.c        | 32 ++++++++++++++++++++++++++++++++
>  xen/arch/x86/mm/altp2m.c     |  6 ++++++
>  xen/arch/x86/mm/p2m.c        |  6 ------
>  xen/common/vm_event.c        |  3 ++-
>  xen/include/asm-arm/altp2m.h |  7 ++++---
>  xen/include/asm-arm/p2m.h    |  6 ------
>  xen/include/asm-x86/altp2m.h |  3 +++
>  xen/include/asm-x86/p2m.h    |  3 ---
>  8 files changed, 47 insertions(+), 19 deletions(-)

The x86 parts of the change look really independent of the rest, so
you could have done yourself a favor by splitting this out, as then
the individual patches would each require separate acks rather than
the one patch here requiring an x86/mm one along with the ARM and
VM-event ones.

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 36/38] altp2m: Allow specifying external-only use-case
  2016-08-16 22:17 ` [PATCH v3 36/38] altp2m: Allow specifying external-only use-case Sergej Proskurin
@ 2016-08-17 10:08   ` Jan Beulich
  2016-08-17 14:47   ` Daniel De Graaf
  2016-08-24 12:18   ` Wei Liu
  2 siblings, 0 replies; 116+ messages in thread
From: Jan Beulich @ 2016-08-17 10:08 UTC (permalink / raw)
  To: Sergej Proskurin
  Cc: Wei Liu, Tamas K Lengyel, Ian Jackson, Andrew Cooper, xen-devel,
	Daniel De Graaf

>>> On 17.08.16 at 00:17, <proskurin@sec.in.tum.de> wrote:
> From: Tamas K Lengyel <tamas.lengyel@zentific.com>
> 
> Currently setting altp2mhvm=1 in the domain configuration allows access to the
> altp2m interface for both in-guest and external privileged tools. This poses
> a problem for use-cases where only external access should be allowed, requiring
> the user to compile Xen with XSM enabled to be able to appropriately restrict
> access.
> 
> In this patch we deprecate the altp2mhvm domain configuration option and
> introduce the altp2m option, which allows specifying if by default the altp2m
> interface should be external-only. The information is stored in
> HVM_PARAM_ALTP2M which we now define with specific XEN_ALTP2M_* modes.
> If external_only mode is selected, the XSM check is shifted to use XSM_DM_PRIV
> type check, thus restricting access to the interface by the guest itself. Note
> that we keep the default XSM policy untouched. Users of XSM who wish to enforce
> external_only mode for altp2m can do so by adjusting their XSM policy directly,
> as this domain config option does not override an active XSM policy.
> 
> Also, as part of this patch we adjust the hvmop handler to require
> HVM_PARAM_ALTP2M to be of a type other then disabled for all ops. This has been
> previously only required for get/set altp2m domain state, all other options
> were gated on altp2m_enabled. Since altp2m_enabled only gets set during set
> altp2m domain state, this change introduces no new requirements to the other
> ops but makes it more clear that it is required for all ops.
> 
> Signed-off-by: Tamas K Lengyel <tamas.lengyel@zentific.com>
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>

x86 and public header parts:
Acked-by: Jan Beulich <jbeulich@suse.com>


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 37/38] arm/p2m: Extend xen-access for altp2m on ARM
  2016-08-16 22:17 ` [PATCH v3 37/38] arm/p2m: Extend xen-access for altp2m on ARM Sergej Proskurin
@ 2016-08-17 11:26   ` Razvan Cojocaru
  0 siblings, 0 replies; 116+ messages in thread
From: Razvan Cojocaru @ 2016-08-17 11:26 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Wei Liu, Tamas K Lengyel, Ian Jackson

On 08/17/2016 01:17 AM, Sergej Proskurin wrote:
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
> Acked-by: Razvan Cojocaru <rcojocaru@bitdefender.com>
> ---
> Cc: Razvan Cojocaru <rcojocaru@bitdefender.com>
> Cc: Tamas K Lengyel <tamas@tklengyel.com>
> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> Cc: Wei Liu <wei.liu2@citrix.com>
> ---
>  tools/tests/xen-access/xen-access.c | 27 +++++++++++++++++----------
>  1 file changed, 17 insertions(+), 10 deletions(-)

Acked-by: Razvan Cojocaru <rcojocaru@bitdefender.com>


Thanks,
Razvan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 38/38] arm/p2m: Add test of xc_altp2m_change_gfn
  2016-08-16 22:17 ` [PATCH v3 38/38] arm/p2m: Add test of xc_altp2m_change_gfn Sergej Proskurin
@ 2016-08-17 12:06   ` Razvan Cojocaru
  2016-08-24 12:27   ` Wei Liu
  1 sibling, 0 replies; 116+ messages in thread
From: Razvan Cojocaru @ 2016-08-17 12:06 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Wei Liu, Tamas K Lengyel, Ian Jackson

On 08/17/2016 01:17 AM, Sergej Proskurin wrote:
> This commit extends xen-access by a simple test of the functionality
> provided by "xc_altp2m_change_gfn". The idea is to dynamically remap a
> trapping gfn to another mfn, which holds the same content as the
> original mfn. On success, the guest will continue to run. Subsequent
> altp2m access violations will trap into Xen and be forced by xen-access
> to switch to the default view (altp2m[0]) as before. The introduced test
> can be invoked by providing the argument "altp2m_remap".
> 
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
> ---
> Cc: Razvan Cojocaru <rcojocaru@bitdefender.com>
> Cc: Tamas K Lengyel <tamas@tklengyel.com>
> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> Cc: Wei Liu <wei.liu2@citrix.com>
> ---
> v3: Cosmetic fixes in "xenaccess_copy_gfn" and "xenaccess_change_gfn".
> 
>     Added munmap in "copy_gfn" in the second error case.
> 
>     Added option "altp2m_remap" selecting the altp2m-remap test.
> ---
>  tools/tests/xen-access/xen-access.c | 162 +++++++++++++++++++++++++++++++++++-
>  1 file changed, 158 insertions(+), 4 deletions(-)

Acked-by: Razvan Cojocaru <rcojocaru@bitdefender.com>


Thanks,
Razvan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 31/38] altp2m: Introduce altp2m_switch_vcpu_altp2m_by_id
  2016-08-16 22:17 ` [PATCH v3 31/38] altp2m: Introduce altp2m_switch_vcpu_altp2m_by_id Sergej Proskurin
  2016-08-17 10:05   ` Jan Beulich
@ 2016-08-17 12:08   ` Razvan Cojocaru
  2016-08-18 10:35   ` George Dunlap
  2 siblings, 0 replies; 116+ messages in thread
From: Razvan Cojocaru @ 2016-08-17 12:08 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel
  Cc: Stefano Stabellini, George Dunlap, Andrew Cooper, Julien Grall,
	Tamas K Lengyel, Jan Beulich

On 08/17/2016 01:17 AM, Sergej Proskurin wrote:
> This commit adds the function "altp2m_switch_vcpu_altp2m_by_id" that is
> executed after checking whether the vcpu should be switched to a
> different altp2m within the function "altp2m_check".
> 
> Please note that in this commit, the function "p2m_altp2m_check" is
> renamed to "altp2m_check" and moved from p2m.c to altp2m.c for the x86
> architecuture. This change was perfomed in order to move altp2m related
> functions to one spot (which is altp2m.c). The reason for modifying the
> function's name is due the association of the function with the
> associated .c file.
> 
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> Cc: George Dunlap <george.dunlap@eu.citrix.com>
> Cc: Jan Beulich <jbeulich@suse.com>
> Cc: Andrew Cooper <andrew.cooper3@citrix.com>
> Cc: Razvan Cojocaru <rcojocaru@bitdefender.com>
> Cc: Tamas K Lengyel <tamas@tklengyel.com>
> ---
> v3: This commit has been moved out of the commit "arm/p2m: Add altp2m
>     paging mechanism".
> 
>     Moved the function "p2m_altp2m_check" from p2m.c to altp2m.c and
>     renamed it to "altp2m_check". This change required the adoption of
>     the complementary function in the x86 architecture.
> ---
>  xen/arch/arm/altp2m.c        | 32 ++++++++++++++++++++++++++++++++
>  xen/arch/x86/mm/altp2m.c     |  6 ++++++
>  xen/arch/x86/mm/p2m.c        |  6 ------
>  xen/common/vm_event.c        |  3 ++-
>  xen/include/asm-arm/altp2m.h |  7 ++++---
>  xen/include/asm-arm/p2m.h    |  6 ------
>  xen/include/asm-x86/altp2m.h |  3 +++
>  xen/include/asm-x86/p2m.h    |  3 ---
>  8 files changed, 47 insertions(+), 19 deletions(-)

For the vm_event bits (there are only mechanical changes there):

Acked-by: Razvan Cojocaru <rcojocaru@bitdefender.com>


Thanks,
Razvan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 31/38] altp2m: Introduce altp2m_switch_vcpu_altp2m_by_id
  2016-08-17 10:05   ` Jan Beulich
@ 2016-08-17 12:37     ` Sergej Proskurin
  2016-08-17 12:48       ` Julien Grall
  0 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-08-17 12:37 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Stefano Stabellini, Razvan Cojocaru, George Dunlap,
	Andrew Cooper, Julien Grall, Tamas K Lengyel, xen-devel

Hi Jan,


On 08/17/2016 12:05 PM, Jan Beulich wrote:
>>>> On 17.08.16 at 00:17, <proskurin@sec.in.tum.de> wrote:
>>  xen/arch/arm/altp2m.c        | 32 ++++++++++++++++++++++++++++++++
>>  xen/arch/x86/mm/altp2m.c     |  6 ++++++
>>  xen/arch/x86/mm/p2m.c        |  6 ------
>>  xen/common/vm_event.c        |  3 ++-
>>  xen/include/asm-arm/altp2m.h |  7 ++++---
>>  xen/include/asm-arm/p2m.h    |  6 ------
>>  xen/include/asm-x86/altp2m.h |  3 +++
>>  xen/include/asm-x86/p2m.h    |  3 ---
>>  8 files changed, 47 insertions(+), 19 deletions(-)
> The x86 parts of the change look really independent of the rest, so
> you could have done yourself a favor by splitting this out, as then
> the individual patches would each require separate acks rather than
> the one patch here requiring an x86/mm one along with the ARM and
> VM-event ones.
>
> Jan
>

Ok, I will split the patch accordingly. Thank you.

Best regards,
~Sergej

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 31/38] altp2m: Introduce altp2m_switch_vcpu_altp2m_by_id
  2016-08-17 12:37     ` Sergej Proskurin
@ 2016-08-17 12:48       ` Julien Grall
  0 siblings, 0 replies; 116+ messages in thread
From: Julien Grall @ 2016-08-17 12:48 UTC (permalink / raw)
  To: Sergej Proskurin, Jan Beulich
  Cc: Stefano Stabellini, Razvan Cojocaru, George Dunlap,
	Andrew Cooper, Tamas K Lengyel, xen-devel



On 17/08/16 13:37, Sergej Proskurin wrote:
> On 08/17/2016 12:05 PM, Jan Beulich wrote:
>>>>> On 17.08.16 at 00:17, <proskurin@sec.in.tum.de> wrote:
>>>  xen/arch/arm/altp2m.c        | 32 ++++++++++++++++++++++++++++++++
>>>  xen/arch/x86/mm/altp2m.c     |  6 ++++++
>>>  xen/arch/x86/mm/p2m.c        |  6 ------
>>>  xen/common/vm_event.c        |  3 ++-
>>>  xen/include/asm-arm/altp2m.h |  7 ++++---
>>>  xen/include/asm-arm/p2m.h    |  6 ------
>>>  xen/include/asm-x86/altp2m.h |  3 +++
>>>  xen/include/asm-x86/p2m.h    |  3 ---
>>>  8 files changed, 47 insertions(+), 19 deletions(-)
>> The x86 parts of the change look really independent of the rest, so
>> you could have done yourself a favor by splitting this out, as then
>> the individual patches would each require separate acks rather than
>> the one patch here requiring an x86/mm one along with the ARM and
>> VM-event ones.
>>
>> Jan
>>
>
> Ok, I will split the patch accordingly. Thank you.

I think it is worth to mention again that patches doing one logical 
thing (i.e moving code, renaming function) are easier to review compare 
to patch doing multiple one.

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 36/38] altp2m: Allow specifying external-only use-case
  2016-08-16 22:17 ` [PATCH v3 36/38] altp2m: Allow specifying external-only use-case Sergej Proskurin
  2016-08-17 10:08   ` Jan Beulich
@ 2016-08-17 14:47   ` Daniel De Graaf
  2016-08-24 12:18   ` Wei Liu
  2 siblings, 0 replies; 116+ messages in thread
From: Daniel De Graaf @ 2016-08-17 14:47 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel
  Cc: Tamas K Lengyel, Ian Jackson, Wei Liu, Jan Beulich, Andrew Cooper

On 08/16/2016 06:17 PM, Sergej Proskurin wrote:
> From: Tamas K Lengyel <tamas.lengyel@zentific.com>
>
> Currently setting altp2mhvm=1 in the domain configuration allows access to the
> altp2m interface for both in-guest and external privileged tools. This poses
> a problem for use-cases where only external access should be allowed, requiring
> the user to compile Xen with XSM enabled to be able to appropriately restrict
> access.
>
> In this patch we deprecate the altp2mhvm domain configuration option and
> introduce the altp2m option, which allows specifying if by default the altp2m
> interface should be external-only. The information is stored in
> HVM_PARAM_ALTP2M which we now define with specific XEN_ALTP2M_* modes.
> If external_only mode is selected, the XSM check is shifted to use XSM_DM_PRIV
> type check, thus restricting access to the interface by the guest itself. Note
> that we keep the default XSM policy untouched. Users of XSM who wish to enforce
> external_only mode for altp2m can do so by adjusting their XSM policy directly,
> as this domain config option does not override an active XSM policy.
>
> Also, as part of this patch we adjust the hvmop handler to require
> HVM_PARAM_ALTP2M to be of a type other then disabled for all ops. This has been
> previously only required for get/set altp2m domain state, all other options
> were gated on altp2m_enabled. Since altp2m_enabled only gets set during set
> altp2m domain state, this change introduces no new requirements to the other
> ops but makes it more clear that it is required for all ops.
>
> Signed-off-by: Tamas K Lengyel <tamas.lengyel@zentific.com>
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>

Acked-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 31/38] altp2m: Introduce altp2m_switch_vcpu_altp2m_by_id
  2016-08-16 22:17 ` [PATCH v3 31/38] altp2m: Introduce altp2m_switch_vcpu_altp2m_by_id Sergej Proskurin
  2016-08-17 10:05   ` Jan Beulich
  2016-08-17 12:08   ` Razvan Cojocaru
@ 2016-08-18 10:35   ` George Dunlap
  2 siblings, 0 replies; 116+ messages in thread
From: George Dunlap @ 2016-08-18 10:35 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel
  Cc: Stefano Stabellini, Razvan Cojocaru, George Dunlap,
	Andrew Cooper, Julien Grall, Tamas K Lengyel, Jan Beulich

On 16/08/16 23:17, Sergej Proskurin wrote:
> This commit adds the function "altp2m_switch_vcpu_altp2m_by_id" that is
> executed after checking whether the vcpu should be switched to a
> different altp2m within the function "altp2m_check".
> 
> Please note that in this commit, the function "p2m_altp2m_check" is
> renamed to "altp2m_check" and moved from p2m.c to altp2m.c for the x86
> architecuture. This change was perfomed in order to move altp2m related
> functions to one spot (which is altp2m.c). The reason for modifying the
> function's name is due the association of the function with the
> associated .c file.
> 
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>

x86/p2m bits:

Acked-by: George Dunlap <george.dunlap@citrix.com>

> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> Cc: George Dunlap <george.dunlap@eu.citrix.com>
> Cc: Jan Beulich <jbeulich@suse.com>
> Cc: Andrew Cooper <andrew.cooper3@citrix.com>
> Cc: Razvan Cojocaru <rcojocaru@bitdefender.com>
> Cc: Tamas K Lengyel <tamas@tklengyel.com>
> ---
> v3: This commit has been moved out of the commit "arm/p2m: Add altp2m
>     paging mechanism".
> 
>     Moved the function "p2m_altp2m_check" from p2m.c to altp2m.c and
>     renamed it to "altp2m_check". This change required the adoption of
>     the complementary function in the x86 architecture.
> ---
>  xen/arch/arm/altp2m.c        | 32 ++++++++++++++++++++++++++++++++
>  xen/arch/x86/mm/altp2m.c     |  6 ++++++
>  xen/arch/x86/mm/p2m.c        |  6 ------
>  xen/common/vm_event.c        |  3 ++-
>  xen/include/asm-arm/altp2m.h |  7 ++++---
>  xen/include/asm-arm/p2m.h    |  6 ------
>  xen/include/asm-x86/altp2m.h |  3 +++
>  xen/include/asm-x86/p2m.h    |  3 ---
>  8 files changed, 47 insertions(+), 19 deletions(-)
> 
> diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
> index b10711e..11272e9 100644
> --- a/xen/arch/arm/altp2m.c
> +++ b/xen/arch/arm/altp2m.c
> @@ -32,6 +32,38 @@ struct p2m_domain *altp2m_get_altp2m(struct vcpu *v)
>      return v->domain->arch.altp2m_p2m[index];
>  }
>  
> +static bool_t altp2m_switch_vcpu_altp2m_by_id(struct vcpu *v, unsigned int idx)
> +{
> +    struct domain *d = v->domain;
> +    bool_t rc = false;
> +
> +    if ( idx >= MAX_ALTP2M )
> +        return rc;
> +
> +    altp2m_lock(d);
> +
> +    if ( d->arch.altp2m_p2m[idx] != NULL )
> +    {
> +        if ( idx != altp2m_vcpu(v).p2midx )
> +        {
> +            atomic_dec(&altp2m_get_altp2m(v)->active_vcpus);
> +            altp2m_vcpu(v).p2midx = idx;
> +            atomic_inc(&altp2m_get_altp2m(v)->active_vcpus);
> +        }
> +        rc = true;
> +    }
> +
> +    altp2m_unlock(d);
> +
> +    return rc;
> +}
> +
> +void altp2m_check(struct vcpu *v, uint16_t idx)
> +{
> +    if ( altp2m_active(v->domain) )
> +        altp2m_switch_vcpu_altp2m_by_id(v, idx);
> +}
> +
>  int altp2m_switch_domain_altp2m_by_id(struct domain *d, unsigned int idx)
>  {
>      struct vcpu *v;
> diff --git a/xen/arch/x86/mm/altp2m.c b/xen/arch/x86/mm/altp2m.c
> index 930bdc2..00abb5a 100644
> --- a/xen/arch/x86/mm/altp2m.c
> +++ b/xen/arch/x86/mm/altp2m.c
> @@ -65,6 +65,12 @@ altp2m_vcpu_destroy(struct vcpu *v)
>          vcpu_unpause(v);
>  }
>  
> +void altp2m_check(struct vcpu *v, uint16_t idx)
> +{
> +    if ( altp2m_active(v->domain) )
> +        p2m_switch_vcpu_altp2m_by_id(v, idx);
> +}
> +
>  /*
>   * Local variables:
>   * mode: C
> diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
> index 812dbf6..cb28cc2 100644
> --- a/xen/arch/x86/mm/p2m.c
> +++ b/xen/arch/x86/mm/p2m.c
> @@ -1646,12 +1646,6 @@ void p2m_mem_access_emulate_check(struct vcpu *v,
>      }
>  }
>  
> -void p2m_altp2m_check(struct vcpu *v, uint16_t idx)
> -{
> -    if ( altp2m_active(v->domain) )
> -        p2m_switch_vcpu_altp2m_by_id(v, idx);
> -}
> -
>  bool_t p2m_mem_access_check(paddr_t gpa, unsigned long gla,
>                              struct npfec npfec,
>                              vm_event_request_t **req_ptr)
> diff --git a/xen/common/vm_event.c b/xen/common/vm_event.c
> index 8398af7..e48d111 100644
> --- a/xen/common/vm_event.c
> +++ b/xen/common/vm_event.c
> @@ -29,6 +29,7 @@
>  #include <asm/monitor.h>
>  #include <asm/vm_event.h>
>  #include <xsm/xsm.h>
> +#include <asm/altp2m.h>
>  
>  /* for public/io/ring.h macros */
>  #define xen_mb()   mb()
> @@ -423,7 +424,7 @@ void vm_event_resume(struct domain *d, struct vm_event_domain *ved)
>  
>          /* Check for altp2m switch */
>          if ( rsp.flags & VM_EVENT_FLAG_ALTERNATE_P2M )
> -            p2m_altp2m_check(v, rsp.altp2m_idx);
> +            altp2m_check(v, rsp.altp2m_idx);
>  
>          /* Check flags which apply only when the vCPU is paused */
>          if ( atomic_read(&v->vm_event_pause_count) )
> diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
> index 7f385d9..ef80829 100644
> --- a/xen/include/asm-arm/altp2m.h
> +++ b/xen/include/asm-arm/altp2m.h
> @@ -38,9 +38,7 @@ static inline bool_t altp2m_active(const struct domain *d)
>  /* Alternate p2m VCPU */
>  static inline uint16_t altp2m_vcpu_idx(const struct vcpu *v)
>  {
> -    /* Not implemented on ARM, should not be reached. */
> -    BUG();
> -    return 0;
> +    return altp2m_vcpu(v).p2midx;
>  }
>  
>  int altp2m_init(struct domain *d);
> @@ -52,6 +50,9 @@ void altp2m_vcpu_destroy(struct vcpu *v);
>  /* Get current alternate p2m table. */
>  struct p2m_domain *altp2m_get_altp2m(struct vcpu *v);
>  
> +/* Check to see if vcpu should be switched to a different p2m. */
> +void altp2m_check(struct vcpu *v, uint16_t idx);
> +
>  /* Switch alternate p2m for entire domain */
>  int altp2m_switch_domain_altp2m_by_id(struct domain *d,
>                                        unsigned int idx);
> diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
> index 384ef3b..b01baec 100644
> --- a/xen/include/asm-arm/p2m.h
> +++ b/xen/include/asm-arm/p2m.h
> @@ -161,12 +161,6 @@ void p2m_mem_access_emulate_check(struct vcpu *v,
>      /* Not supported on ARM. */
>  }
>  
> -static inline
> -void p2m_altp2m_check(struct vcpu *v, uint16_t idx)
> -{
> -    /* Not supported on ARM. */
> -}
> -
>  /* Initialise vmid allocator */
>  void p2m_vmid_allocator_init(void);
>  
> diff --git a/xen/include/asm-x86/altp2m.h b/xen/include/asm-x86/altp2m.h
> index 64c7618..67d0205 100644
> --- a/xen/include/asm-x86/altp2m.h
> +++ b/xen/include/asm-x86/altp2m.h
> @@ -38,4 +38,7 @@ static inline uint16_t altp2m_vcpu_idx(const struct vcpu *v)
>      return vcpu_altp2m(v).p2midx;
>  }
>  
> +/* Check to see if vcpu should be switched to a different p2m. */
> +void altp2m_check(struct vcpu *v, uint16_t idx);
> +
>  #endif /* __ASM_X86_ALTP2M_H */
> diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
> index d5fd546..438c676 100644
> --- a/xen/include/asm-x86/p2m.h
> +++ b/xen/include/asm-x86/p2m.h
> @@ -787,9 +787,6 @@ unsigned int p2m_find_altp2m_by_eptp(struct domain *d, uint64_t eptp);
>  /* Switch alternate p2m for a single vcpu */
>  bool_t p2m_switch_vcpu_altp2m_by_id(struct vcpu *v, unsigned int idx);
>  
> -/* Check to see if vcpu should be switched to a different p2m. */
> -void p2m_altp2m_check(struct vcpu *v, uint16_t idx);
> -
>  /* Flush all the alternate p2m's for a domain */
>  void p2m_flush_altp2m(struct domain *d);
>  
> 


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 36/38] altp2m: Allow specifying external-only use-case
  2016-08-16 22:17 ` [PATCH v3 36/38] altp2m: Allow specifying external-only use-case Sergej Proskurin
  2016-08-17 10:08   ` Jan Beulich
  2016-08-17 14:47   ` Daniel De Graaf
@ 2016-08-24 12:18   ` Wei Liu
  2 siblings, 0 replies; 116+ messages in thread
From: Wei Liu @ 2016-08-24 12:18 UTC (permalink / raw)
  To: Sergej Proskurin
  Cc: Wei Liu, Andrew Cooper, Ian Jackson, Jan Beulich,
	Tamas K Lengyel, xen-devel, Daniel De Graaf

On Wed, Aug 17, 2016 at 12:17:12AM +0200, Sergej Proskurin wrote:
> From: Tamas K Lengyel <tamas.lengyel@zentific.com>
> 
> Currently setting altp2mhvm=1 in the domain configuration allows access to the
> altp2m interface for both in-guest and external privileged tools. This poses
> a problem for use-cases where only external access should be allowed, requiring
> the user to compile Xen with XSM enabled to be able to appropriately restrict
> access.
> 
> In this patch we deprecate the altp2mhvm domain configuration option and
> introduce the altp2m option, which allows specifying if by default the altp2m
> interface should be external-only. The information is stored in
> HVM_PARAM_ALTP2M which we now define with specific XEN_ALTP2M_* modes.
> If external_only mode is selected, the XSM check is shifted to use XSM_DM_PRIV
> type check, thus restricting access to the interface by the guest itself. Note
> that we keep the default XSM policy untouched. Users of XSM who wish to enforce
> external_only mode for altp2m can do so by adjusting their XSM policy directly,
> as this domain config option does not override an active XSM policy.
> 
> Also, as part of this patch we adjust the hvmop handler to require
> HVM_PARAM_ALTP2M to be of a type other then disabled for all ops. This has been
> previously only required for get/set altp2m domain state, all other options
> were gated on altp2m_enabled. Since altp2m_enabled only gets set during set
> altp2m domain state, this change introduces no new requirements to the other
> ops but makes it more clear that it is required for all ops.
> 
> Signed-off-by: Tamas K Lengyel <tamas.lengyel@zentific.com>
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>


During my review of Tamas's original patch, I figured that it would
be quite ugly to handle the old type vs new type of altp2m in order to
not break compilation for older application.

But it seems that we shall just keep altp2mhvm libxl_def_bool and use
the new type for altp2m.  I think by taking this patch in the series, we
manage to reduce the compatibility cruft needed, which is good.

> ---
> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> Cc: Wei Liu <wei.liu2@citrix.com>
> Cc: Jan Beulich <jbeulich@suse.com>
> Cc: Andrew Cooper <andrew.cooper3@citrix.com>
> Cc: Daniel De Graaf <dgdegra@tycho.nsa.gov>
> 
> v2: Rename HVMALTP2M_* to XEN_ALTP2M_*
>     Relax xsm check to XSM_DM_PRIV for external-only mode
> 
> v3: Introduce macro LIBXL_HAVE_ARM_ALTP2M in parallel to the former
>     LIBXL_HAVE_ALTP2M to differentiate between altp2m for x86 and and
>     altp2m for ARM architectures.
> 
>     Document the option "altp2m" in ./docs/man/xl.cfg.pod.5.in.
> 
>     Maintain the legacy info->u.hvm.altp2m field for x86 HVM domains in
>     parallel to the introduced info->altp2m field for x86 HVM and ARM
>     domains.
> ---
>  docs/man/xl.cfg.pod.5.in        | 37 ++++++++++++++++++++++++++++++++++++-
>  tools/libxl/libxl.h             | 10 +++++++++-
>  tools/libxl/libxl_create.c      |  7 +++++--
>  tools/libxl/libxl_dom.c         | 30 ++++++++++++++++++++++++++++--
>  tools/libxl/libxl_types.idl     | 13 +++++++++++++
>  tools/libxl/xl_cmdimpl.c        | 25 ++++++++++++++++++++++++-
>  xen/arch/arm/hvm.c              | 14 +++++++++++++-
>  xen/arch/x86/hvm/hvm.c          | 20 ++++++++++----------
>  xen/include/public/hvm/params.h | 10 +++++++++-
>  xen/include/xsm/dummy.h         | 14 +++++++++++---
>  xen/include/xsm/xsm.h           |  6 +++---
>  xen/xsm/flask/hooks.c           |  2 +-
>  12 files changed, 162 insertions(+), 26 deletions(-)
> 
> diff --git a/docs/man/xl.cfg.pod.5.in b/docs/man/xl.cfg.pod.5.in
> index 48c9c0d..bf9a48a 100644
> --- a/docs/man/xl.cfg.pod.5.in
> +++ b/docs/man/xl.cfg.pod.5.in
> @@ -1268,6 +1268,37 @@ enabled by default and you should usually omit it. It may be necessary
>  to disable the HPET in order to improve compatibility with guest
>  Operating Systems (X86 only)
>  
> +=item B<altp2m=MODE>
> +
> +Specifies access mode to the alternate-p2m capability. Alternate-p2m allows a
> +guest to manage multiple p2m guest physical "memory views" (as opposed to a
> +single p2m). This option is disabled by default and is available to x86 hvm and
> +ARM domains. You may want this option if you want to access-control/isolate
> +access to specific guest physical memory pages accessed by the guest, e.g. for
> +domain memory introspection or for isolation/access-control of memory between
> +components within a single guest domain.
> +
> +The valid values are as follows:
> +
> +=over 4
> +
> +=item B<"disabled">
> +
> +Altp2m is disabled for the domain (default).
> +
> +=item B<"mixed">
> +
> +The mixed mode allows access to the altp2m interface for both in-guest
> +and external tools as well.
> +
> +=item B<"external_only">
> +
> +Enables access to the alternate-p2m capability for hvm guests only
> +by external privileged tools. Note: if XSM is enabled then the XSM policy
> +should be used to specify external-only access to the interface.
> +
> +=back
> +
>  =item B<altp2mhvm=BOOLEAN>
>  
>  Enables or disables hvm guest access to alternate-p2m capability.
> @@ -1278,7 +1309,11 @@ You may want this option if you want to access-control/isolate
>  access to specific guest physical memory pages accessed by
>  the guest, e.g. for HVM domain memory introspection or
>  for isolation/access-control of memory between components within
> -a single guest hvm domain.
> +a single guest hvm domain. This option is deprecated, use the option
> +"altp2m" instead.
> +
> +Note: While the option "altp2mhvm" is deprecated, legacy applications for
> +x86 systems will continue to work using it.
>  
>  =item B<nestedhvm=BOOLEAN>
>  
> diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
> index ae21302..f78d63e 100644
> --- a/tools/libxl/libxl.h
> +++ b/tools/libxl/libxl.h
> @@ -847,11 +847,19 @@ typedef struct libxl__ctx libxl_ctx;
>  
>  /*
>   * LIBXL_HAVE_ALTP2M
> - * If this is defined, then libxl supports alternate p2m functionality.
> + * If this is defined, then libxl supports alternate p2m functionality for
> + * x86 HVM guests.
>   */
>  #define LIBXL_HAVE_ALTP2M 1
>  
>  /*
> + * LIBXL_HAVE_ARM_ALTP2M
> + * If this is defined, then libxl supports alternate p2m functionality for
> + * ARM guests.
> + */
> +#define LIBXL_HAVE_ARM_ALTP2M 1
> +
> +/*
>   * LIBXL_HAVE_REMUS
>   * If this is defined, then libxl supports remus.
>   */
> diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
> index 04f8ae9..21e32c9 100644
> --- a/tools/libxl/libxl_create.c
> +++ b/tools/libxl/libxl_create.c
> @@ -406,6 +406,7 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc,
>              libxl_domain_type_to_string(b_info->type));
>          return ERROR_INVAL;
>      }
> +

Unrelated change.

>      return 0;
>  }
>  
> @@ -918,8 +919,10 @@ static void initiate_domain_create(libxl__egc *egc,
>  
>      if (d_config->c_info.type == LIBXL_DOMAIN_TYPE_HVM &&
>          (libxl_defbool_val(d_config->b_info.u.hvm.nested_hvm) &&
> -         libxl_defbool_val(d_config->b_info.u.hvm.altp2m))) {
> -        LOG(ERROR, "nestedhvm and altp2mhvm cannot be used together");
> +        /* Cannot combine nested_hvm with altp2m or altp2mhvm params. */

No need to have this comment. The code is self-explanatory and the error
message already states that.

> +        (libxl_defbool_val(d_config->b_info.u.hvm.altp2m) ||
> +        (d_config->b_info.altp2m != LIBXL_ALTP2M_MODE_DISABLED)))) {
> +        LOG(ERROR, "nestedhvm and altp2m cannot be used together");
>          goto error_out;
>      }
>  
> diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
> index eef5045..32af757 100644
> --- a/tools/libxl/libxl_dom.c
> +++ b/tools/libxl/libxl_dom.c
> @@ -291,8 +291,6 @@ static void hvm_set_conf_params(xc_interface *handle, uint32_t domid,
>                      libxl_defbool_val(info->u.hvm.vpt_align));
>      xc_hvm_param_set(handle, domid, HVM_PARAM_NESTEDHVM,
>                      libxl_defbool_val(info->u.hvm.nested_hvm));
> -    xc_hvm_param_set(handle, domid, HVM_PARAM_ALTP2M,
> -                    libxl_defbool_val(info->u.hvm.altp2m));
>  }
>  
>  int libxl__build_pre(libxl__gc *gc, uint32_t domid,
> @@ -301,6 +299,7 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid,
>      libxl_domain_build_info *const info = &d_config->b_info;
>      libxl_ctx *ctx = libxl__gc_owner(gc);
>      char *xs_domid, *con_domid;
> +    bool altp2m_support = false;
>      int rc;
>  
>      if (xc_domain_max_vcpus(ctx->xch, domid, info->max_vcpus) != 0) {
> @@ -434,6 +433,33 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid,
>  #endif
>      }
>  
> +#if defined(__i386__) || defined(__x86_64__)
> +    /* Alternate p2m support on x86 is available only for HVM guests. */
> +    if (info->type == LIBXL_DOMAIN_TYPE_HVM)
> +        altp2m_support = true;
> +#elif defined(__arm__) || defined(__aarch64__)
> +    /* Alternate p2m support on ARM is available for all guests. */
> +    altp2m_support = true;
> +#endif

Sorry for not mentioning this earlier, can you please make a function
called libxl__arch_altp2m_supported in libxl_{x86,arm}.c?

> +
> +    if (altp2m_support) {
> +        /* The config parameter "altp2m" replaces the parameter "altp2mhvm". For
> +         * legacy reasons, both parameters are accepted on x86 HVM guests (only
> +         * "altp2m" is accepted on ARM guests).
> +         *
> +         * If the legacy field info->u.hvm.altp2m is set, activate altp2m.
> +         * Otherwise set altp2m based on the field info->altp2m. */
> +#if defined(__i386__) || defined(__x86_64__)
> +        if (info->altp2m == LIBXL_ALTP2M_MODE_DISABLED &&
> +            libxl_defbool_val(info->u.hvm.altp2m))
> +            xc_hvm_param_set(ctx->xch, domid, HVM_PARAM_ALTP2M,
> +                             libxl_defbool_val(info->u.hvm.altp2m));
> +        else
> +#endif
> +            xc_hvm_param_set(ctx->xch, domid, HVM_PARAM_ALTP2M,
> +                             info->altp2m);
> +    }
> +

Or even move this snippet and the support check to a function named
libxl__arch_set_altp2m?

Wei.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 38/38] arm/p2m: Add test of xc_altp2m_change_gfn
  2016-08-16 22:17 ` [PATCH v3 38/38] arm/p2m: Add test of xc_altp2m_change_gfn Sergej Proskurin
  2016-08-17 12:06   ` Razvan Cojocaru
@ 2016-08-24 12:27   ` Wei Liu
  2016-09-13 15:45     ` Sergej Proskurin
  1 sibling, 1 reply; 116+ messages in thread
From: Wei Liu @ 2016-08-24 12:27 UTC (permalink / raw)
  To: Sergej Proskurin
  Cc: xen-devel, Tamas K Lengyel, Ian Jackson, Wei Liu, Razvan Cojocaru

On Wed, Aug 17, 2016 at 12:17:14AM +0200, Sergej Proskurin wrote:
> This commit extends xen-access by a simple test of the functionality
> provided by "xc_altp2m_change_gfn". The idea is to dynamically remap a
> trapping gfn to another mfn, which holds the same content as the
> original mfn. On success, the guest will continue to run. Subsequent
> altp2m access violations will trap into Xen and be forced by xen-access
> to switch to the default view (altp2m[0]) as before. The introduced test
> can be invoked by providing the argument "altp2m_remap".
> 
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
> ---
> Cc: Razvan Cojocaru <rcojocaru@bitdefender.com>
> Cc: Tamas K Lengyel <tamas@tklengyel.com>
> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> Cc: Wei Liu <wei.liu2@citrix.com>
> ---
> v3: Cosmetic fixes in "xenaccess_copy_gfn" and "xenaccess_change_gfn".
> 
>     Added munmap in "copy_gfn" in the second error case.
> 
>     Added option "altp2m_remap" selecting the altp2m-remap test.
> ---
>  tools/tests/xen-access/xen-access.c | 162 +++++++++++++++++++++++++++++++++++-
>  1 file changed, 158 insertions(+), 4 deletions(-)
> 
> diff --git a/tools/tests/xen-access/xen-access.c b/tools/tests/xen-access/xen-access.c
> index eafd7d6..5909a8a 100644
> --- a/tools/tests/xen-access/xen-access.c
> +++ b/tools/tests/xen-access/xen-access.c
> @@ -38,6 +38,7 @@
>  #include <sys/mman.h>
>  #include <sys/poll.h>
>  
> +#define XC_WANT_COMPAT_MAP_FOREIGN_API

I know Razvan already acked this, but general you shouldn't use the
COMPAT APIs. You should use libs/foreignmemory library, which is a
stable library.

>  #include <xenctrl.h>
>  #include <xenevtchn.h>
>  #include <xen/vm_event.h>
> @@ -49,6 +50,8 @@
>  #define START_PFN 0ULL
>  #endif
>  
> +#define INVALID_GFN ~(0UL)
> +
>  #define DPRINTF(a, b...) fprintf(stderr, a, ## b)
>  #define ERROR(a, b...) fprintf(stderr, a "\n", ## b)
>  #define PERROR(a, b...) fprintf(stderr, a ": %s\n", ## b, strerror(errno))
> @@ -72,9 +75,14 @@ typedef struct xenaccess {
>      xen_pfn_t max_gpfn;
>  
>      vm_event_t vm_event;
> +
> +    unsigned int ap2m_idx;
> +    xen_pfn_t gfn_old;
> +    xen_pfn_t gfn_new;
>  } xenaccess_t;
>  
>  static int interrupted;
> +static int gfn_changed = 0;
>  bool evtchn_bind = 0, evtchn_open = 0, mem_access_enable = 0;
>  
>  static void close_handler(int sig)
> @@ -82,6 +90,100 @@ static void close_handler(int sig)
>      interrupted = sig;
>  }
>  
> +static int xenaccess_copy_gfn(xc_interface *xch,
> +                              domid_t domain_id,
> +                              xen_pfn_t dst_gfn,
> +                              xen_pfn_t src_gfn)
> +{
> +    void *src_vaddr = NULL;
> +    void *dst_vaddr = NULL;
> +
> +    src_vaddr = xc_map_foreign_range(xch, domain_id, XC_PAGE_SIZE,
> +                                     PROT_READ, src_gfn);
> +    if ( src_vaddr == MAP_FAILED || src_vaddr == NULL)
> +        return -1;
> +
> +    dst_vaddr = xc_map_foreign_range(xch, domain_id, XC_PAGE_SIZE,
> +                                     PROT_WRITE, dst_gfn);

You can have a look at libxc/xc_foreign_memory.c for how to replace this
legacy call with the new function.

Wei.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 01/38] arm/p2m: Cosmetic fixes - apply p2m_get_hostp2m
  2016-08-16 22:16 ` [PATCH v3 01/38] arm/p2m: Cosmetic fixes - apply p2m_get_hostp2m Sergej Proskurin
@ 2016-09-01 15:46   ` Julien Grall
  0 siblings, 0 replies; 116+ messages in thread
From: Julien Grall @ 2016-09-01 15:46 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/16 23:16, Sergej Proskurin wrote:
> This commit substitutes the direct access of the host's p2m
> (&d->arch.p2m) for the macro "p2m_get_hostp2m". This macro simplifies
> the differentiation between the host's p2m and introduced alternative
> p2m's, in the following commits.
>
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>

Acked-by: Julien Grall <julien.grall@arm.com>

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 02/38] arm/p2m: Expose p2m_*lock helpers
  2016-08-16 22:16 ` [PATCH v3 02/38] arm/p2m: Expose p2m_*lock helpers Sergej Proskurin
@ 2016-09-01 15:48   ` Julien Grall
  2016-09-02 10:12     ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-01 15:48 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/16 23:16, Sergej Proskurin wrote:
> This commit exposes the "p2m_*lock" helpers, as they will be used within
> the file ./xen/arch/arm/altp2m.c, as will be shown in the following
> commits.
>
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> ---
>  xen/arch/arm/p2m.c        | 12 ++++++------
>  xen/include/asm-arm/p2m.h | 16 ++++++++++++++++
>  2 files changed, 22 insertions(+), 6 deletions(-)
>
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index da6c7d4..08114d8 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -62,14 +62,14 @@ static inline bool_t p2m_is_superpage(lpae_t pte, unsigned int level)
>      return (level < 3) && p2m_mapping(pte);
>  }
>
> -static inline void p2m_write_lock(struct p2m_domain *p2m)
> +void p2m_write_lock(struct p2m_domain *p2m)

This will introduce an overhead when locking the p2m. Those helpers 
should be moved a inline in p2m.h and not transform to a functions.

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 03/38] arm/p2m: Introduce p2m_(switch|restore)_vttbr_and_(g|s)et_flags
  2016-08-16 22:16 ` [PATCH v3 03/38] arm/p2m: Introduce p2m_(switch|restore)_vttbr_and_(g|s)et_flags Sergej Proskurin
@ 2016-09-01 15:51   ` Julien Grall
  2016-09-02  8:40     ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-01 15:51 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/16 23:16, Sergej Proskurin wrote:
> This commit introduces macros for switching and restoring the vttbr
> considering the currently set irq flags. We define these macros, as the
> following commits will use the associated functionality multiple times
> throughout the file ./xen/arch/arm/p2m.c.
>
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> ---
>  xen/arch/arm/p2m.c | 37 +++++++++++++++++++++++--------------
>  1 file changed, 23 insertions(+), 14 deletions(-)
>
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index 08114d8..02e9ee7 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -27,6 +27,26 @@ static unsigned int __read_mostly p2m_root_level;
>
>  #define P2M_ROOT_PAGES    (1<<P2M_ROOT_ORDER)
>
> +#define p2m_switch_vttbr_and_get_flags(ovttbr, nvttbr, flags)       \
> +({                                                                  \

It makes more sense to save the content of VTTBR_EL2 in the macro.

> +    if ( ovttbr != nvttbr )                                         \
> +    {                                                               \
> +        local_irq_save(flags);                                      \
> +        WRITE_SYSREG64(nvttbr, VTTBR_EL2);                          \
> +        isb();                                                      \
> +    }                                                               \
> +})
> +
> +#define p2m_restore_vttbr_and_set_flags(ovttbr, flags)              \
> +({                                                                  \
> +    if ( ovttbr != READ_SYSREG64(VTTBR_EL2) )                       \
> +    {                                                               \
> +        WRITE_SYSREG64(ovttbr, VTTBR_EL2);                          \
> +        isb();                                                      \
> +        local_irq_restore(flags);                                   \
> +    }                                                               \
> +})
> +
>  unsigned int __read_mostly p2m_ipa_bits;
>
>  /* Helpers to lookup the properties of each level */
> @@ -173,28 +193,17 @@ void p2m_restore_state(struct vcpu *n)
>  static void p2m_flush_tlb(struct p2m_domain *p2m)
>  {
>      unsigned long flags = 0;
> -    uint64_t ovttbr;
> +    uint64_t ovttbr = READ_SYSREG64(VTTBR_EL2);
>
>      /*
>       * ARM only provides an instruction to flush TLBs for the current
>       * VMID. So switch to the VTTBR of a given P2M if different.
>       */
> -    ovttbr = READ_SYSREG64(VTTBR_EL2);
> -    if ( ovttbr != p2m->vttbr )
> -    {
> -        local_irq_save(flags);
> -        WRITE_SYSREG64(p2m->vttbr, VTTBR_EL2);
> -        isb();
> -    }
> +    p2m_switch_vttbr_and_get_flags(ovttbr, p2m->vttbr, flags);
>
>      flush_tlb();
>
> -    if ( ovttbr != READ_SYSREG64(VTTBR_EL2) )
> -    {
> -        WRITE_SYSREG64(ovttbr, VTTBR_EL2);
> -        isb();
> -        local_irq_restore(flags);
> -    }
> +    p2m_restore_vttbr_and_set_flags(ovttbr, flags);
>  }
>
>  /*
>

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 04/38] arm/p2m: Add first altp2m HVMOP stubs
  2016-08-16 22:16 ` [PATCH v3 04/38] arm/p2m: Add first altp2m HVMOP stubs Sergej Proskurin
@ 2016-09-01 16:09   ` Julien Grall
  2016-09-02  9:26     ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-01 16:09 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/16 23:16, Sergej Proskurin wrote:
> This commit moves the altp2m-related code from x86 to ARM. Functions

s/moves/copies/

However, this is not really true because the code is current patch is 
not a verbatim copy.

Lastly, what is the status to have x86 and ARM implementation of 
do_altp2m_op merged?

It would allow us to get code clean-up more easily. I have in mind the 
recent patch [1] from Paul Lai.

I am also worry to see the code diverging, for instance the locking is 
likely needed on x86 too.

> that are no yet supported notify the caller or print a BUG message
> stating their absence.
>
> Also, the struct arch_domain is extended with the altp2m_active
> attribute, representing the current altp2m activity configuration of the
> domain.
>
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> ---
> v2: Removed altp2m command-line option: Guard through HVM_PARAM_ALTP2M.
>     Removed not used altp2m helper stubs in altp2m.h.
>
> v3: Cosmetic fixes.
>
>     Added domain lock in "do_altp2m_op" to avoid concurrent execution of
>     altp2m-related HVMOPs.
>
>     Added check making sure that HVM_PARAM_ALTP2M is set before
>     execution of altp2m-related HVMOPs.
> ---
>  xen/arch/arm/hvm.c           | 89 ++++++++++++++++++++++++++++++++++++++++++++
>  xen/include/asm-arm/altp2m.h |  4 +-
>  xen/include/asm-arm/domain.h |  3 ++
>  3 files changed, 94 insertions(+), 2 deletions(-)
>
> diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
> index d999bde..45d51c6 100644
> --- a/xen/arch/arm/hvm.c
> +++ b/xen/arch/arm/hvm.c
> @@ -32,6 +32,91 @@
>
>  #include <asm/hypercall.h>
>
> +#include <asm/altp2m.h>
> +
> +static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
> +{
> +    struct xen_hvm_altp2m_op a;
> +    struct domain *d = NULL;
> +    int rc = 0;
> +
> +    if ( copy_from_guest(&a, arg, 1) )
> +        return -EFAULT;
> +
> +    if ( a.pad1 || a.pad2 ||
> +         (a.version != HVMOP_ALTP2M_INTERFACE_VERSION) ||
> +         (a.cmd < HVMOP_altp2m_get_domain_state) ||
> +         (a.cmd > HVMOP_altp2m_change_gfn) )
> +        return -EINVAL;
> +
> +    d = (a.cmd != HVMOP_altp2m_vcpu_enable_notify) ?
> +        rcu_lock_domain_by_any_id(a.domain) : rcu_lock_current_domain();
> +
> +    if ( d == NULL )
> +        return -ESRCH;
> +
> +    /* Prevent concurrent execution of the following HVMOPs. */
> +    domain_lock(d);

So you are not allowing concurrent call of set_mem_access on different 
altp2m. Is it something that you plan to fix in the future?

> +
> +    if ( (a.cmd != HVMOP_altp2m_get_domain_state) &&
> +         (a.cmd != HVMOP_altp2m_set_domain_state) &&
> +         !altp2m_active(d) )
> +    {
> +        rc = -EOPNOTSUPP;
> +        goto out;
> +    }
> +
> +    if ( !(d)->arch.hvm_domain.params[HVM_PARAM_ALTP2M] )
> +    {
> +        rc = -EINVAL;
> +        goto out;
> +    }
> +
> +    if ( (rc = xsm_hvm_altp2mhvm_op(XSM_TARGET, d)) )
> +        goto out;
> +
> +    switch ( a.cmd )
> +    {
> +    case HVMOP_altp2m_get_domain_state:
> +        rc = -EOPNOTSUPP;
> +        break;
> +
> +    case HVMOP_altp2m_set_domain_state:
> +        rc = -EOPNOTSUPP;
> +        break;
> +
> +    case HVMOP_altp2m_vcpu_enable_notify:
> +        rc = -EOPNOTSUPP;
> +        break;
> +
> +    case HVMOP_altp2m_create_p2m:
> +        rc = -EOPNOTSUPP;
> +        break;
> +
> +    case HVMOP_altp2m_destroy_p2m:
> +        rc = -EOPNOTSUPP;
> +        break;
> +
> +    case HVMOP_altp2m_switch_p2m:
> +        rc = -EOPNOTSUPP;
> +        break;
> +
> +    case HVMOP_altp2m_set_mem_access:
> +        rc = -EOPNOTSUPP;
> +        break;
> +
> +    case HVMOP_altp2m_change_gfn:
> +        rc = -EOPNOTSUPP;
> +        break;
> +    }
> +
> +out:
> +    domain_unlock(d);
> +    rcu_unlock_domain(d);
> +
> +    return rc;
> +}
> +
>  long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
>  {
>      long rc = 0;
> @@ -80,6 +165,10 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
>              rc = -EINVAL;
>          break;
>
> +    case HVMOP_altp2m:
> +        rc = do_altp2m_op(arg);
> +        break;
> +
>      default:
>      {
>          gdprintk(XENLOG_DEBUG, "HVMOP op=%lu: not implemented\n", op);
> diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
> index a87747a..0711796 100644
> --- a/xen/include/asm-arm/altp2m.h
> +++ b/xen/include/asm-arm/altp2m.h
> @@ -2,6 +2,7 @@
>   * Alternate p2m
>   *
>   * Copyright (c) 2014, Intel Corporation.
> + * Copyright (c) 2016, Sergej Proskurin <proskurin@sec.in.tum.de>.
>   *
>   * This program is free software; you can redistribute it and/or modify it
>   * under the terms and conditions of the GNU General Public License,
> @@ -24,8 +25,7 @@
>  /* Alternate p2m on/off per domain */
>  static inline bool_t altp2m_active(const struct domain *d)
>  {
> -    /* Not implemented on ARM. */
> -    return 0;
> +    return d->arch.altp2m_active;
>  }
>
>  /* Alternate p2m VCPU */
> diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
> index 9452fcd..cc4bda0 100644
> --- a/xen/include/asm-arm/domain.h
> +++ b/xen/include/asm-arm/domain.h
> @@ -126,6 +126,9 @@ struct arch_domain
>      paddr_t efi_acpi_gpa;
>      paddr_t efi_acpi_len;
>  #endif
> +
> +    /* altp2m: allow multiple copies of host p2m */
> +    bool_t altp2m_active;
>  }  __cacheline_aligned;
>
>  struct arch_vcpu
>

Regards,

[1] 
https://lists.xenproject.org/archives/html/xen-devel/2016-08/msg02407.html

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 06/38] arm/p2m: Add HVMOP_altp2m_get_domain_state
  2016-08-16 22:16 ` [PATCH v3 06/38] arm/p2m: Add HVMOP_altp2m_get_domain_state Sergej Proskurin
@ 2016-09-01 17:06   ` Julien Grall
  2016-09-02  8:45     ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-01 17:06 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/16 23:16, Sergej Proskurin wrote:
> This commit adopts the x86 HVMOP_altp2m_get_domain_state implementation.
>
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> ---
> v3: Removed the "altp2m_enabled" check in HVMOP_altp2m_get_domain_state
>     case as it has been moved in front of the switch statement in
>     "do_altp2m_op".
>
>     Removed the macro "altp2m_enabled". Instead, check directly for the
>     HVM_PARAM_ALTP2M param in d->arch.hvm_domain.
> ---
>  xen/arch/arm/hvm.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
> index ce6a436..180154e 100644
> --- a/xen/arch/arm/hvm.c
> +++ b/xen/arch/arm/hvm.c
> @@ -66,7 +66,7 @@ static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
>          goto out;
>      }
>
> -    if ( !(d)->arch.hvm_domain.params[HVM_PARAM_ALTP2M] )
> +    if ( !d->arch.hvm_domain.params[HVM_PARAM_ALTP2M] )

Spurious change. This should be merged in patch #4.

>      {
>          rc = -EINVAL;
>          goto out;
> @@ -78,7 +78,8 @@ static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
>      switch ( a.cmd )
>      {
>      case HVMOP_altp2m_get_domain_state:
> -        rc = -EOPNOTSUPP;
> +        a.u.domain_state.state = altp2m_active(d);
> +        rc = __copy_to_guest(arg, &a, 1) ? -EFAULT : 0;
>          break;
>
>      case HVMOP_altp2m_set_domain_state:
>

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 08/38] arm/p2m: Free p2m entries only in the hostp2m
  2016-08-16 22:16 ` [PATCH v3 08/38] arm/p2m: Free p2m entries only in the hostp2m Sergej Proskurin
@ 2016-09-01 17:08   ` Julien Grall
  2016-09-02  9:38     ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-01 17:08 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/16 23:16, Sergej Proskurin wrote:
> Freeing p2m entries of arbitrary p2m's (in particular in alternate
> p2m's) will lead to unpredicted behavior as the entries might still be
> used within the host's p2m. The host's p2m should, however, free the
> entries, as it is the main instance responsible for their management. If
> entries were freed in the host's p2m, but still reside in one or more of
> the alternate p2m's, the change will be propagated to these functions as
> will be shown in the following commits.
>
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> ---
>  xen/arch/arm/p2m.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index 02e9ee7..bfbccca 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -1004,7 +1004,9 @@ static int __p2m_set_entry(struct p2m_domain *p2m,
>       * Free the entry only if the original pte was valid and the base
>       * is different (to avoid freeing when permission is changed).
>       */
> -    if ( p2m_valid(orig_pte) && entry->p2m.base != orig_pte.p2m.base )
> +    if ( p2m_valid(orig_pte) &&
> +         entry->p2m.base != orig_pte.p2m.base &&
> +         p2m_is_hostp2m(p2m) )

With this change, intermediate page table will not be freed which will 
lead to keep the memory used (and therefore unavailable for others) 
until the p2m is effectively destroyed.

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 10/38] arm/p2m: Move hostp2m init/teardown to individual functions
  2016-08-16 22:16 ` [PATCH v3 10/38] arm/p2m: Move hostp2m init/teardown to individual functions Sergej Proskurin
@ 2016-09-01 17:36   ` Julien Grall
  2016-09-02  9:09     ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-01 17:36 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/16 23:16, Sergej Proskurin wrote:
> ---
>  xen/arch/arm/p2m.c        | 71 +++++++++++++++++++++++++++++++++++++++++------
>  xen/include/asm-arm/p2m.h | 11 ++++++++
>  2 files changed, 73 insertions(+), 9 deletions(-)
>
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index e859fca..9ef19d4 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -1245,27 +1245,53 @@ static void p2m_free_vmid(struct domain *d)
>      spin_unlock(&vmid_alloc_lock);
>  }
>
> -void p2m_teardown(struct domain *d)
> +/* Reset this p2m table to be empty. */
> +void p2m_flush_table(struct p2m_domain *p2m)
>  {
> -    struct p2m_domain *p2m = p2m_get_hostp2m(d);
> -    struct page_info *pg;
> +    struct page_info *page, *pg;
> +    unsigned int i;
> +
> +    if ( p2m->root )
> +    {
> +        page = p2m->root;
> +
> +        /* Clear all concatenated first level pages. */

s/first/root/

> +        for ( i = 0; i < P2M_ROOT_PAGES; i++ )
> +            clear_and_clean_page(page + i);

Clearing live page table like that is not safe. Each entry (64-bit) 
should be written atomically to avoid breaking coherency (e.g if the MMU 
is walking the page table at the same time). However you don't know the 
implementation of clear_and_clean_page.

Also, this adds a small overhead when tearing down a p2m because the 
clear is not necessary.

> +    }
> +
> +    /*
> +     * Flush TLBs before releasing remaining intermediate p2m page tables to
> +     * prevent illegal access to stalled TLB entries.
> +     */
> +    p2m_flush_tlb(p2m);

p2m_flush_table is called in 2 places:
	- p2m_teardown_one
	- altp2m_reset

For p2m_teardown_one, the p2m may not have been allocated because the 
initialization failed. So try flush the TLBs may lead to a panic in Xen 
(the vttbr is invalid).

For altp2m_reset, this is called while updating the page tables (see 
altp2m_propagate_change). vCPU may still use the page tables at that time.

I am a bit worry that clear_and_clean_page

>
> +    /* Free the rest of the trie pages back to the paging pool. */
>      while ( (pg = page_list_remove_head(&p2m->pages)) )
>          free_domheap_page(pg);
>
> +    p2m->lowest_mapped_gfn = INVALID_GFN;
> +    p2m->max_mapped_gfn = _gfn(0);
> +}
> +
> +void p2m_teardown_one(struct p2m_domain *p2m)
> +{
> +    p2m_flush_table(p2m);
> +
>      if ( p2m->root )
>          free_domheap_pages(p2m->root, P2M_ROOT_ORDER);
>
>      p2m->root = NULL;
>
> -    p2m_free_vmid(d);
> +    p2m_free_vmid(p2m->domain);
> +
> +    p2m->vttbr = INVALID_VTTBR;

Why did you add this line?

>
>      radix_tree_destroy(&p2m->mem_access_settings, NULL);
>  }
>
> -int p2m_init(struct domain *d)
> +int p2m_init_one(struct domain *d, struct p2m_domain *p2m)
>  {
> -    struct p2m_domain *p2m = p2m_get_hostp2m(d);
>      int rc = 0;
>
>      rwlock_init(&p2m->lock);
> @@ -1278,11 +1304,14 @@ int p2m_init(struct domain *d)
>          return rc;
>
>      p2m->max_mapped_gfn = _gfn(0);
> -    p2m->lowest_mapped_gfn = _gfn(ULONG_MAX);
> +    p2m->lowest_mapped_gfn = INVALID_GFN;

Why this change?

>
>      p2m->domain = d;
> +    p2m->access_required = false;

This is not necessary as the p2m is zeroed during the allocation.

>      p2m->default_access = p2m_access_rwx;
>      p2m->mem_access_enabled = false;
> +    p2m->root = NULL;
> +    p2m->vttbr = INVALID_VTTBR;

Why do you add those 2 lines?

>      radix_tree_init(&p2m->mem_access_settings);
>
>      /*
> @@ -1293,9 +1322,33 @@ int p2m_init(struct domain *d)
>      p2m->clean_pte = iommu_enabled &&
>          !iommu_has_feature(d, IOMMU_FEAT_COHERENT_WALK);
>
> -    rc = p2m_alloc_table(d);
> +    return p2m_alloc_table(d);
> +}
>
> -    return rc;
> +static void p2m_teardown_hostp2m(struct domain *d)
> +{
> +    struct p2m_domain *p2m = p2m_get_hostp2m(d);
> +
> +    p2m_teardown_one(p2m);
> +}
> +
> +void p2m_teardown(struct domain *d)
> +{
> +    p2m_teardown_hostp2m(d);
> +}
> +
> +static int p2m_init_hostp2m(struct domain *d)
> +{
> +    struct p2m_domain *p2m = p2m_get_hostp2m(d);
> +
> +    p2m->p2m_class = p2m_host;
> +
> +    return p2m_init_one(d, p2m);
> +}
> +
> +int p2m_init(struct domain *d)
> +{
> +    return p2m_init_hostp2m(d);
>  }
>
>  /*
> diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
> index fa07e19..1a004ed 100644
> --- a/xen/include/asm-arm/p2m.h
> +++ b/xen/include/asm-arm/p2m.h
> @@ -11,6 +11,8 @@
>
>  #define paddr_bits PADDR_BITS
>
> +#define INVALID_VTTBR (0UL)

Looking at the current use, you only use INVALID_VTTBR to set but not 
tested. However, the 2 places where it is use are not necessary.

> +
>  /* Holds the bit size of IPAs in p2m tables.  */
>  extern unsigned int p2m_ipa_bits;
>
> @@ -226,6 +228,15 @@ void guest_physmap_remove_page(struct domain *d,
>
>  mfn_t gfn_to_mfn(struct domain *d, gfn_t gfn);
>
> +/* Flushes the page table held by the p2m. */
> +void p2m_flush_table(struct p2m_domain *p2m);
> +
> +/* Initialize the p2m structure. */
> +int p2m_init_one(struct domain *d, struct p2m_domain *p2m);
> +
> +/* Release resources held by the p2m structure. */
> +void p2m_teardown_one(struct p2m_domain *p2m);
> +
>  /*
>   * P2M rwlock helpers.
>   */
>

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 03/38] arm/p2m: Introduce p2m_(switch|restore)_vttbr_and_(g|s)et_flags
  2016-09-01 15:51   ` Julien Grall
@ 2016-09-02  8:40     ` Sergej Proskurin
  2016-09-02  9:57       ` Julien Grall
  0 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-02  8:40 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,

On 09/01/2016 05:51 PM, Julien Grall wrote:
> Hello Sergej,
> 
> On 16/08/16 23:16, Sergej Proskurin wrote:
>> This commit introduces macros for switching and restoring the vttbr
>> considering the currently set irq flags. We define these macros, as the
>> following commits will use the associated functionality multiple times
>> throughout the file ./xen/arch/arm/p2m.c.
>>
>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>> ---
>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>> Cc: Julien Grall <julien.grall@arm.com>
>> ---
>>  xen/arch/arm/p2m.c | 37 +++++++++++++++++++++++--------------
>>  1 file changed, 23 insertions(+), 14 deletions(-)
>>
>> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
>> index 08114d8..02e9ee7 100644
>> --- a/xen/arch/arm/p2m.c
>> +++ b/xen/arch/arm/p2m.c
>> @@ -27,6 +27,26 @@ static unsigned int __read_mostly p2m_root_level;
>>
>>  #define P2M_ROOT_PAGES    (1<<P2M_ROOT_ORDER)
>>
>> +#define p2m_switch_vttbr_and_get_flags(ovttbr, nvttbr, flags)       \
>> +({                                                                  \
> 
> It makes more sense to save the content of VTTBR_EL2 in the macro.
> 

I assume you mean the VTTBR_EL2 within the macro parameter ovttbr. I
will move the definition of the ovttbr variable into the macro and
return its value at the end so that it can be subsequently provided with
the "p2m_restore_vttbr_and_set_flags" macro. Thank you.

>> +    if ( ovttbr != nvttbr )                                         \
>> +    {                                                               \
>> +        local_irq_save(flags);                                      \
>> +        WRITE_SYSREG64(nvttbr, VTTBR_EL2);                          \
>> +        isb();                                                      \
>> +    }                                                               \
>> +})
>> +
>> +#define p2m_restore_vttbr_and_set_flags(ovttbr, flags)              \
>> +({                                                                  \
>> +    if ( ovttbr != READ_SYSREG64(VTTBR_EL2) )                       \
>> +    {                                                               \
>> +        WRITE_SYSREG64(ovttbr, VTTBR_EL2);                          \
>> +        isb();                                                      \
>> +        local_irq_restore(flags);                                   \
>> +    }                                                               \
>> +})
>> +
>>  unsigned int __read_mostly p2m_ipa_bits;
>>
>>  /* Helpers to lookup the properties of each level */
>> @@ -173,28 +193,17 @@ void p2m_restore_state(struct vcpu *n)
>>  static void p2m_flush_tlb(struct p2m_domain *p2m)
>>  {
>>      unsigned long flags = 0;
>> -    uint64_t ovttbr;
>> +    uint64_t ovttbr = READ_SYSREG64(VTTBR_EL2);
>>
>>      /*
>>       * ARM only provides an instruction to flush TLBs for the current
>>       * VMID. So switch to the VTTBR of a given P2M if different.
>>       */
>> -    ovttbr = READ_SYSREG64(VTTBR_EL2);
>> -    if ( ovttbr != p2m->vttbr )
>> -    {
>> -        local_irq_save(flags);
>> -        WRITE_SYSREG64(p2m->vttbr, VTTBR_EL2);
>> -        isb();
>> -    }
>> +    p2m_switch_vttbr_and_get_flags(ovttbr, p2m->vttbr, flags);
>>
>>      flush_tlb();
>>
>> -    if ( ovttbr != READ_SYSREG64(VTTBR_EL2) )
>> -    {
>> -        WRITE_SYSREG64(ovttbr, VTTBR_EL2);
>> -        isb();
>> -        local_irq_restore(flags);
>> -    }
>> +    p2m_restore_vttbr_and_set_flags(ovttbr, flags);
>>  }
>>
>>  /*
>>
> 
> Regards,
> 


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 06/38] arm/p2m: Add HVMOP_altp2m_get_domain_state
  2016-09-01 17:06   ` Julien Grall
@ 2016-09-02  8:45     ` Sergej Proskurin
  0 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-02  8:45 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,

On 09/01/2016 07:06 PM, Julien Grall wrote:
> Hello Sergej,
> 
> On 16/08/16 23:16, Sergej Proskurin wrote:
>> This commit adopts the x86 HVMOP_altp2m_get_domain_state implementation.
>>
>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>> ---
>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>> Cc: Julien Grall <julien.grall@arm.com>
>> ---
>> v3: Removed the "altp2m_enabled" check in HVMOP_altp2m_get_domain_state
>>     case as it has been moved in front of the switch statement in
>>     "do_altp2m_op".
>>
>>     Removed the macro "altp2m_enabled". Instead, check directly for the
>>     HVM_PARAM_ALTP2M param in d->arch.hvm_domain.
>> ---
>>  xen/arch/arm/hvm.c | 5 +++--
>>  1 file changed, 3 insertions(+), 2 deletions(-)
>>
>> diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
>> index ce6a436..180154e 100644
>> --- a/xen/arch/arm/hvm.c
>> +++ b/xen/arch/arm/hvm.c
>> @@ -66,7 +66,7 @@ static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void)
>> arg)
>>          goto out;
>>      }
>>
>> -    if ( !(d)->arch.hvm_domain.params[HVM_PARAM_ALTP2M] )
>> +    if ( !d->arch.hvm_domain.params[HVM_PARAM_ALTP2M] )
> 
> Spurious change. This should be merged in patch #4.
> 

I will change that, thanks.

>>      {
>>          rc = -EINVAL;
>>          goto out;
>> @@ -78,7 +78,8 @@ static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void)
>> arg)
>>      switch ( a.cmd )
>>      {
>>      case HVMOP_altp2m_get_domain_state:
>> -        rc = -EOPNOTSUPP;
>> +        a.u.domain_state.state = altp2m_active(d);
>> +        rc = __copy_to_guest(arg, &a, 1) ? -EFAULT : 0;
>>          break;
>>
>>      case HVMOP_altp2m_set_domain_state:
>>
> 
> Regards,
> 

Best regards,
~Sergej

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 10/38] arm/p2m: Move hostp2m init/teardown to individual functions
  2016-09-01 17:36   ` Julien Grall
@ 2016-09-02  9:09     ` Sergej Proskurin
  2016-09-02 10:51       ` Julien Grall
  0 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-02  9:09 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,

On 09/01/2016 07:36 PM, Julien Grall wrote:
> Hello Sergej,
> 
> On 16/08/16 23:16, Sergej Proskurin wrote:
>> ---
>>  xen/arch/arm/p2m.c        | 71
>> +++++++++++++++++++++++++++++++++++++++++------
>>  xen/include/asm-arm/p2m.h | 11 ++++++++
>>  2 files changed, 73 insertions(+), 9 deletions(-)
>>
>> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
>> index e859fca..9ef19d4 100644
>> --- a/xen/arch/arm/p2m.c
>> +++ b/xen/arch/arm/p2m.c
>> @@ -1245,27 +1245,53 @@ static void p2m_free_vmid(struct domain *d)
>>      spin_unlock(&vmid_alloc_lock);
>>  }
>>
>> -void p2m_teardown(struct domain *d)
>> +/* Reset this p2m table to be empty. */
>> +void p2m_flush_table(struct p2m_domain *p2m)
>>  {
>> -    struct p2m_domain *p2m = p2m_get_hostp2m(d);
>> -    struct page_info *pg;
>> +    struct page_info *page, *pg;
>> +    unsigned int i;
>> +
>> +    if ( p2m->root )
>> +    {
>> +        page = p2m->root;
>> +
>> +        /* Clear all concatenated first level pages. */
> 
> s/first/root/
> 

Ok.

>> +        for ( i = 0; i < P2M_ROOT_PAGES; i++ )
>> +            clear_and_clean_page(page + i);
> 
> Clearing live page table like that is not safe. Each entry (64-bit)
> should be written atomically to avoid breaking coherency (e.g if the MMU
> is walking the page table at the same time). However you don't know the
> implementation of clear_and_clean_page.

The function p2m_flush_table gets called by the altp2m subsystem
indrectly through the function p2m_teardown_one when the associated view
gets destroyed. In this case we should not worry about crashing the
domain, as the altp2m views are not active anyway.

The function altp2m_reset calls the function p2m_flush_table directly
(with active altp2m views), however, locks the p2m before flushing the
table. I did not find any locks on page-granularity, so please provide
me with further information about the solution you had in mind.

> 
> Also, this adds a small overhead when tearing down a p2m because the
> clear is not necessary.
> 

The p2m views are cleared very rarely so the overhead is really minimal
as it affects clearing the root tables. Besides the function
altp2m_reset calls the function p2m_flush_table and assumes that the
root tables are cleared as well. If the root tables would not be cleared
at this point, stalled entries in the altp2m views that got wiped out in
the hostp2m would make the system unstable.

>> +    }
>> +
>> +    /*
>> +     * Flush TLBs before releasing remaining intermediate p2m page
>> tables to
>> +     * prevent illegal access to stalled TLB entries.
>> +     */
>> +    p2m_flush_tlb(p2m);
> 
> p2m_flush_table is called in 2 places:
>     - p2m_teardown_one
>     - altp2m_reset
> 
> For p2m_teardown_one, the p2m may not have been allocated because the
> initialization failed. So try flush the TLBs may lead to a panic in Xen
> (the vttbr is invalid).
> 
> For altp2m_reset, this is called while updating the page tables (see
> altp2m_propagate_change). vCPU may still use the page tables at that time.
> 
> I am a bit worry that clear_and_clean_page
> 
>>
>> +    /* Free the rest of the trie pages back to the paging pool. */
>>      while ( (pg = page_list_remove_head(&p2m->pages)) )
>>          free_domheap_page(pg);
>>
>> +    p2m->lowest_mapped_gfn = INVALID_GFN;
>> +    p2m->max_mapped_gfn = _gfn(0);
>> +}
>> +
>> +void p2m_teardown_one(struct p2m_domain *p2m)
>> +{
>> +    p2m_flush_table(p2m);
>> +
>>      if ( p2m->root )
>>          free_domheap_pages(p2m->root, P2M_ROOT_ORDER);
>>
>>      p2m->root = NULL;
>>
>> -    p2m_free_vmid(d);
>> +    p2m_free_vmid(p2m->domain);
>> +
>> +    p2m->vttbr = INVALID_VTTBR;
> 
> Why did you add this line?
> 

Ok. On every p2m_teardown_one invocation the p2m gets destroyed. That
is, I will remove this additional resetting of the VTTBR in the next
patch. Thank you.

>>
>>      radix_tree_destroy(&p2m->mem_access_settings, NULL);
>>  }
>>
>> -int p2m_init(struct domain *d)
>> +int p2m_init_one(struct domain *d, struct p2m_domain *p2m)
>>  {
>> -    struct p2m_domain *p2m = p2m_get_hostp2m(d);
>>      int rc = 0;
>>
>>      rwlock_init(&p2m->lock);
>> @@ -1278,11 +1304,14 @@ int p2m_init(struct domain *d)
>>          return rc;
>>
>>      p2m->max_mapped_gfn = _gfn(0);
>> -    p2m->lowest_mapped_gfn = _gfn(ULONG_MAX);
>> +    p2m->lowest_mapped_gfn = INVALID_GFN;
> 
> Why this change?
> 

Since we compare the gfn's with INVALID_GFN throughout the code it makes
sense to use the macro instead of a hardcoded value.

>>
>>      p2m->domain = d;
>> +    p2m->access_required = false;
> 
> This is not necessary as the p2m is zeroed during the allocation.
> 

Since the p2m is zeroed out at this moment, I can savely remove this
initialization.

>>      p2m->default_access = p2m_access_rwx;
>>      p2m->mem_access_enabled = false;
>> +    p2m->root = NULL;
>> +    p2m->vttbr = INVALID_VTTBR;
> 
> Why do you add those 2 lines?
> 

Same here.

>>      radix_tree_init(&p2m->mem_access_settings);
>>
>>      /*
>> @@ -1293,9 +1322,33 @@ int p2m_init(struct domain *d)
>>      p2m->clean_pte = iommu_enabled &&
>>          !iommu_has_feature(d, IOMMU_FEAT_COHERENT_WALK);
>>
>> -    rc = p2m_alloc_table(d);
>> +    return p2m_alloc_table(d);
>> +}
>>
>> -    return rc;
>> +static void p2m_teardown_hostp2m(struct domain *d)
>> +{
>> +    struct p2m_domain *p2m = p2m_get_hostp2m(d);
>> +
>> +    p2m_teardown_one(p2m);
>> +}
>> +
>> +void p2m_teardown(struct domain *d)
>> +{
>> +    p2m_teardown_hostp2m(d);
>> +}
>> +
>> +static int p2m_init_hostp2m(struct domain *d)
>> +{
>> +    struct p2m_domain *p2m = p2m_get_hostp2m(d);
>> +
>> +    p2m->p2m_class = p2m_host;
>> +
>> +    return p2m_init_one(d, p2m);
>> +}
>> +
>> +int p2m_init(struct domain *d)
>> +{
>> +    return p2m_init_hostp2m(d);
>>  }
>>
>>  /*
>> diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
>> index fa07e19..1a004ed 100644
>> --- a/xen/include/asm-arm/p2m.h
>> +++ b/xen/include/asm-arm/p2m.h
>> @@ -11,6 +11,8 @@
>>
>>  #define paddr_bits PADDR_BITS
>>
>> +#define INVALID_VTTBR (0UL)
> 
> Looking at the current use, you only use INVALID_VTTBR to set but not
> tested. However, the 2 places where it is use are not necessary.
> 

I will remove the macro including the both cases, where it is used for
initialization.

>> +
>>  /* Holds the bit size of IPAs in p2m tables.  */
>>  extern unsigned int p2m_ipa_bits;
>>
>> @@ -226,6 +228,15 @@ void guest_physmap_remove_page(struct domain *d,
>>
>>  mfn_t gfn_to_mfn(struct domain *d, gfn_t gfn);
>>
>> +/* Flushes the page table held by the p2m. */
>> +void p2m_flush_table(struct p2m_domain *p2m);
>> +
>> +/* Initialize the p2m structure. */
>> +int p2m_init_one(struct domain *d, struct p2m_domain *p2m);
>> +
>> +/* Release resources held by the p2m structure. */
>> +void p2m_teardown_one(struct p2m_domain *p2m);
>> +
>>  /*
>>   * P2M rwlock helpers.
>>   */
>>
> 
> Regards,
> 

Best regards,
~Sergej

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 04/38] arm/p2m: Add first altp2m HVMOP stubs
  2016-09-01 16:09   ` Julien Grall
@ 2016-09-02  9:26     ` Sergej Proskurin
  2016-09-02 10:12       ` Julien Grall
  0 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-02  9:26 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,

On 09/01/2016 06:09 PM, Julien Grall wrote:
> Hello Sergej,
> 
> On 16/08/16 23:16, Sergej Proskurin wrote:
>> This commit moves the altp2m-related code from x86 to ARM. Functions
> 
> s/moves/copies/
> 
> However, this is not really true because the code is current patch is
> not a verbatim copy.
> 

Ok, I will adapt the commit msg to "copies and extends" in the next patch.

> Lastly, what is the status to have x86 and ARM implementation of
> do_altp2m_op merged?
> 
> It would allow us to get code clean-up more easily. I have in mind the
> recent patch [1] from Paul Lai.
> 
> I am also worry to see the code diverging, for instance the locking is
> likely needed on x86 too.
> 

We believe that (while merging of both code bases definitely does makes
sense) it is out of scope in this patch. The changes you are suggesting
would further blow up this patch series. The current patch series is
already large enough and we really think we should keep focusing on the
implementation the ARM architecture in the first place. We agree that a
merge of both architectures is necessary but also strongly believe that
the merging should be done in a separate patch.

>> that are no yet supported notify the caller or print a BUG message
>> stating their absence.
>>
>> Also, the struct arch_domain is extended with the altp2m_active
>> attribute, representing the current altp2m activity configuration of the
>> domain.
>>
>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>> ---
>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>> Cc: Julien Grall <julien.grall@arm.com>
>> ---
>> v2: Removed altp2m command-line option: Guard through HVM_PARAM_ALTP2M.
>>     Removed not used altp2m helper stubs in altp2m.h.
>>
>> v3: Cosmetic fixes.
>>
>>     Added domain lock in "do_altp2m_op" to avoid concurrent execution of
>>     altp2m-related HVMOPs.
>>
>>     Added check making sure that HVM_PARAM_ALTP2M is set before
>>     execution of altp2m-related HVMOPs.
>> ---
>>  xen/arch/arm/hvm.c           | 89
>> ++++++++++++++++++++++++++++++++++++++++++++
>>  xen/include/asm-arm/altp2m.h |  4 +-
>>  xen/include/asm-arm/domain.h |  3 ++
>>  3 files changed, 94 insertions(+), 2 deletions(-)
>>
>> diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
>> index d999bde..45d51c6 100644
>> --- a/xen/arch/arm/hvm.c
>> +++ b/xen/arch/arm/hvm.c
>> @@ -32,6 +32,91 @@
>>
>>  #include <asm/hypercall.h>
>>
>> +#include <asm/altp2m.h>
>> +
>> +static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
>> +{
>> +    struct xen_hvm_altp2m_op a;
>> +    struct domain *d = NULL;
>> +    int rc = 0;
>> +
>> +    if ( copy_from_guest(&a, arg, 1) )
>> +        return -EFAULT;
>> +
>> +    if ( a.pad1 || a.pad2 ||
>> +         (a.version != HVMOP_ALTP2M_INTERFACE_VERSION) ||
>> +         (a.cmd < HVMOP_altp2m_get_domain_state) ||
>> +         (a.cmd > HVMOP_altp2m_change_gfn) )
>> +        return -EINVAL;
>> +
>> +    d = (a.cmd != HVMOP_altp2m_vcpu_enable_notify) ?
>> +        rcu_lock_domain_by_any_id(a.domain) : rcu_lock_current_domain();
>> +
>> +    if ( d == NULL )
>> +        return -ESRCH;
>> +
>> +    /* Prevent concurrent execution of the following HVMOPs. */
>> +    domain_lock(d);
> 
> So you are not allowing concurrent call of set_mem_access on different
> altp2m. Is it something that you plan to fix in the future?
> 

Concurrent access of the altp2m interface, including the set_mem_access
on different altp2m views, is not performance relevant. However, we will
definitely think about which HVMOPs can be executed concurrently without
causing troubles.

>> +
>> +    if ( (a.cmd != HVMOP_altp2m_get_domain_state) &&
>> +         (a.cmd != HVMOP_altp2m_set_domain_state) &&
>> +         !altp2m_active(d) )
>> +    {
>> +        rc = -EOPNOTSUPP;
>> +        goto out;
>> +    }
>> +
>> +    if ( !(d)->arch.hvm_domain.params[HVM_PARAM_ALTP2M] )
>> +    {
>> +        rc = -EINVAL;
>> +        goto out;
>> +    }
>> +
>> +    if ( (rc = xsm_hvm_altp2mhvm_op(XSM_TARGET, d)) )
>> +        goto out;
>> +
>> +    switch ( a.cmd )
>> +    {
>> +    case HVMOP_altp2m_get_domain_state:
>> +        rc = -EOPNOTSUPP;
>> +        break;
>> +
>> +    case HVMOP_altp2m_set_domain_state:
>> +        rc = -EOPNOTSUPP;
>> +        break;
>> +
>> +    case HVMOP_altp2m_vcpu_enable_notify:
>> +        rc = -EOPNOTSUPP;
>> +        break;
>> +
>> +    case HVMOP_altp2m_create_p2m:
>> +        rc = -EOPNOTSUPP;
>> +        break;
>> +
>> +    case HVMOP_altp2m_destroy_p2m:
>> +        rc = -EOPNOTSUPP;
>> +        break;
>> +
>> +    case HVMOP_altp2m_switch_p2m:
>> +        rc = -EOPNOTSUPP;
>> +        break;
>> +
>> +    case HVMOP_altp2m_set_mem_access:
>> +        rc = -EOPNOTSUPP;
>> +        break;
>> +
>> +    case HVMOP_altp2m_change_gfn:
>> +        rc = -EOPNOTSUPP;
>> +        break;
>> +    }
>> +
>> +out:
>> +    domain_unlock(d);
>> +    rcu_unlock_domain(d);
>> +
>> +    return rc;
>> +}
>> +
>>  long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
>>  {
>>      long rc = 0;
>> @@ -80,6 +165,10 @@ long do_hvm_op(unsigned long op,
>> XEN_GUEST_HANDLE_PARAM(void) arg)
>>              rc = -EINVAL;
>>          break;
>>
>> +    case HVMOP_altp2m:
>> +        rc = do_altp2m_op(arg);
>> +        break;
>> +
>>      default:
>>      {
>>          gdprintk(XENLOG_DEBUG, "HVMOP op=%lu: not implemented\n", op);
>> diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
>> index a87747a..0711796 100644
>> --- a/xen/include/asm-arm/altp2m.h
>> +++ b/xen/include/asm-arm/altp2m.h
>> @@ -2,6 +2,7 @@
>>   * Alternate p2m
>>   *
>>   * Copyright (c) 2014, Intel Corporation.
>> + * Copyright (c) 2016, Sergej Proskurin <proskurin@sec.in.tum.de>.
>>   *
>>   * This program is free software; you can redistribute it and/or
>> modify it
>>   * under the terms and conditions of the GNU General Public License,
>> @@ -24,8 +25,7 @@
>>  /* Alternate p2m on/off per domain */
>>  static inline bool_t altp2m_active(const struct domain *d)
>>  {
>> -    /* Not implemented on ARM. */
>> -    return 0;
>> +    return d->arch.altp2m_active;
>>  }
>>
>>  /* Alternate p2m VCPU */
>> diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
>> index 9452fcd..cc4bda0 100644
>> --- a/xen/include/asm-arm/domain.h
>> +++ b/xen/include/asm-arm/domain.h
>> @@ -126,6 +126,9 @@ struct arch_domain
>>      paddr_t efi_acpi_gpa;
>>      paddr_t efi_acpi_len;
>>  #endif
>> +
>> +    /* altp2m: allow multiple copies of host p2m */
>> +    bool_t altp2m_active;
>>  }  __cacheline_aligned;
>>
>>  struct arch_vcpu
>>
> 
> Regards,
> 
> [1]
> https://lists.xenproject.org/archives/html/xen-devel/2016-08/msg02407.html
> 

Best regards,
~Sergej

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 08/38] arm/p2m: Free p2m entries only in the hostp2m
  2016-09-01 17:08   ` Julien Grall
@ 2016-09-02  9:38     ` Sergej Proskurin
  0 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-02  9:38 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,

On 09/01/2016 07:08 PM, Julien Grall wrote:
> Hello Sergej,
> 
> On 16/08/16 23:16, Sergej Proskurin wrote:
>> Freeing p2m entries of arbitrary p2m's (in particular in alternate
>> p2m's) will lead to unpredicted behavior as the entries might still be
>> used within the host's p2m. The host's p2m should, however, free the
>> entries, as it is the main instance responsible for their management. If
>> entries were freed in the host's p2m, but still reside in one or more of
>> the alternate p2m's, the change will be propagated to these functions as
>> will be shown in the following commits.
>>
>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>> ---
>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>> Cc: Julien Grall <julien.grall@arm.com>
>> ---
>>  xen/arch/arm/p2m.c | 4 +++-
>>  1 file changed, 3 insertions(+), 1 deletion(-)
>>
>> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
>> index 02e9ee7..bfbccca 100644
>> --- a/xen/arch/arm/p2m.c
>> +++ b/xen/arch/arm/p2m.c
>> @@ -1004,7 +1004,9 @@ static int __p2m_set_entry(struct p2m_domain *p2m,
>>       * Free the entry only if the original pte was valid and the base
>>       * is different (to avoid freeing when permission is changed).
>>       */
>> -    if ( p2m_valid(orig_pte) && entry->p2m.base != orig_pte.p2m.base )
>> +    if ( p2m_valid(orig_pte) &&
>> +         entry->p2m.base != orig_pte.p2m.base &&
>> +         p2m_is_hostp2m(p2m) )
> 
> With this change, intermediate page table will not be freed which will
> lead to keep the memory used (and therefore unavailable for others)
> until the p2m is effectively destroyed.
> 

Makes sense. I will come back to this comment after I have done more
testing.

Best regards,
~Sergej

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 03/38] arm/p2m: Introduce p2m_(switch|restore)_vttbr_and_(g|s)et_flags
  2016-09-02  8:40     ` Sergej Proskurin
@ 2016-09-02  9:57       ` Julien Grall
  2016-09-02 10:15         ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-02  9:57 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini



On 02/09/16 09:40, Sergej Proskurin wrote:
> Hi Julien,

Hello Sergej,

> On 09/01/2016 05:51 PM, Julien Grall wrote:
>> Hello Sergej,
>>
>> On 16/08/16 23:16, Sergej Proskurin wrote:
>>> This commit introduces macros for switching and restoring the vttbr
>>> considering the currently set irq flags. We define these macros, as the
>>> following commits will use the associated functionality multiple times
>>> throughout the file ./xen/arch/arm/p2m.c.
>>>
>>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>>> ---
>>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>>> Cc: Julien Grall <julien.grall@arm.com>
>>> ---
>>>  xen/arch/arm/p2m.c | 37 +++++++++++++++++++++++--------------
>>>  1 file changed, 23 insertions(+), 14 deletions(-)
>>>
>>> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
>>> index 08114d8..02e9ee7 100644
>>> --- a/xen/arch/arm/p2m.c
>>> +++ b/xen/arch/arm/p2m.c
>>> @@ -27,6 +27,26 @@ static unsigned int __read_mostly p2m_root_level;
>>>
>>>  #define P2M_ROOT_PAGES    (1<<P2M_ROOT_ORDER)
>>>
>>> +#define p2m_switch_vttbr_and_get_flags(ovttbr, nvttbr, flags)       \
>>> +({                                                                  \
>>
>> It makes more sense to save the content of VTTBR_EL2 in the macro.
>>
> 
> I assume you mean the VTTBR_EL2 within the macro parameter ovttbr. I
> will move the definition of the ovttbr variable into the macro and
> return its value at the end so that it can be subsequently provided with
> the "p2m_restore_vttbr_and_set_flags" macro. Thank you.

I meant

#define p2m_switch_vttbr_and_get_flags(ovttbr, nvttbr, flags)		\
({									\
	ovttbr = READ_SYSREG(VTTBR_EL2);				\
	if ( ovttbr != nvttbr )						\
	{								\
		local_irq_save(flags);					\
		WRITE_SYSREG64(nvttbr, VTTBR_EL2);			\
		isb();							\
	}
})

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 04/38] arm/p2m: Add first altp2m HVMOP stubs
  2016-09-02  9:26     ` Sergej Proskurin
@ 2016-09-02 10:12       ` Julien Grall
  2016-09-02 10:24         ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-02 10:12 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini



On 02/09/16 10:26, Sergej Proskurin wrote:
> Hi Julien,

Hello Sergej,

> On 09/01/2016 06:09 PM, Julien Grall wrote:
>> Hello Sergej,
>>
>> On 16/08/16 23:16, Sergej Proskurin wrote:
>>> This commit moves the altp2m-related code from x86 to ARM. Functions
>>
>> s/moves/copies/
>>
>> However, this is not really true because the code is current patch is
>> not a verbatim copy.
>>
>
> Ok, I will adapt the commit msg to "copies and extends" in the next patch.
>
>> Lastly, what is the status to have x86 and ARM implementation of
>> do_altp2m_op merged?
>>
>> It would allow us to get code clean-up more easily. I have in mind the
>> recent patch [1] from Paul Lai.
>>
>> I am also worry to see the code diverging, for instance the locking is
>> likely needed on x86 too.
>>
>
> We believe that (while merging of both code bases definitely does makes
> sense) it is out of scope in this patch. The changes you are suggesting
> would further blow up this patch series. The current patch series is
> already large enough and we really think we should keep focusing on the
> implementation the ARM architecture in the first place. We agree that a
> merge of both architectures is necessary but also strongly believe that
> the merging should be done in a separate patch.

That's why you usually have small series to clean-up/move the code 
beforehand. Some of the patch in this series could have been avoided if 
you had a series beforehand to move the x86 code in the common code 
(which is very straight forward).

My concern here is this code will never get merged and it will continue 
to diverge. A lot of locking issue are also present in x86 path, so I 
don't understand why they should not be fixed now and wait until it get 
merged. So with the plan suggested, ARM and x86 does not benefit of each 
others patches.

Anyway, I would like to get an action from you to send a series merging 
the two implementation as soon as possible (i.e before Xen 4.9).

>>> that are no yet supported notify the caller or print a BUG message
>>> stating their absence.
>>>
>>> Also, the struct arch_domain is extended with the altp2m_active
>>> attribute, representing the current altp2m activity configuration of the
>>> domain.
>>>
>>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>>> ---
>>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>>> Cc: Julien Grall <julien.grall@arm.com>
>>> ---
>>> v2: Removed altp2m command-line option: Guard through HVM_PARAM_ALTP2M.
>>>     Removed not used altp2m helper stubs in altp2m.h.
>>>
>>> v3: Cosmetic fixes.
>>>
>>>     Added domain lock in "do_altp2m_op" to avoid concurrent execution of
>>>     altp2m-related HVMOPs.
>>>
>>>     Added check making sure that HVM_PARAM_ALTP2M is set before
>>>     execution of altp2m-related HVMOPs.
>>> ---
>>>  xen/arch/arm/hvm.c           | 89
>>> ++++++++++++++++++++++++++++++++++++++++++++
>>>  xen/include/asm-arm/altp2m.h |  4 +-
>>>  xen/include/asm-arm/domain.h |  3 ++
>>>  3 files changed, 94 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
>>> index d999bde..45d51c6 100644
>>> --- a/xen/arch/arm/hvm.c
>>> +++ b/xen/arch/arm/hvm.c
>>> @@ -32,6 +32,91 @@
>>>
>>>  #include <asm/hypercall.h>
>>>
>>> +#include <asm/altp2m.h>
>>> +
>>> +static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
>>> +{
>>> +    struct xen_hvm_altp2m_op a;
>>> +    struct domain *d = NULL;
>>> +    int rc = 0;
>>> +
>>> +    if ( copy_from_guest(&a, arg, 1) )
>>> +        return -EFAULT;
>>> +
>>> +    if ( a.pad1 || a.pad2 ||
>>> +         (a.version != HVMOP_ALTP2M_INTERFACE_VERSION) ||
>>> +         (a.cmd < HVMOP_altp2m_get_domain_state) ||
>>> +         (a.cmd > HVMOP_altp2m_change_gfn) )
>>> +        return -EINVAL;
>>> +
>>> +    d = (a.cmd != HVMOP_altp2m_vcpu_enable_notify) ?
>>> +        rcu_lock_domain_by_any_id(a.domain) : rcu_lock_current_domain();
>>> +
>>> +    if ( d == NULL )
>>> +        return -ESRCH;
>>> +
>>> +    /* Prevent concurrent execution of the following HVMOPs. */
>>> +    domain_lock(d);
>>
>> So you are not allowing concurrent call of set_mem_access on different
>> altp2m. Is it something that you plan to fix in the future?
>>
>
> Concurrent access of the altp2m interface, including the set_mem_access
> on different altp2m views, is not performance relevant. However, we will
> definitely think about which HVMOPs can be executed concurrently without
> causing troubles.

It might be worth to add a TODO here.

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 02/38] arm/p2m: Expose p2m_*lock helpers
  2016-09-01 15:48   ` Julien Grall
@ 2016-09-02 10:12     ` Sergej Proskurin
  2016-09-02 10:15       ` Julien Grall
  0 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-02 10:12 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,

On 09/01/2016 05:48 PM, Julien Grall wrote:
> Hello Sergej,
> 
> On 16/08/16 23:16, Sergej Proskurin wrote:
>> This commit exposes the "p2m_*lock" helpers, as they will be used within
>> the file ./xen/arch/arm/altp2m.c, as will be shown in the following
>> commits.
>>
>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>> ---
>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>> Cc: Julien Grall <julien.grall@arm.com>
>> ---
>>  xen/arch/arm/p2m.c        | 12 ++++++------
>>  xen/include/asm-arm/p2m.h | 16 ++++++++++++++++
>>  2 files changed, 22 insertions(+), 6 deletions(-)
>>
>> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
>> index da6c7d4..08114d8 100644
>> --- a/xen/arch/arm/p2m.c
>> +++ b/xen/arch/arm/p2m.c
>> @@ -62,14 +62,14 @@ static inline bool_t p2m_is_superpage(lpae_t pte,
>> unsigned int level)
>>      return (level < 3) && p2m_mapping(pte);
>>  }
>>
>> -static inline void p2m_write_lock(struct p2m_domain *p2m)
>> +void p2m_write_lock(struct p2m_domain *p2m)
> 
> This will introduce an overhead when locking the p2m. Those helpers
> should be moved a inline in p2m.h and not transform to a functions.
> 

I did not move the definitions of the functions into the header file to
avoid exposing the static function p2m_flush_tlb. However, what I can do
is to declare the function prototypes in p2m.h and define them as inline
in p2m.c, which should provide the same effect.

Best regards,
~Sergej

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 03/38] arm/p2m: Introduce p2m_(switch|restore)_vttbr_and_(g|s)et_flags
  2016-09-02  9:57       ` Julien Grall
@ 2016-09-02 10:15         ` Sergej Proskurin
  0 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-02 10:15 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,

On 09/02/2016 11:57 AM, Julien Grall wrote:
> 
> 
> On 02/09/16 09:40, Sergej Proskurin wrote:
>> Hi Julien,
> 
> Hello Sergej,
> 
>> On 09/01/2016 05:51 PM, Julien Grall wrote:
>>> Hello Sergej,
>>>
>>> On 16/08/16 23:16, Sergej Proskurin wrote:
>>>> This commit introduces macros for switching and restoring the vttbr
>>>> considering the currently set irq flags. We define these macros, as the
>>>> following commits will use the associated functionality multiple times
>>>> throughout the file ./xen/arch/arm/p2m.c.
>>>>
>>>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>>>> ---
>>>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>>>> Cc: Julien Grall <julien.grall@arm.com>
>>>> ---
>>>>  xen/arch/arm/p2m.c | 37 +++++++++++++++++++++++--------------
>>>>  1 file changed, 23 insertions(+), 14 deletions(-)
>>>>
>>>> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
>>>> index 08114d8..02e9ee7 100644
>>>> --- a/xen/arch/arm/p2m.c
>>>> +++ b/xen/arch/arm/p2m.c
>>>> @@ -27,6 +27,26 @@ static unsigned int __read_mostly p2m_root_level;
>>>>
>>>>  #define P2M_ROOT_PAGES    (1<<P2M_ROOT_ORDER)
>>>>
>>>> +#define p2m_switch_vttbr_and_get_flags(ovttbr, nvttbr, flags)       \
>>>> +({                                                                  \
>>>
>>> It makes more sense to save the content of VTTBR_EL2 in the macro.
>>>
>>
>> I assume you mean the VTTBR_EL2 within the macro parameter ovttbr. I
>> will move the definition of the ovttbr variable into the macro and

s/definition/initialization/

>> return its value at the end so that it can be subsequently provided with
>> the "p2m_restore_vttbr_and_set_flags" macro. Thank you.
> 
> I meant
> 
> #define p2m_switch_vttbr_and_get_flags(ovttbr, nvttbr, flags)		\
> ({									\
> 	ovttbr = READ_SYSREG(VTTBR_EL2);				\
> 	if ( ovttbr != nvttbr )						\
> 	{								\
> 		local_irq_save(flags);					\
> 		WRITE_SYSREG64(nvttbr, VTTBR_EL2);			\
> 		isb();							\
> 	}
> })
> 

That is what I understood, thank you :)

Cheers,
~Sergej

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 02/38] arm/p2m: Expose p2m_*lock helpers
  2016-09-02 10:12     ` Sergej Proskurin
@ 2016-09-02 10:15       ` Julien Grall
  2016-09-02 10:29         ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-02 10:15 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

On 02/09/16 11:12, Sergej Proskurin wrote:
> Hi Julien,

Hello Sergej,

> On 09/01/2016 05:48 PM, Julien Grall wrote:
>> Hello Sergej,
>>
>> On 16/08/16 23:16, Sergej Proskurin wrote:
>>> This commit exposes the "p2m_*lock" helpers, as they will be used within
>>> the file ./xen/arch/arm/altp2m.c, as will be shown in the following
>>> commits.
>>>
>>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>>> ---
>>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>>> Cc: Julien Grall <julien.grall@arm.com>
>>> ---
>>>  xen/arch/arm/p2m.c        | 12 ++++++------
>>>  xen/include/asm-arm/p2m.h | 16 ++++++++++++++++
>>>  2 files changed, 22 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
>>> index da6c7d4..08114d8 100644
>>> --- a/xen/arch/arm/p2m.c
>>> +++ b/xen/arch/arm/p2m.c
>>> @@ -62,14 +62,14 @@ static inline bool_t p2m_is_superpage(lpae_t pte,
>>> unsigned int level)
>>>      return (level < 3) && p2m_mapping(pte);
>>>  }
>>>
>>> -static inline void p2m_write_lock(struct p2m_domain *p2m)
>>> +void p2m_write_lock(struct p2m_domain *p2m)
>>
>> This will introduce an overhead when locking the p2m. Those helpers
>> should be moved a inline in p2m.h and not transform to a functions.
>>
> 
> I did not move the definitions of the functions into the header file to
> avoid exposing the static function p2m_flush_tlb. However, what I can do
> is to declare the function prototypes in p2m.h and define them as inline
> in p2m.c, which should provide the same effect.

It will not have the same effect for call of p2m_*lock outside of p2m.c.
p2m_flush_tlb is only used in p2m_write_unlock, so what is the problem to
move the implement of all p2m_*lock but p2m_write_unlock in p2m.h?

commit 57b5214c6225c113b3cc50edbadce81b84e0a32c
Author: Julien Grall <julien.grall@arm.com>
Date:   Tue Aug 2 15:48:48 2016 +0100

    xen/arm: p2m: Export p2m_*_lock helpers
    
    Early patch exported the p2m interface (p2m_get_entry and p2m_set_entry)
    to allow splitting xen/arch/arm/p2m.c. Those functions require the
    callers to lock the p2m, so we need to export p2m_*_lock helpers.
    
    All helpers but p2m_write_unlock but p2m_write_unlock are moved in
    xen/include/asm-arm/p2m.h to allow inlining. The helpers
    p2m_write_unlock is kept in p2m.c because it depends on a static
    function.
    
    Signed-off-by: Julien Grall <julien.grall@arm.com>
    
    ---
        Changes in v2:
            - Patch added

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index f4a808c..e41ed3c 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -62,14 +62,10 @@ static inline bool_t p2m_is_superpage(lpae_t pte, unsigned int level)
     return (level < 3) && p2m_mapping(pte);
 }
 
-static inline void p2m_write_lock(struct p2m_domain *p2m)
-{
-    write_lock(&p2m->lock);
-}
-
 static void p2m_flush_tlb(struct p2m_domain *p2m);
 
-static inline void p2m_write_unlock(struct p2m_domain *p2m)
+/* Unlock the flush and do a P2M TLB flush if necessary */
+void p2m_write_unlock(struct p2m_domain *p2m)
 {
     if ( p2m->need_flush )
     {
@@ -85,26 +81,6 @@ static inline void p2m_write_unlock(struct p2m_domain *p2m)
     write_unlock(&p2m->lock);
 }
 
-static inline void p2m_read_lock(struct p2m_domain *p2m)
-{
-    read_lock(&p2m->lock);
-}
-
-static inline void p2m_read_unlock(struct p2m_domain *p2m)
-{
-    read_unlock(&p2m->lock);
-}
-
-static inline int p2m_is_locked(struct p2m_domain *p2m)
-{
-    return rw_is_locked(&p2m->lock);
-}
-
-static inline int p2m_is_write_locked(struct p2m_domain *p2m)
-{
-    return rw_is_write_locked(&p2m->lock);
-}
-
 void p2m_dump_info(struct domain *d)
 {
     struct p2m_domain *p2m = &d->arch.p2m;
diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
index c2f4f98..9b0cade 100644
--- a/xen/include/asm-arm/p2m.h
+++ b/xen/include/asm-arm/p2m.h
@@ -173,6 +173,33 @@ void p2m_restore_state(struct vcpu *n);
 /* Print debugging/statistial info about a domain's p2m */
 void p2m_dump_info(struct domain *d);
 
+static inline void p2m_write_lock(struct p2m_domain *p2m)
+{
+    write_lock(&p2m->lock);
+}
+
+void p2m_write_unlock(struct p2m_domain *p2m);
+
+static inline void p2m_read_lock(struct p2m_domain *p2m)
+{
+    read_lock(&p2m->lock);
+}
+
+static inline void p2m_read_unlock(struct p2m_domain *p2m)
+{
+    read_unlock(&p2m->lock);
+}
+
+static inline int p2m_is_locked(struct p2m_domain *p2m)
+{
+    return rw_is_locked(&p2m->lock);
+}
+
+static inline int p2m_is_write_locked(struct p2m_domain *p2m)
+{
+    return rw_is_write_locked(&p2m->lock);
+}
+
 /* Look up the MFN corresponding to a domain's GFN. */
 mfn_t p2m_lookup(struct domain *d, gfn_t gfn, p2m_type_t *t);
 
-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 04/38] arm/p2m: Add first altp2m HVMOP stubs
  2016-09-02 10:12       ` Julien Grall
@ 2016-09-02 10:24         ` Sergej Proskurin
  0 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-02 10:24 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,

On 09/02/2016 12:12 PM, Julien Grall wrote:
> 
> 
> On 02/09/16 10:26, Sergej Proskurin wrote:
>> Hi Julien,
> 
> Hello Sergej,
> 
>> On 09/01/2016 06:09 PM, Julien Grall wrote:
>>> Hello Sergej,
>>>
>>> On 16/08/16 23:16, Sergej Proskurin wrote:
>>>> This commit moves the altp2m-related code from x86 to ARM. Functions
>>>
>>> s/moves/copies/
>>>
>>> However, this is not really true because the code is current patch is
>>> not a verbatim copy.
>>>
>>
>> Ok, I will adapt the commit msg to "copies and extends" in the next
>> patch.
>>
>>> Lastly, what is the status to have x86 and ARM implementation of
>>> do_altp2m_op merged?
>>>
>>> It would allow us to get code clean-up more easily. I have in mind the
>>> recent patch [1] from Paul Lai.
>>>
>>> I am also worry to see the code diverging, for instance the locking is
>>> likely needed on x86 too.
>>>
>>
>> We believe that (while merging of both code bases definitely does makes
>> sense) it is out of scope in this patch. The changes you are suggesting
>> would further blow up this patch series. The current patch series is
>> already large enough and we really think we should keep focusing on the
>> implementation the ARM architecture in the first place. We agree that a
>> merge of both architectures is necessary but also strongly believe that
>> the merging should be done in a separate patch.
> 
> That's why you usually have small series to clean-up/move the code
> beforehand. Some of the patch in this series could have been avoided if
> you had a series beforehand to move the x86 code in the common code
> (which is very straight forward).
> 
> My concern here is this code will never get merged and it will continue
> to diverge. A lot of locking issue are also present in x86 path, so I
> don't understand why they should not be fixed now and wait until it get
> merged. So with the plan suggested, ARM and x86 does not benefit of each
> others patches.
> 
> Anyway, I would like to get an action from you to send a series merging
> the two implementation as soon as possible (i.e before Xen 4.9).
> 

I understand your concern and agree on working towards a merged version
between both architectures. Thank you.

>>>> that are no yet supported notify the caller or print a BUG message
>>>> stating their absence.
>>>>
>>>> Also, the struct arch_domain is extended with the altp2m_active
>>>> attribute, representing the current altp2m activity configuration of
>>>> the
>>>> domain.
>>>>
>>>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>>>> ---
>>>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>>>> Cc: Julien Grall <julien.grall@arm.com>
>>>> ---
>>>> v2: Removed altp2m command-line option: Guard through HVM_PARAM_ALTP2M.
>>>>     Removed not used altp2m helper stubs in altp2m.h.
>>>>
>>>> v3: Cosmetic fixes.
>>>>
>>>>     Added domain lock in "do_altp2m_op" to avoid concurrent
>>>> execution of
>>>>     altp2m-related HVMOPs.
>>>>
>>>>     Added check making sure that HVM_PARAM_ALTP2M is set before
>>>>     execution of altp2m-related HVMOPs.
>>>> ---
>>>>  xen/arch/arm/hvm.c           | 89
>>>> ++++++++++++++++++++++++++++++++++++++++++++
>>>>  xen/include/asm-arm/altp2m.h |  4 +-
>>>>  xen/include/asm-arm/domain.h |  3 ++
>>>>  3 files changed, 94 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
>>>> index d999bde..45d51c6 100644
>>>> --- a/xen/arch/arm/hvm.c
>>>> +++ b/xen/arch/arm/hvm.c
>>>> @@ -32,6 +32,91 @@
>>>>
>>>>  #include <asm/hypercall.h>
>>>>
>>>> +#include <asm/altp2m.h>
>>>> +
>>>> +static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
>>>> +{
>>>> +    struct xen_hvm_altp2m_op a;
>>>> +    struct domain *d = NULL;
>>>> +    int rc = 0;
>>>> +
>>>> +    if ( copy_from_guest(&a, arg, 1) )
>>>> +        return -EFAULT;
>>>> +
>>>> +    if ( a.pad1 || a.pad2 ||
>>>> +         (a.version != HVMOP_ALTP2M_INTERFACE_VERSION) ||
>>>> +         (a.cmd < HVMOP_altp2m_get_domain_state) ||
>>>> +         (a.cmd > HVMOP_altp2m_change_gfn) )
>>>> +        return -EINVAL;
>>>> +
>>>> +    d = (a.cmd != HVMOP_altp2m_vcpu_enable_notify) ?
>>>> +        rcu_lock_domain_by_any_id(a.domain) :
>>>> rcu_lock_current_domain();
>>>> +
>>>> +    if ( d == NULL )
>>>> +        return -ESRCH;
>>>> +
>>>> +    /* Prevent concurrent execution of the following HVMOPs. */
>>>> +    domain_lock(d);
>>>
>>> So you are not allowing concurrent call of set_mem_access on different
>>> altp2m. Is it something that you plan to fix in the future?
>>>
>>
>> Concurrent access of the altp2m interface, including the set_mem_access
>> on different altp2m views, is not performance relevant. However, we will
>> definitely think about which HVMOPs can be executed concurrently without
>> causing troubles.
> 
> It might be worth to add a TODO here.
> 

I will add a TODO stating the upper idea, thank you.

Cheers,
~Sergej

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 02/38] arm/p2m: Expose p2m_*lock helpers
  2016-09-02 10:15       ` Julien Grall
@ 2016-09-02 10:29         ` Sergej Proskurin
  0 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-02 10:29 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,

On 09/02/2016 12:15 PM, Julien Grall wrote:
> On 02/09/16 11:12, Sergej Proskurin wrote:
>> Hi Julien,
> 
> Hello Sergej,
> 
>> On 09/01/2016 05:48 PM, Julien Grall wrote:
>>> Hello Sergej,
>>>
>>> On 16/08/16 23:16, Sergej Proskurin wrote:
>>>> This commit exposes the "p2m_*lock" helpers, as they will be used within
>>>> the file ./xen/arch/arm/altp2m.c, as will be shown in the following
>>>> commits.
>>>>
>>>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>>>> ---
>>>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>>>> Cc: Julien Grall <julien.grall@arm.com>
>>>> ---
>>>>  xen/arch/arm/p2m.c        | 12 ++++++------
>>>>  xen/include/asm-arm/p2m.h | 16 ++++++++++++++++
>>>>  2 files changed, 22 insertions(+), 6 deletions(-)
>>>>
>>>> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
>>>> index da6c7d4..08114d8 100644
>>>> --- a/xen/arch/arm/p2m.c
>>>> +++ b/xen/arch/arm/p2m.c
>>>> @@ -62,14 +62,14 @@ static inline bool_t p2m_is_superpage(lpae_t pte,
>>>> unsigned int level)
>>>>      return (level < 3) && p2m_mapping(pte);
>>>>  }
>>>>
>>>> -static inline void p2m_write_lock(struct p2m_domain *p2m)
>>>> +void p2m_write_lock(struct p2m_domain *p2m)
>>>
>>> This will introduce an overhead when locking the p2m. Those helpers
>>> should be moved a inline in p2m.h and not transform to a functions.
>>>
>>
>> I did not move the definitions of the functions into the header file to
>> avoid exposing the static function p2m_flush_tlb. However, what I can do
>> is to declare the function prototypes in p2m.h and define them as inline
>> in p2m.c, which should provide the same effect.
> 
> It will not have the same effect for call of p2m_*lock outside of p2m.c.
> p2m_flush_tlb is only used in p2m_write_unlock, so what is the problem to
> move the implement of all p2m_*lock but p2m_write_unlock in p2m.h?
> 

There is no problem at all. I will adapt this patch based on your
suggested patch, thank you.

> commit 57b5214c6225c113b3cc50edbadce81b84e0a32c
> Author: Julien Grall <julien.grall@arm.com>
> Date:   Tue Aug 2 15:48:48 2016 +0100
> 
>     xen/arm: p2m: Export p2m_*_lock helpers
>     
>     Early patch exported the p2m interface (p2m_get_entry and p2m_set_entry)
>     to allow splitting xen/arch/arm/p2m.c. Those functions require the
>     callers to lock the p2m, so we need to export p2m_*_lock helpers.
>     
>     All helpers but p2m_write_unlock but p2m_write_unlock are moved in
>     xen/include/asm-arm/p2m.h to allow inlining. The helpers
>     p2m_write_unlock is kept in p2m.c because it depends on a static
>     function.
>     
>     Signed-off-by: Julien Grall <julien.grall@arm.com>
>     
>     ---
>         Changes in v2:
>             - Patch added
> 
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index f4a808c..e41ed3c 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -62,14 +62,10 @@ static inline bool_t p2m_is_superpage(lpae_t pte, unsigned int level)
>      return (level < 3) && p2m_mapping(pte);
>  }
>  
> -static inline void p2m_write_lock(struct p2m_domain *p2m)
> -{
> -    write_lock(&p2m->lock);
> -}
> -
>  static void p2m_flush_tlb(struct p2m_domain *p2m);
>  
> -static inline void p2m_write_unlock(struct p2m_domain *p2m)
> +/* Unlock the flush and do a P2M TLB flush if necessary */
> +void p2m_write_unlock(struct p2m_domain *p2m)
>  {
>      if ( p2m->need_flush )
>      {
> @@ -85,26 +81,6 @@ static inline void p2m_write_unlock(struct p2m_domain *p2m)
>      write_unlock(&p2m->lock);
>  }
>  
> -static inline void p2m_read_lock(struct p2m_domain *p2m)
> -{
> -    read_lock(&p2m->lock);
> -}
> -
> -static inline void p2m_read_unlock(struct p2m_domain *p2m)
> -{
> -    read_unlock(&p2m->lock);
> -}
> -
> -static inline int p2m_is_locked(struct p2m_domain *p2m)
> -{
> -    return rw_is_locked(&p2m->lock);
> -}
> -
> -static inline int p2m_is_write_locked(struct p2m_domain *p2m)
> -{
> -    return rw_is_write_locked(&p2m->lock);
> -}
> -
>  void p2m_dump_info(struct domain *d)
>  {
>      struct p2m_domain *p2m = &d->arch.p2m;
> diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
> index c2f4f98..9b0cade 100644
> --- a/xen/include/asm-arm/p2m.h
> +++ b/xen/include/asm-arm/p2m.h
> @@ -173,6 +173,33 @@ void p2m_restore_state(struct vcpu *n);
>  /* Print debugging/statistial info about a domain's p2m */
>  void p2m_dump_info(struct domain *d);
>  
> +static inline void p2m_write_lock(struct p2m_domain *p2m)
> +{
> +    write_lock(&p2m->lock);
> +}
> +
> +void p2m_write_unlock(struct p2m_domain *p2m);
> +
> +static inline void p2m_read_lock(struct p2m_domain *p2m)
> +{
> +    read_lock(&p2m->lock);
> +}
> +
> +static inline void p2m_read_unlock(struct p2m_domain *p2m)
> +{
> +    read_unlock(&p2m->lock);
> +}
> +
> +static inline int p2m_is_locked(struct p2m_domain *p2m)
> +{
> +    return rw_is_locked(&p2m->lock);
> +}
> +
> +static inline int p2m_is_write_locked(struct p2m_domain *p2m)
> +{
> +    return rw_is_write_locked(&p2m->lock);
> +}
> +
>  /* Look up the MFN corresponding to a domain's GFN. */
>  mfn_t p2m_lookup(struct domain *d, gfn_t gfn, p2m_type_t *t);
>  
> 

Cheers,
~Sergej

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 10/38] arm/p2m: Move hostp2m init/teardown to individual functions
  2016-09-02  9:09     ` Sergej Proskurin
@ 2016-09-02 10:51       ` Julien Grall
  2016-09-05 10:23         ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-02 10:51 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini



On 02/09/16 10:09, Sergej Proskurin wrote:
> Hi Julien,
>
> On 09/01/2016 07:36 PM, Julien Grall wrote:
>> Hello Sergej,
>>
>> On 16/08/16 23:16, Sergej Proskurin wrote:
>>> ---
>>>  xen/arch/arm/p2m.c        | 71
>>> +++++++++++++++++++++++++++++++++++++++++------
>>>  xen/include/asm-arm/p2m.h | 11 ++++++++
>>>  2 files changed, 73 insertions(+), 9 deletions(-)
>>>
>>> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
>>> index e859fca..9ef19d4 100644
>>> --- a/xen/arch/arm/p2m.c
>>> +++ b/xen/arch/arm/p2m.c
>>> @@ -1245,27 +1245,53 @@ static void p2m_free_vmid(struct domain *d)
>>>      spin_unlock(&vmid_alloc_lock);
>>>  }
>>>
>>> -void p2m_teardown(struct domain *d)
>>> +/* Reset this p2m table to be empty. */
>>> +void p2m_flush_table(struct p2m_domain *p2m)
>>>  {
>>> -    struct p2m_domain *p2m = p2m_get_hostp2m(d);
>>> -    struct page_info *pg;
>>> +    struct page_info *page, *pg;
>>> +    unsigned int i;
>>> +
>>> +    if ( p2m->root )
>>> +    {
>>> +        page = p2m->root;
>>> +
>>> +        /* Clear all concatenated first level pages. */
>>
>> s/first/root/
>>
>
> Ok.
>
>>> +        for ( i = 0; i < P2M_ROOT_PAGES; i++ )
>>> +            clear_and_clean_page(page + i);
>>
>> Clearing live page table like that is not safe. Each entry (64-bit)
>> should be written atomically to avoid breaking coherency (e.g if the MMU
>> is walking the page table at the same time). However you don't know the
>> implementation of clear_and_clean_page.
>
> The function p2m_flush_table gets called by the altp2m subsystem
> indrectly through the function p2m_teardown_one when the associated view
> gets destroyed. In this case we should not worry about crashing the
> domain, as the altp2m views are not active anyway.
>
> The function altp2m_reset calls the function p2m_flush_table directly
> (with active altp2m views), however, locks the p2m before flushing the
> table. I did not find any locks on page-granularity, so please provide
> me with further information about the solution you had in mind.

I never mentioned any locking problem. As said in my previous mail, the 
altp2m may still be in use by another vCPU. So the MMU (i.e the 
hardware) may want do a table walk whilst you modify the entry.

The MMU is reading the entry (64-bit) at once so it also expects the 
entry to be modified atomically. However, you don't know the 
implementation of clean_and_clean_page. The function might write 32-bit 
at the time, which means that the MMU will see bogus entry. At best it 
will lead to a crash, at worst open a security issue.

>>
>> Also, this adds a small overhead when tearing down a p2m because the
>> clear is not necessary.
>>
>
> The p2m views are cleared very rarely so the overhead is really minimal
> as it affects clearing the root tables.

You seem to forget the p2m teardown is also called during domain 
destruction.

> Besides the function
> altp2m_reset calls the function p2m_flush_table and assumes that the
> root tables are cleared as well. If the root tables would not be cleared
> at this point, stalled entries in the altp2m views that got wiped out in
> the hostp2m would make the system unstable.

As I already mentioned in the previous version, this code was not 
present before and based of the description of this commit the patch is 
supposed to only move code around. This is not the case here.


>>>
>>>      radix_tree_destroy(&p2m->mem_access_settings, NULL);
>>>  }
>>>
>>> -int p2m_init(struct domain *d)
>>> +int p2m_init_one(struct domain *d, struct p2m_domain *p2m)
>>>  {
>>> -    struct p2m_domain *p2m = p2m_get_hostp2m(d);
>>>      int rc = 0;
>>>
>>>      rwlock_init(&p2m->lock);
>>> @@ -1278,11 +1304,14 @@ int p2m_init(struct domain *d)
>>>          return rc;
>>>
>>>      p2m->max_mapped_gfn = _gfn(0);
>>> -    p2m->lowest_mapped_gfn = _gfn(ULONG_MAX);
>>> +    p2m->lowest_mapped_gfn = INVALID_GFN;
>>
>> Why this change?
>>
>
> Since we compare the gfn's with INVALID_GFN throughout the code it makes
> sense to use the macro instead of a hardcoded value.

Please don't do unnecessary change. This patch is complex enough to review.

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 10/38] arm/p2m: Move hostp2m init/teardown to individual functions
  2016-09-02 10:51       ` Julien Grall
@ 2016-09-05 10:23         ` Sergej Proskurin
  2016-09-09 16:44           ` Julien Grall
  0 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-05 10:23 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,


On 09/02/2016 12:51 PM, Julien Grall wrote:
>
>
> On 02/09/16 10:09, Sergej Proskurin wrote:
>> Hi Julien,
>>
>> On 09/01/2016 07:36 PM, Julien Grall wrote:
>>> Hello Sergej,
>>>
>>> On 16/08/16 23:16, Sergej Proskurin wrote:
>>>> ---
>>>>  xen/arch/arm/p2m.c        | 71
>>>> +++++++++++++++++++++++++++++++++++++++++------
>>>>  xen/include/asm-arm/p2m.h | 11 ++++++++
>>>>  2 files changed, 73 insertions(+), 9 deletions(-)
>>>>
>>>> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
>>>> index e859fca..9ef19d4 100644
>>>> --- a/xen/arch/arm/p2m.c
>>>> +++ b/xen/arch/arm/p2m.c
>>>> @@ -1245,27 +1245,53 @@ static void p2m_free_vmid(struct domain *d)
>>>>      spin_unlock(&vmid_alloc_lock);
>>>>  }
>>>>
>>>> -void p2m_teardown(struct domain *d)
>>>> +/* Reset this p2m table to be empty. */
>>>> +void p2m_flush_table(struct p2m_domain *p2m)
>>>>  {
>>>> -    struct p2m_domain *p2m = p2m_get_hostp2m(d);
>>>> -    struct page_info *pg;
>>>> +    struct page_info *page, *pg;
>>>> +    unsigned int i;
>>>> +
>>>> +    if ( p2m->root )
>>>> +    {
>>>> +        page = p2m->root;
>>>> +
>>>> +        /* Clear all concatenated first level pages. */
>>>
>>> s/first/root/
>>>
>>
>> Ok.
>>
>>>> +        for ( i = 0; i < P2M_ROOT_PAGES; i++ )
>>>> +            clear_and_clean_page(page + i);
>>>
>>> Clearing live page table like that is not safe. Each entry (64-bit)
>>> should be written atomically to avoid breaking coherency (e.g if the
>>> MMU
>>> is walking the page table at the same time). However you don't know the
>>> implementation of clear_and_clean_page.
>>
>> The function p2m_flush_table gets called by the altp2m subsystem
>> indrectly through the function p2m_teardown_one when the associated view
>> gets destroyed. In this case we should not worry about crashing the
>> domain, as the altp2m views are not active anyway.
>>
>> The function altp2m_reset calls the function p2m_flush_table directly
>> (with active altp2m views), however, locks the p2m before flushing the
>> table. I did not find any locks on page-granularity, so please provide
>> me with further information about the solution you had in mind.
>
> I never mentioned any locking problem. As said in my previous mail,
> the altp2m may still be in use by another vCPU. So the MMU (i.e the
> hardware) may want do a table walk whilst you modify the entry.
>
> The MMU is reading the entry (64-bit) at once so it also expects the
> entry to be modified atomically. However, you don't know the
> implementation of clean_and_clean_page. The function might write
> 32-bit at the time, which means that the MMU will see bogus entry. At
> best it will lead to a crash, at worst open a security issue.
>

I see your point. Not sure how to fix this, though. I believe that the
described issue would remain if we would use free_domheap_pages.
Instead, maybe we should manually set the value in the translation tables?

Or, what if we flush the TLBs immediately before unmapping the root
pages? This would cause the system to load the mappings from memory and
delay a MMU table walk so that it would potentially resolve the
atomicity issue.

Do you have another suggestion?

>>>
>>> Also, this adds a small overhead when tearing down a p2m because the
>>> clear is not necessary.
>>>
>>
>> The p2m views are cleared very rarely so the overhead is really minimal
>> as it affects clearing the root tables.
>
> You seem to forget the p2m teardown is also called during domain
> destruction.
>
>> Besides the function
>> altp2m_reset calls the function p2m_flush_table and assumes that the
>> root tables are cleared as well. If the root tables would not be cleared
>> at this point, stalled entries in the altp2m views that got wiped out in
>> the hostp2m would make the system unstable.
>
> As I already mentioned in the previous version, this code was not
> present before and based of the description of this commit the patch
> is supposed to only move code around. This is not the case here.
>

I will move the part with the clear_and_clean_page invocation into a
separate patch.

>
>>>>
>>>>      radix_tree_destroy(&p2m->mem_access_settings, NULL);
>>>>  }
>>>>
>>>> -int p2m_init(struct domain *d)
>>>> +int p2m_init_one(struct domain *d, struct p2m_domain *p2m)
>>>>  {
>>>> -    struct p2m_domain *p2m = p2m_get_hostp2m(d);
>>>>      int rc = 0;
>>>>
>>>>      rwlock_init(&p2m->lock);
>>>> @@ -1278,11 +1304,14 @@ int p2m_init(struct domain *d)
>>>>          return rc;
>>>>
>>>>      p2m->max_mapped_gfn = _gfn(0);
>>>> -    p2m->lowest_mapped_gfn = _gfn(ULONG_MAX);
>>>> +    p2m->lowest_mapped_gfn = INVALID_GFN;
>>>
>>> Why this change?
>>>
>>
>> Since we compare the gfn's with INVALID_GFN throughout the code it makes
>> sense to use the macro instead of a hardcoded value.
>
> Please don't do unnecessary change. This patch is complex enough to
> review.

Ok.

Cheers,
~Sergej


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 10/38] arm/p2m: Move hostp2m init/teardown to individual functions
  2016-09-05 10:23         ` Sergej Proskurin
@ 2016-09-09 16:44           ` Julien Grall
  0 siblings, 0 replies; 116+ messages in thread
From: Julien Grall @ 2016-09-09 16:44 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 05/09/16 11:23, Sergej Proskurin wrote:
> On 09/02/2016 12:51 PM, Julien Grall wrote:
>> On 02/09/16 10:09, Sergej Proskurin wrote:
>>> On 09/01/2016 07:36 PM, Julien Grall wrote:
>>>> On 16/08/16 23:16, Sergej Proskurin wrote:
>>>> Clearing live page table like that is not safe. Each entry (64-bit)
>>>> should be written atomically to avoid breaking coherency (e.g if the
>>>> MMU
>>>> is walking the page table at the same time). However you don't know the
>>>> implementation of clear_and_clean_page.
>>>
>>> The function p2m_flush_table gets called by the altp2m subsystem
>>> indrectly through the function p2m_teardown_one when the associated view
>>> gets destroyed. In this case we should not worry about crashing the
>>> domain, as the altp2m views are not active anyway.
>>>
>>> The function altp2m_reset calls the function p2m_flush_table directly
>>> (with active altp2m views), however, locks the p2m before flushing the
>>> table. I did not find any locks on page-granularity, so please provide
>>> me with further information about the solution you had in mind.
>>
>> I never mentioned any locking problem. As said in my previous mail,
>> the altp2m may still be in use by another vCPU. So the MMU (i.e the
>> hardware) may want do a table walk whilst you modify the entry.
>>
>> The MMU is reading the entry (64-bit) at once so it also expects the
>> entry to be modified atomically. However, you don't know the
>> implementation of clean_and_clean_page. The function might write
>> 32-bit at the time, which means that the MMU will see bogus entry. At
>> best it will lead to a crash, at worst open a security issue.
>>
>
> I see your point. Not sure how to fix this, though. I believe that the
> described issue would remain if we would use free_domheap_pages.
> Instead, maybe we should manually set the value in the translation tables?

This is the right way to go.

>
> Or, what if we flush the TLBs immediately before unmapping the root
> pages? This would cause the system to load the mappings from memory and
> delay a MMU table walk so that it would potentially resolve the
> atomicity issue.

I am not sure to fully understand this suggestion. Anyway, the first 
suggestion (i.e invalidating the entry one by one is the right way to go).

>>
>>>>>
>>>>>      radix_tree_destroy(&p2m->mem_access_settings, NULL);
>>>>>  }
>>>>>
>>>>> -int p2m_init(struct domain *d)
>>>>> +int p2m_init_one(struct domain *d, struct p2m_domain *p2m)
>>>>>  {
>>>>> -    struct p2m_domain *p2m = p2m_get_hostp2m(d);
>>>>>      int rc = 0;
>>>>>
>>>>>      rwlock_init(&p2m->lock);
>>>>> @@ -1278,11 +1304,14 @@ int p2m_init(struct domain *d)
>>>>>          return rc;
>>>>>
>>>>>      p2m->max_mapped_gfn = _gfn(0);
>>>>> -    p2m->lowest_mapped_gfn = _gfn(ULONG_MAX);
>>>>> +    p2m->lowest_mapped_gfn = INVALID_GFN;
>>>>
>>>> Why this change?
>>>>
>>>
>>> Since we compare the gfn's with INVALID_GFN throughout the code it makes
>>> sense to use the macro instead of a hardcoded value.
>>
>> Please don't do unnecessary change. This patch is complex enough to
>> review.
>
> Ok.

If you want to do the change, then it should be done separately.

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 11/38] arm/p2m: Cosmetic fix - function prototype of p2m_alloc_table
  2016-08-16 22:16 ` [PATCH v3 11/38] arm/p2m: Cosmetic fix - function prototype of p2m_alloc_table Sergej Proskurin
@ 2016-09-09 16:45   ` Julien Grall
  0 siblings, 0 replies; 116+ messages in thread
From: Julien Grall @ 2016-09-09 16:45 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/16 23:16, Sergej Proskurin wrote:
> The function "p2m_alloc_table" should be able to allocate 2nd stage
> translation tables not only for the host's p2m but also for alternate
> p2m's.
>
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>

Acked-by: Julien Grall <julien.grall@arm.com>

> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> ---
> v2: Removed altp2m table initialization from "p2m_table_init".
>
> v3: Removed initialization of the field d->arch.altp2m_active in
>     "p2m_table_init" to avoid altp2m initialization throughout different
>     files.
>
>     Merged the function "p2m_alloc_table" and "p2m_table_init".
> ---
>  xen/arch/arm/p2m.c | 5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
>
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index 9ef19d4..dd5d700 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -1162,9 +1162,8 @@ void guest_physmap_remove_page(struct domain *d,
>      p2m_remove_mapping(d, gfn, (1 << page_order), mfn);
>  }
>
> -static int p2m_alloc_table(struct domain *d)
> +static int p2m_alloc_table(struct p2m_domain *p2m)
>  {
> -    struct p2m_domain *p2m = p2m_get_hostp2m(d);
>      struct page_info *page;
>      unsigned int i;
>
> @@ -1322,7 +1321,7 @@ int p2m_init_one(struct domain *d, struct p2m_domain *p2m)
>      p2m->clean_pte = iommu_enabled &&
>          !iommu_has_feature(d, IOMMU_FEAT_COHERENT_WALK);
>
> -    return p2m_alloc_table(d);
> +    return p2m_alloc_table(p2m);
>  }
>
>  static void p2m_teardown_hostp2m(struct domain *d)
>

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 14/38] arm/p2m: Add altp2m init/teardown routines
  2016-08-16 22:16 ` [PATCH v3 14/38] arm/p2m: Add altp2m init/teardown routines Sergej Proskurin
@ 2016-09-09 16:56   ` Julien Grall
  2016-09-13 19:35     ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-09 16:56 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej

On 16/08/16 23:16, Sergej Proskurin wrote:
> diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
> index 23aaf52..4a7f660 100644
> --- a/xen/arch/arm/Makefile
> +++ b/xen/arch/arm/Makefile
> @@ -5,6 +5,7 @@ subdir-$(CONFIG_ARM_64) += efi
>  subdir-$(CONFIG_ACPI) += acpi
>
>  obj-$(CONFIG_ALTERNATIVE) += alternative.o
> +obj-y += altp2m.o
>  obj-y += bootfdt.o
>  obj-y += cpu.o
>  obj-y += cpuerrata.o
> diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
> new file mode 100644
> index 0000000..66a373a
> --- /dev/null
> +++ b/xen/arch/arm/altp2m.c
> @@ -0,0 +1,61 @@
> +/*
> + * arch/arm/altp2m.c
> + *
> + * Alternate p2m
> + * Copyright (c) 2016 Sergej Proskurin <proskurin@sec.in.tum.de>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License, version 2,
> + * as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT ANY
> + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
> + * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
> + * details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program; If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <asm/p2m.h>
> +#include <asm/altp2m.h>
> +
> +int altp2m_init(struct domain *d)
> +{
> +    unsigned int i;
> +
> +    spin_lock_init(&d->arch.altp2m_lock);
> +
> +    for ( i = 0; i < MAX_ALTP2M; i++ )
> +        d->arch.altp2m_p2m[i] = NULL;

The structure domain is already initialized to 0, so this loop is pointless.

> +
> +    d->arch.altp2m_active = false;
> +
> +    return 0;
> +}
> +

[...]

> diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
> index 0711796..a156109 100644
> --- a/xen/include/asm-arm/altp2m.h
> +++ b/xen/include/asm-arm/altp2m.h
> @@ -22,6 +22,9 @@
>
>  #include <xen/sched.h>
>
> +#define altp2m_lock(d)    spin_lock(&(d)->arch.altp2m_lock)
> +#define altp2m_unlock(d)  spin_unlock(&(d)->arch.altp2m_lock)
> +
>  /* Alternate p2m on/off per domain */
>  static inline bool_t altp2m_active(const struct domain *d)
>  {
> @@ -36,4 +39,7 @@ static inline uint16_t altp2m_vcpu_idx(const struct vcpu *v)
>      return 0;
>  }
>
> +int altp2m_init(struct domain *d);
> +void altp2m_teardown(struct domain *d);
> +
>  #endif /* __ASM_ARM_ALTP2M_H */
> diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
> index cc4bda0..a4e4762 100644
> --- a/xen/include/asm-arm/domain.h
> +++ b/xen/include/asm-arm/domain.h
> @@ -127,8 +127,14 @@ struct arch_domain
>      paddr_t efi_acpi_len;
>  #endif
>
> +    /*
> +     * Lock that protects access to altp2m related fields in both struct
> +     * arch_domain and struct p2m_domain.

This comment looks wrong. struct p2m_domain is protected by its own 
lock. altp2m lock should not protect it.

> +     */
> +    spinlock_t altp2m_lock;
>      /* altp2m: allow multiple copies of host p2m */
>      bool_t altp2m_active;
> +    struct p2m_domain *altp2m_p2m[MAX_ALTP2M];
>  }  __cacheline_aligned;
>
>  struct arch_vcpu
> diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
> index 1a004ed..de0c90a 100644
> --- a/xen/include/asm-arm/p2m.h
> +++ b/xen/include/asm-arm/p2m.h
> @@ -9,6 +9,8 @@
>  #include <xen/p2m-common.h>
>  #include <public/memory.h>
>
> +#define MAX_ALTP2M 10           /* ARM might contain an arbitrary number of
> +                                   altp2m views. */

This should belong to altp2m.h and not p2m.h

>  #define paddr_bits PADDR_BITS
>
>  #define INVALID_VTTBR (0UL)
>

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 15/38] arm/p2m: Add altp2m table flushing routine
  2016-08-16 22:16 ` [PATCH v3 15/38] arm/p2m: Add altp2m table flushing routine Sergej Proskurin
@ 2016-09-09 17:02   ` Julien Grall
  2016-09-13  9:13     ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-09 17:02 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/16 23:16, Sergej Proskurin wrote:
> The current implementation differentiates between flushing and
> destroying altp2m views. This commit adds the function altp2m_flush,
> which allows to release all of the alternate p2m views.
>
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> ---
> v2: Pages in p2m->pages are not cleared in p2m_flush_table anymore.
>     VMID is freed in p2m_free_one.
>     Cosmetic fixes.
>
> v3: Changed the locking mechanism to "p2m_write_lock" inside the
>     function "altp2m_flush".
>
>     Do not flush but rather teardown the altp2m in the function
>     "altp2m_flush".
>
>     Exchanged the check "altp2m_vttbr[idx] == INVALID_VTTBR" for
>     "altp2m_p2m[idx] == NULL" in "altp2m_flush".
> ---
>  xen/arch/arm/altp2m.c        | 31 +++++++++++++++++++++++++++++++
>  xen/include/asm-arm/altp2m.h |  3 +++
>  2 files changed, 34 insertions(+)
>
> diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
> index 66a373a..02cffd7 100644
> --- a/xen/arch/arm/altp2m.c
> +++ b/xen/arch/arm/altp2m.c
> @@ -34,6 +34,37 @@ int altp2m_init(struct domain *d)
>      return 0;
>  }
>
> +void altp2m_flush(struct domain *d)
> +{
> +    unsigned int i;
> +    struct p2m_domain *p2m;
> +
> +    /*
> +     * If altp2m is active, we are not allowed to flush altp2m[0]. This special
> +     * view is considered as the hostp2m as long as altp2m is active.
> +     */
> +    ASSERT(!altp2m_active(d));
> +
> +    altp2m_lock(d);
> +
> +    for ( i = 0; i < MAX_ALTP2M; i++ )
> +    {
> +        if ( d->arch.altp2m_p2m[i] == NULL )
> +            continue;
> +
> +        p2m = d->arch.altp2m_p2m[i];
> +
> +        p2m_write_lock(p2m);

Why do you take the lock here? The p2m should not be used by anyone at 
that time.

> +        p2m_teardown_one(p2m);

You may want to add an ASSERT(!atomic_read(p2m->active_vcpus)) somewhere.

> +        p2m_write_unlock(p2m);
> +
> +        xfree(p2m);
> +        d->arch.altp2m_p2m[i] = NULL;
> +    }
> +
> +    altp2m_unlock(d);
> +}
> +
>  void altp2m_teardown(struct domain *d)
>  {
>      unsigned int i;
> diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
> index a156109..4c15b75 100644
> --- a/xen/include/asm-arm/altp2m.h
> +++ b/xen/include/asm-arm/altp2m.h
> @@ -42,4 +42,7 @@ static inline uint16_t altp2m_vcpu_idx(const struct vcpu *v)
>  int altp2m_init(struct domain *d);
>  void altp2m_teardown(struct domain *d);
>
> +/* Flush all the alternate p2m's for a domain. */
> +void altp2m_flush(struct domain *d);
> +
>  #endif /* __ASM_ARM_ALTP2M_H */
>

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 16/38] arm/p2m: Add HVMOP_altp2m_set_domain_state
  2016-08-16 22:16 ` [PATCH v3 16/38] arm/p2m: Add HVMOP_altp2m_set_domain_state Sergej Proskurin
@ 2016-09-09 17:14   ` Julien Grall
  2016-09-13  9:22     ` Sergej Proskurin
  2016-09-14 11:07   ` Julien Grall
  1 sibling, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-09 17:14 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/16 23:16, Sergej Proskurin wrote:
> +static int altp2m_init_helper(struct domain *d, unsigned int idx)
> +{
> +    int rc;
> +    struct p2m_domain *p2m = d->arch.altp2m_p2m[idx];
> +
> +    ASSERT(p2m == NULL);
> +
> +    /* Allocate a new, zeroed altp2m view. */
> +    p2m = xzalloc(struct p2m_domain);
> +    if ( p2m == NULL)
> +    {
> +        rc = -ENOMEM;
> +        goto err;
> +    }

This could be simplified with just return -ENOMEM.

> +
> +    p2m->p2m_class = p2m_alternate;
> +
> +    /* Initialize the new altp2m view. */
> +    rc = p2m_init_one(d, p2m);
> +    if ( rc )
> +        goto err;
> +
> +    p2m->access_required = false;
> +    _atomic_set(&p2m->active_vcpus, 0);

the p2m is initialized to 0, so both access_required and active_vcpus 
initialization is not necessary.

> +
> +    d->arch.altp2m_p2m[idx] = p2m;
> +
> +    return rc;
> +
> +err:
> +    if ( p2m )
> +        xfree(p2m);

xfree is able to handle NULL pointer.

> +
> +    d->arch.altp2m_p2m[idx] = NULL;
> +
> +    return rc;
> +}
> +
> +int altp2m_init_by_id(struct domain *d, unsigned int idx)
> +{
> +    int rc = -EINVAL;
> +
> +    if ( idx >= MAX_ALTP2M )
> +        return rc;
> +
> +    altp2m_lock(d);
> +
> +    if ( d->arch.altp2m_p2m[idx] == NULL )
> +        rc = altp2m_init_helper(d, idx);
> +
> +    altp2m_unlock(d);
> +
> +    return rc;
> +}
> +

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 17/38] arm/p2m: Add HVMOP_altp2m_create_p2m
  2016-08-16 22:16 ` [PATCH v3 17/38] arm/p2m: Add HVMOP_altp2m_create_p2m Sergej Proskurin
@ 2016-09-12  8:38   ` Julien Grall
  0 siblings, 0 replies; 116+ messages in thread
From: Julien Grall @ 2016-09-12  8:38 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/2016 23:16, Sergej Proskurin wrote:
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>

Acked-by: Julien Grall <julien.grall@arm.com>

Regards,

> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> ---
> v2: Cosmetic fixes.
>
> v3: Cosmetic fixes.
>
>     Renamed the function "altp2m_init_next" to
>     "altp2m_init_next_available".
>
>     Exchanged the check "altp2m_vttbr[idx] == INVALID_VTTBR" for
>     "altp2m_p2m[idx] == NULL" in "altp2m_init_next_available".
> ---
>  xen/arch/arm/altp2m.c        | 23 +++++++++++++++++++++++
>  xen/arch/arm/hvm.c           |  3 ++-
>  xen/include/asm-arm/altp2m.h |  4 ++++
>  3 files changed, 29 insertions(+), 1 deletion(-)
>
> diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
> index 02a52ec..b5d1951 100644
> --- a/xen/arch/arm/altp2m.c
> +++ b/xen/arch/arm/altp2m.c
> @@ -122,6 +122,29 @@ int altp2m_init_by_id(struct domain *d, unsigned int idx)
>      return rc;
>  }
>
> +int altp2m_init_next_available(struct domain *d, uint16_t *idx)
> +{
> +    int rc = -EINVAL;
> +    uint16_t i;
> +
> +    altp2m_lock(d);
> +
> +    for ( i = 0; i < MAX_ALTP2M; i++ )
> +    {
> +        if ( d->arch.altp2m_p2m[i] != NULL )
> +            continue;
> +
> +        rc = altp2m_init_helper(d, i);
> +        *idx = i;
> +
> +        break;
> +    }
> +
> +    altp2m_unlock(d);
> +
> +    return rc;
> +}
> +
>  int altp2m_init(struct domain *d)
>  {
>      unsigned int i;
> diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
> index c69da36..a504dfd 100644
> --- a/xen/arch/arm/hvm.c
> +++ b/xen/arch/arm/hvm.c
> @@ -123,7 +123,8 @@ static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
>          break;
>
>      case HVMOP_altp2m_create_p2m:
> -        rc = -EOPNOTSUPP;
> +        if ( !(rc = altp2m_init_next_available(d, &a.u.view.view)) )
> +            rc = __copy_to_guest(arg, &a, 1) ? -EFAULT : 0;
>          break;
>
>      case HVMOP_altp2m_destroy_p2m:
> diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
> index f604ffd..5701012 100644
> --- a/xen/include/asm-arm/altp2m.h
> +++ b/xen/include/asm-arm/altp2m.h
> @@ -56,6 +56,10 @@ struct p2m_domain *altp2m_get_altp2m(struct vcpu *v);
>  int altp2m_init_by_id(struct domain *d,
>                        unsigned int idx);
>
> +/* Find and initialize the next available alternate p2m. */
> +int altp2m_init_next_available(struct domain *d,
> +                               uint16_t *idx);
> +
>  /* Flush all the alternate p2m's for a domain. */
>  void altp2m_flush(struct domain *d);
>
>

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 18/38] arm/p2m: Add HVMOP_altp2m_destroy_p2m
  2016-08-16 22:16 ` [PATCH v3 18/38] arm/p2m: Add HVMOP_altp2m_destroy_p2m Sergej Proskurin
@ 2016-09-12  8:41   ` Julien Grall
  2016-09-13 12:43     ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-12  8:41 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/2016 23:16, Sergej Proskurin wrote:
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> ---
> v2: Substituted the call to tlb_flush for p2m_flush_table.
>     Added comments.
>     Cosmetic fixes.
>
> v3: Changed the locking mechanism to "p2m_write_lock" inside the
>     function "altp2m_destroy_by_id".
>
>     Do not flush but rather teardown the altp2m in the function
>     "altp2m_destroy_by_id".
>
>     Exchanged the check "altp2m_vttbr[idx] == INVALID_VTTBR" for
>     "altp2m_p2m[idx] == NULL" in "altp2m_destroy_by_id".
> ---
>  xen/arch/arm/altp2m.c        | 43 +++++++++++++++++++++++++++++++++++++++++++
>  xen/arch/arm/hvm.c           |  2 +-
>  xen/include/asm-arm/altp2m.h |  4 ++++
>  3 files changed, 48 insertions(+), 1 deletion(-)
>
> diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
> index b5d1951..c14ab0b 100644
> --- a/xen/arch/arm/altp2m.c
> +++ b/xen/arch/arm/altp2m.c
> @@ -190,6 +190,49 @@ void altp2m_flush(struct domain *d)
>      altp2m_unlock(d);
>  }
>
> +int altp2m_destroy_by_id(struct domain *d, unsigned int idx)
> +{
> +    struct p2m_domain *p2m;
> +    int rc = -EBUSY;
> +
> +    /*
> +     * The altp2m[0] is considered as the hostp2m and is used as a safe harbor
> +     * to which you can switch as long as altp2m is active. After deactivating
> +     * altp2m, the system switches back to the original hostp2m view. That is,
> +     * altp2m[0] should only be destroyed/flushed/freed, when altp2m is
> +     * deactivated.
> +     */
> +    if ( !idx || idx >= MAX_ALTP2M )
> +        return rc;
> +
> +    domain_pause_except_self(d);
> +
> +    altp2m_lock(d);
> +
> +    if ( d->arch.altp2m_p2m[idx] != NULL )
> +    {
> +        p2m = d->arch.altp2m_p2m[idx];
> +
> +        if ( !_atomic_read(p2m->active_vcpus) )
> +        {
> +            p2m_write_lock(p2m);

I am not sure why you take the lock here. It will not protect you from 
anything as the p2m will get freed just after. So if someone else is 
using it, it will be in big trouble.

> +            p2m_teardown_one(p2m);
> +            p2m_write_unlock(p2m);
> +
> +            xfree(p2m);
> +            d->arch.altp2m_p2m[idx] = NULL;
> +
> +            rc = 0;
> +        }
> +    }
> +
> +    altp2m_unlock(d);
> +
> +    domain_unpause_except_self(d);
> +
> +    return rc;
> +}
> +
>  void altp2m_teardown(struct domain *d)
>  {
>      unsigned int i;
> diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
> index a504dfd..df973ef 100644
> --- a/xen/arch/arm/hvm.c
> +++ b/xen/arch/arm/hvm.c
> @@ -128,7 +128,7 @@ static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
>          break;
>
>      case HVMOP_altp2m_destroy_p2m:
> -        rc = -EOPNOTSUPP;
> +        rc = altp2m_destroy_by_id(d, a.u.view.view);
>          break;
>
>      case HVMOP_altp2m_switch_p2m:
> diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
> index 5701012..6074079 100644
> --- a/xen/include/asm-arm/altp2m.h
> +++ b/xen/include/asm-arm/altp2m.h
> @@ -63,4 +63,8 @@ int altp2m_init_next_available(struct domain *d,
>  /* Flush all the alternate p2m's for a domain. */
>  void altp2m_flush(struct domain *d);
>
> +/* Make a specific alternate p2m invalid */
> +int altp2m_destroy_by_id(struct domain *d,
> +                         unsigned int idx);
> +
>  #endif /* __ASM_ARM_ALTP2M_H */
>

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 19/38] arm/p2m: Add HVMOP_altp2m_switch_p2m
  2016-08-16 22:16 ` [PATCH v3 19/38] arm/p2m: Add HVMOP_altp2m_switch_p2m Sergej Proskurin
@ 2016-09-12  8:47   ` Julien Grall
  2016-09-13 13:00     ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-12  8:47 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/2016 23:16, Sergej Proskurin wrote:
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> ---
> v3: Extended the function "altp2m_switch_domain_altp2m_by_id" so that if
>     the guest domain indirectly calles this function, the current vcpu also
>     changes the altp2m view without performing an explicit context switch.
>
>     Exchanged the check "altp2m_vttbr[idx] == INVALID_VTTBR" for
>     "altp2m_p2m[idx] == NULL" in "altp2m_switch_domain_altp2m_by_id".
> ---
>  xen/arch/arm/altp2m.c        | 48 ++++++++++++++++++++++++++++++++++++++++++++
>  xen/arch/arm/hvm.c           |  2 +-
>  xen/include/asm-arm/altp2m.h |  4 ++++
>  3 files changed, 53 insertions(+), 1 deletion(-)
>
> diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
> index c14ab0b..ba345b9 100644
> --- a/xen/arch/arm/altp2m.c
> +++ b/xen/arch/arm/altp2m.c
> @@ -32,6 +32,54 @@ struct p2m_domain *altp2m_get_altp2m(struct vcpu *v)
>      return v->domain->arch.altp2m_p2m[index];
>  }
>
> +int altp2m_switch_domain_altp2m_by_id(struct domain *d, unsigned int idx)
> +{
> +    struct vcpu *v;
> +    int rc = -EINVAL;
> +
> +    if ( idx >= MAX_ALTP2M )
> +        return rc;
> +
> +    domain_pause_except_self(d);
> +
> +    altp2m_lock(d);
> +
> +    if ( d->arch.altp2m_p2m[idx] != NULL )
> +    {
> +        for_each_vcpu( d, v )
> +            if ( idx != altp2m_vcpu(v).p2midx )

Could you invert the condition to avoid another layer of nested if?

> +            {
> +                atomic_dec(&altp2m_get_altp2m(v)->active_vcpus);
> +                altp2m_vcpu(v).p2midx = idx;
> +                atomic_inc(&altp2m_get_altp2m(v)->active_vcpus);
> +
> +                /*
> +                 * In case it is the guest domain, which indirectly called this
> +                 * function, the current vcpu will not switch its context
> +                 * within the function "p2m_restore_state". That is, changing
> +                 * the altp2m_vcpu(v).p2midx will not lead to the requested
> +                 * altp2m switch on that specific vcpu. To achieve the desired
> +                 * behavior, we write to VTTBR_EL2 directly.
> +                 */
> +                if ( v->domain == d && v == current )

v == current is enough.

> +                {
> +                    struct p2m_domain *ap2m = d->arch.altp2m_p2m[idx];
> +
> +                    WRITE_SYSREG64(ap2m->vttbr, VTTBR_EL2);
> +                    isb();

I don't like the open-coding of VTTBR_EL2. I would much prefer a 
separate helper to update it.

> +                }
> +            }
> +
> +        rc = 0;
> +    }
> +
> +    altp2m_unlock(d);
> +
> +    domain_unpause_except_self(d);
> +
> +    return rc;
> +}
> +
>  static void altp2m_vcpu_reset(struct vcpu *v)
>  {
>      struct altp2mvcpu *av = &altp2m_vcpu(v);
> diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
> index df973ef..9ac3422 100644
> --- a/xen/arch/arm/hvm.c
> +++ b/xen/arch/arm/hvm.c
> @@ -132,7 +132,7 @@ static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
>          break;
>
>      case HVMOP_altp2m_switch_p2m:
> -        rc = -EOPNOTSUPP;
> +        rc = altp2m_switch_domain_altp2m_by_id(d, a.u.view.view);
>          break;
>
>      case HVMOP_altp2m_set_mem_access:
> diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
> index 6074079..c2e44ab 100644
> --- a/xen/include/asm-arm/altp2m.h
> +++ b/xen/include/asm-arm/altp2m.h
> @@ -52,6 +52,10 @@ void altp2m_vcpu_destroy(struct vcpu *v);
>  /* Get current alternate p2m table. */
>  struct p2m_domain *altp2m_get_altp2m(struct vcpu *v);
>
> +/* Switch alternate p2m for entire domain */
> +int altp2m_switch_domain_altp2m_by_id(struct domain *d,
> +                                      unsigned int idx);
> +
>  /* Make a specific alternate p2m valid. */
>  int altp2m_init_by_id(struct domain *d,
>                        unsigned int idx);
>

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 20/38] arm/p2m: Add p2m_get_active_p2m macro
  2016-08-16 22:16 ` [PATCH v3 20/38] arm/p2m: Add p2m_get_active_p2m macro Sergej Proskurin
@ 2016-09-12  8:50   ` Julien Grall
  0 siblings, 0 replies; 116+ messages in thread
From: Julien Grall @ 2016-09-12  8:50 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/2016 23:16, Sergej Proskurin wrote:
> This commit introduces the macro "p2m_get_active_p2m" returning the
> currently active (alt)p2m. The need for this macro will be shown in the
> following commits.
>
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>

Acked-by: Julien Grall <julien.grall@arm.com>

Regards,

> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> ---
>  xen/arch/arm/p2m.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index 63c0df0..12b3dcc 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -29,6 +29,9 @@ static unsigned int __read_mostly p2m_root_level;
>
>  #define P2M_ROOT_PAGES    (1<<P2M_ROOT_ORDER)
>
> +#define p2m_get_active_p2m(v) unlikely(altp2m_active(v->domain)) ?  \
> +                              altp2m_get_altp2m(v) : p2m_get_hostp2m(v->domain);
> +
>  #define p2m_switch_vttbr_and_get_flags(ovttbr, nvttbr, flags)       \
>  ({                                                                  \
>      if ( ovttbr != nvttbr )                                         \
>

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 21/38] arm/p2m: Make p2m_restore_state ready for altp2m
  2016-08-16 22:16 ` [PATCH v3 21/38] arm/p2m: Make p2m_restore_state ready for altp2m Sergej Proskurin
@ 2016-09-12  8:51   ` Julien Grall
  0 siblings, 0 replies; 116+ messages in thread
From: Julien Grall @ 2016-09-12  8:51 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/2016 23:16, Sergej Proskurin wrote:
> This commit adapts the function "p2m_restore_state" in a way that the
> currently active altp2m table is considered during state restoration.
>
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>

Acked-by: Julien Grall <julien.grall@arm.com>

Regards,

> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> ---
> v3: Moved declaration of "altp2m_switch_domain_altp2m_by_id" out of this
>     patch.
> ---
>  xen/arch/arm/p2m.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index 12b3dcc..15abd39 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -171,7 +171,7 @@ void p2m_save_state(struct vcpu *p)
>  void p2m_restore_state(struct vcpu *n)
>  {
>      register_t hcr;
> -    struct p2m_domain *p2m = p2m_get_hostp2m(n->domain);
> +    struct p2m_domain *p2m = p2m_get_active_p2m(n);
>
>      if ( is_idle_vcpu(n) )
>          return;
>

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 23/38] arm/p2m: Cosmetic fixes -- __p2m_get_mem_access
  2016-08-16 22:16 ` [PATCH v3 23/38] arm/p2m: Cosmetic fixes -- __p2m_get_mem_access Sergej Proskurin
@ 2016-09-12  8:53   ` Julien Grall
  2016-09-13 13:27     ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-12  8:53 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/2016 23:16, Sergej Proskurin wrote:
> This commit extends the function prototypes of the functions:
> * __p2m_get_mem_access
> * p2m_mem_access_check_and_get_page
>
> We extend the function prototype of "__p2m_get_mem_access" to hold an
> argument of type "struct p2m_domain*", as we need to distinguish between
> the host's p2m and different altp2m views. While doing so, we needed to
> extend the function's prototype of "p2m_mem_access_check_and_get_page"
> to hold an argument of type "struct vcpu*".

Please details in the commit message why it is necessary to pass a 
"struct vcpu *" to p2m_mem_access_check_and_get_page.

Regards,

>
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> ---
> v3: Changed the parameter of "p2m_mem_access_check_and_get_page"
>     from "struct p2m_domain*" to "struct vcpu*".
> ---
>  xen/arch/arm/p2m.c | 15 +++++++--------
>  1 file changed, 7 insertions(+), 8 deletions(-)
>
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index 06f7eb8..5819ae0 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -606,10 +606,9 @@ static int p2m_create_table(struct p2m_domain *p2m, lpae_t *entry)
>      return 0;
>  }
>
> -static int __p2m_get_mem_access(struct domain *d, gfn_t gfn,
> +static int __p2m_get_mem_access(struct p2m_domain *p2m, gfn_t gfn,
>                                  xenmem_access_t *access)
>  {
> -    struct p2m_domain *p2m = p2m_get_hostp2m(d);
>      void *i;
>      unsigned int index;
>
> @@ -1471,7 +1470,7 @@ mfn_t gfn_to_mfn(struct domain *d, gfn_t gfn)
>   * we indeed found a conflicting mem_access setting.
>   */
>  static struct page_info*
> -p2m_mem_access_check_and_get_page(vaddr_t gva, unsigned long flag)
> +p2m_mem_access_check_and_get_page(struct vcpu *v, vaddr_t gva, unsigned long flag)
>  {
>      long rc;
>      paddr_t ipa;
> @@ -1480,7 +1479,7 @@ p2m_mem_access_check_and_get_page(vaddr_t gva, unsigned long flag)
>      xenmem_access_t xma;
>      p2m_type_t t;
>      struct page_info *page = NULL;
> -    struct p2m_domain *p2m = p2m_get_hostp2m(current->domain);
> +    struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
>
>      rc = gva_to_ipa(gva, &ipa, flag);
>      if ( rc < 0 )
> @@ -1492,7 +1491,7 @@ p2m_mem_access_check_and_get_page(vaddr_t gva, unsigned long flag)
>       * We do this first as this is faster in the default case when no
>       * permission is set on the page.
>       */
> -    rc = __p2m_get_mem_access(current->domain, gfn, &xma);
> +    rc = __p2m_get_mem_access(p2m, gfn, &xma);
>      if ( rc < 0 )
>          goto err;
>
> @@ -1556,7 +1555,7 @@ p2m_mem_access_check_and_get_page(vaddr_t gva, unsigned long flag)
>
>      page = mfn_to_page(mfn_x(mfn));
>
> -    if ( unlikely(!get_page(page, current->domain)) )
> +    if ( unlikely(!get_page(page, v->domain)) )
>          page = NULL;
>
>  err:
> @@ -1614,7 +1613,7 @@ struct page_info *get_page_from_gva(struct vcpu *v, vaddr_t va,
>
>  err:
>      if ( !page && p2m->mem_access_enabled )
> -        page = p2m_mem_access_check_and_get_page(va, flags);
> +        page = p2m_mem_access_check_and_get_page(v, va, flags);
>
>      p2m_read_unlock(p2m);
>
> @@ -1927,7 +1926,7 @@ int p2m_get_mem_access(struct domain *d, gfn_t gfn,
>      struct p2m_domain *p2m = p2m_get_hostp2m(d);
>
>      p2m_read_lock(p2m);
> -    ret = __p2m_get_mem_access(d, gfn, access);
> +    ret = __p2m_get_mem_access(p2m, gfn, access);
>      p2m_read_unlock(p2m);
>
>      return ret;
>

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 24/38] arm/p2m: Make p2m_mem_access_check ready for altp2m
  2016-08-16 22:17 ` [PATCH v3 24/38] arm/p2m: Make p2m_mem_access_check ready for altp2m Sergej Proskurin
@ 2016-09-12  9:02   ` Julien Grall
  2016-09-13 14:00     ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-12  9:02 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/2016 23:17, Sergej Proskurin wrote:
> This commit extends the function "p2m_mem_access_check" and
> "p2m_mem_access_check_and_get_page" to consider altp2m. The function
> "p2m_mem_access_check_and_get_page" needs to translate the gva upon the
> hostp2m's vttbr, as it contains all valid mappings while the currently
> active altp2m view might not have the required gva mapping yet.
>
> Also, the new implementation fills the request buffer to hold
> altp2m-related information.
>
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> ---
> v3: Extended the function "p2m_mem_access_check_and_get_page" to
>     consider altp2m. Similar to "get_page_from_gva", the function
>     "p2m_mem_access_check_and_get_page" needs to translate the gva upon
>     the hostp2m's vttbr. Although, the function "gva_to_ipa" (called in
>     "p2m_mem_access_check_and_get_page") performs a stage 1 table walk,
>     it will access page tables residing in memory. Accesses to this
>     memory are controlled by the underlying 2nd stage translation table
>     and hence require the original mappings of the hostp2m.
> ---
>  xen/arch/arm/p2m.c | 43 +++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 39 insertions(+), 4 deletions(-)
>
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index 5819ae0..ed9e0f0 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -14,6 +14,7 @@
>  #include <asm/hardirq.h>
>  #include <asm/page.h>
>
> +#include <asm/vm_event.h>
>  #include <asm/altp2m.h>
>
>  #ifdef CONFIG_ARM_64
> @@ -1479,9 +1480,32 @@ p2m_mem_access_check_and_get_page(struct vcpu *v, vaddr_t gva, unsigned long fla
>      xenmem_access_t xma;
>      p2m_type_t t;
>      struct page_info *page = NULL;
> -    struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
> +    struct domain *d = v->domain;
> +    struct p2m_domain *p2m = p2m_get_hostp2m(d);
> +
> +    /*
> +     * If altp2m is active, we need to translate the gva upon the hostp2m's
> +     * vttbr, as it contains all valid mappings while the currently active
> +     * altp2m view might not have the required gva mapping yet. Although, the
> +     * function gva_to_ipa performs a stage 1 table walk, it will access page
> +     * tables residing in memory. Accesses to this memory are controlled by the
> +     * underlying 2nd stage translation table and hence require the original
> +     * mappings of the hostp2m.

As I already mentioned a few times now, this function is broken and 
needs to be fixed before anymore change in it.

The underlying memory of stage-1 page table may have been restricted and 
therefore hardware page table walk (gva_to_ipa) may fail.

> +     */
> +    if ( unlikely(altp2m_active(d)) )
> +    {
> +        unsigned long flags = 0;
> +        uint64_t ovttbr = READ_SYSREG64(VTTBR_EL2);
> +
> +        p2m_switch_vttbr_and_get_flags(ovttbr, p2m->vttbr, flags);
> +
> +        rc = gva_to_ipa(gva, &ipa, flag);
> +
> +        p2m_restore_vttbr_and_set_flags(ovttbr, flags);
> +    }
> +    else
> +        rc = gva_to_ipa(gva, &ipa, flag);
>
> -    rc = gva_to_ipa(gva, &ipa, flag);
>      if ( rc < 0 )
>          goto err;
>
> @@ -1698,13 +1722,16 @@ bool_t p2m_mem_access_check(paddr_t gpa, vaddr_t gla, const struct npfec npfec)
>      xenmem_access_t xma;
>      vm_event_request_t *req;
>      struct vcpu *v = current;
> -    struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
> +    struct domain *d = v->domain;
> +    struct p2m_domain *p2m = p2m_get_active_p2m(v);
>
>      /* Mem_access is not in use. */
>      if ( !p2m->mem_access_enabled )
>          return true;
>
> -    rc = p2m_get_mem_access(v->domain, _gfn(paddr_to_pfn(gpa)), &xma);
> +    p2m_read_lock(p2m);
> +    rc = __p2m_get_mem_access(p2m, _gfn(paddr_to_pfn(gpa)), &xma);
> +    p2m_read_unlock(p2m);
>      if ( rc )
>          return true;
>
> @@ -1810,6 +1837,14 @@ bool_t p2m_mem_access_check(paddr_t gpa, vaddr_t gla, const struct npfec npfec)
>          req->u.mem_access.flags |= npfec.insn_fetch     ? MEM_ACCESS_X : 0;
>          req->vcpu_id = v->vcpu_id;
>
> +        vm_event_fill_regs(req);

I don't think this change belongs to this patch.

> +
> +        if ( unlikely(altp2m_active(d)) )
> +        {
> +            req->flags |= VM_EVENT_FLAG_ALTERNATE_P2M;
> +            req->altp2m_idx = altp2m_vcpu(v).p2midx;
> +        }
> +
>          mem_access_send_req(v->domain, req);
>          xfree(req);
>      }
>

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 26/38] arm/p2m: Introduce helpers managing altp2m entries
  2016-08-16 22:17 ` [PATCH v3 26/38] arm/p2m: Introduce helpers managing altp2m entries Sergej Proskurin
@ 2016-09-12  9:04   ` Julien Grall
  0 siblings, 0 replies; 116+ messages in thread
From: Julien Grall @ 2016-09-12  9:04 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/2016 23:17, Sergej Proskurin wrote:
> This commit introduces the following functions:
> * remove_altp2m_entry
> * modify_altp2m_entry
>
> These functions are responsible to manage an altp2m view's entries and
> their attributes.
>
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> ---
> v3: Changed the function prototype of "modify_altp2m_entry" and
>     "remove_altp2m_entry" to hold arguments of type gfn_t/mfn_t instead
>     of addresses.
>
>     Remove the argument of type "struct domain*" from the function's
>     prototypes.
>
>     Remove the function "modify_altp2m_range".
> ---
>  xen/arch/arm/p2m.c        | 36 ++++++++++++++++++++++++++++++++++++
>  xen/include/asm-arm/p2m.h | 14 ++++++++++++++
>  2 files changed, 50 insertions(+)
>
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index ca5ae97..1d3df0f 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -1165,6 +1165,42 @@ void guest_physmap_remove_page(struct domain *d,
>      p2m_remove_mapping(p2m_get_hostp2m(d), gfn, (1 << page_order), mfn);
>  }
>
> +int remove_altp2m_entry(struct p2m_domain *ap2m,
> +                        gfn_t gfn,
> +                        mfn_t mfn,
> +                        unsigned int page_order)
> +{
> +    ASSERT(p2m_is_altp2m(ap2m));
> +
> +    /* Align the gfn and mfn to the given pager order. */
> +    gfn = _gfn(gfn_x(gfn) & ~((1UL << page_order)-1));
> +    mfn = _mfn(mfn_x(mfn) & ~((1UL << page_order)-1));
> +
> +    return p2m_remove_mapping(ap2m, gfn, (1UL << page_order), mfn);
> +}
> +
> +int modify_altp2m_entry(struct p2m_domain *ap2m,
> +                        gfn_t gfn,
> +                        mfn_t mfn,
> +                        p2m_type_t t,
> +                        p2m_access_t a,
> +                        unsigned int page_order)
> +{
> +    int rc;
> +
> +    ASSERT(p2m_is_altp2m(ap2m));
> +
> +    /* Align the gfn and mfn to the given pager order. */
> +    gfn = _gfn(gfn_x(gfn) & ~((1UL << page_order)-1));
> +    mfn = _mfn(mfn_x(mfn) & ~((1UL << page_order)-1));
> +
> +    p2m_write_lock(ap2m);
> +    rc = p2m_set_entry(ap2m, gfn, (1UL << page_order), mfn, t, a);
> +    p2m_write_unlock(ap2m);
> +
> +    return rc;
> +}
> +

I don't want to see any altp2m function in p2m.c. The altp2m code should 
use p2m_set_entry directly with the correct order.

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 27/38] arm/p2m: Introduce p2m_lookup_attr
  2016-08-16 22:17 ` [PATCH v3 27/38] arm/p2m: Introduce p2m_lookup_attr Sergej Proskurin
@ 2016-09-12  9:15   ` Julien Grall
  0 siblings, 0 replies; 116+ messages in thread
From: Julien Grall @ 2016-09-12  9:15 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/2016 23:17, Sergej Proskurin wrote:
> The function "p2m_lookup_attr" allows to lookup the mfn, memory type,
> access rights, and page order corresponding to a domain's gfn.
>
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> ---
> v3: Change function prototype of "p2m_lookup_attr" by removing the
>     function parameter "unsigned int *mattr", as it is not needed by the
>     callers.
>
>     Change function prototype of "p2m_lookup_attr" by changing the
>     parameter of type xenmem_access_t to p2m_access_t.
> ---
>  xen/arch/arm/p2m.c        | 15 +++++++++++++++
>  xen/include/asm-arm/p2m.h | 10 ++++++++++
>  2 files changed, 25 insertions(+)
>
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index 1d3df0f..cef05ed 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -429,6 +429,21 @@ mfn_t p2m_lookup(struct domain *d, gfn_t gfn, p2m_type_t *t)
>      return ret;
>  }
>
> +mfn_t p2m_lookup_attr(struct p2m_domain *p2m,
> +                      gfn_t gfn,
> +                      p2m_type_t *t,
> +                      p2m_access_t *a,
> +                      unsigned int *page_order)
> +{
> +    mfn_t ret;
> +
> +    p2m_read_lock(p2m);
> +    ret = p2m_get_entry(p2m, gfn, t, a, page_order);
> +    p2m_read_unlock(p2m);
> +
> +    return ret;
> +}
> +

Why don't you directly use p2m_get_entry from altp2m code? Looking at 
the callers, there is a potential chance of deadlock because you use 
sequentially twice p2m_read_lock on the same p2m.

Give a look on how you handle h2pm in altp2m_set_mem_access.

In any case, I really don't think this function is useful as most of the 
time you will already have the lock taken.

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 28/38] arm/p2m: Modify reference count only if hostp2m active
  2016-08-16 22:17 ` [PATCH v3 28/38] arm/p2m: Modify reference count only if hostp2m active Sergej Proskurin
@ 2016-09-12  9:17   ` Julien Grall
  2016-09-13 14:16     ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-12  9:17 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/2016 23:17, Sergej Proskurin wrote:
> This commit makes sure that the page reference count is updated through
> the function "p2m_put_l3_page" only the entries have been freed from the
> hosts's p2m.
>
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> ---
>  xen/arch/arm/p2m.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index cef05ed..df2b85b 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -754,7 +754,7 @@ static void p2m_free_entry(struct p2m_domain *p2m,
>      if ( !p2m_valid(entry) || p2m_is_superpage(entry, level) )
>          return;
>
> -    if ( level == 3 )
> +    if ( level == 3 && p2m_is_hostp2m(p2m) )

This check should be pushed in p2m_put_l3_page as we want to have 
removing reference for all the callers of p2m_put_l3_page.

>      {
>          p2m_put_l3_page(_mfn(entry.p2m.base), entry.p2m.type);
>          return;
>

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 29/38] arm/p2m: Add HVMOP_altp2m_set_mem_access
  2016-08-16 22:17 ` [PATCH v3 29/38] arm/p2m: Add HVMOP_altp2m_set_mem_access Sergej Proskurin
@ 2016-09-12 12:08   ` Julien Grall
  2016-09-14 15:20     ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-12 12:08 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hi Sergej,

On 16/08/16 23:17, Sergej Proskurin wrote:
> The HVMOP_altp2m_set_mem_access allows to set gfn permissions of
> (currently one page at a time) of a specific altp2m view. In case the
> view does not hold the requested gfn entry, it will be first copied from
> the host's p2m table and then modified as requested.
>
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> ---
> v2: Prevent the page reference count from being falsely updated on
>     altp2m modification. Therefore, we add a check determining whether
>     the target p2m is a hostp2m before p2m_put_l3_page is called.
>
> v3: Cosmetic fixes.
>
>     Added the functionality to set/get the default_access also in/from
>     the requested altp2m view.
>
>     Read-locked hp2m in "altp2m_set_mem_access".
>
>     Moved the functions "p2m_is_(hostp2m|altp2m)" out of this commit.
>
>     Moved the funtion "modify_altp2m_entry" out of this commit.
>
>     Moved the function "p2m_lookup_attr" out of this commit.
>
>     Moved guards for "p2m_put_l3_page" out of this commit.
> ---
>  xen/arch/arm/altp2m.c        | 53 ++++++++++++++++++++++++++++
>  xen/arch/arm/hvm.c           |  7 +++-
>  xen/arch/arm/p2m.c           | 82 ++++++++++++++++++++++++++++++++------------
>  xen/include/asm-arm/altp2m.h | 12 +++++++
>  4 files changed, 131 insertions(+), 23 deletions(-)
>
> diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
> index ba345b9..03b8ce5 100644
> --- a/xen/arch/arm/altp2m.c
> +++ b/xen/arch/arm/altp2m.c
> @@ -80,6 +80,59 @@ int altp2m_switch_domain_altp2m_by_id(struct domain *d, unsigned int idx)
>      return rc;
>  }
>
> +int altp2m_set_mem_access(struct domain *d,
> +                          struct p2m_domain *hp2m,
> +                          struct p2m_domain *ap2m,
> +                          p2m_access_t a,
> +                          gfn_t gfn)
> +{
> +    p2m_type_t p2mt;
> +    p2m_access_t old_a;
> +    mfn_t mfn;
> +    unsigned int page_order;
> +    int rc;
> +
> +    altp2m_lock(d);

Why do you have this lock? This will serialize all the mem access 
modification even if the ap2m is different.

I am also surprised that you only lock the altp2m in 
modify_altp2m_entry. IHMO, the change in the same a2pm should be serialized.

> +    p2m_read_lock(hp2m);
> +
> +    /* Check if entry is part of the altp2m view. */
> +    mfn = p2m_lookup_attr(ap2m, gfn, &p2mt, NULL, &page_order);
> +
> +    /* Check host p2m if no valid entry in ap2m. */
> +    if ( mfn_eq(mfn, INVALID_MFN) )
> +    {
> +        /* Check if entry is part of the host p2m view. */
> +        mfn = p2m_lookup_attr(hp2m, gfn, &p2mt, &old_a, &page_order);

As mentioned in patch #27, p2m_lookup_attr will take a read reference on 
the hp2m lock. However you already did it above.

Anyway, I really think that p2m_lookup_attr should not exist and ever 
caller be replaced by a direct call to p2m_get_entry.


> +        if ( mfn_eq(mfn, INVALID_MFN) ||
> +             ((p2mt != p2m_ram_rw) && (p2mt != p2m_ram_ro)) )

Please use p2m_is_ram rather than open-coding the check on p2mt.

However, I don't understand why access restriction on altp2m is limited 
to RAM whilst the hostp2m allows restriction on any type of page.

> +        {
> +            rc = -ESRCH;
> +            goto out;
> +        }
> +
> +        /* If this is a superpage, copy that first. */
> +        if ( page_order != THIRD_ORDER )
> +        {
> +            rc = modify_altp2m_entry(ap2m, gfn, mfn, p2mt, old_a, page_order);
> +            if ( rc < 0 )
> +            {
> +                rc = -ESRCH;
> +                goto out;
> +            }
> +        }
> +    }
> +
> +    /* Set mem access attributes - currently supporting only one (4K) page. */
> +    page_order = THIRD_ORDER;

This looks pointless, please use THIRD_ORDER directly as argument.

> +    rc = modify_altp2m_entry(ap2m, gfn, mfn, p2mt, a, page_order);
> +
> +out:
> +    p2m_read_unlock(hp2m);
> +    altp2m_unlock(d);
> +
> +    return rc;
> +}
> +
>  static void altp2m_vcpu_reset(struct vcpu *v)
>  {
>      struct altp2mvcpu *av = &altp2m_vcpu(v);
> diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
> index 9ac3422..df78893 100644
> --- a/xen/arch/arm/hvm.c
> +++ b/xen/arch/arm/hvm.c
> @@ -136,7 +136,12 @@ static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
>          break;
>
>      case HVMOP_altp2m_set_mem_access:
> -        rc = -EOPNOTSUPP;
> +        if ( a.u.set_mem_access.pad )
> +            rc = -EINVAL;
> +        else
> +            rc = p2m_set_mem_access(d, _gfn(a.u.set_mem_access.gfn), 1, 0, 0,
> +                                    a.u.set_mem_access.hvmmem_access,
> +                                    a.u.set_mem_access.view);
>          break;
>
>      case HVMOP_altp2m_change_gfn:
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index df2b85b..8dee02187 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -1913,7 +1913,7 @@ long p2m_set_mem_access(struct domain *d, gfn_t gfn, uint32_t nr,
>                          uint32_t start, uint32_t mask, xenmem_access_t access,
>                          unsigned int altp2m_idx)
>  {
> -    struct p2m_domain *p2m = p2m_get_hostp2m(d);
> +    struct p2m_domain *hp2m = p2m_get_hostp2m(d), *ap2m = NULL;
>      p2m_access_t a;
>      unsigned int order;
>      long rc = 0;
> @@ -1933,13 +1933,26 @@ long p2m_set_mem_access(struct domain *d, gfn_t gfn, uint32_t nr,
>  #undef ACCESS
>      };
>
> +    /* altp2m view 0 is treated as the hostp2m */
> +    if ( altp2m_idx )
> +    {
> +        if ( altp2m_idx >= MAX_ALTP2M ||
> +             d->arch.altp2m_p2m[altp2m_idx] == NULL )
> +            return -EINVAL;
> +
> +        ap2m = d->arch.altp2m_p2m[altp2m_idx];
> +    }
> +
>      switch ( access )
>      {
>      case 0 ... ARRAY_SIZE(memaccess) - 1:
>          a = memaccess[access];
>          break;
>      case XENMEM_access_default:
> -        a = p2m->default_access;
> +        if ( ap2m )
> +            a = ap2m->default_access;
> +        else
> +            a = hp2m->default_access;

On the previous version, I requested to have this change documented in 
the code [1]. I don't see it here.

>          break;
>      default:
>          return -EINVAL;
> @@ -1949,39 +1962,66 @@ long p2m_set_mem_access(struct domain *d, gfn_t gfn, uint32_t nr,
>       * Flip mem_access_enabled to true when a permission is set, as to prevent
>       * allocating or inserting super-pages.
>       */
> -    p2m->mem_access_enabled = true;
> +    if ( ap2m )
> +        ap2m->mem_access_enabled = true;
> +    else
> +        hp2m->mem_access_enabled = true;
>
>      /* If request to set default access. */
>      if ( gfn_eq(gfn, INVALID_GFN) )
>      {
> -        p2m->default_access = a;
> +        if ( ap2m )
> +            ap2m->default_access = a;
> +        else
> +            hp2m->default_access = a;
> +
>          return 0;
>      }
>
> -    p2m_write_lock(p2m);
> -
>      for ( gfn = gfn_add(gfn, start); nr > start; gfn = gfn_add(gfn, 1UL << order) )
>      {
> -        p2m_type_t t;
> -        mfn_t mfn = p2m_get_entry(p2m, gfn, &t, NULL, &order);
> -
> -        /* Skip hole */
> -        if ( mfn_eq(mfn, INVALID_MFN) )
> +        if ( ap2m )
>          {
> +            order = THIRD_ORDER;
> +
>              /*
> -             * the order corresponds to the order of the mapping in the
> -             * page table. so we need to align the gfn before
> -             * incrementing.
> +             * ARM altp2m currently supports only setting of memory access rights
> +             * of only one (4K) page at a time.

This looks like a TODO to me. So please add either : "XXX:" or "TODO:" 
in front.

>               */
> -            gfn = _gfn(gfn_x(gfn) & ~((1UL << order) - 1));
> -            continue;
> +            rc = altp2m_set_mem_access(d, hp2m, ap2m, a, gfn);
> +            if ( rc && rc != -ESRCH )
> +                break;
>          }
>          else
>          {
> -            order = 0;
> -            rc = __p2m_set_entry(p2m, gfn, 0, mfn, t, a);
> -            if ( rc )
> -                break;
> +            p2m_type_t t;
> +            mfn_t mfn;
> +
> +            p2m_write_lock(hp2m);
> +
> +            mfn = p2m_get_entry(hp2m, gfn, &t, NULL, &order);
> +
> +            /* Skip hole */
> +            if ( mfn_eq(mfn, INVALID_MFN) )
> +            {
> +                /*
> +                 * the order corresponds to the order of the mapping in the
> +                 * page table. so we need to align the gfn before
> +                 * incrementing.
> +                 */
> +                gfn = _gfn(gfn_x(gfn) & ~((1UL << order) - 1));
> +                continue;

I just noticed that my series is buggy. The "continue" should be 
dropped. I will do it in the next version.

> +            }
> +            else
> +            {
> +                order = 0;
> +
> +                rc = __p2m_set_entry(hp2m, gfn, 0, mfn, t, a);
> +                if ( rc )
> +                    break;
> +            }
> +
> +            p2m_write_unlock(hp2m);

By moving the lock within the loop, you will impose a TLB flush per-4K 
which is currently not the case.

Looking at the function, I think the implementation the support of 
altp2m could really be simplified. The main difference is if the entry 
is not present in the altp2m then you lookup the host p2m.

>          }
>
>          start += (1UL << order);
> @@ -1993,8 +2033,6 @@ long p2m_set_mem_access(struct domain *d, gfn_t gfn, uint32_t nr,
>          }
>      }
>
> -    p2m_write_unlock(p2m);
> -
>      if ( rc < 0 )
>          return rc;
>      else if ( rc > 0 )
> diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
> index c2e44ab..3e4c36d 100644
> --- a/xen/include/asm-arm/altp2m.h
> +++ b/xen/include/asm-arm/altp2m.h
> @@ -71,4 +71,16 @@ void altp2m_flush(struct domain *d);
>  int altp2m_destroy_by_id(struct domain *d,
>                           unsigned int idx);
>
> +/*
> + * Set memory access attributes of the gfn in the altp2m view. If the altp2m
> + * view does not contain the particular entry, copy it first from the hostp2m.
> + *
> + * Currently supports memory attribute adoptions of only one (4K) page.
> + */
> +int altp2m_set_mem_access(struct domain *d,
> +                          struct p2m_domain *hp2m,
> +                          struct p2m_domain *ap2m,
> +                          p2m_access_t a,
> +                          gfn_t gfn);
> +
>  #endif /* __ASM_ARM_ALTP2M_H */
>

Regards,

[1] 
https://lists.xenproject.org/archives/html/xen-devel/2016-08/msg01007.html

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 32/38] arm/p2m: Code movement in instr/data abort handlers
  2016-08-16 22:17 ` [PATCH v3 32/38] arm/p2m: Code movement in instr/data abort handlers Sergej Proskurin
@ 2016-09-12 13:54   ` Julien Grall
  0 siblings, 0 replies; 116+ messages in thread
From: Julien Grall @ 2016-09-12 13:54 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hi Sergej,

On 16/08/16 23:17, Sergej Proskurin wrote:
> This commit moves code in the functions
> "do_trap_data_(instr|abort)_guest" without changing the original
> functionality. The code movement is limited to moving the struct npfec
> out of the switch statements in both functions. This commit acts as a
> basis for the following commit implementing the altp2m paging mechanism.

Looking at the implementation on the next patch, it is passed as an 
argument but never used but the caller.

So in the current state, this patch is not useful at all.

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 33/38] arm/p2m: Add altp2m paging mechanism
  2016-08-16 22:17 ` [PATCH v3 33/38] arm/p2m: Add altp2m paging mechanism Sergej Proskurin
@ 2016-09-12 14:18   ` Julien Grall
  2016-09-13 15:06     ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-12 14:18 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/16 23:17, Sergej Proskurin wrote:
> This commit adds the function "altp2m_lazy_copy" implementing the altp2m
> paging mechanism. The function "altp2m_lazy_copy" lazily copies the
> hostp2m's mapping into the currently active altp2m view on 2nd stage
> translation faults on instruction or data access.
>
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> ---
> v3: Cosmetic fixes.
>
>     Locked hostp2m in the function "altp2m_lazy_copy" to avoid a mapping
>     being changed in hostp2m before it has been inserted into the
>     valtp2m view.
>
>     Removed unnecessary calls to "p2m_mem_access_check" in the functions
>     "do_trap_instr_abort_guest" and "do_trap_data_abort_guest" after a
>     translation fault has been handled by the function
>     "altp2m_lazy_copy".
>
>     Adapted "altp2m_lazy_copy" to return the value "true" if the
>     encountered translation fault encounters a valid entry inside of the
>     currently active altp2m view. If multiple vcpu's are using the same
>     altp2m, it is likely that both generate a translation fault, whereas
>     the first one will be already handled by "altp2m_lazy_copy". With
>     this change the 2nd vcpu will retry accessing the faulting address.
>
>     Changed order of altp2m checking and MMIO emulation within the
>     function "do_trap_data_abort_guest".  Now, altp2m is checked and
>     handled only if the MMIO does not have to be emulated.
>
>     Changed the function prototype of "altp2m_lazy_copy".  This commit
>     removes the unnecessary struct p2m_domain* from the previous
>     function prototype.  Also, this commit removes the unnecessary
>     argument gva.  Finally, this commit changes the address of the
>     function parameter gpa from paddr_t to gfn_t and renames it to gfn.
>
>     Moved the altp2m handling mechanism into a separate function
>     "try_handle_altp2m".
>
>     Moved the functions "p2m_altp2m_check" and
>     "altp2m_switch_vcpu_altp2m_by_id" out of this patch.
>
>     Moved applied code movement into a separate patch.
> ---
>  xen/arch/arm/altp2m.c        | 62 ++++++++++++++++++++++++++++++++++++++++++++
>  xen/arch/arm/traps.c         | 35 +++++++++++++++++++++++++
>  xen/include/asm-arm/altp2m.h |  5 ++++
>  3 files changed, 102 insertions(+)
>
> diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
> index 11272e9..2009bad 100644
> --- a/xen/arch/arm/altp2m.c
> +++ b/xen/arch/arm/altp2m.c
> @@ -165,6 +165,68 @@ out:
>      return rc;
>  }
>
> +/*
> + * The function altp2m_lazy_copy returns "false" on error.  The return value
> + * "true" signals that either the mapping has been successfully lazy-copied
> + * from the hostp2m to the currently active altp2m view or that the altp2m view
> + * holds already a valid mapping. The latter is the case if multiple vcpu's
> + * using the same altp2m view generate a translation fault that is led back in
> + * both cases to the same mapping and the first fault has been already handled.
> + */
> +bool_t altp2m_lazy_copy(struct vcpu *v,
> +                        gfn_t gfn,
> +                        struct npfec npfec)

Please don't introduce parameters that are not used at all.

> +{
> +    struct domain *d = v->domain;
> +    struct p2m_domain *hp2m = p2m_get_hostp2m(d), *ap2m = NULL;
> +    p2m_type_t p2mt;
> +    p2m_access_t p2ma;
> +    mfn_t mfn;
> +    unsigned int page_order;
> +    int rc;
> +
> +    ap2m = altp2m_get_altp2m(v);
> +    if ( ap2m == NULL)
> +        return false;
> +
> +    /* Check if entry is part of the altp2m view. */
> +    mfn = p2m_lookup_attr(ap2m, gfn, NULL, NULL, NULL);
> +    if ( !mfn_eq(mfn, INVALID_MFN) )
> +        /*
> +         * If multiple vcpu's are using the same altp2m, it is likely that both

s/vcpu's/vcpus/

> +         * generate a translation fault, whereas the first one will be handled
> +         * successfully and the second will encounter a valid mapping that has
> +         * already been added as a result of the previous translation fault.
> +         * In this case, the 2nd vcpu need to retry accessing the faulting

s/need/needs/

> +         * address.
> +         */
> +        return true;
> +
> +    /*
> +     * Lock hp2m to prevent the hostp2m to change a mapping before it is added
> +     * to the altp2m view.
> +     */
> +    p2m_read_lock(hp2m);
> +
> +    /* Check if entry is part of the host p2m view. */
> +    mfn = p2m_lookup_attr(hp2m, gfn, &p2mt, &p2ma, &page_order);
> +    if ( mfn_eq(mfn, INVALID_MFN) )
> +        goto out;
> +
> +    rc = modify_altp2m_entry(ap2m, gfn, mfn, p2mt, p2ma, page_order);
> +    if ( rc )
> +    {
> +        gdprintk(XENLOG_ERR, "altp2m[%d] failed to set entry for %#"PRI_gfn" -> %#"PRI_mfn"\n",

p2midx is unsigned so this should be %u.

> +                 altp2m_vcpu(v).p2midx, gfn_x(gfn), mfn_x(mfn));
> +        domain_crash(hp2m->domain);

You already have the domain in hand with 'd'.

> +    }
> +
> +out:
> +    p2m_read_unlock(hp2m);
> +
> +    return true;
> +}
> +
>  static inline void altp2m_reset(struct p2m_domain *p2m)
>  {
>      p2m_write_lock(p2m);
> diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> index 0bf1653..a4c923c 100644
> --- a/xen/arch/arm/traps.c
> +++ b/xen/arch/arm/traps.c
> @@ -48,6 +48,8 @@
>  #include <asm/vgic.h>
>  #include <asm/cpuerrata.h>
>
> +#include <asm/altp2m.h>
> +
>  /* The base of the stack must always be double-word aligned, which means
>   * that both the kernel half of struct cpu_user_regs (which is pushed in
>   * entry.S) and struct cpu_info (which lives at the bottom of a Xen
> @@ -2397,6 +2399,24 @@ static inline bool hpfar_is_valid(bool s1ptw, uint8_t fsc)
>      return s1ptw || (fsc == FSC_FLT_TRANS && !check_workaround_834220());
>  }
>
> +static bool_t try_handle_altp2m(struct vcpu *v,
> +                                paddr_t gpa,
> +                                struct npfec npfec)

I am not convinced about the usefulness of this function.

> +{
> +    bool_t rc = false;
> +
> +    if ( altp2m_active(v->domain) )

I might be worth to include an unlikely in altp2m_active to tell the 
compiler that altp2m is not the main path.

> +        /*
> +         * Copy the mapping of the faulting address into the currently
> +         * active altp2m view. Return true on success or if the particular
> +         * mapping has already been lazily copied to the currently active
> +         * altp2m view by another vcpu. Return false otherwise.
> +         */
> +        rc = altp2m_lazy_copy(v, _gfn(paddr_to_pfn(gpa)), npfec);
> +
> +    return rc;
> +}
> +
>  static void do_trap_instr_abort_guest(struct cpu_user_regs *regs,
>                                        const union hsr hsr)
>  {
> @@ -2445,6 +2465,14 @@ static void do_trap_instr_abort_guest(struct cpu_user_regs *regs,
>          break;
>      case FSC_FLT_TRANS:
>          /*
> +         * The guest shall retry accessing the page if the altp2m handler
> +         * succeeds. Otherwise, we continue injecting an instruction abort
> +         * exception.
> +         */
> +        if ( try_handle_altp2m(current, gpa, npfec) )
> +            return;

I would have expected that altp2m is the last thing we want to check in 
the abort handler. I.e after p2m_lookup.

> +
> +        /*
>           * The PT walk may have failed because someone was playing
>           * with the Stage-2 page table. Walk the Stage-2 PT to check
>           * if the entry exists. If it's the case, return to the guest
> @@ -2547,6 +2575,13 @@ static void do_trap_data_abort_guest(struct cpu_user_regs *regs,
>          }
>
>          /*
> +         * The guest shall retry accessing the page if the altp2m handler
> +         * succeeds. Otherwise, we continue injecting a data abort exception.
> +         */
> +        if ( try_handle_altp2m(current, info.gpa, npfec) )
> +            return;

Ditto here.

> +
> +        /*
>           * The PT walk may have failed because someone was playing
>           * with the Stage-2 page table. Walk the Stage-2 PT to check
>           * if the entry exists. If it's the case, return to the guest
> diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
> index ef80829..8e40c45 100644
> --- a/xen/include/asm-arm/altp2m.h
> +++ b/xen/include/asm-arm/altp2m.h
> @@ -84,6 +84,11 @@ int altp2m_set_mem_access(struct domain *d,
>                            p2m_access_t a,
>                            gfn_t gfn);
>
> +/* Alternate p2m paging mechanism. */
> +bool_t altp2m_lazy_copy(struct vcpu *v,
> +                        gfn_t gfn,
> +                        struct npfec npfec);
> +
>  /* Propagates changes made to hostp2m to affected altp2m views. */
>  int altp2m_propagate_change(struct domain *d,
>                              gfn_t sgfn,
>

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 34/38] arm/p2m: Add HVMOP_altp2m_change_gfn
  2016-08-16 22:17 ` [PATCH v3 34/38] arm/p2m: Add HVMOP_altp2m_change_gfn Sergej Proskurin
@ 2016-09-12 14:27   ` Julien Grall
  0 siblings, 0 replies; 116+ messages in thread
From: Julien Grall @ 2016-09-12 14:27 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/16 23:17, Sergej Proskurin wrote:
> This commit adds the functionality to change mfn mappings for specified
> gfn's in altp2m views. This mechanism can be used within the context of
> VMI, e.g., to establish stealthy debugging.
>
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> ---
> v3: Moved the altp2m_lock to guard access to d->arch.altp2m_vttbr[idx]
>     in altp2m_change_gfn.
>
>     Locked hp2m to prevent hp2m entries from being modified while the
>     function "altp2m_change_gfn" is active.
>
>     Removed setting ap2m->mem_access_enabled in "altp2m_change_gfn", as
>     we do not need explicitly splitting pages at this point.
>
>     Extended checks allowing to change gfn's in p2m_ram_(rw|ro) memory
>     only.
>
>     Moved the funtion "remove_altp2m_entry" out of this commit.
> ---
>  xen/arch/arm/altp2m.c        | 98 ++++++++++++++++++++++++++++++++++++++++++++
>  xen/arch/arm/hvm.c           |  7 +++-
>  xen/include/asm-arm/altp2m.h |  6 +++
>  3 files changed, 110 insertions(+), 1 deletion(-)
>
> diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
> index 2009bad..fa8d526 100644
> --- a/xen/arch/arm/altp2m.c
> +++ b/xen/arch/arm/altp2m.c
> @@ -301,6 +301,104 @@ out:
>      return rc;
>  }
>
> +int altp2m_change_gfn(struct domain *d,
> +                      unsigned int idx,
> +                      gfn_t old_gfn,
> +                      gfn_t new_gfn)
> +{
> +    struct p2m_domain *hp2m, *ap2m;
> +    mfn_t mfn;
> +    p2m_access_t p2ma;
> +    p2m_type_t p2mt;
> +    unsigned int page_order;
> +    int rc = -EINVAL;
> +
> +    hp2m = p2m_get_hostp2m(d);
> +    ap2m = d->arch.altp2m_p2m[idx];
> +
> +    altp2m_lock(d);

Similar comment as a previous patch, I am not sure to understand you 
lock using altp2m_lock and not p2m_write_lock(ap2m).

The latter would make more sense as it will limit the number of TLB 
flush because all the change will be done in a batch.

> +    p2m_read_lock(hp2m);
> +
> +    if ( idx >= MAX_ALTP2M || d->arch.altp2m_p2m[idx] == NULL )
> +        goto out;
> +
> +    mfn = p2m_lookup_attr(ap2m, old_gfn, &p2mt, NULL, &page_order);
> +
> +    /* Check whether the page needs to be reset. */
> +    if ( gfn_eq(new_gfn, INVALID_GFN) )
> +    {
> +        /* If mfn is mapped by old_gfn, remove old_gfn from the altp2m table. */
> +        if ( !mfn_eq(mfn, INVALID_MFN) )
> +        {
> +            rc = remove_altp2m_entry(ap2m, old_gfn, mfn, page_order);

 From my understanding, altp2m_change_gfn is working on page 
granularity. So here, you would remove a superpage even if the user 
requested to remove a specific gfn.

> +            if ( rc )
> +            {
> +                rc = -EINVAL;
> +                goto out;
> +            }
> +        }
> +
> +        rc = 0;
> +        goto out;
> +    }
> +
> +    /* Check hostp2m if no valid entry in altp2m present. */
> +    if ( mfn_eq(mfn, INVALID_MFN) )
> +    {
> +        mfn = p2m_lookup_attr(hp2m, old_gfn, &p2mt, &p2ma, &page_order);
> +        if ( mfn_eq(mfn, INVALID_MFN) ||
> +             /* Allow changing gfn's in p2m_ram_(rw|ro) memory only. */
> +             ((p2mt != p2m_ram_rw) && (p2mt != p2m_ram_ro)) )
> +        {
> +            rc = -EINVAL;
> +            goto out;
> +        }
> +
> +        /* If this is a superpage, copy that first. */
> +        if ( page_order != THIRD_ORDER )
> +        {
> +            rc = modify_altp2m_entry(ap2m, old_gfn, mfn, p2mt, p2ma, page_order);
> +            if ( rc )
> +            {
> +                rc = -EINVAL;
> +                goto out;
> +            }
> +        }
> +    }
> +
> +    mfn = p2m_lookup_attr(ap2m, new_gfn, &p2mt, &p2ma, &page_order);
> +
> +    /* If new_gfn is not part of altp2m, get the mapping information from hp2m */
> +    if ( mfn_eq(mfn, INVALID_MFN) )
> +        mfn = p2m_lookup_attr(hp2m, new_gfn, &p2mt, &p2ma, &page_order);
> +
> +    if ( mfn_eq(mfn, INVALID_MFN) ||
> +         /* Allow changing gfn's in p2m_ram_(rw|ro) memory only. */
> +         ((p2mt != p2m_ram_rw) && (p2mt != p2m_ram_ro)) )
> +    {
> +        rc = -EINVAL;
> +        goto out;
> +    }
> +
> +    /* Set mem access attributes - currently supporting only one (4K) page. */

I don't understand why memaccess matters here. p2m_set_entry is handling 
for you the memaccess case.

> +    page_order = THIRD_ORDER;
> +    rc = modify_altp2m_entry(ap2m, old_gfn, mfn, p2mt, p2ma, page_order);
> +    if ( rc )
> +    {
> +        rc = -EINVAL;
> +        goto out;
> +    }
> +
> +    rc = 0;
> +
> +out:
> +    p2m_read_unlock(hp2m);
> +    altp2m_unlock(d);
> +
> +    return rc;
> +}
> +
> +
>  static void altp2m_vcpu_reset(struct vcpu *v)
>  {
>      struct altp2mvcpu *av = &altp2m_vcpu(v);
> diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
> index df78893..c754ad1 100644
> --- a/xen/arch/arm/hvm.c
> +++ b/xen/arch/arm/hvm.c
> @@ -145,7 +145,12 @@ static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
>          break;
>
>      case HVMOP_altp2m_change_gfn:
> -        rc = -EOPNOTSUPP;
> +        if ( a.u.change_gfn.pad1 || a.u.change_gfn.pad2 )
> +            rc = -EINVAL;
> +        else
> +            rc = altp2m_change_gfn(d, a.u.change_gfn.view,
> +                                   _gfn(a.u.change_gfn.old_gfn),
> +                                   _gfn(a.u.change_gfn.new_gfn));
>          break;
>      }
>
> diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
> index 8e40c45..8b459bf 100644
> --- a/xen/include/asm-arm/altp2m.h
> +++ b/xen/include/asm-arm/altp2m.h
> @@ -97,4 +97,10 @@ int altp2m_propagate_change(struct domain *d,
>                              p2m_type_t p2mt,
>                              p2m_access_t p2ma);
>
> +/* Change a gfn->mfn mapping */
> +int altp2m_change_gfn(struct domain *d,
> +                      unsigned int idx,
> +                      gfn_t old_gfn,
> +                      gfn_t new_gfn);
> +
>  #endif /* __ASM_ARM_ALTP2M_H */
>

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 35/38] arm/p2m: Adjust debug information to altp2m
  2016-08-16 22:17 ` [PATCH v3 35/38] arm/p2m: Adjust debug information to altp2m Sergej Proskurin
@ 2016-09-12 14:29   ` Julien Grall
  2016-09-13 15:13     ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-12 14:29 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/16 23:17, Sergej Proskurin wrote:
> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> ---
> v2: Dump p2m information of the hostp2m and all altp2m views.
> ---
>  xen/arch/arm/p2m.c | 20 ++++++++++++++++++++
>  1 file changed, 20 insertions(+)
>
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index dea3038..86e2a1d 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -162,6 +162,26 @@ void dump_p2m_lookup(struct domain *d, paddr_t addr)
>
>      dump_pt_walk(page_to_maddr(p2m->root), addr,
>                   P2M_ROOT_LEVEL, P2M_ROOT_PAGES);
> +    printk("\n");
> +
> +    if ( altp2m_active(d) )
> +    {
> +        unsigned int i;
> +
> +        for ( i = 0; i < MAX_ALTP2M; i++ )
> +        {
> +            if ( d->arch.altp2m_p2m[i] == NULL )
> +                continue;
> +
> +            p2m = d->arch.altp2m_p2m[i];
> +
> +            printk("AP2M[%d] @ %p mfn:0x%lx\n",

s/%d/%u/ as the p2m index is unsigned
s/0x%lx/%#PRI_mfn/ because we should avoid open format from now.

> +                    i, p2m->root, page_to_mfn(p2m->root));
> +
> +            dump_pt_walk(page_to_maddr(p2m->root), addr, P2M_ROOT_LEVEL, P2M_ROOT_PAGES);
> +            printk("\n");
> +        }
> +    }
>  }
>
>  void p2m_save_state(struct vcpu *p)
>

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 15/38] arm/p2m: Add altp2m table flushing routine
  2016-09-09 17:02   ` Julien Grall
@ 2016-09-13  9:13     ` Sergej Proskurin
  0 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-13  9:13 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,


On 09/09/2016 07:02 PM, Julien Grall wrote:
> Hello Sergej,
>
> On 16/08/16 23:16, Sergej Proskurin wrote:
>> The current implementation differentiates between flushing and
>> destroying altp2m views. This commit adds the function altp2m_flush,
>> which allows to release all of the alternate p2m views.
>>
>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>> ---
>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>> Cc: Julien Grall <julien.grall@arm.com>
>> ---
>> v2: Pages in p2m->pages are not cleared in p2m_flush_table anymore.
>>     VMID is freed in p2m_free_one.
>>     Cosmetic fixes.
>>
>> v3: Changed the locking mechanism to "p2m_write_lock" inside the
>>     function "altp2m_flush".
>>
>>     Do not flush but rather teardown the altp2m in the function
>>     "altp2m_flush".
>>
>>     Exchanged the check "altp2m_vttbr[idx] == INVALID_VTTBR" for
>>     "altp2m_p2m[idx] == NULL" in "altp2m_flush".
>> ---
>>  xen/arch/arm/altp2m.c        | 31 +++++++++++++++++++++++++++++++
>>  xen/include/asm-arm/altp2m.h |  3 +++
>>  2 files changed, 34 insertions(+)
>>
>> diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
>> index 66a373a..02cffd7 100644
>> --- a/xen/arch/arm/altp2m.c
>> +++ b/xen/arch/arm/altp2m.c
>> @@ -34,6 +34,37 @@ int altp2m_init(struct domain *d)
>>      return 0;
>>  }
>>
>> +void altp2m_flush(struct domain *d)
>> +{
>> +    unsigned int i;
>> +    struct p2m_domain *p2m;
>> +
>> +    /*
>> +     * If altp2m is active, we are not allowed to flush altp2m[0].
>> This special
>> +     * view is considered as the hostp2m as long as altp2m is active.
>> +     */
>> +    ASSERT(!altp2m_active(d));
>> +
>> +    altp2m_lock(d);
>> +
>> +    for ( i = 0; i < MAX_ALTP2M; i++ )
>> +    {
>> +        if ( d->arch.altp2m_p2m[i] == NULL )
>> +            continue;
>> +
>> +        p2m = d->arch.altp2m_p2m[i];
>> +
>> +        p2m_write_lock(p2m);
>
> Why do you take the lock here? The p2m should not be used by anyone at
> that time.

Good point. I will not acquire the lock at this point. Thank you.

>
>> +        p2m_teardown_one(p2m);
>
> You may want to add an ASSERT(!atomic_read(p2m->active_vcpus)) somewhere.

Ok.

>
>> +        p2m_write_unlock(p2m);
>> +
>> +        xfree(p2m);
>> +        d->arch.altp2m_p2m[i] = NULL;
>> +    }
>> +
>> +    altp2m_unlock(d);
>> +}
>> +
>>  void altp2m_teardown(struct domain *d)
>>  {
>>      unsigned int i;
>> diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
>> index a156109..4c15b75 100644
>> --- a/xen/include/asm-arm/altp2m.h
>> +++ b/xen/include/asm-arm/altp2m.h
>> @@ -42,4 +42,7 @@ static inline uint16_t altp2m_vcpu_idx(const struct
>> vcpu *v)
>>  int altp2m_init(struct domain *d);
>>  void altp2m_teardown(struct domain *d);
>>
>> +/* Flush all the alternate p2m's for a domain. */
>> +void altp2m_flush(struct domain *d);
>> +
>>  #endif /* __ASM_ARM_ALTP2M_H */
>>

Best regards,
~Sergej

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 16/38] arm/p2m: Add HVMOP_altp2m_set_domain_state
  2016-09-09 17:14   ` Julien Grall
@ 2016-09-13  9:22     ` Sergej Proskurin
  0 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-13  9:22 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,


On 09/09/2016 07:14 PM, Julien Grall wrote:
> Hello Sergej,
>
> On 16/08/16 23:16, Sergej Proskurin wrote:
>> +static int altp2m_init_helper(struct domain *d, unsigned int idx)
>> +{
>> +    int rc;
>> +    struct p2m_domain *p2m = d->arch.altp2m_p2m[idx];
>> +
>> +    ASSERT(p2m == NULL);
>> +
>> +    /* Allocate a new, zeroed altp2m view. */
>> +    p2m = xzalloc(struct p2m_domain);
>> +    if ( p2m == NULL)
>> +    {
>> +        rc = -ENOMEM;
>> +        goto err;
>> +    }
>
> This could be simplified with just return -ENOMEM.
>

True. I will do that.

>> +
>> +    p2m->p2m_class = p2m_alternate;
>> +
>> +    /* Initialize the new altp2m view. */
>> +    rc = p2m_init_one(d, p2m);
>> +    if ( rc )
>> +        goto err;
>> +
>> +    p2m->access_required = false;
>> +    _atomic_set(&p2m->active_vcpus, 0);
>
> the p2m is initialized to 0, so both access_required and active_vcpus
> initialization is not necessary.
>

I will remove these initializations in the next patch.

>> +
>> +    d->arch.altp2m_p2m[idx] = p2m;
>> +
>> +    return rc;
>> +
>> +err:
>> +    if ( p2m )
>> +        xfree(p2m);
>
> xfree is able to handle NULL pointer.
>

Ok, thank you.

>> +
>> +    d->arch.altp2m_p2m[idx] = NULL;
>> +
>> +    return rc;
>> +}
>> +
>> +int altp2m_init_by_id(struct domain *d, unsigned int idx)
>> +{
>> +    int rc = -EINVAL;
>> +
>> +    if ( idx >= MAX_ALTP2M )
>> +        return rc;
>> +
>> +    altp2m_lock(d);
>> +
>> +    if ( d->arch.altp2m_p2m[idx] == NULL )
>> +        rc = altp2m_init_helper(d, idx);
>> +
>> +    altp2m_unlock(d);
>> +
>> +    return rc;
>> +}
>> +

Cheers,
~Sergej

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 18/38] arm/p2m: Add HVMOP_altp2m_destroy_p2m
  2016-09-12  8:41   ` Julien Grall
@ 2016-09-13 12:43     ` Sergej Proskurin
  0 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-13 12:43 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,


On 09/12/2016 10:41 AM, Julien Grall wrote:
> Hello Sergej,
>
> On 16/08/2016 23:16, Sergej Proskurin wrote:
>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>> ---
>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>> Cc: Julien Grall <julien.grall@arm.com>
>> ---
>> v2: Substituted the call to tlb_flush for p2m_flush_table.
>>     Added comments.
>>     Cosmetic fixes.
>>
>> v3: Changed the locking mechanism to "p2m_write_lock" inside the
>>     function "altp2m_destroy_by_id".
>>
>>     Do not flush but rather teardown the altp2m in the function
>>     "altp2m_destroy_by_id".
>>
>>     Exchanged the check "altp2m_vttbr[idx] == INVALID_VTTBR" for
>>     "altp2m_p2m[idx] == NULL" in "altp2m_destroy_by_id".
>> ---
>>  xen/arch/arm/altp2m.c        | 43
>> +++++++++++++++++++++++++++++++++++++++++++
>>  xen/arch/arm/hvm.c           |  2 +-
>>  xen/include/asm-arm/altp2m.h |  4 ++++
>>  3 files changed, 48 insertions(+), 1 deletion(-)
>>
>> diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
>> index b5d1951..c14ab0b 100644
>> --- a/xen/arch/arm/altp2m.c
>> +++ b/xen/arch/arm/altp2m.c
>> @@ -190,6 +190,49 @@ void altp2m_flush(struct domain *d)
>>      altp2m_unlock(d);
>>  }
>>
>> +int altp2m_destroy_by_id(struct domain *d, unsigned int idx)
>> +{
>> +    struct p2m_domain *p2m;
>> +    int rc = -EBUSY;
>> +
>> +    /*
>> +     * The altp2m[0] is considered as the hostp2m and is used as a
>> safe harbor
>> +     * to which you can switch as long as altp2m is active. After
>> deactivating
>> +     * altp2m, the system switches back to the original hostp2m
>> view. That is,
>> +     * altp2m[0] should only be destroyed/flushed/freed, when altp2m is
>> +     * deactivated.
>> +     */
>> +    if ( !idx || idx >= MAX_ALTP2M )
>> +        return rc;
>> +
>> +    domain_pause_except_self(d);
>> +
>> +    altp2m_lock(d);
>> +
>> +    if ( d->arch.altp2m_p2m[idx] != NULL )
>> +    {
>> +        p2m = d->arch.altp2m_p2m[idx];
>> +
>> +        if ( !_atomic_read(p2m->active_vcpus) )
>> +        {
>> +            p2m_write_lock(p2m);
>
> I am not sure why you take the lock here. It will not protect you from
> anything as the p2m will get freed just after. So if someone else is
> using it, it will be in big trouble.
>

I will remove the lock in the next patch, thank you.

>> +            p2m_teardown_one(p2m);
>> +            p2m_write_unlock(p2m);
>> +
>> +            xfree(p2m);
>> +            d->arch.altp2m_p2m[idx] = NULL;
>> +
>> +            rc = 0;
>> +        }
>> +    }
>> +
>> +    altp2m_unlock(d);
>> +
>> +    domain_unpause_except_self(d);
>> +
>> +    return rc;
>> +}
>> +
>>  void altp2m_teardown(struct domain *d)
>>  {
>>      unsigned int i;
>> diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
>> index a504dfd..df973ef 100644
>> --- a/xen/arch/arm/hvm.c
>> +++ b/xen/arch/arm/hvm.c
>> @@ -128,7 +128,7 @@ static int
>> do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
>>          break;
>>
>>      case HVMOP_altp2m_destroy_p2m:
>> -        rc = -EOPNOTSUPP;
>> +        rc = altp2m_destroy_by_id(d, a.u.view.view);
>>          break;
>>
>>      case HVMOP_altp2m_switch_p2m:
>> diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
>> index 5701012..6074079 100644
>> --- a/xen/include/asm-arm/altp2m.h
>> +++ b/xen/include/asm-arm/altp2m.h
>> @@ -63,4 +63,8 @@ int altp2m_init_next_available(struct domain *d,
>>  /* Flush all the alternate p2m's for a domain. */
>>  void altp2m_flush(struct domain *d);
>>
>> +/* Make a specific alternate p2m invalid */
>> +int altp2m_destroy_by_id(struct domain *d,
>> +                         unsigned int idx);
>> +
>>  #endif /* __ASM_ARM_ALTP2M_H */
>>

Cheers,
~Sergej

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 19/38] arm/p2m: Add HVMOP_altp2m_switch_p2m
  2016-09-12  8:47   ` Julien Grall
@ 2016-09-13 13:00     ` Sergej Proskurin
  2016-09-14 10:57       ` Julien Grall
  0 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-13 13:00 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,


On 09/12/2016 10:47 AM, Julien Grall wrote:
> Hello Sergej,
>
> On 16/08/2016 23:16, Sergej Proskurin wrote:
>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>> ---
>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>> Cc: Julien Grall <julien.grall@arm.com>
>> ---
>> v3: Extended the function "altp2m_switch_domain_altp2m_by_id" so that if
>>     the guest domain indirectly calles this function, the current
>> vcpu also
>>     changes the altp2m view without performing an explicit context
>> switch.
>>
>>     Exchanged the check "altp2m_vttbr[idx] == INVALID_VTTBR" for
>>     "altp2m_p2m[idx] == NULL" in "altp2m_switch_domain_altp2m_by_id".
>> ---
>>  xen/arch/arm/altp2m.c        | 48
>> ++++++++++++++++++++++++++++++++++++++++++++
>>  xen/arch/arm/hvm.c           |  2 +-
>>  xen/include/asm-arm/altp2m.h |  4 ++++
>>  3 files changed, 53 insertions(+), 1 deletion(-)
>>
>> diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
>> index c14ab0b..ba345b9 100644
>> --- a/xen/arch/arm/altp2m.c
>> +++ b/xen/arch/arm/altp2m.c
>> @@ -32,6 +32,54 @@ struct p2m_domain *altp2m_get_altp2m(struct vcpu *v)
>>      return v->domain->arch.altp2m_p2m[index];
>>  }
>>
>> +int altp2m_switch_domain_altp2m_by_id(struct domain *d, unsigned int
>> idx)
>> +{
>> +    struct vcpu *v;
>> +    int rc = -EINVAL;
>> +
>> +    if ( idx >= MAX_ALTP2M )
>> +        return rc;
>> +
>> +    domain_pause_except_self(d);
>> +
>> +    altp2m_lock(d);
>> +
>> +    if ( d->arch.altp2m_p2m[idx] != NULL )
>> +    {
>> +        for_each_vcpu( d, v )
>> +            if ( idx != altp2m_vcpu(v).p2midx )
>
> Could you invert the condition to avoid another layer of nested if?
>

Did you mean checking for (idx == altp2m_vcpu(v).p2midx) and continue
the loop if the condition should be satisfied? If so, then sure thing :)

>> +            {
>> +                atomic_dec(&altp2m_get_altp2m(v)->active_vcpus);
>> +                altp2m_vcpu(v).p2midx = idx;
>> +                atomic_inc(&altp2m_get_altp2m(v)->active_vcpus);
>> +
>> +                /*
>> +                 * In case it is the guest domain, which indirectly
>> called this
>> +                 * function, the current vcpu will not switch its
>> context
>> +                 * within the function "p2m_restore_state". That is,
>> changing
>> +                 * the altp2m_vcpu(v).p2midx will not lead to the
>> requested
>> +                 * altp2m switch on that specific vcpu. To achieve
>> the desired
>> +                 * behavior, we write to VTTBR_EL2 directly.
>> +                 */
>> +                if ( v->domain == d && v == current )
>
> v == current is enough.
>

Ok.

>> +                {
>> +                    struct p2m_domain *ap2m = d->arch.altp2m_p2m[idx];
>> +
>> +                    WRITE_SYSREG64(ap2m->vttbr, VTTBR_EL2);
>> +                    isb();
>
> I don't like the open-coding of VTTBR_EL2. I would much prefer a
> separate helper to update it.
>

Sure, I can introduce an UPDATE_VTTBR macro (including the isb call) in
p2m.h and adjust the remaining writes to VTTBR_EL2 in p2m.c as well. I
hope, I understood you correctly.

>> +                }
>> +            }
>> +
>> +        rc = 0;
>> +    }
>> +
>> +    altp2m_unlock(d);
>> +
>> +    domain_unpause_except_self(d);
>> +
>> +    return rc;
>> +}
>> +
>>  static void altp2m_vcpu_reset(struct vcpu *v)
>>  {
>>      struct altp2mvcpu *av = &altp2m_vcpu(v);
>> diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
>> index df973ef..9ac3422 100644
>> --- a/xen/arch/arm/hvm.c
>> +++ b/xen/arch/arm/hvm.c
>> @@ -132,7 +132,7 @@ static int
>> do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
>>          break;
>>
>>      case HVMOP_altp2m_switch_p2m:
>> -        rc = -EOPNOTSUPP;
>> +        rc = altp2m_switch_domain_altp2m_by_id(d, a.u.view.view);
>>          break;
>>
>>      case HVMOP_altp2m_set_mem_access:
>> diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
>> index 6074079..c2e44ab 100644
>> --- a/xen/include/asm-arm/altp2m.h
>> +++ b/xen/include/asm-arm/altp2m.h
>> @@ -52,6 +52,10 @@ void altp2m_vcpu_destroy(struct vcpu *v);
>>  /* Get current alternate p2m table. */
>>  struct p2m_domain *altp2m_get_altp2m(struct vcpu *v);
>>
>> +/* Switch alternate p2m for entire domain */
>> +int altp2m_switch_domain_altp2m_by_id(struct domain *d,
>> +                                      unsigned int idx);
>> +
>>  /* Make a specific alternate p2m valid. */
>>  int altp2m_init_by_id(struct domain *d,
>>                        unsigned int idx);
>>

Cheers,
~Sergej


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 23/38] arm/p2m: Cosmetic fixes -- __p2m_get_mem_access
  2016-09-12  8:53   ` Julien Grall
@ 2016-09-13 13:27     ` Sergej Proskurin
  2016-09-13 13:30       ` Julien Grall
  0 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-13 13:27 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,


On 09/12/2016 10:53 AM, Julien Grall wrote:
> Hello Sergej,
>
> On 16/08/2016 23:16, Sergej Proskurin wrote:
>> This commit extends the function prototypes of the functions:
>> * __p2m_get_mem_access
>> * p2m_mem_access_check_and_get_page
>>
>> We extend the function prototype of "__p2m_get_mem_access" to hold an
>> argument of type "struct p2m_domain*", as we need to distinguish between
>> the host's p2m and different altp2m views. While doing so, we needed to
>> extend the function's prototype of "p2m_mem_access_check_and_get_page"
>> to hold an argument of type "struct vcpu*".
>
> Please details in the commit message why it is necessary to pass a
> "struct vcpu *" to p2m_mem_access_check_and_get_page.
>

Actually, it is already sufficient to provide a "struct domain *".
Thanks for the hint. I will extend the commit message in the next patch
accordingly.

Cheers,
~Sergej


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 23/38] arm/p2m: Cosmetic fixes -- __p2m_get_mem_access
  2016-09-13 13:27     ` Sergej Proskurin
@ 2016-09-13 13:30       ` Julien Grall
  2016-09-13 13:42         ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-13 13:30 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini



On 13/09/16 14:27, Sergej Proskurin wrote:
> Hi Julien,

Hello Sergej,

>
> On 09/12/2016 10:53 AM, Julien Grall wrote:
>> Hello Sergej,
>>
>> On 16/08/2016 23:16, Sergej Proskurin wrote:
>>> This commit extends the function prototypes of the functions:
>>> * __p2m_get_mem_access
>>> * p2m_mem_access_check_and_get_page
>>>
>>> We extend the function prototype of "__p2m_get_mem_access" to hold an
>>> argument of type "struct p2m_domain*", as we need to distinguish between
>>> the host's p2m and different altp2m views. While doing so, we needed to
>>> extend the function's prototype of "p2m_mem_access_check_and_get_page"
>>> to hold an argument of type "struct vcpu*".
>>
>> Please details in the commit message why it is necessary to pass a
>> "struct vcpu *" to p2m_mem_access_check_and_get_page.
>>
>
> Actually, it is already sufficient to provide a "struct domain *".
> Thanks for the hint. I will extend the commit message in the next patch
> accordingly.

No it is not, the stage-1 page table (VTTBR0, VTTBR1...) are per-vCPU 
and if the current vCPU is not the correct one, you will have to context 
switch few registers before.

It is not handled today, but we should avoid to have a broken interface.

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 23/38] arm/p2m: Cosmetic fixes -- __p2m_get_mem_access
  2016-09-13 13:30       ` Julien Grall
@ 2016-09-13 13:42         ` Sergej Proskurin
  2016-09-13 13:45           ` Julien Grall
  0 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-13 13:42 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,


On 09/13/2016 03:30 PM, Julien Grall wrote:
>
>
> On 13/09/16 14:27, Sergej Proskurin wrote:
>> Hi Julien,
>
> Hello Sergej,
>
>>
>> On 09/12/2016 10:53 AM, Julien Grall wrote:
>>> Hello Sergej,
>>>
>>> On 16/08/2016 23:16, Sergej Proskurin wrote:
>>>> This commit extends the function prototypes of the functions:
>>>> * __p2m_get_mem_access
>>>> * p2m_mem_access_check_and_get_page
>>>>
>>>> We extend the function prototype of "__p2m_get_mem_access" to hold an
>>>> argument of type "struct p2m_domain*", as we need to distinguish
>>>> between
>>>> the host's p2m and different altp2m views. While doing so, we
>>>> needed to
>>>> extend the function's prototype of "p2m_mem_access_check_and_get_page"
>>>> to hold an argument of type "struct vcpu*".
>>>
>>> Please details in the commit message why it is necessary to pass a
>>> "struct vcpu *" to p2m_mem_access_check_and_get_page.
>>>
>>
>> Actually, it is already sufficient to provide a "struct domain *".
>> Thanks for the hint. I will extend the commit message in the next patch
>> accordingly.
>
> No it is not, the stage-1 page table (VTTBR0, VTTBR1...) are per-vCPU
> and if the current vCPU is not the correct one, you will have to
> context switch few registers before.
>
> It is not handled today, but we should avoid to have a broken interface.

I see. Ok, since it is not really used today, I will state that we will
need the "struct vcpu*" to access vcpu-related registers in the future.
Would that be ok?

Cheers,
~Sergej

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 23/38] arm/p2m: Cosmetic fixes -- __p2m_get_mem_access
  2016-09-13 13:42         ` Sergej Proskurin
@ 2016-09-13 13:45           ` Julien Grall
  0 siblings, 0 replies; 116+ messages in thread
From: Julien Grall @ 2016-09-13 13:45 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini



On 13/09/16 14:42, Sergej Proskurin wrote:
> Hi Julien,
>
>
> On 09/13/2016 03:30 PM, Julien Grall wrote:
>>
>>
>> On 13/09/16 14:27, Sergej Proskurin wrote:
>>> Hi Julien,
>>
>> Hello Sergej,
>>
>>>
>>> On 09/12/2016 10:53 AM, Julien Grall wrote:
>>>> Hello Sergej,
>>>>
>>>> On 16/08/2016 23:16, Sergej Proskurin wrote:
>>>>> This commit extends the function prototypes of the functions:
>>>>> * __p2m_get_mem_access
>>>>> * p2m_mem_access_check_and_get_page
>>>>>
>>>>> We extend the function prototype of "__p2m_get_mem_access" to hold an
>>>>> argument of type "struct p2m_domain*", as we need to distinguish
>>>>> between
>>>>> the host's p2m and different altp2m views. While doing so, we
>>>>> needed to
>>>>> extend the function's prototype of "p2m_mem_access_check_and_get_page"
>>>>> to hold an argument of type "struct vcpu*".
>>>>
>>>> Please details in the commit message why it is necessary to pass a
>>>> "struct vcpu *" to p2m_mem_access_check_and_get_page.
>>>>
>>>
>>> Actually, it is already sufficient to provide a "struct domain *".
>>> Thanks for the hint. I will extend the commit message in the next patch
>>> accordingly.
>>
>> No it is not, the stage-1 page table (VTTBR0, VTTBR1...) are per-vCPU
>> and if the current vCPU is not the correct one, you will have to
>> context switch few registers before.
>>
>> It is not handled today, but we should avoid to have a broken interface.
>
> I see. Ok, since it is not really used today, I will state that we will
> need the "struct vcpu*" to access vcpu-related registers in the future.
> Would that be ok?

I would recommend you to have a think on the problem mentioned in patch 
#24 first. You may need the vCPU to fix the bug.

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 24/38] arm/p2m: Make p2m_mem_access_check ready for altp2m
  2016-09-12  9:02   ` Julien Grall
@ 2016-09-13 14:00     ` Sergej Proskurin
  2016-09-13 14:20       ` Julien Grall
  0 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-13 14:00 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,


On 09/12/2016 11:02 AM, Julien Grall wrote:
> Hello Sergej,
>
> On 16/08/2016 23:17, Sergej Proskurin wrote:
>> This commit extends the function "p2m_mem_access_check" and
>> "p2m_mem_access_check_and_get_page" to consider altp2m. The function
>> "p2m_mem_access_check_and_get_page" needs to translate the gva upon the
>> hostp2m's vttbr, as it contains all valid mappings while the currently
>> active altp2m view might not have the required gva mapping yet.
>>
>> Also, the new implementation fills the request buffer to hold
>> altp2m-related information.
>>
>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>> ---
>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>> Cc: Julien Grall <julien.grall@arm.com>
>> ---
>> v3: Extended the function "p2m_mem_access_check_and_get_page" to
>>     consider altp2m. Similar to "get_page_from_gva", the function
>>     "p2m_mem_access_check_and_get_page" needs to translate the gva upon
>>     the hostp2m's vttbr. Although, the function "gva_to_ipa" (called in
>>     "p2m_mem_access_check_and_get_page") performs a stage 1 table walk,
>>     it will access page tables residing in memory. Accesses to this
>>     memory are controlled by the underlying 2nd stage translation table
>>     and hence require the original mappings of the hostp2m.
>> ---
>>  xen/arch/arm/p2m.c | 43 +++++++++++++++++++++++++++++++++++++++----
>>  1 file changed, 39 insertions(+), 4 deletions(-)
>>
>> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
>> index 5819ae0..ed9e0f0 100644
>> --- a/xen/arch/arm/p2m.c
>> +++ b/xen/arch/arm/p2m.c
>> @@ -14,6 +14,7 @@
>>  #include <asm/hardirq.h>
>>  #include <asm/page.h>
>>
>> +#include <asm/vm_event.h>
>>  #include <asm/altp2m.h>
>>
>>  #ifdef CONFIG_ARM_64
>> @@ -1479,9 +1480,32 @@ p2m_mem_access_check_and_get_page(struct vcpu
>> *v, vaddr_t gva, unsigned long fla
>>      xenmem_access_t xma;
>>      p2m_type_t t;
>>      struct page_info *page = NULL;
>> -    struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
>> +    struct domain *d = v->domain;
>> +    struct p2m_domain *p2m = p2m_get_hostp2m(d);
>> +
>> +    /*
>> +     * If altp2m is active, we need to translate the gva upon the
>> hostp2m's
>> +     * vttbr, as it contains all valid mappings while the currently
>> active
>> +     * altp2m view might not have the required gva mapping yet.
>> Although, the
>> +     * function gva_to_ipa performs a stage 1 table walk, it will
>> access page
>> +     * tables residing in memory. Accesses to this memory are
>> controlled by the
>> +     * underlying 2nd stage translation table and hence require the
>> original
>> +     * mappings of the hostp2m.
>
> As I already mentioned a few times now, this function is broken and
> needs to be fixed before anymore change in it.
>
> The underlying memory of stage-1 page table may have been restricted
> and therefore hardware page table walk (gva_to_ipa) may fail.
>

Based on our previous discussion I believed that it would be enough to
temporary change the VTTBR to the one of the host's p2m as it is done in
the implementation below. Your argument was that (without changing the
VTTBR) it might come to an issue during the process address translation
as accesses to the memory view in the altp2m tables might be restricted.

Would it not be sufficient to temporary switch to the VTTBR of the
host's p2m (similarly as I did in the the following implementation)? In
this way, as far as I understand, changes in the active altp2m view
should not affect the process of address translation.

>> +     */
>> +    if ( unlikely(altp2m_active(d)) )
>> +    {
>> +        unsigned long flags = 0;
>> +        uint64_t ovttbr = READ_SYSREG64(VTTBR_EL2);
>> +
>> +        p2m_switch_vttbr_and_get_flags(ovttbr, p2m->vttbr, flags);
>> +
>> +        rc = gva_to_ipa(gva, &ipa, flag);
>> +
>> +        p2m_restore_vttbr_and_set_flags(ovttbr, flags);
>> +    }
>> +    else
>> +        rc = gva_to_ipa(gva, &ipa, flag);
>>
>> -    rc = gva_to_ipa(gva, &ipa, flag);
>>      if ( rc < 0 )
>>          goto err;
>>
>> @@ -1698,13 +1722,16 @@ bool_t p2m_mem_access_check(paddr_t gpa,
>> vaddr_t gla, const struct npfec npfec)
>>      xenmem_access_t xma;
>>      vm_event_request_t *req;
>>      struct vcpu *v = current;
>> -    struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
>> +    struct domain *d = v->domain;
>> +    struct p2m_domain *p2m = p2m_get_active_p2m(v);
>>
>>      /* Mem_access is not in use. */
>>      if ( !p2m->mem_access_enabled )
>>          return true;
>>
>> -    rc = p2m_get_mem_access(v->domain, _gfn(paddr_to_pfn(gpa)), &xma);
>> +    p2m_read_lock(p2m);
>> +    rc = __p2m_get_mem_access(p2m, _gfn(paddr_to_pfn(gpa)), &xma);
>> +    p2m_read_unlock(p2m);
>>      if ( rc )
>>          return true;
>>
>> @@ -1810,6 +1837,14 @@ bool_t p2m_mem_access_check(paddr_t gpa,
>> vaddr_t gla, const struct npfec npfec)
>>          req->u.mem_access.flags |= npfec.insn_fetch     ?
>> MEM_ACCESS_X : 0;
>>          req->vcpu_id = v->vcpu_id;
>>
>> +        vm_event_fill_regs(req);
>
> I don't think this change belongs to this patch.
>

Thanks.

>> +
>> +        if ( unlikely(altp2m_active(d)) )
>> +        {
>> +            req->flags |= VM_EVENT_FLAG_ALTERNATE_P2M;
>> +            req->altp2m_idx = altp2m_vcpu(v).p2midx;
>> +        }
>> +
>>          mem_access_send_req(v->domain, req);
>>          xfree(req);
>>      }
>>

Cheers,
~Sergej


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 28/38] arm/p2m: Modify reference count only if hostp2m active
  2016-09-12  9:17   ` Julien Grall
@ 2016-09-13 14:16     ` Sergej Proskurin
  0 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-13 14:16 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,


On 09/12/2016 11:17 AM, Julien Grall wrote:
> Hello Sergej,
>
> On 16/08/2016 23:17, Sergej Proskurin wrote:
>> This commit makes sure that the page reference count is updated through
>> the function "p2m_put_l3_page" only the entries have been freed from the
>> hosts's p2m.
>>
>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>> ---
>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>> Cc: Julien Grall <julien.grall@arm.com>
>> ---
>>  xen/arch/arm/p2m.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
>> index cef05ed..df2b85b 100644
>> --- a/xen/arch/arm/p2m.c
>> +++ b/xen/arch/arm/p2m.c
>> @@ -754,7 +754,7 @@ static void p2m_free_entry(struct p2m_domain *p2m,
>>      if ( !p2m_valid(entry) || p2m_is_superpage(entry, level) )
>>          return;
>>
>> -    if ( level == 3 )
>> +    if ( level == 3 && p2m_is_hostp2m(p2m) )
>
> This check should be pushed in p2m_put_l3_page as we want to have
> removing reference for all the callers of p2m_put_l3_page.
>

Make sense. Thank you.

>>      {
>>          p2m_put_l3_page(_mfn(entry.p2m.base), entry.p2m.type);
>>          return;
>>

Cheers,
~Sergej

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 24/38] arm/p2m: Make p2m_mem_access_check ready for altp2m
  2016-09-13 14:00     ` Sergej Proskurin
@ 2016-09-13 14:20       ` Julien Grall
  0 siblings, 0 replies; 116+ messages in thread
From: Julien Grall @ 2016-09-13 14:20 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini



On 13/09/16 15:00, Sergej Proskurin wrote:
> Hi Julien,

Hello Sergej,

> On 09/12/2016 11:02 AM, Julien Grall wrote:
>> On 16/08/2016 23:17, Sergej Proskurin wrote:
>>> This commit extends the function "p2m_mem_access_check" and
>>> "p2m_mem_access_check_and_get_page" to consider altp2m. The function
>>> "p2m_mem_access_check_and_get_page" needs to translate the gva upon the
>>> hostp2m's vttbr, as it contains all valid mappings while the currently
>>> active altp2m view might not have the required gva mapping yet.
>>>
>>> Also, the new implementation fills the request buffer to hold
>>> altp2m-related information.
>>>
>>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>>> ---
>>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>>> Cc: Julien Grall <julien.grall@arm.com>
>>> ---
>>> v3: Extended the function "p2m_mem_access_check_and_get_page" to
>>>     consider altp2m. Similar to "get_page_from_gva", the function
>>>     "p2m_mem_access_check_and_get_page" needs to translate the gva upon
>>>     the hostp2m's vttbr. Although, the function "gva_to_ipa" (called in
>>>     "p2m_mem_access_check_and_get_page") performs a stage 1 table walk,
>>>     it will access page tables residing in memory. Accesses to this
>>>     memory are controlled by the underlying 2nd stage translation table
>>>     and hence require the original mappings of the hostp2m.
>>> ---
>>>  xen/arch/arm/p2m.c | 43 +++++++++++++++++++++++++++++++++++++++----
>>>  1 file changed, 39 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
>>> index 5819ae0..ed9e0f0 100644
>>> --- a/xen/arch/arm/p2m.c
>>> +++ b/xen/arch/arm/p2m.c
>>> @@ -14,6 +14,7 @@
>>>  #include <asm/hardirq.h>
>>>  #include <asm/page.h>
>>>
>>> +#include <asm/vm_event.h>
>>>  #include <asm/altp2m.h>
>>>
>>>  #ifdef CONFIG_ARM_64
>>> @@ -1479,9 +1480,32 @@ p2m_mem_access_check_and_get_page(struct vcpu
>>> *v, vaddr_t gva, unsigned long fla
>>>      xenmem_access_t xma;
>>>      p2m_type_t t;
>>>      struct page_info *page = NULL;
>>> -    struct p2m_domain *p2m = p2m_get_hostp2m(v->domain);
>>> +    struct domain *d = v->domain;
>>> +    struct p2m_domain *p2m = p2m_get_hostp2m(d);
>>> +
>>> +    /*
>>> +     * If altp2m is active, we need to translate the gva upon the
>>> hostp2m's
>>> +     * vttbr, as it contains all valid mappings while the currently
>>> active
>>> +     * altp2m view might not have the required gva mapping yet.
>>> Although, the
>>> +     * function gva_to_ipa performs a stage 1 table walk, it will
>>> access page
>>> +     * tables residing in memory. Accesses to this memory are
>>> controlled by the
>>> +     * underlying 2nd stage translation table and hence require the
>>> original
>>> +     * mappings of the hostp2m.
>>
>> As I already mentioned a few times now, this function is broken and
>> needs to be fixed before anymore change in it.
>>
>> The underlying memory of stage-1 page table may have been restricted
>> and therefore hardware page table walk (gva_to_ipa) may fail.
>>
>
> Based on our previous discussion I believed that it would be enough to
> temporary change the VTTBR to the one of the host's p2m as it is done in
> the implementation below. Your argument was that (without changing the
> VTTBR) it might come to an issue during the process address translation
> as accesses to the memory view in the altp2m tables might be restricted.
>
> Would it not be sufficient to temporary switch to the VTTBR of the
> host's p2m (similarly as I did in the the following implementation)? In
> this way, as far as I understand, changes in the active altp2m view
> should not affect the process of address translation.

Well, p2m_set_mem_access could change the permission on view 0 (i.e the 
hostp2m). If the underlying memory of stage-1 page table have been 
restricted, the hardware will not be able to the address translation and 
gva_to_ipa will return an error.

copy_{from,to}_guest may fail because of memaccess restriction. However 
the goal of this function was to avoid those helpers to fail.

So switching to the hostp2m will not help here.

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 33/38] arm/p2m: Add altp2m paging mechanism
  2016-09-12 14:18   ` Julien Grall
@ 2016-09-13 15:06     ` Sergej Proskurin
  2016-09-13 15:08       ` Julien Grall
  2016-09-14  7:53       ` Sergej Proskurin
  0 siblings, 2 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-13 15:06 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,


On 09/12/2016 04:18 PM, Julien Grall wrote:
> Hello Sergej,
>
> On 16/08/16 23:17, Sergej Proskurin wrote:
>> This commit adds the function "altp2m_lazy_copy" implementing the altp2m
>> paging mechanism. The function "altp2m_lazy_copy" lazily copies the
>> hostp2m's mapping into the currently active altp2m view on 2nd stage
>> translation faults on instruction or data access.
>>
>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>> ---
>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>> Cc: Julien Grall <julien.grall@arm.com>
>> ---
>> v3: Cosmetic fixes.
>>
>>     Locked hostp2m in the function "altp2m_lazy_copy" to avoid a mapping
>>     being changed in hostp2m before it has been inserted into the
>>     valtp2m view.
>>
>>     Removed unnecessary calls to "p2m_mem_access_check" in the functions
>>     "do_trap_instr_abort_guest" and "do_trap_data_abort_guest" after a
>>     translation fault has been handled by the function
>>     "altp2m_lazy_copy".
>>
>>     Adapted "altp2m_lazy_copy" to return the value "true" if the
>>     encountered translation fault encounters a valid entry inside of the
>>     currently active altp2m view. If multiple vcpu's are using the same
>>     altp2m, it is likely that both generate a translation fault, whereas
>>     the first one will be already handled by "altp2m_lazy_copy". With
>>     this change the 2nd vcpu will retry accessing the faulting address.
>>
>>     Changed order of altp2m checking and MMIO emulation within the
>>     function "do_trap_data_abort_guest".  Now, altp2m is checked and
>>     handled only if the MMIO does not have to be emulated.
>>
>>     Changed the function prototype of "altp2m_lazy_copy".  This commit
>>     removes the unnecessary struct p2m_domain* from the previous
>>     function prototype.  Also, this commit removes the unnecessary
>>     argument gva.  Finally, this commit changes the address of the
>>     function parameter gpa from paddr_t to gfn_t and renames it to gfn.
>>
>>     Moved the altp2m handling mechanism into a separate function
>>     "try_handle_altp2m".
>>
>>     Moved the functions "p2m_altp2m_check" and
>>     "altp2m_switch_vcpu_altp2m_by_id" out of this patch.
>>
>>     Moved applied code movement into a separate patch.
>> ---
>>  xen/arch/arm/altp2m.c        | 62
>> ++++++++++++++++++++++++++++++++++++++++++++
>>  xen/arch/arm/traps.c         | 35 +++++++++++++++++++++++++
>>  xen/include/asm-arm/altp2m.h |  5 ++++
>>  3 files changed, 102 insertions(+)
>>
>> diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
>> index 11272e9..2009bad 100644
>> --- a/xen/arch/arm/altp2m.c
>> +++ b/xen/arch/arm/altp2m.c
>> @@ -165,6 +165,68 @@ out:
>>      return rc;
>>  }
>>
>> +/*
>> + * The function altp2m_lazy_copy returns "false" on error.  The
>> return value
>> + * "true" signals that either the mapping has been successfully
>> lazy-copied
>> + * from the hostp2m to the currently active altp2m view or that the
>> altp2m view
>> + * holds already a valid mapping. The latter is the case if multiple
>> vcpu's
>> + * using the same altp2m view generate a translation fault that is
>> led back in
>> + * both cases to the same mapping and the first fault has been
>> already handled.
>> + */
>> +bool_t altp2m_lazy_copy(struct vcpu *v,
>> +                        gfn_t gfn,
>> +                        struct npfec npfec)
>
> Please don't introduce parameters that are not used at all.
>

It was a stupid mistake from my part. Thanks for noticing.

>> +{
>> +    struct domain *d = v->domain;
>> +    struct p2m_domain *hp2m = p2m_get_hostp2m(d), *ap2m = NULL;
>> +    p2m_type_t p2mt;
>> +    p2m_access_t p2ma;
>> +    mfn_t mfn;
>> +    unsigned int page_order;
>> +    int rc;
>> +
>> +    ap2m = altp2m_get_altp2m(v);
>> +    if ( ap2m == NULL)
>> +        return false;
>> +
>> +    /* Check if entry is part of the altp2m view. */
>> +    mfn = p2m_lookup_attr(ap2m, gfn, NULL, NULL, NULL);
>> +    if ( !mfn_eq(mfn, INVALID_MFN) )
>> +        /*
>> +         * If multiple vcpu's are using the same altp2m, it is
>> likely that both
>
> s/vcpu's/vcpus/
>

Ok.

>> +         * generate a translation fault, whereas the first one will
>> be handled
>> +         * successfully and the second will encounter a valid
>> mapping that has
>> +         * already been added as a result of the previous
>> translation fault.
>> +         * In this case, the 2nd vcpu need to retry accessing the
>> faulting
>
> s/need/needs/
>

Ok.

>> +         * address.
>> +         */
>> +        return true;
>> +
>> +    /*
>> +     * Lock hp2m to prevent the hostp2m to change a mapping before
>> it is added
>> +     * to the altp2m view.
>> +     */
>> +    p2m_read_lock(hp2m);
>> +
>> +    /* Check if entry is part of the host p2m view. */
>> +    mfn = p2m_lookup_attr(hp2m, gfn, &p2mt, &p2ma, &page_order);
>> +    if ( mfn_eq(mfn, INVALID_MFN) )
>> +        goto out;
>> +
>> +    rc = modify_altp2m_entry(ap2m, gfn, mfn, p2mt, p2ma, page_order);
>> +    if ( rc )
>> +    {
>> +        gdprintk(XENLOG_ERR, "altp2m[%d] failed to set entry for
>> %#"PRI_gfn" -> %#"PRI_mfn"\n",
>
> p2midx is unsigned so this should be %u.
>

Ok.

>> +                 altp2m_vcpu(v).p2midx, gfn_x(gfn), mfn_x(mfn));
>> +        domain_crash(hp2m->domain);
>
> You already have the domain in hand with 'd'.
>

Thanks.

>> +    }
>> +
>> +out:
>> +    p2m_read_unlock(hp2m);
>> +
>> +    return true;
>> +}
>> +
>>  static inline void altp2m_reset(struct p2m_domain *p2m)
>>  {
>>      p2m_write_lock(p2m);
>> diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
>> index 0bf1653..a4c923c 100644
>> --- a/xen/arch/arm/traps.c
>> +++ b/xen/arch/arm/traps.c
>> @@ -48,6 +48,8 @@
>>  #include <asm/vgic.h>
>>  #include <asm/cpuerrata.h>
>>
>> +#include <asm/altp2m.h>
>> +
>>  /* The base of the stack must always be double-word aligned, which
>> means
>>   * that both the kernel half of struct cpu_user_regs (which is
>> pushed in
>>   * entry.S) and struct cpu_info (which lives at the bottom of a Xen
>> @@ -2397,6 +2399,24 @@ static inline bool hpfar_is_valid(bool s1ptw,
>> uint8_t fsc)
>>      return s1ptw || (fsc == FSC_FLT_TRANS &&
>> !check_workaround_834220());
>>  }
>>
>> +static bool_t try_handle_altp2m(struct vcpu *v,
>> +                                paddr_t gpa,
>> +                                struct npfec npfec)
>
> I am not convinced about the usefulness of this function.
>

Your call. However, I believe it is better to have the altp2m handling
routine at one place.

>> +{
>> +    bool_t rc = false;
>> +
>> +    if ( altp2m_active(v->domain) )
>
> I might be worth to include an unlikely in altp2m_active to tell the
> compiler that altp2m is not the main path.
>

Done.

>> +        /*
>> +         * Copy the mapping of the faulting address into the currently
>> +         * active altp2m view. Return true on success or if the
>> particular
>> +         * mapping has already been lazily copied to the currently
>> active
>> +         * altp2m view by another vcpu. Return false otherwise.
>> +         */
>> +        rc = altp2m_lazy_copy(v, _gfn(paddr_to_pfn(gpa)), npfec);
>> +
>> +    return rc;
>> +}
>> +
>>  static void do_trap_instr_abort_guest(struct cpu_user_regs *regs,
>>                                        const union hsr hsr)
>>  {
>> @@ -2445,6 +2465,14 @@ static void do_trap_instr_abort_guest(struct
>> cpu_user_regs *regs,
>>          break;
>>      case FSC_FLT_TRANS:
>>          /*
>> +         * The guest shall retry accessing the page if the altp2m
>> handler
>> +         * succeeds. Otherwise, we continue injecting an instruction
>> abort
>> +         * exception.
>> +         */
>> +        if ( try_handle_altp2m(current, gpa, npfec) )
>> +            return;
>
> I would have expected that altp2m is the last thing we want to check
> in the abort handler. I.e after p2m_lookup.
>

Alright, I will reorder both calls, thank you.

>> +
>> +        /*
>>           * The PT walk may have failed because someone was playing
>>           * with the Stage-2 page table. Walk the Stage-2 PT to check
>>           * if the entry exists. If it's the case, return to the guest
>> @@ -2547,6 +2575,13 @@ static void do_trap_data_abort_guest(struct
>> cpu_user_regs *regs,
>>          }
>>
>>          /*
>> +         * The guest shall retry accessing the page if the altp2m
>> handler
>> +         * succeeds. Otherwise, we continue injecting a data abort
>> exception.
>> +         */
>> +        if ( try_handle_altp2m(current, info.gpa, npfec) )
>> +            return;
>
> Ditto here.
>

Same here, thanks.

>> +
>> +        /*
>>           * The PT walk may have failed because someone was playing
>>           * with the Stage-2 page table. Walk the Stage-2 PT to check
>>           * if the entry exists. If it's the case, return to the guest
>> diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
>> index ef80829..8e40c45 100644
>> --- a/xen/include/asm-arm/altp2m.h
>> +++ b/xen/include/asm-arm/altp2m.h
>> @@ -84,6 +84,11 @@ int altp2m_set_mem_access(struct domain *d,
>>                            p2m_access_t a,
>>                            gfn_t gfn);
>>
>> +/* Alternate p2m paging mechanism. */
>> +bool_t altp2m_lazy_copy(struct vcpu *v,
>> +                        gfn_t gfn,
>> +                        struct npfec npfec);
>> +
>>  /* Propagates changes made to hostp2m to affected altp2m views. */
>>  int altp2m_propagate_change(struct domain *d,
>>                              gfn_t sgfn,
>>
>
> Regards,
>

Cheers,
~Sergej


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 33/38] arm/p2m: Add altp2m paging mechanism
  2016-09-13 15:06     ` Sergej Proskurin
@ 2016-09-13 15:08       ` Julien Grall
  2016-09-13 15:53         ` Sergej Proskurin
  2016-09-14  7:53       ` Sergej Proskurin
  1 sibling, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-13 15:08 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini



On 13/09/16 16:06, Sergej Proskurin wrote:
>>> +    }
>>> +
>>> +out:
>>> +    p2m_read_unlock(hp2m);
>>> +
>>> +    return true;
>>> +}
>>> +
>>>  static inline void altp2m_reset(struct p2m_domain *p2m)
>>>  {
>>>      p2m_write_lock(p2m);
>>> diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
>>> index 0bf1653..a4c923c 100644
>>> --- a/xen/arch/arm/traps.c
>>> +++ b/xen/arch/arm/traps.c
>>> @@ -48,6 +48,8 @@
>>>  #include <asm/vgic.h>
>>>  #include <asm/cpuerrata.h>
>>>
>>> +#include <asm/altp2m.h>
>>> +
>>>  /* The base of the stack must always be double-word aligned, which
>>> means
>>>   * that both the kernel half of struct cpu_user_regs (which is
>>> pushed in
>>>   * entry.S) and struct cpu_info (which lives at the bottom of a Xen
>>> @@ -2397,6 +2399,24 @@ static inline bool hpfar_is_valid(bool s1ptw,
>>> uint8_t fsc)
>>>      return s1ptw || (fsc == FSC_FLT_TRANS &&
>>> !check_workaround_834220());
>>>  }
>>>
>>> +static bool_t try_handle_altp2m(struct vcpu *v,
>>> +                                paddr_t gpa,
>>> +                                struct npfec npfec)
>>
>> I am not convinced about the usefulness of this function.
>>
>
> Your call. However, I believe it is better to have the altp2m handling
> routine at one place.

Then, why it is not done in altp2m_lazy_copy?

Regards,
-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 35/38] arm/p2m: Adjust debug information to altp2m
  2016-09-12 14:29   ` Julien Grall
@ 2016-09-13 15:13     ` Sergej Proskurin
  0 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-13 15:13 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,


On 09/12/2016 04:29 PM, Julien Grall wrote:
> Hello Sergej,
>
> On 16/08/16 23:17, Sergej Proskurin wrote:
>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>> ---
>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>> Cc: Julien Grall <julien.grall@arm.com>
>> ---
>> v2: Dump p2m information of the hostp2m and all altp2m views.
>> ---
>>  xen/arch/arm/p2m.c | 20 ++++++++++++++++++++
>>  1 file changed, 20 insertions(+)
>>
>> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
>> index dea3038..86e2a1d 100644
>> --- a/xen/arch/arm/p2m.c
>> +++ b/xen/arch/arm/p2m.c
>> @@ -162,6 +162,26 @@ void dump_p2m_lookup(struct domain *d, paddr_t
>> addr)
>>
>>      dump_pt_walk(page_to_maddr(p2m->root), addr,
>>                   P2M_ROOT_LEVEL, P2M_ROOT_PAGES);
>> +    printk("\n");
>> +
>> +    if ( altp2m_active(d) )
>> +    {
>> +        unsigned int i;
>> +
>> +        for ( i = 0; i < MAX_ALTP2M; i++ )
>> +        {
>> +            if ( d->arch.altp2m_p2m[i] == NULL )
>> +                continue;
>> +
>> +            p2m = d->arch.altp2m_p2m[i];
>> +
>> +            printk("AP2M[%d] @ %p mfn:0x%lx\n",
>
> s/%d/%u/ as the p2m index is unsigned
> s/0x%lx/%#PRI_mfn/ because we should avoid open format from now.
>

Thank you.

>> +                    i, p2m->root, page_to_mfn(p2m->root));
>> +
>> +            dump_pt_walk(page_to_maddr(p2m->root), addr,
>> P2M_ROOT_LEVEL, P2M_ROOT_PAGES);
>> +            printk("\n");
>> +        }
>> +    }
>>  }
>>
>>  void p2m_save_state(struct vcpu *p)
>>

Cheers,
~Sergej

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 38/38] arm/p2m: Add test of xc_altp2m_change_gfn
  2016-08-24 12:27   ` Wei Liu
@ 2016-09-13 15:45     ` Sergej Proskurin
  0 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-13 15:45 UTC (permalink / raw)
  To: Wei Liu; +Cc: xen-devel, Tamas K Lengyel, Ian Jackson, Razvan Cojocaru

Hi Wei,


On 08/24/2016 02:27 PM, Wei Liu wrote:
> On Wed, Aug 17, 2016 at 12:17:14AM +0200, Sergej Proskurin wrote:
>> This commit extends xen-access by a simple test of the functionality
>> provided by "xc_altp2m_change_gfn". The idea is to dynamically remap a
>> trapping gfn to another mfn, which holds the same content as the
>> original mfn. On success, the guest will continue to run. Subsequent
>> altp2m access violations will trap into Xen and be forced by xen-access
>> to switch to the default view (altp2m[0]) as before. The introduced test
>> can be invoked by providing the argument "altp2m_remap".
>>
>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>> ---
>> Cc: Razvan Cojocaru <rcojocaru@bitdefender.com>
>> Cc: Tamas K Lengyel <tamas@tklengyel.com>
>> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
>> Cc: Wei Liu <wei.liu2@citrix.com>
>> ---
>> v3: Cosmetic fixes in "xenaccess_copy_gfn" and "xenaccess_change_gfn".
>>
>>     Added munmap in "copy_gfn" in the second error case.
>>
>>     Added option "altp2m_remap" selecting the altp2m-remap test.
>> ---
>>  tools/tests/xen-access/xen-access.c | 162 +++++++++++++++++++++++++++++++++++-
>>  1 file changed, 158 insertions(+), 4 deletions(-)
>>
>> diff --git a/tools/tests/xen-access/xen-access.c b/tools/tests/xen-access/xen-access.c
>> index eafd7d6..5909a8a 100644
>> --- a/tools/tests/xen-access/xen-access.c
>> +++ b/tools/tests/xen-access/xen-access.c
>> @@ -38,6 +38,7 @@
>>  #include <sys/mman.h>
>>  #include <sys/poll.h>
>>  
>> +#define XC_WANT_COMPAT_MAP_FOREIGN_API
> I know Razvan already acked this, but general you shouldn't use the
> COMPAT APIs. You should use libs/foreignmemory library, which is a
> stable library.

Alright, I will adapt the implementation accordingly. Thanks for the hint.

>>  #include <xenctrl.h>
>>  #include <xenevtchn.h>
>>  #include <xen/vm_event.h>
>> @@ -49,6 +50,8 @@
>>  #define START_PFN 0ULL
>>  #endif
>>  
>> +#define INVALID_GFN ~(0UL)
>> +
>>  #define DPRINTF(a, b...) fprintf(stderr, a, ## b)
>>  #define ERROR(a, b...) fprintf(stderr, a "\n", ## b)
>>  #define PERROR(a, b...) fprintf(stderr, a ": %s\n", ## b, strerror(errno))
>> @@ -72,9 +75,14 @@ typedef struct xenaccess {
>>      xen_pfn_t max_gpfn;
>>  
>>      vm_event_t vm_event;
>> +
>> +    unsigned int ap2m_idx;
>> +    xen_pfn_t gfn_old;
>> +    xen_pfn_t gfn_new;
>>  } xenaccess_t;
>>  
>>  static int interrupted;
>> +static int gfn_changed = 0;
>>  bool evtchn_bind = 0, evtchn_open = 0, mem_access_enable = 0;
>>  
>>  static void close_handler(int sig)
>> @@ -82,6 +90,100 @@ static void close_handler(int sig)
>>      interrupted = sig;
>>  }
>>  
>> +static int xenaccess_copy_gfn(xc_interface *xch,
>> +                              domid_t domain_id,
>> +                              xen_pfn_t dst_gfn,
>> +                              xen_pfn_t src_gfn)
>> +{
>> +    void *src_vaddr = NULL;
>> +    void *dst_vaddr = NULL;
>> +
>> +    src_vaddr = xc_map_foreign_range(xch, domain_id, XC_PAGE_SIZE,
>> +                                     PROT_READ, src_gfn);
>> +    if ( src_vaddr == MAP_FAILED || src_vaddr == NULL)
>> +        return -1;
>> +
>> +    dst_vaddr = xc_map_foreign_range(xch, domain_id, XC_PAGE_SIZE,
>> +                                     PROT_WRITE, dst_gfn);
> You can have a look at libxc/xc_foreign_memory.c for how to replace this
> legacy call with the new function.

Will do, thanks.

Cheers,
~Sergej

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 33/38] arm/p2m: Add altp2m paging mechanism
  2016-09-13 15:08       ` Julien Grall
@ 2016-09-13 15:53         ` Sergej Proskurin
  0 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-13 15:53 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,


On 09/13/2016 05:08 PM, Julien Grall wrote:
>
>
> On 13/09/16 16:06, Sergej Proskurin wrote:
>>>> +    }
>>>> +
>>>> +out:
>>>> +    p2m_read_unlock(hp2m);
>>>> +
>>>> +    return true;
>>>> +}
>>>> +
>>>>  static inline void altp2m_reset(struct p2m_domain *p2m)
>>>>  {
>>>>      p2m_write_lock(p2m);
>>>> diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
>>>> index 0bf1653..a4c923c 100644
>>>> --- a/xen/arch/arm/traps.c
>>>> +++ b/xen/arch/arm/traps.c
>>>> @@ -48,6 +48,8 @@
>>>>  #include <asm/vgic.h>
>>>>  #include <asm/cpuerrata.h>
>>>>
>>>> +#include <asm/altp2m.h>
>>>> +
>>>>  /* The base of the stack must always be double-word aligned, which
>>>> means
>>>>   * that both the kernel half of struct cpu_user_regs (which is
>>>> pushed in
>>>>   * entry.S) and struct cpu_info (which lives at the bottom of a Xen
>>>> @@ -2397,6 +2399,24 @@ static inline bool hpfar_is_valid(bool s1ptw,
>>>> uint8_t fsc)
>>>>      return s1ptw || (fsc == FSC_FLT_TRANS &&
>>>> !check_workaround_834220());
>>>>  }
>>>>
>>>> +static bool_t try_handle_altp2m(struct vcpu *v,
>>>> +                                paddr_t gpa,
>>>> +                                struct npfec npfec)
>>>
>>> I am not convinced about the usefulness of this function.
>>>
>>
>> Your call. However, I believe it is better to have the altp2m handling
>> routine at one place.
>
> Then, why it is not done in altp2m_lazy_copy?

Alright, I will remove the function.

Cheers,
~Sergej

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 14/38] arm/p2m: Add altp2m init/teardown routines
  2016-09-09 16:56   ` Julien Grall
@ 2016-09-13 19:35     ` Sergej Proskurin
  2016-09-14  6:28       ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-13 19:35 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,

On 09/09/2016 06:56 PM, Julien Grall wrote:
> Hello Sergej
> 
> On 16/08/16 23:16, Sergej Proskurin wrote:
>> diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
>> index 23aaf52..4a7f660 100644
>> --- a/xen/arch/arm/Makefile
>> +++ b/xen/arch/arm/Makefile
>> @@ -5,6 +5,7 @@ subdir-$(CONFIG_ARM_64) += efi
>>  subdir-$(CONFIG_ACPI) += acpi
>>
>>  obj-$(CONFIG_ALTERNATIVE) += alternative.o
>> +obj-y += altp2m.o
>>  obj-y += bootfdt.o
>>  obj-y += cpu.o
>>  obj-y += cpuerrata.o
>> diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
>> new file mode 100644
>> index 0000000..66a373a
>> --- /dev/null
>> +++ b/xen/arch/arm/altp2m.c
>> @@ -0,0 +1,61 @@
>> +/*
>> + * arch/arm/altp2m.c
>> + *
>> + * Alternate p2m
>> + * Copyright (c) 2016 Sergej Proskurin <proskurin@sec.in.tum.de>
>> + *
>> + * This program is free software; you can redistribute it and/or
>> modify it
>> + * under the terms and conditions of the GNU General Public License,
>> version 2,
>> + * as published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope it will be useful, but
>> WITHOUT ANY
>> + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> FITNESS
>> + * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
>> more
>> + * details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> along with
>> + * this program; If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <asm/p2m.h>
>> +#include <asm/altp2m.h>
>> +
>> +int altp2m_init(struct domain *d)
>> +{
>> +    unsigned int i;
>> +
>> +    spin_lock_init(&d->arch.altp2m_lock);
>> +
>> +    for ( i = 0; i < MAX_ALTP2M; i++ )
>> +        d->arch.altp2m_p2m[i] = NULL;
> 
> The structure domain is already initialized to 0, so this loop is
> pointless.
> 

I will remove the loop, thank you.

>> +
>> +    d->arch.altp2m_active = false;
>> +
>> +    return 0;
>> +}
>> +
> 
> [...]
> 
>> diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
>> index 0711796..a156109 100644
>> --- a/xen/include/asm-arm/altp2m.h
>> +++ b/xen/include/asm-arm/altp2m.h
>> @@ -22,6 +22,9 @@
>>
>>  #include <xen/sched.h>
>>
>> +#define altp2m_lock(d)    spin_lock(&(d)->arch.altp2m_lock)
>> +#define altp2m_unlock(d)  spin_unlock(&(d)->arch.altp2m_lock)
>> +
>>  /* Alternate p2m on/off per domain */
>>  static inline bool_t altp2m_active(const struct domain *d)
>>  {
>> @@ -36,4 +39,7 @@ static inline uint16_t altp2m_vcpu_idx(const struct
>> vcpu *v)
>>      return 0;
>>  }
>>
>> +int altp2m_init(struct domain *d);
>> +void altp2m_teardown(struct domain *d);
>> +
>>  #endif /* __ASM_ARM_ALTP2M_H */
>> diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
>> index cc4bda0..a4e4762 100644
>> --- a/xen/include/asm-arm/domain.h
>> +++ b/xen/include/asm-arm/domain.h
>> @@ -127,8 +127,14 @@ struct arch_domain
>>      paddr_t efi_acpi_len;
>>  #endif
>>
>> +    /*
>> +     * Lock that protects access to altp2m related fields in both struct
>> +     * arch_domain and struct p2m_domain.
> 
> This comment looks wrong. struct p2m_domain is protected by its own
> lock. altp2m lock should not protect it.
> 

In the next patch, I will provide a comment stating that the altp2m_lock
protects critical altp2m operation that must not be performed concurrently.

>> +     */
>> +    spinlock_t altp2m_lock;
>>      /* altp2m: allow multiple copies of host p2m */
>>      bool_t altp2m_active;
>> +    struct p2m_domain *altp2m_p2m[MAX_ALTP2M];
>>  }  __cacheline_aligned;
>>
>>  struct arch_vcpu
>> diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
>> index 1a004ed..de0c90a 100644
>> --- a/xen/include/asm-arm/p2m.h
>> +++ b/xen/include/asm-arm/p2m.h
>> @@ -9,6 +9,8 @@
>>  #include <xen/p2m-common.h>
>>  #include <public/memory.h>
>>
>> +#define MAX_ALTP2M 10           /* ARM might contain an arbitrary
>> number of
>> +                                   altp2m views. */
> 
> This should belong to altp2m.h and not p2m.h
>

Unfortunately, this won't work. We cannot move this define into altp2m.h
as it would result in an header conflict: The header asm/altp2m.h
includes xen/domain.h, which in turn includes asm/domain.h. So by
including asm/altp2m.h in asm/domain.h (as MAX_ALTP2M is used there), we
would create a loop of header dependencies.

>>  #define paddr_bits PADDR_BITS
>>
>>  #define INVALID_VTTBR (0UL)
>>

Cheers,
~Sergej

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 14/38] arm/p2m: Add altp2m init/teardown routines
  2016-09-13 19:35     ` Sergej Proskurin
@ 2016-09-14  6:28       ` Sergej Proskurin
  2016-09-14 10:53         ` Julien Grall
  0 siblings, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-14  6:28 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,


>>>  struct arch_vcpu
>>> diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
>>> index 1a004ed..de0c90a 100644
>>> --- a/xen/include/asm-arm/p2m.h
>>> +++ b/xen/include/asm-arm/p2m.h
>>> @@ -9,6 +9,8 @@
>>>  #include <xen/p2m-common.h>
>>>  #include <public/memory.h>
>>>
>>> +#define MAX_ALTP2M 10           /* ARM might contain an arbitrary
>>> number of
>>> +                                   altp2m views. */
>> This should belong to altp2m.h and not p2m.h
>>
> Unfortunately, this won't work. We cannot move this define into altp2m.h
> as it would result in an header conflict: The header asm/altp2m.h
> includes xen/domain.h, which in turn includes asm/domain.h. So by
> including asm/altp2m.h in asm/domain.h (as MAX_ALTP2M is used there), we
> would create a loop of header dependencies.

Sorry, I forgot one header: altp2m.h includes xen/sched.h, which in turn
includes xen/domain.h and so on.

Cheers,
~Sergej


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 33/38] arm/p2m: Add altp2m paging mechanism
  2016-09-13 15:06     ` Sergej Proskurin
  2016-09-13 15:08       ` Julien Grall
@ 2016-09-14  7:53       ` Sergej Proskurin
  2016-09-14 11:15         ` Julien Grall
  1 sibling, 1 reply; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-14  7:53 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien


[...]

>>>  static void do_trap_instr_abort_guest(struct cpu_user_regs *regs,
>>>                                        const union hsr hsr)
>>>  {
>>> @@ -2445,6 +2465,14 @@ static void do_trap_instr_abort_guest(struct
>>> cpu_user_regs *regs,
>>>          break;
>>>      case FSC_FLT_TRANS:
>>>          /*
>>> +         * The guest shall retry accessing the page if the altp2m
>>> handler
>>> +         * succeeds. Otherwise, we continue injecting an instruction
>>> abort
>>> +         * exception.
>>> +         */
>>> +        if ( try_handle_altp2m(current, gpa, npfec) )
>>> +            return;
>> I would have expected that altp2m is the last thing we want to check
>> in the abort handler. I.e after p2m_lookup.
>>
> Alright, I will reorder both calls, thank you.

Actually, reordering of these calls (try_handle_altp2m/altp2m_lazy_copy
and p2m_lookup) would make the system stall if altp2m is active. This is
because the p2m_lookup routine considers only the host's p2m, which will
most likely return a mfn != INVALID_MFN and thus entirely skip the call
to altp2m_lazy_copy. Thus, both calls should rather be conditional as
shown in the following:

if ( likely(!altp2m_active(current->domain)) )
{
    /*
     * The PT walk may have failed because someone was playing
     * with the Stage-2 page table. Walk the Stage-2 PT to check
     * if the entry exists. If it's the case, return to the guest
     */
    mfn = p2m_lookup(current->domain, _gfn(paddr_to_pfn(gpa)), NULL);
    if ( !mfn_eq(mfn, INVALID_MFN) )
        return;
}
else
    /*
     * The guest shall retry accessing the page if the altp2m handler
     * succeeds. Otherwise, we continue injecting an instruction abort
     * exception.
     */
    if ( altp2m_lazy_copy(current, _gfn(paddr_to_pfn(gpa))) )
        return;


Please excuse me for the confusion.

>>> +
>>> +        /*
>>>           * The PT walk may have failed because someone was playing
>>>           * with the Stage-2 page table. Walk the Stage-2 PT to check
>>>           * if the entry exists. If it's the case, return to the guest
>>> @@ -2547,6 +2575,13 @@ static void do_trap_data_abort_guest(struct
>>> cpu_user_regs *regs,
>>>          }
>>>
>>>          /*
>>> +         * The guest shall retry accessing the page if the altp2m
>>> handler
>>> +         * succeeds. Otherwise, we continue injecting a data abort
>>> exception.
>>> +         */
>>> +        if ( try_handle_altp2m(current, info.gpa, npfec) )
>>> +            return;
>> Ditto here.
>>

Same here.

Cheers,
~Sergej


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 14/38] arm/p2m: Add altp2m init/teardown routines
  2016-09-14  6:28       ` Sergej Proskurin
@ 2016-09-14 10:53         ` Julien Grall
  0 siblings, 0 replies; 116+ messages in thread
From: Julien Grall @ 2016-09-14 10:53 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini



On 14/09/16 07:28, Sergej Proskurin wrote:
> Hi Julien,
>
>
>>>>  struct arch_vcpu
>>>> diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
>>>> index 1a004ed..de0c90a 100644
>>>> --- a/xen/include/asm-arm/p2m.h
>>>> +++ b/xen/include/asm-arm/p2m.h
>>>> @@ -9,6 +9,8 @@
>>>>  #include <xen/p2m-common.h>
>>>>  #include <public/memory.h>
>>>>
>>>> +#define MAX_ALTP2M 10           /* ARM might contain an arbitrary
>>>> number of
>>>> +                                   altp2m views. */
>>> This should belong to altp2m.h and not p2m.h
>>>
>> Unfortunately, this won't work. We cannot move this define into altp2m.h
>> as it would result in an header conflict: The header asm/altp2m.h
>> includes xen/domain.h, which in turn includes asm/domain.h. So by
>> including asm/altp2m.h in asm/domain.h (as MAX_ALTP2M is used there), we
>> would create a loop of header dependencies.
>
> Sorry, I forgot one header: altp2m.h includes xen/sched.h, which in turn
> includes xen/domain.h and so on.

Fair enough, let's keep like that for now.

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 19/38] arm/p2m: Add HVMOP_altp2m_switch_p2m
  2016-09-13 13:00     ` Sergej Proskurin
@ 2016-09-14 10:57       ` Julien Grall
  2016-09-14 15:28         ` Sergej Proskurin
  0 siblings, 1 reply; 116+ messages in thread
From: Julien Grall @ 2016-09-14 10:57 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini



On 13/09/16 14:00, Sergej Proskurin wrote:
> Hi Julien,

Hello Sergej,

>
> On 09/12/2016 10:47 AM, Julien Grall wrote:
>> Hello Sergej,
>>
>> On 16/08/2016 23:16, Sergej Proskurin wrote:
>>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>>> ---
>>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>>> Cc: Julien Grall <julien.grall@arm.com>
>>> ---
>>> v3: Extended the function "altp2m_switch_domain_altp2m_by_id" so that if
>>>     the guest domain indirectly calles this function, the current
>>> vcpu also
>>>     changes the altp2m view without performing an explicit context
>>> switch.
>>>
>>>     Exchanged the check "altp2m_vttbr[idx] == INVALID_VTTBR" for
>>>     "altp2m_p2m[idx] == NULL" in "altp2m_switch_domain_altp2m_by_id".
>>> ---
>>>  xen/arch/arm/altp2m.c        | 48
>>> ++++++++++++++++++++++++++++++++++++++++++++
>>>  xen/arch/arm/hvm.c           |  2 +-
>>>  xen/include/asm-arm/altp2m.h |  4 ++++
>>>  3 files changed, 53 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
>>> index c14ab0b..ba345b9 100644
>>> --- a/xen/arch/arm/altp2m.c
>>> +++ b/xen/arch/arm/altp2m.c
>>> @@ -32,6 +32,54 @@ struct p2m_domain *altp2m_get_altp2m(struct vcpu *v)
>>>      return v->domain->arch.altp2m_p2m[index];
>>>  }
>>>
>>> +int altp2m_switch_domain_altp2m_by_id(struct domain *d, unsigned int
>>> idx)
>>> +{
>>> +    struct vcpu *v;
>>> +    int rc = -EINVAL;
>>> +
>>> +    if ( idx >= MAX_ALTP2M )
>>> +        return rc;
>>> +
>>> +    domain_pause_except_self(d);
>>> +
>>> +    altp2m_lock(d);
>>> +
>>> +    if ( d->arch.altp2m_p2m[idx] != NULL )
>>> +    {
>>> +        for_each_vcpu( d, v )
>>> +            if ( idx != altp2m_vcpu(v).p2midx )
>>
>> Could you invert the condition to avoid another layer of nested if?
>>
>
> Did you mean checking for (idx == altp2m_vcpu(v).p2midx) and continue
> the loop if the condition should be satisfied? If so, then sure thing :)

Correct.

>
>>> +            {
>>> +                atomic_dec(&altp2m_get_altp2m(v)->active_vcpus);
>>> +                altp2m_vcpu(v).p2midx = idx;
>>> +                atomic_inc(&altp2m_get_altp2m(v)->active_vcpus);
>>> +
>>> +                /*
>>> +                 * In case it is the guest domain, which indirectly
>>> called this
>>> +                 * function, the current vcpu will not switch its
>>> context
>>> +                 * within the function "p2m_restore_state". That is,
>>> changing
>>> +                 * the altp2m_vcpu(v).p2midx will not lead to the
>>> requested
>>> +                 * altp2m switch on that specific vcpu. To achieve
>>> the desired
>>> +                 * behavior, we write to VTTBR_EL2 directly.
>>> +                 */
>>> +                if ( v->domain == d && v == current )
>>
>> v == current is enough.
>>
>
> Ok.
>
>>> +                {
>>> +                    struct p2m_domain *ap2m = d->arch.altp2m_p2m[idx];
>>> +
>>> +                    WRITE_SYSREG64(ap2m->vttbr, VTTBR_EL2);
>>> +                    isb();
>>
>> I don't like the open-coding of VTTBR_EL2. I would much prefer a
>> separate helper to update it.
>>
>
> Sure, I can introduce an UPDATE_VTTBR macro (including the isb call) in
> p2m.h and adjust the remaining writes to VTTBR_EL2 in p2m.c as well. I
> hope, I understood you correctly.

Actually, I was concerned about having the following sequence spread:
    VTTBR_EL2
    isb

However, the isb is not necessary here because VTTBR_EL2 will not be 
used until we return to the guest.

So I would be fine to keep WRITE_SYSREG64(ap2m->vttbr, VTTBR_EL2);

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 16/38] arm/p2m: Add HVMOP_altp2m_set_domain_state
  2016-08-16 22:16 ` [PATCH v3 16/38] arm/p2m: Add HVMOP_altp2m_set_domain_state Sergej Proskurin
  2016-09-09 17:14   ` Julien Grall
@ 2016-09-14 11:07   ` Julien Grall
  1 sibling, 0 replies; 116+ messages in thread
From: Julien Grall @ 2016-09-14 11:07 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini

Hello Sergej,

On 16/08/16 23:16, Sergej Proskurin wrote:
> diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
> index 180154e..c69da36 100644
> --- a/xen/arch/arm/hvm.c
> +++ b/xen/arch/arm/hvm.c
> @@ -83,8 +83,40 @@ static int do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
>          break;
>
>      case HVMOP_altp2m_set_domain_state:
> -        rc = -EOPNOTSUPP;
> +    {
> +        struct vcpu *v;
> +        bool_t ostate, nstate;
> +
> +        ostate = d->arch.altp2m_active;
> +        nstate = !!a.u.domain_state.state;
> +
> +        /* If the alternate p2m state has changed, handle appropriately */
> +        if ( (nstate != ostate) &&
> +             (ostate || !(rc = altp2m_init_by_id(d, 0))) )
> +        {
> +            for_each_vcpu( d, v )
> +            {
> +                if ( !ostate )
> +                {
> +                    altp2m_vcpu_initialise(v);
> +                    d->arch.altp2m_active = nstate;

Why do you set d->arch.altp2m_active for each vCPU?

> +                }
> +                else
> +                {
> +                    d->arch.altp2m_active = nstate;
> +                    altp2m_vcpu_destroy(v);
> +                }
> +            }
> +
> +            /*
> +             * The altp2m_active state has been deactivated. It is now safe to
> +             * flush all altp2m views -- including altp2m[0].
> +             */
> +            if ( ostate )
> +                altp2m_flush(d);
> +        }
>          break;
> +    }
>
>      case HVMOP_altp2m_vcpu_enable_notify:
>          rc = -EOPNOTSUPP;

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 33/38] arm/p2m: Add altp2m paging mechanism
  2016-09-14  7:53       ` Sergej Proskurin
@ 2016-09-14 11:15         ` Julien Grall
  0 siblings, 0 replies; 116+ messages in thread
From: Julien Grall @ 2016-09-14 11:15 UTC (permalink / raw)
  To: Sergej Proskurin, xen-devel; +Cc: Stefano Stabellini



On 14/09/16 08:53, Sergej Proskurin wrote:
> Hi Julien
>
>
> [...]
>
>>>>  static void do_trap_instr_abort_guest(struct cpu_user_regs *regs,
>>>>                                        const union hsr hsr)
>>>>  {
>>>> @@ -2445,6 +2465,14 @@ static void do_trap_instr_abort_guest(struct
>>>> cpu_user_regs *regs,
>>>>          break;
>>>>      case FSC_FLT_TRANS:
>>>>          /*
>>>> +         * The guest shall retry accessing the page if the altp2m
>>>> handler
>>>> +         * succeeds. Otherwise, we continue injecting an instruction
>>>> abort
>>>> +         * exception.
>>>> +         */
>>>> +        if ( try_handle_altp2m(current, gpa, npfec) )
>>>> +            return;
>>> I would have expected that altp2m is the last thing we want to check
>>> in the abort handler. I.e after p2m_lookup.
>>>
>> Alright, I will reorder both calls, thank you.
>
> Actually, reordering of these calls (try_handle_altp2m/altp2m_lazy_copy
> and p2m_lookup) would make the system stall if altp2m is active. This is
> because the p2m_lookup routine considers only the host's p2m, which will
> most likely return a mfn != INVALID_MFN and thus entirely skip the call
> to altp2m_lazy_copy. Thus, both calls should rather be conditional as
> shown in the following:
> if ( likely(!altp2m_active(current->domain)) )
> {
>     /*
>      * The PT walk may have failed because someone was playing
>      * with the Stage-2 page table. Walk the Stage-2 PT to check
>      * if the entry exists. If it's the case, return to the guest
>      */
>     mfn = p2m_lookup(current->domain, _gfn(paddr_to_pfn(gpa)), NULL);
>     if ( !mfn_eq(mfn, INVALID_MFN) )
>         return;
> }
> else
>     /*
>      * The guest shall retry accessing the page if the altp2m handler
>      * succeeds. Otherwise, we continue injecting an instruction abort
>      * exception.
>      */
>     if ( altp2m_lazy_copy(current, _gfn(paddr_to_pfn(gpa))) )
>         return;

I think this solution is racy because altp2m_active could be changed by 
another physical CPU whilst we are in the abort handler.

So the best here is to keep the previous solution:

if ( altp2m_lazy_copy(current, _gfn(paddr_to_pfn(gpa))) )
   return;

if ( p2m_lookup(current->domain, _gfn(paddr_to_pfn(gpa)), NULL )
   return;

Regards,

-- 
Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 29/38] arm/p2m: Add HVMOP_altp2m_set_mem_access
  2016-09-12 12:08   ` Julien Grall
@ 2016-09-14 15:20     ` Sergej Proskurin
  0 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-14 15:20 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini


[-- Attachment #1.1: Type: text/plain, Size: 12720 bytes --]

Hi Julien,


On 09/12/2016 02:08 PM, Julien Grall wrote:
> Hi Sergej,
>
> On 16/08/16 23:17, Sergej Proskurin wrote:
>> The HVMOP_altp2m_set_mem_access allows to set gfn permissions of
>> (currently one page at a time) of a specific altp2m view. In case the
>> view does not hold the requested gfn entry, it will be first copied from
>> the host's p2m table and then modified as requested.
>>
>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>> ---
>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>> Cc: Julien Grall <julien.grall@arm.com>
>> ---
>> v2: Prevent the page reference count from being falsely updated on
>>     altp2m modification. Therefore, we add a check determining whether
>>     the target p2m is a hostp2m before p2m_put_l3_page is called.
>>
>> v3: Cosmetic fixes.
>>
>>     Added the functionality to set/get the default_access also in/from
>>     the requested altp2m view.
>>
>>     Read-locked hp2m in "altp2m_set_mem_access".
>>
>>     Moved the functions "p2m_is_(hostp2m|altp2m)" out of this commit.
>>
>>     Moved the funtion "modify_altp2m_entry" out of this commit.
>>
>>     Moved the function "p2m_lookup_attr" out of this commit.
>>
>>     Moved guards for "p2m_put_l3_page" out of this commit.
>> ---
>>  xen/arch/arm/altp2m.c        | 53 ++++++++++++++++++++++++++++
>>  xen/arch/arm/hvm.c           |  7 +++-
>>  xen/arch/arm/p2m.c           | 82
>> ++++++++++++++++++++++++++++++++------------
>>  xen/include/asm-arm/altp2m.h | 12 +++++++
>>  4 files changed, 131 insertions(+), 23 deletions(-)
>>
>> diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
>> index ba345b9..03b8ce5 100644
>> --- a/xen/arch/arm/altp2m.c
>> +++ b/xen/arch/arm/altp2m.c
>> @@ -80,6 +80,59 @@ int altp2m_switch_domain_altp2m_by_id(struct
>> domain *d, unsigned int idx)
>>      return rc;
>>  }
>>
>> +int altp2m_set_mem_access(struct domain *d,
>> +                          struct p2m_domain *hp2m,
>> +                          struct p2m_domain *ap2m,
>> +                          p2m_access_t a,
>> +                          gfn_t gfn)
>> +{
>> +    p2m_type_t p2mt;
>> +    p2m_access_t old_a;
>> +    mfn_t mfn;
>> +    unsigned int page_order;
>> +    int rc;
>> +
>> +    altp2m_lock(d);
>
> Why do you have this lock? This will serialize all the mem access
> modification even if the ap2m is different.
>
> I am also surprised that you only lock the altp2m in
> modify_altp2m_entry. IHMO, the change in the same a2pm should be
> serialized.
>

You are correct, the implementation in the upcoming patch write-locks
the altp2m view and hence also removes the need for the locking the
altp2m_lock. Thank you.

>> +    p2m_read_lock(hp2m);
>> +
>> +    /* Check if entry is part of the altp2m view. */
>> +    mfn = p2m_lookup_attr(ap2m, gfn, &p2mt, NULL, &page_order);
>> +
>> +    /* Check host p2m if no valid entry in ap2m. */
>> +    if ( mfn_eq(mfn, INVALID_MFN) )
>> +    {
>> +        /* Check if entry is part of the host p2m view. */
>> +        mfn = p2m_lookup_attr(hp2m, gfn, &p2mt, &old_a, &page_order);
>
> As mentioned in patch #27, p2m_lookup_attr will take a read reference
> on the hp2m lock. However you already did it above.
>
> Anyway, I really think that p2m_lookup_attr should not exist and ever
> caller be replaced by a direct call to p2m_get_entry.
>

Sounds good. I thought you did not want have the functions
p2m_(set|get)_entry exported, which is the reason for the wrappers. I
have already removed these wrappers in the upcoming patch. Thank you.

>
>> +        if ( mfn_eq(mfn, INVALID_MFN) ||
>> +             ((p2mt != p2m_ram_rw) && (p2mt != p2m_ram_ro)) )
>
> Please use p2m_is_ram rather than open-coding the check on p2mt.
>
> However, I don't understand why access restriction on altp2m is
> limited to RAM whilst the hostp2m allows restriction on any type of page.
>

I agree: It makes sense to allow setting memory permissions without such
restrictions. It it seems to be a remnant of the old implementation, in
which invalid mfn's were not guaranteed to be marked as INVALID_MFN.
Anyway, I will remove this check. Thank you.

>> +        {
>> +            rc = -ESRCH;
>> +            goto out;
>> +        }
>> +
>> +        /* If this is a superpage, copy that first. */
>> +        if ( page_order != THIRD_ORDER )
>> +        {
>> +            rc = modify_altp2m_entry(ap2m, gfn, mfn, p2mt, old_a,
>> page_order);
>> +            if ( rc < 0 )
>> +            {
>> +                rc = -ESRCH;
>> +                goto out;
>> +            }
>> +        }
>> +    }
>> +
>> +    /* Set mem access attributes - currently supporting only one
>> (4K) page. */
>> +    page_order = THIRD_ORDER;
>
> This looks pointless, please use THIRD_ORDER directly as argument.
>
>> +    rc = modify_altp2m_entry(ap2m, gfn, mfn, p2mt, a, page_order);
>> +
>> +out:
>> +    p2m_read_unlock(hp2m);
>> +    altp2m_unlock(d);
>> +
>> +    return rc;
>> +}
>> +
>>  static void altp2m_vcpu_reset(struct vcpu *v)
>>  {
>>      struct altp2mvcpu *av = &altp2m_vcpu(v);
>> diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
>> index 9ac3422..df78893 100644
>> --- a/xen/arch/arm/hvm.c
>> +++ b/xen/arch/arm/hvm.c
>> @@ -136,7 +136,12 @@ static int
>> do_altp2m_op(XEN_GUEST_HANDLE_PARAM(void) arg)
>>          break;
>>
>>      case HVMOP_altp2m_set_mem_access:
>> -        rc = -EOPNOTSUPP;
>> +        if ( a.u.set_mem_access.pad )
>> +            rc = -EINVAL;
>> +        else
>> +            rc = p2m_set_mem_access(d, _gfn(a.u.set_mem_access.gfn),
>> 1, 0, 0,
>> +                                    a.u.set_mem_access.hvmmem_access,
>> +                                    a.u.set_mem_access.view);
>>          break;
>>
>>      case HVMOP_altp2m_change_gfn:
>> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
>> index df2b85b..8dee02187 100644
>> --- a/xen/arch/arm/p2m.c
>> +++ b/xen/arch/arm/p2m.c
>> @@ -1913,7 +1913,7 @@ long p2m_set_mem_access(struct domain *d, gfn_t
>> gfn, uint32_t nr,
>>                          uint32_t start, uint32_t mask,
>> xenmem_access_t access,
>>                          unsigned int altp2m_idx)
>>  {
>> -    struct p2m_domain *p2m = p2m_get_hostp2m(d);
>> +    struct p2m_domain *hp2m = p2m_get_hostp2m(d), *ap2m = NULL;
>>      p2m_access_t a;
>>      unsigned int order;
>>      long rc = 0;
>> @@ -1933,13 +1933,26 @@ long p2m_set_mem_access(struct domain *d,
>> gfn_t gfn, uint32_t nr,
>>  #undef ACCESS
>>      };
>>
>> +    /* altp2m view 0 is treated as the hostp2m */
>> +    if ( altp2m_idx )
>> +    {
>> +        if ( altp2m_idx >= MAX_ALTP2M ||
>> +             d->arch.altp2m_p2m[altp2m_idx] == NULL )
>> +            return -EINVAL;
>> +
>> +        ap2m = d->arch.altp2m_p2m[altp2m_idx];
>> +    }
>> +
>>      switch ( access )
>>      {
>>      case 0 ... ARRAY_SIZE(memaccess) - 1:
>>          a = memaccess[access];
>>          break;
>>      case XENMEM_access_default:
>> -        a = p2m->default_access;
>> +        if ( ap2m )
>> +            a = ap2m->default_access;
>> +        else
>> +            a = hp2m->default_access;
>
> On the previous version, I requested to have this change documented in
> the code [1]. I don't see it here.
>

You have requested to explain, why the default_access is set on the
hostp2m and not the altp2m. With this patch, we changed this behavior
and allow to set the default_access of both the hostp2m and altp2m. Not
sure what kind of explanation you expect at this point.

>>          break;
>>      default:
>>          return -EINVAL;
>> @@ -1949,39 +1962,66 @@ long p2m_set_mem_access(struct domain *d,
>> gfn_t gfn, uint32_t nr,
>>       * Flip mem_access_enabled to true when a permission is set, as
>> to prevent
>>       * allocating or inserting super-pages.
>>       */
>> -    p2m->mem_access_enabled = true;
>> +    if ( ap2m )
>> +        ap2m->mem_access_enabled = true;
>> +    else
>> +        hp2m->mem_access_enabled = true;
>>
>>      /* If request to set default access. */
>>      if ( gfn_eq(gfn, INVALID_GFN) )
>>      {
>> -        p2m->default_access = a;
>> +        if ( ap2m )
>> +            ap2m->default_access = a;
>> +        else
>> +            hp2m->default_access = a;
>> +
>>          return 0;
>>      }
>>
>> -    p2m_write_lock(p2m);
>> -
>>      for ( gfn = gfn_add(gfn, start); nr > start; gfn = gfn_add(gfn,
>> 1UL << order) )
>>      {
>> -        p2m_type_t t;
>> -        mfn_t mfn = p2m_get_entry(p2m, gfn, &t, NULL, &order);
>> -
>> -        /* Skip hole */
>> -        if ( mfn_eq(mfn, INVALID_MFN) )
>> +        if ( ap2m )
>>          {
>> +            order = THIRD_ORDER;
>> +
>>              /*
>> -             * the order corresponds to the order of the mapping in the
>> -             * page table. so we need to align the gfn before
>> -             * incrementing.
>> +             * ARM altp2m currently supports only setting of memory
>> access rights
>> +             * of only one (4K) page at a time.
>
> This looks like a TODO to me. So please add either : "XXX:" or "TODO:"
> in front.
>

Done.

>>               */
>> -            gfn = _gfn(gfn_x(gfn) & ~((1UL << order) - 1));
>> -            continue;
>> +            rc = altp2m_set_mem_access(d, hp2m, ap2m, a, gfn);
>> +            if ( rc && rc != -ESRCH )
>> +                break;
>>          }
>>          else
>>          {
>> -            order = 0;
>> -            rc = __p2m_set_entry(p2m, gfn, 0, mfn, t, a);
>> -            if ( rc )
>> -                break;
>> +            p2m_type_t t;
>> +            mfn_t mfn;
>> +
>> +            p2m_write_lock(hp2m);
>> +
>> +            mfn = p2m_get_entry(hp2m, gfn, &t, NULL, &order);
>> +
>> +            /* Skip hole */
>> +            if ( mfn_eq(mfn, INVALID_MFN) )
>> +            {
>> +                /*
>> +                 * the order corresponds to the order of the mapping
>> in the
>> +                 * page table. so we need to align the gfn before
>> +                 * incrementing.
>> +                 */
>> +                gfn = _gfn(gfn_x(gfn) & ~((1UL << order) - 1));
>> +                continue;
>
> I just noticed that my series is buggy. The "continue" should be
> dropped. I will do it in the next version.
>

Ok.

>> +            }
>> +            else
>> +            {
>> +                order = 0;
>> +
>> +                rc = __p2m_set_entry(hp2m, gfn, 0, mfn, t, a);
>> +                if ( rc )
>> +                    break;
>> +            }
>> +
>> +            p2m_write_unlock(hp2m);
>
> By moving the lock within the loop, you will impose a TLB flush per-4K
> which is currently not the case.
>

True. Since I needed to lock the hp2m explicitly inside of
altp2m_set_mem_access, I could not move the lock outside of the loop.
Now, this restriction has changed.

> Looking at the function, I think the implementation the support of
> altp2m could really be simplified. The main difference is if the entry
> is not present in the altp2m then you lookup the host p2m.
>

I will try to simplify the function.

>>          }
>>
>>          start += (1UL << order);
>> @@ -1993,8 +2033,6 @@ long p2m_set_mem_access(struct domain *d, gfn_t
>> gfn, uint32_t nr,
>>          }
>>      }
>>
>> -    p2m_write_unlock(p2m);
>> -
>>      if ( rc < 0 )
>>          return rc;
>>      else if ( rc > 0 )
>> diff --git a/xen/include/asm-arm/altp2m.h b/xen/include/asm-arm/altp2m.h
>> index c2e44ab..3e4c36d 100644
>> --- a/xen/include/asm-arm/altp2m.h
>> +++ b/xen/include/asm-arm/altp2m.h
>> @@ -71,4 +71,16 @@ void altp2m_flush(struct domain *d);
>>  int altp2m_destroy_by_id(struct domain *d,
>>                           unsigned int idx);
>>
>> +/*
>> + * Set memory access attributes of the gfn in the altp2m view. If
>> the altp2m
>> + * view does not contain the particular entry, copy it first from
>> the hostp2m.
>> + *
>> + * Currently supports memory attribute adoptions of only one (4K) page.
>> + */
>> +int altp2m_set_mem_access(struct domain *d,
>> +                          struct p2m_domain *hp2m,
>> +                          struct p2m_domain *ap2m,
>> +                          p2m_access_t a,
>> +                          gfn_t gfn);
>> +
>>  #endif /* __ASM_ARM_ALTP2M_H */
>>
>
> Regards,
>
> [1]
> https://lists.xenproject.org/archives/html/xen-devel/2016-08/msg01007.html
>
> Regards,
>

Cheers,
~Sergej

[-- Attachment #1.2: Type: text/html, Size: 19849 bytes --]

[-- Attachment #2: Type: text/plain, Size: 127 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

* Re: [PATCH v3 19/38] arm/p2m: Add HVMOP_altp2m_switch_p2m
  2016-09-14 10:57       ` Julien Grall
@ 2016-09-14 15:28         ` Sergej Proskurin
  0 siblings, 0 replies; 116+ messages in thread
From: Sergej Proskurin @ 2016-09-14 15:28 UTC (permalink / raw)
  To: Julien Grall, xen-devel; +Cc: Stefano Stabellini

Hi Julien,


On 09/14/2016 12:57 PM, Julien Grall wrote:
>
>
> On 13/09/16 14:00, Sergej Proskurin wrote:
>> Hi Julien,
>
> Hello Sergej,
>
>>
>> On 09/12/2016 10:47 AM, Julien Grall wrote:
>>> Hello Sergej,
>>>
>>> On 16/08/2016 23:16, Sergej Proskurin wrote:
>>>> Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
>>>> ---
>>>> Cc: Stefano Stabellini <sstabellini@kernel.org>
>>>> Cc: Julien Grall <julien.grall@arm.com>
>>>> ---
>>>> v3: Extended the function "altp2m_switch_domain_altp2m_by_id" so
>>>> that if
>>>>     the guest domain indirectly calles this function, the current
>>>> vcpu also
>>>>     changes the altp2m view without performing an explicit context
>>>> switch.
>>>>
>>>>     Exchanged the check "altp2m_vttbr[idx] == INVALID_VTTBR" for
>>>>     "altp2m_p2m[idx] == NULL" in "altp2m_switch_domain_altp2m_by_id".
>>>> ---
>>>>  xen/arch/arm/altp2m.c        | 48
>>>> ++++++++++++++++++++++++++++++++++++++++++++
>>>>  xen/arch/arm/hvm.c           |  2 +-
>>>>  xen/include/asm-arm/altp2m.h |  4 ++++
>>>>  3 files changed, 53 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/xen/arch/arm/altp2m.c b/xen/arch/arm/altp2m.c
>>>> index c14ab0b..ba345b9 100644
>>>> --- a/xen/arch/arm/altp2m.c
>>>> +++ b/xen/arch/arm/altp2m.c
>>>> @@ -32,6 +32,54 @@ struct p2m_domain *altp2m_get_altp2m(struct vcpu
>>>> *v)
>>>>      return v->domain->arch.altp2m_p2m[index];
>>>>  }
>>>>
>>>> +int altp2m_switch_domain_altp2m_by_id(struct domain *d, unsigned int
>>>> idx)
>>>> +{
>>>> +    struct vcpu *v;
>>>> +    int rc = -EINVAL;
>>>> +
>>>> +    if ( idx >= MAX_ALTP2M )
>>>> +        return rc;
>>>> +
>>>> +    domain_pause_except_self(d);
>>>> +
>>>> +    altp2m_lock(d);
>>>> +
>>>> +    if ( d->arch.altp2m_p2m[idx] != NULL )
>>>> +    {
>>>> +        for_each_vcpu( d, v )
>>>> +            if ( idx != altp2m_vcpu(v).p2midx )
>>>
>>> Could you invert the condition to avoid another layer of nested if?
>>>
>>
>> Did you mean checking for (idx == altp2m_vcpu(v).p2midx) and continue
>> the loop if the condition should be satisfied? If so, then sure thing :)
>
> Correct.
>

Ok, done.

>>
>>>> +            {
>>>> +                atomic_dec(&altp2m_get_altp2m(v)->active_vcpus);
>>>> +                altp2m_vcpu(v).p2midx = idx;
>>>> +                atomic_inc(&altp2m_get_altp2m(v)->active_vcpus);
>>>> +
>>>> +                /*
>>>> +                 * In case it is the guest domain, which indirectly
>>>> called this
>>>> +                 * function, the current vcpu will not switch its
>>>> context
>>>> +                 * within the function "p2m_restore_state". That is,
>>>> changing
>>>> +                 * the altp2m_vcpu(v).p2midx will not lead to the
>>>> requested
>>>> +                 * altp2m switch on that specific vcpu. To achieve
>>>> the desired
>>>> +                 * behavior, we write to VTTBR_EL2 directly.
>>>> +                 */
>>>> +                if ( v->domain == d && v == current )
>>>
>>> v == current is enough.
>>>
>>
>> Ok.
>>
>>>> +                {
>>>> +                    struct p2m_domain *ap2m =
>>>> d->arch.altp2m_p2m[idx];
>>>> +
>>>> +                    WRITE_SYSREG64(ap2m->vttbr, VTTBR_EL2);
>>>> +                    isb();
>>>
>>> I don't like the open-coding of VTTBR_EL2. I would much prefer a
>>> separate helper to update it.
>>>
>>
>> Sure, I can introduce an UPDATE_VTTBR macro (including the isb call) in
>> p2m.h and adjust the remaining writes to VTTBR_EL2 in p2m.c as well. I
>> hope, I understood you correctly.
>
> Actually, I was concerned about having the following sequence spread:
>    VTTBR_EL2
>    isb
>
> However, the isb is not necessary here because VTTBR_EL2 will not be
> used until we return to the guest.
>
> So I would be fine to keep WRITE_SYSREG64(ap2m->vttbr, VTTBR_EL2);

I will change that, thank you.

Cheers,
~Sergej


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 116+ messages in thread

end of thread, other threads:[~2016-09-14 15:28 UTC | newest]

Thread overview: 116+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-16 22:16 [PATCH v3 00/38] arm/altp2m: Introducing altp2m to ARM Sergej Proskurin
2016-08-16 22:16 ` [PATCH v3 01/38] arm/p2m: Cosmetic fixes - apply p2m_get_hostp2m Sergej Proskurin
2016-09-01 15:46   ` Julien Grall
2016-08-16 22:16 ` [PATCH v3 02/38] arm/p2m: Expose p2m_*lock helpers Sergej Proskurin
2016-09-01 15:48   ` Julien Grall
2016-09-02 10:12     ` Sergej Proskurin
2016-09-02 10:15       ` Julien Grall
2016-09-02 10:29         ` Sergej Proskurin
2016-08-16 22:16 ` [PATCH v3 03/38] arm/p2m: Introduce p2m_(switch|restore)_vttbr_and_(g|s)et_flags Sergej Proskurin
2016-09-01 15:51   ` Julien Grall
2016-09-02  8:40     ` Sergej Proskurin
2016-09-02  9:57       ` Julien Grall
2016-09-02 10:15         ` Sergej Proskurin
2016-08-16 22:16 ` [PATCH v3 04/38] arm/p2m: Add first altp2m HVMOP stubs Sergej Proskurin
2016-09-01 16:09   ` Julien Grall
2016-09-02  9:26     ` Sergej Proskurin
2016-09-02 10:12       ` Julien Grall
2016-09-02 10:24         ` Sergej Proskurin
2016-08-16 22:16 ` [PATCH v3 05/38] arm/p2m: Add hvm_allow_(set|get)_param Sergej Proskurin
2016-08-16 22:16 ` [PATCH v3 06/38] arm/p2m: Add HVMOP_altp2m_get_domain_state Sergej Proskurin
2016-09-01 17:06   ` Julien Grall
2016-09-02  8:45     ` Sergej Proskurin
2016-08-16 22:16 ` [PATCH v3 07/38] arm/p2m: Introduce p2m_is_(hostp2m|altp2m) Sergej Proskurin
2016-08-16 22:16 ` [PATCH v3 08/38] arm/p2m: Free p2m entries only in the hostp2m Sergej Proskurin
2016-09-01 17:08   ` Julien Grall
2016-09-02  9:38     ` Sergej Proskurin
2016-08-16 22:16 ` [PATCH v3 09/38] arm/p2m: Add backpointer to the domain in p2m_domain Sergej Proskurin
2016-08-16 22:16 ` [PATCH v3 10/38] arm/p2m: Move hostp2m init/teardown to individual functions Sergej Proskurin
2016-09-01 17:36   ` Julien Grall
2016-09-02  9:09     ` Sergej Proskurin
2016-09-02 10:51       ` Julien Grall
2016-09-05 10:23         ` Sergej Proskurin
2016-09-09 16:44           ` Julien Grall
2016-08-16 22:16 ` [PATCH v3 11/38] arm/p2m: Cosmetic fix - function prototype of p2m_alloc_table Sergej Proskurin
2016-09-09 16:45   ` Julien Grall
2016-08-16 22:16 ` [PATCH v3 12/38] arm/p2m: Rename parameter in p2m_alloc_vmid Sergej Proskurin
2016-08-16 22:16 ` [PATCH v3 13/38] arm/p2m: Change func prototype and impl of p2m_(alloc|free)_vmid Sergej Proskurin
2016-08-16 22:16 ` [PATCH v3 14/38] arm/p2m: Add altp2m init/teardown routines Sergej Proskurin
2016-09-09 16:56   ` Julien Grall
2016-09-13 19:35     ` Sergej Proskurin
2016-09-14  6:28       ` Sergej Proskurin
2016-09-14 10:53         ` Julien Grall
2016-08-16 22:16 ` [PATCH v3 15/38] arm/p2m: Add altp2m table flushing routine Sergej Proskurin
2016-09-09 17:02   ` Julien Grall
2016-09-13  9:13     ` Sergej Proskurin
2016-08-16 22:16 ` [PATCH v3 16/38] arm/p2m: Add HVMOP_altp2m_set_domain_state Sergej Proskurin
2016-09-09 17:14   ` Julien Grall
2016-09-13  9:22     ` Sergej Proskurin
2016-09-14 11:07   ` Julien Grall
2016-08-16 22:16 ` [PATCH v3 17/38] arm/p2m: Add HVMOP_altp2m_create_p2m Sergej Proskurin
2016-09-12  8:38   ` Julien Grall
2016-08-16 22:16 ` [PATCH v3 18/38] arm/p2m: Add HVMOP_altp2m_destroy_p2m Sergej Proskurin
2016-09-12  8:41   ` Julien Grall
2016-09-13 12:43     ` Sergej Proskurin
2016-08-16 22:16 ` [PATCH v3 19/38] arm/p2m: Add HVMOP_altp2m_switch_p2m Sergej Proskurin
2016-09-12  8:47   ` Julien Grall
2016-09-13 13:00     ` Sergej Proskurin
2016-09-14 10:57       ` Julien Grall
2016-09-14 15:28         ` Sergej Proskurin
2016-08-16 22:16 ` [PATCH v3 20/38] arm/p2m: Add p2m_get_active_p2m macro Sergej Proskurin
2016-09-12  8:50   ` Julien Grall
2016-08-16 22:16 ` [PATCH v3 21/38] arm/p2m: Make p2m_restore_state ready for altp2m Sergej Proskurin
2016-09-12  8:51   ` Julien Grall
2016-08-16 22:16 ` [PATCH v3 22/38] arm/p2m: Make get_page_from_gva " Sergej Proskurin
2016-08-16 22:16 ` [PATCH v3 23/38] arm/p2m: Cosmetic fixes -- __p2m_get_mem_access Sergej Proskurin
2016-09-12  8:53   ` Julien Grall
2016-09-13 13:27     ` Sergej Proskurin
2016-09-13 13:30       ` Julien Grall
2016-09-13 13:42         ` Sergej Proskurin
2016-09-13 13:45           ` Julien Grall
2016-08-16 22:17 ` [PATCH v3 24/38] arm/p2m: Make p2m_mem_access_check ready for altp2m Sergej Proskurin
2016-09-12  9:02   ` Julien Grall
2016-09-13 14:00     ` Sergej Proskurin
2016-09-13 14:20       ` Julien Grall
2016-08-16 22:17 ` [PATCH v3 25/38] arm/p2m: Cosmetic fixes - function prototypes Sergej Proskurin
2016-08-16 22:17 ` [PATCH v3 26/38] arm/p2m: Introduce helpers managing altp2m entries Sergej Proskurin
2016-09-12  9:04   ` Julien Grall
2016-08-16 22:17 ` [PATCH v3 27/38] arm/p2m: Introduce p2m_lookup_attr Sergej Proskurin
2016-09-12  9:15   ` Julien Grall
2016-08-16 22:17 ` [PATCH v3 28/38] arm/p2m: Modify reference count only if hostp2m active Sergej Proskurin
2016-09-12  9:17   ` Julien Grall
2016-09-13 14:16     ` Sergej Proskurin
2016-08-16 22:17 ` [PATCH v3 29/38] arm/p2m: Add HVMOP_altp2m_set_mem_access Sergej Proskurin
2016-09-12 12:08   ` Julien Grall
2016-09-14 15:20     ` Sergej Proskurin
2016-08-16 22:17 ` [PATCH v3 30/38] arm/p2m: Add altp2m_propagate_change Sergej Proskurin
2016-08-16 22:17 ` [PATCH v3 31/38] altp2m: Introduce altp2m_switch_vcpu_altp2m_by_id Sergej Proskurin
2016-08-17 10:05   ` Jan Beulich
2016-08-17 12:37     ` Sergej Proskurin
2016-08-17 12:48       ` Julien Grall
2016-08-17 12:08   ` Razvan Cojocaru
2016-08-18 10:35   ` George Dunlap
2016-08-16 22:17 ` [PATCH v3 32/38] arm/p2m: Code movement in instr/data abort handlers Sergej Proskurin
2016-09-12 13:54   ` Julien Grall
2016-08-16 22:17 ` [PATCH v3 33/38] arm/p2m: Add altp2m paging mechanism Sergej Proskurin
2016-09-12 14:18   ` Julien Grall
2016-09-13 15:06     ` Sergej Proskurin
2016-09-13 15:08       ` Julien Grall
2016-09-13 15:53         ` Sergej Proskurin
2016-09-14  7:53       ` Sergej Proskurin
2016-09-14 11:15         ` Julien Grall
2016-08-16 22:17 ` [PATCH v3 34/38] arm/p2m: Add HVMOP_altp2m_change_gfn Sergej Proskurin
2016-09-12 14:27   ` Julien Grall
2016-08-16 22:17 ` [PATCH v3 35/38] arm/p2m: Adjust debug information to altp2m Sergej Proskurin
2016-09-12 14:29   ` Julien Grall
2016-09-13 15:13     ` Sergej Proskurin
2016-08-16 22:17 ` [PATCH v3 36/38] altp2m: Allow specifying external-only use-case Sergej Proskurin
2016-08-17 10:08   ` Jan Beulich
2016-08-17 14:47   ` Daniel De Graaf
2016-08-24 12:18   ` Wei Liu
2016-08-16 22:17 ` [PATCH v3 37/38] arm/p2m: Extend xen-access for altp2m on ARM Sergej Proskurin
2016-08-17 11:26   ` Razvan Cojocaru
2016-08-16 22:17 ` [PATCH v3 38/38] arm/p2m: Add test of xc_altp2m_change_gfn Sergej Proskurin
2016-08-17 12:06   ` Razvan Cojocaru
2016-08-24 12:27   ` Wei Liu
2016-09-13 15:45     ` Sergej Proskurin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.