aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2016-07-24 09:27:09 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2016-08-22 15:26:51 +1000
commitf3ebe66f015e04a2e3a4414d24b3dba90ad3b893 (patch)
tree97a8ef39592773765faee432ca74c4bee9eb8507
parent2ff996194673daf1eee00814c69f588eefb85ef1 (diff)
downloadskiboot-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.S5
-rw-r--r--core/init.c58
2 files changed, 43 insertions, 20 deletions
diff --git a/asm/head.S b/asm/head.S
index 4f976b6..f7ccee1 100644
--- a/asm/head.S
+++ b/asm/head.S
@@ -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);