summaryrefslogtreecommitdiffstats
path: root/sys/boot
diff options
context:
space:
mode:
Diffstat (limited to 'sys/boot')
-rw-r--r--sys/boot/common/bootstrap.h2
-rw-r--r--sys/boot/sparc64/loader/main.c51
2 files changed, 52 insertions, 1 deletions
diff --git a/sys/boot/common/bootstrap.h b/sys/boot/common/bootstrap.h
index 862b06c..6ecd235 100644
--- a/sys/boot/common/bootstrap.h
+++ b/sys/boot/common/bootstrap.h
@@ -292,6 +292,8 @@ struct arch_switch
/* Perform ISA byte port I/O (only for systems with ISA) */
int (*arch_isainb)(int port);
void (*arch_isaoutb)(int port, int value);
+ /* Pass in initial kernel memory size */
+ void (*arch_maphint)(vm_offset_t va, size_t len);
};
extern struct arch_switch archsw;
diff --git a/sys/boot/sparc64/loader/main.c b/sys/boot/sparc64/loader/main.c
index b62570d..a351c2c 100644
--- a/sys/boot/sparc64/loader/main.c
+++ b/sys/boot/sparc64/loader/main.c
@@ -87,6 +87,7 @@ int itlb_slot_max;
/* sun4v */
struct tlb_entry *tlb_store;
+int is_sun4v = 0;
/*
* no direct TLB access on sun4v
* we somewhat arbitrarily declare enough
@@ -249,6 +250,52 @@ sparc64_copyin(const void *src, vm_offset_t dest, size_t len)
return len;
}
+static void
+sparc64_maphint(vm_offset_t va, size_t len)
+{
+ vm_paddr_t pa;
+ vm_offset_t mva;
+ size_t size;
+ int i, ret, free_excess = 0;
+
+ if (!is_sun4v)
+ return;
+
+ if (tlb_store[va >> 22].te_pa != -1)
+ return;
+
+ /* round up to nearest 4MB page */
+ size = (len + PAGE_MASK_4M) & ~PAGE_MASK_4M;
+#if 0
+ pa = (vm_offset_t)OF_alloc_phys(PAGE_SIZE_256M, PAGE_SIZE_256M);
+
+ if (pa != -1)
+ free_excess = 1;
+ else
+#endif
+ pa = (vm_offset_t)OF_alloc_phys(size, PAGE_SIZE_256M);
+ if (pa == -1)
+ pa = (vm_offset_t)OF_alloc_phys(size, PAGE_SIZE_4M);
+ if (pa == -1)
+ panic("out of memory");
+
+ for (i = 0; i < size; i += PAGE_SIZE_4M) {
+ mva = (vm_offset_t)OF_claim_virt(va + i, PAGE_SIZE_4M, 0);
+ if (mva != (va + i)) {
+ panic("can't claim virtual page "
+ "(wanted %#lx, got %#lx)",
+ va, mva);
+ }
+
+ tlb_store[mva >> 22].te_pa = pa + i;
+ if ((ret = OF_map_phys(-1, PAGE_SIZE_4M, mva, pa + i)) != 0)
+ printf("OF_map_phys failed: %d\n", ret);
+ }
+ if (free_excess)
+ OF_release_phys((vm_offset_t)pa, PAGE_SIZE_256M);
+}
+
+
/*
* other MD functions
*/
@@ -277,7 +324,7 @@ __elfN(exec)(struct preloaded_file *fp)
entry = e->e_entry;
- OF_release(heapva, HEAPSZ);
+ OF_release((void *)heapva, HEAPSZ);
((kernel_entry_t *)entry)(mdp, 0, 0, 0, openfirmware);
@@ -467,6 +514,7 @@ main(int (*openfirm)(void *))
archsw.arch_copyout = ofw_copyout;
archsw.arch_readin = sparc64_readin;
archsw.arch_autoload = sparc64_autoload;
+ archsw.arch_maphint = sparc64_maphint;
init_heap();
setheap((void *)heapva, (void *)(heapva + HEAPSZ));
@@ -480,6 +528,7 @@ main(int (*openfirm)(void *))
if (!strcmp(compatible, "sun4v")) {
printf("\nBooting with sun4v support.\n");
mmu_ops = &mmu_ops_sun4v;
+ is_sun4v = 1;
} else {
printf("\nBooting with sun4u support.\n");
mmu_ops = &mmu_ops_sun4u;
OpenPOWER on IntegriCloud