diff options
author | nwhitehorn <nwhitehorn@FreeBSD.org> | 2010-11-12 04:18:19 +0000 |
---|---|---|
committer | nwhitehorn <nwhitehorn@FreeBSD.org> | 2010-11-12 04:18:19 +0000 |
commit | b5495356b24ecdcdf829764b8e2fd95dea55831c (patch) | |
tree | d54d0e93b610c6afc2a3c82b49320ba55e02cad8 /sys/powerpc/aim/slb.c | |
parent | 3d8843cae15a79d5dd48c925dd352a875b214068 (diff) | |
download | FreeBSD-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.c | 55 |
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 ** |