summaryrefslogtreecommitdiffstats
path: root/sys/powerpc/booke
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2015-03-07 20:14:46 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2015-03-07 20:14:46 +0000
commitfd67077071422de4142fee1a503eb3f51ae23a26 (patch)
tree4f8a9355bf11c3502e46145775f18a5dc72d52f1 /sys/powerpc/booke
parent4388fb8eb58edb77cefd62079e82719ee96cc09e (diff)
downloadFreeBSD-src-fd67077071422de4142fee1a503eb3f51ae23a26.zip
FreeBSD-src-fd67077071422de4142fee1a503eb3f51ae23a26.tar.gz
Make 32-bit PowerPC kernels, like 64-bit PowerPC kernels, position-independent
executables. The goal here, not yet accomplished, is to let the e500 kernel run under QEMU by setting KERNBASE to something that fits in low memory and then having the kernel relocate itself at runtime.
Diffstat (limited to 'sys/powerpc/booke')
-rw-r--r--sys/powerpc/booke/locore.S64
-rw-r--r--sys/powerpc/booke/pmap.c4
-rw-r--r--sys/powerpc/booke/trap_subr.S20
3 files changed, 59 insertions, 29 deletions
diff --git a/sys/powerpc/booke/locore.S b/sys/powerpc/booke/locore.S
index 9d00327..37860e5 100644
--- a/sys/powerpc/booke/locore.S
+++ b/sys/powerpc/booke/locore.S
@@ -205,11 +205,29 @@ done_mapping:
/*
* Setup a temporary stack
*/
- lis %r1, tmpstack@ha
- addi %r1, %r1, tmpstack@l
+ bl 1f
+ .long tmpstack-.
+1: mflr %r1
+ lwz %r2,0(%r1)
+ add %r1,%r1,%r2
addi %r1, %r1, (TMPSTACKSZ - 16)
/*
+ * Relocate kernel
+ */
+ bl 1f
+ .long _DYNAMIC-.
+ .long _GLOBAL_OFFSET_TABLE_-.
+1: mflr %r5
+ lwz %r3,0(%r5) /* _DYNAMIC in %r3 */
+ add %r3,%r3,%r5
+ lwz %r4,4(%r5) /* GOT pointer */
+ add %r4,%r4,%r5
+ lwz %r4,4(%r4) /* got[0] is _DYNAMIC link addr */
+ subf %r4,%r4,%r3 /* subtract to calculate relocbase */
+ bl elf_reloc_self
+
+/*
* Initialise exception vector offsets
*/
bl ivor_setup
@@ -338,10 +356,13 @@ bp_tlb1_end:
blt 4b
/* Switch to the final mapping */
- lis %r5, __boot_page@ha
- ori %r5, %r5, __boot_page@l
bl 5f
-5: mflr %r3
+ .long __boot_page-.
+5: mflr %r5
+ lwz %r3,0(%r3)
+ add %r5,%r5,%r3 /* __boot_page in r5 */
+ bl 6f
+6: mflr %r3
rlwinm %r3, %r3, 0, 0xfff /* Offset from boot page start */
add %r3, %r3, %r5 /* Make this virtual address */
addi %r3, %r3, 32
@@ -365,8 +386,11 @@ bp_tlb1_end:
/*
* Setup a temporary stack
*/
- lis %r1, tmpstack@ha
- addi %r1, %r1, tmpstack@l
+ bl 1f
+ .long tmpstack-.
+1: mflr %r1
+ lwz %r2,0(%r1)
+ add %r1,%r1,%r2
addi %r1, %r1, (TMPSTACKSZ - 16)
/*
@@ -377,8 +401,11 @@ bp_tlb1_end:
/*
* Assign our pcpu instance
*/
- lis %r3, ap_pcpu@h
- ori %r3, %r3, ap_pcpu@l
+ bl 1f
+ .long ap_pcpu-.
+1: mflr %r4
+ lwz %r3, 0(%r4)
+ add %r3, %r3, %r4
lwz %r3, 0(%r3)
mtsprg0 %r3
@@ -543,24 +570,14 @@ __boot_page_padding:
* dedicated for cases when invalidation(s) should NOT be propagated to other
* CPUs.
*
- * Global vars tlb0_ways, tlb0_entries_per_way are assumed to have been set up
- * correctly (by tlb0_get_tlbconf()).
+ * void tid_flush(tlbtid_t tid, int tlb0_ways, int tlb0_entries_per_way);
*
+ * XXX: why isn't this in C?
*/
ENTRY(tid_flush)
cmpwi %r3, TID_KERNEL
beq tid_flush_end /* don't evict kernel translations */
- /* Number of TLB0 ways */
- lis %r4, tlb0_ways@h
- ori %r4, %r4, tlb0_ways@l
- lwz %r4, 0(%r4)
-
- /* Number of entries / way */
- lis %r5, tlb0_entries_per_way@h
- ori %r5, %r5, tlb0_entries_per_way@l
- lwz %r5, 0(%r5)
-
/* Disable interrupts */
mfmsr %r10
wrteei 0
@@ -718,6 +735,11 @@ setfault:
/* Data section */
/************************************************************************/
.data
+ .align 3
+GLOBAL(__startkernel)
+ .long begin
+GLOBAL(__endkernel)
+ .long end
.align 4
tmpstack:
.space TMPSTACKSZ
diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c
index 5ee5b0a..573364a 100644
--- a/sys/powerpc/booke/pmap.c
+++ b/sys/powerpc/booke/pmap.c
@@ -159,7 +159,7 @@ unsigned int kernel_ptbls; /* Number of KVA ptbls. */
#define PMAP_REMOVE_DONE(pmap) \
((pmap) != kernel_pmap && (pmap)->pm_stats.resident_count == 0)
-extern void tid_flush(tlbtid_t);
+extern void tid_flush(tlbtid_t tid, int tlb0_ways, int tlb0_entries_per_way);
extern int elf32_nxstack;
/**************************************************************************/
@@ -2818,7 +2818,7 @@ tid_alloc(pmap_t pmap)
tidbusy[thiscpu][tid]->pm_tid[thiscpu] = TID_NONE;
/* Flush all entries from TLB0 matching this TID. */
- tid_flush(tid);
+ tid_flush(tid, tlb0_ways, tlb0_entries_per_way);
}
tidbusy[thiscpu][tid] = pmap;
diff --git a/sys/powerpc/booke/trap_subr.S b/sys/powerpc/booke/trap_subr.S
index 7576449..bc6bad3 100644
--- a/sys/powerpc/booke/trap_subr.S
+++ b/sys/powerpc/booke/trap_subr.S
@@ -542,8 +542,11 @@ INTERRUPT(int_data_tlb_error)
search_kernel_pmap:
/* Load r26 with kernel_pmap address */
- lis %r26, kernel_pmap_store@h
- ori %r26, %r26, kernel_pmap_store@l
+ bl 1f
+ .long kernel_pmap_store-.
+1: mflr %r21
+ lwz %r26, 0(%r21)
+ add %r26, %r21, %r26 /* kernel_pmap_store in r26 */
/* Force kernel tid, set TID to 0 in MAS1. */
li %r21, 0
@@ -737,12 +740,17 @@ INTERRUPT(int_debug)
FRAME_SETUP(SPR_SPRG2, PC_BOOKE_CRITSAVE, EXC_DEBUG)
GET_CPUINFO(%r3)
lwz %r3, (PC_BOOKE_CRITSAVE+CPUSAVE_SRR0)(%r3)
- lis %r4, interrupt_vector_base@ha
- addi %r4, %r4, interrupt_vector_base@l
+ bl 0f
+ .long interrupt_vector_base-.
+ .long interrupt_vector_top-.
+0: mflr %r5
+ lwz %r4,0(%r5) /* interrupt_vector_base in r4 */
+ add %r4,%r4,%r5
cmplw cr0, %r3, %r4
blt 1f
- lis %r4, interrupt_vector_top@ha
- addi %r4, %r4, interrupt_vector_top@l
+ lwz %r4,4(%r5) /* interrupt_vector_top in r4 */
+ add %r4,%r4,%r5
+ addi %r4,%r4,4
cmplw cr0, %r3, %r4
bge 1f
/* Disable single-stepping for the interrupt handlers. */
OpenPOWER on IntegriCloud