summaryrefslogtreecommitdiffstats
path: root/sys/powerpc/aim/slb.c
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2010-11-12 04:18:19 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2010-11-12 04:18:19 +0000
commitb5495356b24ecdcdf829764b8e2fd95dea55831c (patch)
treed54d0e93b610c6afc2a3c82b49320ba55e02cad8 /sys/powerpc/aim/slb.c
parent3d8843cae15a79d5dd48c925dd352a875b214068 (diff)
downloadFreeBSD-src-b5495356b24ecdcdf829764b8e2fd95dea55831c.zip
FreeBSD-src-b5495356b24ecdcdf829764b8e2fd95dea55831c.tar.gz
Add some platform KOBJ extensions and continue integrating PowerPC
hypervisor infrastructure support: - Fix coexistence of multiple platform modules in the same kernel - Allow platform modules to provide an SMP topology - PowerPC hypervisors limit the amount of memory accessible in real mode. Allow the platform modules to specify the maximum real-mode address, and modify the bits of the kernel that need to allocate real-mode-accessible buffers to respect this limits.
Diffstat (limited to 'sys/powerpc/aim/slb.c')
-rw-r--r--sys/powerpc/aim/slb.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/sys/powerpc/aim/slb.c b/sys/powerpc/aim/slb.c
index 9d8828a..d5fb12e 100644
--- a/sys/powerpc/aim/slb.c
+++ b/sys/powerpc/aim/slb.c
@@ -36,9 +36,14 @@
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/uma.h>
+#include <vm/vm.h>
#include <vm/vm_map.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pageout.h>
+#include <vm/vm_phys.h>
#include <machine/md_var.h>
+#include <machine/platform.h>
#include <machine/pmap.h>
#include <machine/vmparam.h>
@@ -474,6 +479,51 @@ slb_insert_user(pmap_t pm, struct slb *slb)
pm->pm_slb[i] = slb;
}
+static void *
+slb_uma_real_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait)
+{
+ static vm_offset_t realmax = 0;
+ void *va;
+ vm_page_t m;
+ int pflags;
+
+ if (realmax == 0)
+ realmax = platform_real_maxaddr();
+
+ *flags = UMA_SLAB_PRIV;
+ if ((wait & (M_NOWAIT|M_USE_RESERVE)) == M_NOWAIT)
+ pflags = VM_ALLOC_INTERRUPT | VM_ALLOC_WIRED;
+ else
+ pflags = VM_ALLOC_SYSTEM | VM_ALLOC_WIRED;
+ if (wait & M_ZERO)
+ pflags |= VM_ALLOC_ZERO;
+
+ for (;;) {
+ m = vm_phys_alloc_contig(1, 0, realmax, PAGE_SIZE,
+ PAGE_SIZE);
+ if (m == NULL) {
+ if (wait & M_NOWAIT)
+ return (NULL);
+ VM_WAIT;
+ } else
+ break;
+ }
+
+ va = (void *) VM_PAGE_TO_PHYS(m);
+
+ if (!hw_direct_map)
+ pmap_kenter((vm_offset_t)va, VM_PAGE_TO_PHYS(m));
+
+ if ((wait & M_ZERO) && (m->flags & PG_ZERO) == 0)
+ bzero(va, PAGE_SIZE);
+
+ /* vm_phys_alloc_contig does not track wiring */
+ atomic_add_int(&cnt.v_wire_count, 1);
+ m->wire_count = 1;
+
+ return (va);
+}
+
static void
slb_zone_init(void *dummy)
{
@@ -482,6 +532,11 @@ slb_zone_init(void *dummy)
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM);
slb_cache_zone = uma_zcreate("SLB cache", 64*sizeof(struct slb *),
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM);
+
+ if (platform_real_maxaddr() != VM_MAX_ADDRESS) {
+ uma_zone_set_allocf(slb_cache_zone, slb_uma_real_alloc);
+ uma_zone_set_allocf(slbt_zone, slb_uma_real_alloc);
+ }
}
struct slb **
OpenPOWER on IntegriCloud