diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2016-07-24 09:27:09 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2016-08-22 15:26:51 +1000 |
commit | f3ebe66f015e04a2e3a4414d24b3dba90ad3b893 (patch) | |
tree | 97a8ef39592773765faee432ca74c4bee9eb8507 | |
parent | 2ff996194673daf1eee00814c69f588eefb85ef1 (diff) | |
download | skiboot-f3ebe66f015e04a2e3a4414d24b3dba90ad3b893.zip skiboot-f3ebe66f015e04a2e3a4414d24b3dba90ad3b893.tar.gz skiboot-f3ebe66f015e04a2e3a4414d24b3dba90ad3b893.tar.bz2 |
main: Copy all exception vectors down
If we aren't loaded at 0 before relocation, we have no exception
handlers. This is annoying when debugging, but will be deadly
when we start using NAP mode which wakes up via the system reset
interrupt at 0x100.
So instead, let's copy the whole vectors block down. We are careful
to avoid 0..0x100 since that contains the boot flags which are
still "hot" as secondaries might still be entering skiboot.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r-- | asm/head.S | 5 | ||||
-rw-r--r-- | core/init.c | 58 |
2 files changed, 43 insertions, 20 deletions
@@ -95,6 +95,11 @@ attn_trigger: hir_trigger: .long 0 + /* + * At 0x100 and 0x180 reside our entry points. Once started, + * we will ovewrite them with our actual 0x100 exception handler + * used for recovering from rvw or nap mode + */ . = 0x100 /* BML entry, load up r3 with device tree location */ li %r3, 0 diff --git a/core/init.c b/core/init.c index d5e119f..cb49d68 100644 --- a/core/init.c +++ b/core/init.c @@ -49,7 +49,9 @@ enum proc_gen proc_gen; static uint64_t kernel_entry; static bool kernel_32bit; -static char zero_location[16]; + +/* We backup the previous vectors here before copying our own */ +static uint8_t old_vectors[0x2000]; #ifdef SKIBOOT_GCOV void skiboot_gcov_done(void); @@ -355,11 +357,11 @@ static bool load_kernel(void) printf("INIT: Kernel image at 0x%llx\n",kernel_entry); kh = (struct elf_hdr *)kernel_entry; /* - * If the kernel is at 0, copy back what we wrote over - * for the null branch catcher. + * If the kernel is at 0, restore it as it was overwritten + * by our vectors. */ - if (kernel_entry == 0) - memcpy(0, zero_location, 16); + if (kernel_entry < 0x2000) + memcpy(NULL, old_vectors, 0x2000); } else { if (!kernel_size) printf("INIT: Assuming kernel at %p\n", @@ -554,18 +556,6 @@ static void branch_null(void) assert_fail("Branch to NULL !"); } -static void setup_branch_null_catcher(void) -{ - void (*bn)(void) = branch_null; - - /* - * FIXME: This copies the function descriptor (16 bytes) for - * ABI v1 (ie. big endian). This will be broken if we ever - * move to ABI v2 (ie little endian) - */ - memcpy(zero_location, 0, 16); /* Save away in case we need it later */ - memcpy(0, bn, 16); -} typedef void (*ctorcall_t)(void); @@ -578,6 +568,32 @@ static void __nomcount do_ctors(void) (*call)(); } +static void setup_branch_null_catcher(void) +{ + void (*bn)(void) = branch_null; + + /* + * FIXME: This copies the function descriptor (16 bytes) for + * ABI v1 (ie. big endian). This will be broken if we ever + * move to ABI v2 (ie little endian) + */ + memcpy(0, bn, 16); +} + +static void copy_exception_vectors(void) +{ + /* Backup previous vectors as this could contain a kernel + * image. + */ + memcpy(old_vectors, NULL, 0x2000); + + /* Copy from 0x100 to 0x2000, avoid below 0x100 as this is + * the boot flag used by CPUs still potentially entering + * skiboot. + */ + memcpy((void *)0x100, (void *)(SKIBOOT_BASE + 0x100), 0x1f00); + sync_icache(); +} /* Called from head.S, thus no prototype. */ void main_cpu_entry(const void *fdt, u32 master_cpu); @@ -604,11 +620,13 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt, u32 master_cpu) */ clear_console(); - /* Put at 0 an OPD to a warning function in case we branch through - * a NULL function pointer - */ + /* Copy all vectors down to 0 */ + copy_exception_vectors(); + + /* Setup a NULL catcher to catch accidental NULL ptr calls */ setup_branch_null_catcher(); + /* Call library constructors */ do_ctors(); printf("SkiBoot %s starting...\n", version); |