]> xenbits.xensource.com Git - people/iwj/xen.git/commitdiff
xen/pvshim: keep track of used PFN ranges
authorWei Liu <wei.liu2@citrix.com>
Wed, 3 Jan 2018 16:50:24 +0000 (16:50 +0000)
committerRoger Pau Monne <roger.pau@citrix.com>
Thu, 11 Jan 2018 17:51:19 +0000 (17:51 +0000)
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@citrix.com>
Signed-off-by: Wei Liu <wei.liu2@citrix.com>
xen/arch/x86/guest/xen.c
xen/arch/x86/setup.c
xen/include/asm-x86/guest/xen.h

index c253ebd9831bf50bf4d8bcbcc4feca42d9fb47c8..abf53ebbc67cdf6e284a0bbb090612358284f5a8 100644 (file)
  * 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
index edb43bf2cb083424b0fa4519153a0c78bf63e65d..b9b97d68f5cc48a3789b9a19bb7b749aee13c1bc 100644 (file)
@@ -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();
 
index 97a7c8d531aecf391da5ef97ed3b33960bf879e7..427837797b1da9e97eb61dd50d0984ececeb2b4e 100644 (file)
 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__ */