[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v2 27/62] xen/pvshim: keep track of used PFN ranges



Simple infrastructure to keep track of PFN space usage, so that we can
use unpopulated PFNs to map special pages like shared info and grant
table.

As rangeset depends on malloc being ready so hypervisor_setup is
introduced for things that can be initialised late in the process.

Note that the PFN is marked as reserved at least up to 4GiB (or more
if the guest has more memory). This is not a perfect solution but
avoids using the MMIO hole below 4GiB. Ideally the shim (L1) should
have a way to ask the underlying Xen (L0) which memory regions are
populated, unpopulated, or MMIO space.

Signed-off-by: Roger Pau Monne <roger.pau@xxxxxxxxxx>
Signed-off-by: Wei Liu <wei.liu2@xxxxxxxxxx>
---
 xen/arch/x86/guest/xen.c        | 56 +++++++++++++++++++++++++++++++++++++++++
 xen/arch/x86/setup.c            |  3 +++
 xen/include/asm-x86/guest/xen.h |  7 ++++++
 3 files changed, 66 insertions(+)

diff --git a/xen/arch/x86/guest/xen.c b/xen/arch/x86/guest/xen.c
index c253ebd983..abf53ebbc6 100644
--- a/xen/arch/x86/guest/xen.c
+++ b/xen/arch/x86/guest/xen.c
@@ -19,8 +19,12 @@
  * Copyright (c) 2017 Citrix Systems Ltd.
  */
 #include <xen/init.h>
+#include <xen/mm.h>
+#include <xen/pfn.h>
+#include <xen/rangeset.h>
 #include <xen/types.h>
 
+#include <asm/e820.h>
 #include <asm/guest.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
@@ -31,6 +35,7 @@ bool __read_mostly xen_guest;
 
 static __read_mostly uint32_t xen_cpuid_base;
 extern char hypercall_page[];
+static struct rangeset *mem;
 
 static void __init find_xen_leaves(void)
 {
@@ -72,6 +77,57 @@ void __init probe_hypervisor(void)
     xen_guest = true;
 }
 
+static void __init init_memmap(void)
+{
+    unsigned int i;
+
+    mem = rangeset_new(NULL, "host memory map", 0);
+    if ( !mem )
+        panic("failed to allocate PFN usage rangeset");
+
+    /*
+     * Mark up to the last memory page (or 4GiB) as RAM. This is done because
+     * Xen doesn't know the position of possible MMIO holes, so at least try to
+     * avoid the know MMIO hole below 4GiB. Note that this is subject to future
+     * discussion and improvements.
+     */
+    if ( rangeset_add_range(mem, 0, max_t(unsigned long, max_page - 1,
+                                          PFN_DOWN(GB(4) - 1))) )
+        panic("unable to add RAM to in-use PFN rangeset");
+
+    for ( i = 0; i < e820.nr_map; i++ )
+    {
+        struct e820entry *e = &e820.map[i];
+
+        if ( rangeset_add_range(mem, PFN_DOWN(e->addr),
+                                PFN_UP(e->addr + e->size - 1)) )
+            panic("unable to add range [%#lx, %#lx] to in-use PFN rangeset",
+                  PFN_DOWN(e->addr), PFN_UP(e->addr + e->size - 1));
+    }
+}
+
+void __init hypervisor_setup(void)
+{
+    init_memmap();
+}
+
+int hypervisor_alloc_unused_page(mfn_t *mfn)
+{
+    unsigned long m;
+    int rc;
+
+    rc = rangeset_claim_range(mem, 1, &m);
+    if ( !rc )
+        *mfn = _mfn(m);
+
+    return rc;
+}
+
+int hypervisor_free_unused_page(mfn_t mfn)
+{
+    return rangeset_remove_range(mem, mfn_x(mfn), mfn_x(mfn));
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 9c3d7563f3..32ec741591 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -1472,6 +1472,9 @@ void __init noreturn __start_xen(unsigned long mbi_p)
         max_cpus = nr_cpu_ids;
     }
 
+    if ( xen_guest )
+        hypervisor_setup();
+
     /* Low mappings were only needed for some BIOS table parsing. */
     zap_low_mappings();
 
diff --git a/xen/include/asm-x86/guest/xen.h b/xen/include/asm-x86/guest/xen.h
index 97a7c8d531..427837797b 100644
--- a/xen/include/asm-x86/guest/xen.h
+++ b/xen/include/asm-x86/guest/xen.h
@@ -26,12 +26,19 @@
 extern bool xen_guest;
 
 void probe_hypervisor(void);
+void hypervisor_setup(void);
+int hypervisor_alloc_unused_page(mfn_t *mfn);
+int hypervisor_free_unused_page(mfn_t mfn);
 
 #else
 
 #define xen_guest 0
 
 static inline void probe_hypervisor(void) {};
+static inline void hypervisor_setup(void)
+{
+    ASSERT_UNREACHABLE();
+}
 
 #endif /* CONFIG_XEN_GUEST */
 #endif /* __X86_GUEST_XEN_H__ */
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.