]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
xen: allocate page for shared info page from low memory
authorJuergen Gross <jgross@suse.com>
Mon, 12 Jun 2017 11:53:56 +0000 (13:53 +0200)
committerJuergen Gross <jgross@suse.com>
Sun, 25 Jun 2017 11:11:27 +0000 (13:11 +0200)
In a HVM guest the kernel allocates the page for mapping the shared
info structure via extend_brk() today. This will lead to a drop of
performance as the underlying EPT entry will have to be split up into
4kB entries as the single shared info page is located in hypervisor
memory.

The issue has been detected by using the libmicro munmap test:
unmapping 8kB of memory was faster by nearly a factor of two when no
pv interfaces were active in the HVM guest.

So instead of taking a page from memory which might be mapped via
large EPT entries use a page which is already mapped via a 4kB EPT
entry: we can take a page from the first 1MB of memory as the video
memory at 640kB disallows using larger EPT entries.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Signed-off-by: Juergen Gross <jgross@suse.com>
arch/x86/xen/enlighten_hvm.c
arch/x86/xen/enlighten_pv.c

index 13b5fa1a211c2d5c7ce3f70a3ece26d7aa0d9714..87d791356ea9052f79f23e00f5d0024ff8cf0b7f 100644 (file)
@@ -1,5 +1,6 @@
 #include <linux/cpu.h>
 #include <linux/kexec.h>
+#include <linux/memblock.h>
 
 #include <xen/features.h>
 #include <xen/events.h>
 #include <asm/reboot.h>
 #include <asm/setup.h>
 #include <asm/hypervisor.h>
+#include <asm/e820/api.h>
 
 #include <asm/xen/cpuid.h>
 #include <asm/xen/hypervisor.h>
+#include <asm/xen/page.h>
 
 #include "xen-ops.h"
 #include "mmu.h"
 void __ref xen_hvm_init_shared_info(void)
 {
        struct xen_add_to_physmap xatp;
-       static struct shared_info *shared_info_page;
+       u64 pa;
+
+       if (HYPERVISOR_shared_info == &xen_dummy_shared_info) {
+               /*
+                * Search for a free page starting at 4kB physical address.
+                * Low memory is preferred to avoid an EPT large page split up
+                * by the mapping.
+                * Starting below X86_RESERVE_LOW (usually 64kB) is fine as
+                * the BIOS used for HVM guests is well behaved and won't
+                * clobber memory other than the first 4kB.
+                */
+               for (pa = PAGE_SIZE;
+                    !e820__mapped_all(pa, pa + PAGE_SIZE, E820_TYPE_RAM) ||
+                    memblock_is_reserved(pa);
+                    pa += PAGE_SIZE)
+                       ;
+
+               memblock_reserve(pa, PAGE_SIZE);
+               HYPERVISOR_shared_info = __va(pa);
+       }
 
-       if (!shared_info_page)
-               shared_info_page = (struct shared_info *)
-                       extend_brk(PAGE_SIZE, PAGE_SIZE);
        xatp.domid = DOMID_SELF;
        xatp.idx = 0;
        xatp.space = XENMAPSPACE_shared_info;
-       xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT;
+       xatp.gpfn = virt_to_pfn(HYPERVISOR_shared_info);
        if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
                BUG();
-
-       HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
 }
 
 static void __init init_hvm_pv_info(void)
index bc44d2175459674e9c1d61c6523ba4cb5ecd5de6..811e4ddb3f37484180c0099e92b4eb351515d5bc 100644 (file)
@@ -89,8 +89,6 @@
 
 void *xen_initial_gdt;
 
-RESERVE_BRK(shared_info_page_brk, PAGE_SIZE);
-
 static int xen_cpu_up_prepare_pv(unsigned int cpu);
 static int xen_cpu_dead_pv(unsigned int cpu);