summaryrefslogtreecommitdiffstats
path: root/sys/powerpc
diff options
context:
space:
mode:
authorjhibbits <jhibbits@FreeBSD.org>2016-04-10 15:48:09 +0000
committerjhibbits <jhibbits@FreeBSD.org>2016-04-10 15:48:09 +0000
commit19c7765e37f00e2171f79cbe90f99eeda55e07c9 (patch)
tree9888c7cc029b8836d6c4a50a3009dc4fa4e5b6d3 /sys/powerpc
parentaac70308f6035bbde1587853967f26e436371d63 (diff)
downloadFreeBSD-src-19c7765e37f00e2171f79cbe90f99eeda55e07c9.zip
FreeBSD-src-19c7765e37f00e2171f79cbe90f99eeda55e07c9.tar.gz
Restructure device mappings for Book-E.
Summary: There is currently a 1GB hole between user and kernel address spaces into which direct (1:1 PA:VA) device mappings go. This appears to go largely unused, leaving all devices to contend with the 128MB block at the end of the 32-bit space (0xf8000000-0xffffffff). This easily fills up, and needs to be densely packed. However, dense packing wastes precious TLB1 space, of which there are only 16 (e500v2) or 64(e5500) entries available. Change this by using the 1GB space for all device mappings, and allow the kernel to use the entire upper 1GB for KVA. This also allows us to use sparse device mappings, freeing up TLB entries. Test Plan: Boot tested on p5020. Differential Revision: https://reviews.freebsd.org/D5832
Diffstat (limited to 'sys/powerpc')
-rw-r--r--sys/powerpc/booke/pmap.c35
-rw-r--r--sys/powerpc/include/vmparam.h2
2 files changed, 19 insertions, 18 deletions
diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c
index 54f215a..fd04ab4 100644
--- a/sys/powerpc/booke/pmap.c
+++ b/sys/powerpc/booke/pmap.c
@@ -96,6 +96,7 @@ __FBSDID("$FreeBSD$");
#include "mmu_if.h"
+#define SPARSE_MAPDEV
#ifdef DEBUG
#define debugf(fmt, args...) printf(fmt, ##args)
#else
@@ -191,7 +192,7 @@ static tlb_entry_t tlb1[TLB1_MAXENTRIES];
/* Next free entry in the TLB1 */
static unsigned int tlb1_idx;
-static vm_offset_t tlb1_map_base = VM_MAX_KERNEL_ADDRESS;
+static vm_offset_t tlb1_map_base = VM_MAXUSER_ADDRESS;
static tlbtid_t tid_alloc(struct pmap *);
static void tid_flush(tlbtid_t tid);
@@ -2796,7 +2797,7 @@ static void *
mmu_booke_mapdev_attr(mmu_t mmu, vm_paddr_t pa, vm_size_t size, vm_memattr_t ma)
{
void *res;
- uintptr_t va;
+ uintptr_t va, tmpva;
vm_size_t sz;
int i;
@@ -2819,22 +2820,22 @@ mmu_booke_mapdev_attr(mmu_t mmu, vm_paddr_t pa, vm_size_t size, vm_memattr_t ma)
size = roundup(size, PAGE_SIZE);
/*
- * We leave a hole for device direct mapping between the maximum user
- * address (0x8000000) and the minimum KVA address (0xc0000000). If
- * devices are in there, just map them 1:1. If not, map them to the
- * device mapping area about VM_MAX_KERNEL_ADDRESS. These mapped
- * addresses should be pulled from an allocator, but since we do not
- * ever free TLB1 entries, it is safe just to increment a counter.
- * Note that there isn't a lot of address space here (128 MB) and it
- * is not at all difficult to imagine running out, since that is a 4:1
- * compression from the 0xc0000000 - 0xf0000000 address space that gets
- * mapped there.
+ * The device mapping area is between VM_MAXUSER_ADDRESS and
+ * VM_MIN_KERNEL_ADDRESS. This gives 1GB of device addressing.
*/
- if (pa >= (VM_MAXUSER_ADDRESS + PAGE_SIZE) &&
- (pa + size - 1) < VM_MIN_KERNEL_ADDRESS)
- va = pa;
- else
- va = atomic_fetchadd_int(&tlb1_map_base, size);
+#ifdef SPARSE_MAPDEV
+ /*
+ * With a sparse mapdev, align to the largest starting region. This
+ * could feasibly be optimized for a 'best-fit' alignment, but that
+ * calculation could be very costly.
+ */
+ do {
+ tmpva = tlb1_map_base;
+ va = roundup(tlb1_map_base, 1 << flsl(size));
+ } while (!atomic_cmpset_int(&tlb1_map_base, tmpva, va + size));
+#else
+ va = atomic_fetchadd_int(&tlb1_map_base, size);
+#endif
res = (void *)va;
do {
diff --git a/sys/powerpc/include/vmparam.h b/sys/powerpc/include/vmparam.h
index 0dd74c9..d7368ec 100644
--- a/sys/powerpc/include/vmparam.h
+++ b/sys/powerpc/include/vmparam.h
@@ -111,7 +111,7 @@
#define KERNBASE 0xc0000000 /* start of kernel virtual */
#define VM_MIN_KERNEL_ADDRESS KERNBASE
-#define VM_MAX_KERNEL_ADDRESS 0xf7ffffff
+#define VM_MAX_KERNEL_ADDRESS 0xffffffff
#define VM_MAX_SAFE_KERNEL_ADDRESS VM_MAX_KERNEL_ADDRESS
#endif /* AIM/E500 */
OpenPOWER on IntegriCloud