All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] minios: allocate machine contiguous pages
@ 2009-03-12 19:43 Rolf Neugebauer
  2009-03-12 23:42 ` Samuel Thibault
  0 siblings, 1 reply; 2+ messages in thread
From: Rolf Neugebauer @ 2009-03-12 19:43 UTC (permalink / raw)
  To: Xen-devel; +Cc: Samuel Thibault

[-- Attachment #1: Type: text/plain, Size: 243 bytes --]

This is a port of XenLinux xen_alloc_contig_memory() to mini-os. A 
sufficiently privileged mini-os guest can exchange a small number of its 
pages with machine contiguous pages.

Signed-off-by: Rolf Neugebauer <rolf.neugebauer@netronome.com>

[-- Attachment #2: minios-contig-mem.patch --]
[-- Type: text/x-patch, Size: 6068 bytes --]

diff -r 3a0165b48266 extras/mini-os/arch/ia64/mm.c
--- a/extras/mini-os/arch/ia64/mm.c	Tue Mar 10 18:03:57 2009 +0000
+++ b/extras/mini-os/arch/ia64/mm.c	Tue Mar 10 18:10:39 2009 +0000
@@ -162,6 +162,12 @@
     ASSERT(0);
 }
 
+unsigned long alloc_contig_pages(int order, unsigned int addr_bits)
+{
+    /* TODO */
+    ASSERT(0);
+}
+
 void arch_init_p2m(unsigned long max_pfn)
 {
     printk("Warn: p2m map not implemented.\n");
diff -r 3a0165b48266 extras/mini-os/arch/x86/mm.c
--- a/extras/mini-os/arch/x86/mm.c	Tue Mar 10 18:03:57 2009 +0000
+++ b/extras/mini-os/arch/x86/mm.c	Tue Mar 10 18:10:39 2009 +0000
@@ -702,6 +702,148 @@
 }
 
 /*
+ * Allocate pages which are contiguous in machine memory.
+ * Returns a VA to where they are mapped or 0 on failure.
+ * 
+ * addr_bits indicates if the region has restrictions on where it is
+ * located. Typical values are 32 (if for example PCI devices can't access
+ * 64bit memory) or 0 for no restrictions.
+ *
+ * Allocated pages can be freed using the page allocators free_pages() 
+ * function.
+ *
+ * based on Linux function xen_create_contiguous_region()
+ */
+#define MAX_CONTIG_ORDER 9 /* 2MB */
+unsigned long alloc_contig_pages(int order, unsigned int addr_bits)
+{
+    unsigned long in_va, va;
+    unsigned long in_frames[1<<MAX_CONTIG_ORDER], out_frames, mfn;
+    multicall_entry_t call[(1UL << MAX_CONTIG_ORDER)];
+    unsigned int i, num_pages = (1UL << order);
+    int ret, exch_success;
+
+    /* pass in num_pages 'extends' of size 1 and
+     * request 1 extend of size 'order */
+	struct xen_memory_exchange exchange = {
+		.in = {
+			.nr_extents   = num_pages,
+			.extent_order = 0,
+			.domid        = DOMID_SELF
+		},
+		.out = {
+			.nr_extents   = 1,
+			.extent_order = order,
+			.address_bits = addr_bits,
+			.domid        = DOMID_SELF
+		},
+        .nr_exchanged = 0
+	};
+
+    if ( order > MAX_CONTIG_ORDER )
+    {
+        printk("alloc_contig_pages: order too large 0x%x > 0x%x\n",
+               order, MAX_CONTIG_ORDER);
+        return 0;
+    }
+
+    /* Allocate some potentially dis-contiguous pages */
+    in_va = alloc_pages(order);
+    if ( !in_va )
+    {
+        printk("alloc_contig_pages: could not get enough pages (order=0x%x\n",
+               order);
+        return 0;
+    }
+
+    /* set up arguments for exchange hyper call */
+    set_xen_guest_handle(exchange.in.extent_start, in_frames);
+	set_xen_guest_handle(exchange.out.extent_start, &out_frames);
+
+    /* unmap current frames, keep a list of MFNs */
+    for ( i = 0; i < num_pages; i++ )
+    {
+        int arg = 0;
+
+        va = in_va + (PAGE_SIZE * i);
+        in_frames[i] = virt_to_mfn(va);
+
+        /* update P2M mapping */
+        phys_to_machine_mapping[virt_to_pfn(va)] = INVALID_P2M_ENTRY;
+
+        /* build multi call */
+        call[i].op = __HYPERVISOR_update_va_mapping;
+        call[i].args[arg++] = va;
+        call[i].args[arg++] = 0;
+#ifdef __i386__
+        call[i].args[arg++] = 0;
+#endif  
+        call[i].args[arg++] = UVMF_INVLPG;
+    }
+
+    ret = HYPERVISOR_multicall(call, i);
+    if ( ret )
+    {
+        printk("Odd, update_va_mapping hypercall failed with rc=%d.\n", ret);
+        return 0;
+    }
+
+    /* try getting a contig range of MFNs */
+    out_frames = virt_to_pfn(in_va); /* PFNs to populate */
+    ret = HYPERVISOR_memory_op(XENMEM_exchange, &exchange);
+    if ( ret ) {
+        printk("mem exchanged order=0x%x failed with rc=%d, nr_exchanged=%d\n", 
+               order, ret, exchange.nr_exchanged);
+        /* we still need to return the allocated pages above to the pool
+         * ie. map them back into the 1:1 mapping etc. so we continue but 
+         * in the end return the pages to the page allocator and return 0. */
+        exch_success = 0;
+    }
+    else
+        exch_success = 1;
+
+    /* map frames into 1:1 and update p2m */
+    for ( i = 0; i < num_pages; i++ )
+    {
+        int arg = 0;
+        pte_t pte;
+
+        va = in_va + (PAGE_SIZE * i);
+        mfn = i < exchange.nr_exchanged ? (out_frames + i) : in_frames[i];
+        pte = __pte(mfn << PAGE_SHIFT | L1_PROT);
+
+        /* update P2M mapping */
+        phys_to_machine_mapping[virt_to_pfn(va)] = mfn;
+
+        /* build multi call */
+        call[i].op = __HYPERVISOR_update_va_mapping;
+        call[i].args[arg++] = va;
+#ifdef __x86_64__
+        call[i].args[arg++] = (pgentry_t)pte.pte;
+#else
+        call[i].args[arg++] = pte.pte_low;
+        call[i].args[arg++] = pte.pte_high;
+#endif  
+        call[i].args[arg++] = UVMF_INVLPG;
+    }
+    ret = HYPERVISOR_multicall(call, i);
+    if ( ret )
+    {
+        printk("update_va_mapping hypercall no. 2 failed with rc=%d.\n", ret);
+        return 0;
+    }
+
+    if ( !exch_success )
+    {
+        /* since the exchanged failed we just free the pages as well */
+        free_pages((void *) in_va, order);
+        return 0;
+    }
+    
+    return in_va;
+}
+
+/*
  * Check if a given MFN refers to real memory
  */
 static long system_ram_end_mfn;
diff -r 3a0165b48266 extras/mini-os/include/mm.h
--- a/extras/mini-os/include/mm.h	Tue Mar 10 18:03:57 2009 +0000
+++ b/extras/mini-os/include/mm.h	Tue Mar 10 18:10:39 2009 +0000
@@ -72,6 +72,7 @@
         unsigned long *f, unsigned long n, unsigned long stride,
 	unsigned long increment, domid_t id, int may_fail, unsigned long prot);
 int unmap_frames(unsigned long va, unsigned long num_frames);
+unsigned long alloc_contig_pages(int order, unsigned int addr_bits);
 #ifdef HAVE_LIBC
 extern unsigned long heap, brk, heap_mapped, heap_end;
 #endif
diff -r 3a0165b48266 extras/mini-os/include/x86/arch_mm.h
--- a/extras/mini-os/include/x86/arch_mm.h	Tue Mar 10 18:03:57 2009 +0000
+++ b/extras/mini-os/include/x86/arch_mm.h	Tue Mar 10 18:10:39 2009 +0000
@@ -137,6 +137,9 @@
 #define IO_PROT (L1_PROT)
 #define IO_PROT_NOCACHE (L1_PROT | _PAGE_PCD)
 
+/* for P2M */
+#define INVALID_P2M_ENTRY (~0UL)
+
 #include "arch_limits.h"
 #define PAGE_SIZE       __PAGE_SIZE
 #define PAGE_SHIFT      __PAGE_SHIFT

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

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

* Re: [PATCH] minios: allocate machine contiguous pages
  2009-03-12 19:43 [PATCH] minios: allocate machine contiguous pages Rolf Neugebauer
@ 2009-03-12 23:42 ` Samuel Thibault
  0 siblings, 0 replies; 2+ messages in thread
From: Samuel Thibault @ 2009-03-12 23:42 UTC (permalink / raw)
  To: Rolf Neugebauer; +Cc: Xen-devel

Rolf Neugebauer, le Thu 12 Mar 2009 19:43:57 +0000, a écrit :
> +#define MAX_CONTIG_ORDER 9 /* 2MB */
> +unsigned long alloc_contig_pages(int order, unsigned int addr_bits)
> +{
> +    unsigned long in_frames[1<<MAX_CONTIG_ORDER], out_frames, mfn;
> +    multicall_entry_t call[(1UL << MAX_CONTIG_ORDER)];

Mmm, can't we assume we have a C99 compiler that can just use order
instead of MAX_CONTIG_ORDER?

> +    /* set up arguments for exchange hyper call */
> +    set_xen_guest_handle(exchange.in.extent_start, in_frames);
> +	set_xen_guest_handle(exchange.out.extent_start, &out_frames);

There are mixed tabs and spaces here.

Samuel

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

end of thread, other threads:[~2009-03-12 23:42 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-03-12 19:43 [PATCH] minios: allocate machine contiguous pages Rolf Neugebauer
2009-03-12 23:42 ` Samuel Thibault

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.