aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2016-07-24 09:27:11 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2016-08-22 15:26:51 +1000
commitad0eb2ca2ca7cab621f990a694746198cbc94ed1 (patch)
tree6e54f3b96625ebdd95fe8e6188c6fbbd51082490
parent3476b2ad3a5a53c92ec5e358dd9c28f5ef09c96d (diff)
downloadskiboot-ad0eb2ca2ca7cab621f990a694746198cbc94ed1.zip
skiboot-ad0eb2ca2ca7cab621f990a694746198cbc94ed1.tar.gz
skiboot-ad0eb2ca2ca7cab621f990a694746198cbc94ed1.tar.bz2
Rename rvwinkle patch to reset patch and install at boot
The patch code itself is unchanged (for now...). Install it during boot so we will be able to use power management instructions. We can't just have a proper exception code built at 0x100 as this is otherwise one of our entry points. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r--asm/head.S10
-rw-r--r--core/init.c16
-rw-r--r--hw/slw.c16
-rw-r--r--include/skiboot.h4
4 files changed, 32 insertions, 14 deletions
diff --git a/asm/head.S b/asm/head.S
index bde6ed2..05715e9 100644
--- a/asm/head.S
+++ b/asm/head.S
@@ -605,10 +605,10 @@ enter_pm_state:
b .
/* This is a little piece of code that is copied down to
- * 0x100 when doing a "rvwinkle reinit"
+ * 0x100 for handling power management wakeups
*/
-.global rvwinkle_patch_start
-rvwinkle_patch_start:
+.global reset_patch_start
+reset_patch_start:
FIXUP_ENDIAN
smt_medium
LOAD_IMM64(%r30, SKIBOOT_BASE)
@@ -616,8 +616,8 @@ rvwinkle_patch_start:
add %r3,%r30,%r3
mtctr %r3
bctr
-.global rvwinkle_patch_end
-rvwinkle_patch_end:
+.global reset_patch_end
+reset_patch_end:
rvwinkle_restore:
/* Get PIR */
diff --git a/core/init.c b/core/init.c
index cb49d68..cc29a3c 100644
--- a/core/init.c
+++ b/core/init.c
@@ -580,6 +580,17 @@ static void setup_branch_null_catcher(void)
memcpy(0, bn, 16);
}
+void setup_reset_vector(void)
+{
+ uint32_t *src, *dst;
+
+ /* Copy the reset code over the entry point. */
+ src = &reset_patch_start;
+ dst = (uint32_t *)0x100;
+ while(src < &reset_patch_end)
+ *(dst++) = *(src++);
+}
+
static void copy_exception_vectors(void)
{
/* Backup previous vectors as this could contain a kernel
@@ -755,6 +766,11 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt, u32 master_cpu)
/* Call in secondary CPUs */
cpu_bringup();
+ /* We can now overwrite the 0x100 vector as we are no longer being
+ * entered there.
+ */
+ setup_reset_vector();
+
/*
* Sycnhronize time bases. Thi resets all the TB values to a small
* value (so they appear to go backward at this point), and synchronize
diff --git a/hw/slw.c b/hw/slw.c
index 9299430..9336679 100644
--- a/hw/slw.c
+++ b/hw/slw.c
@@ -151,17 +151,15 @@ static void slw_do_rvwinkle(void *data)
static void slw_patch_reset(void)
{
- extern uint32_t rvwinkle_patch_start;
- extern uint32_t rvwinkle_patch_end;
uint32_t *src, *dst, *sav;
- BUILD_ASSERT((&rvwinkle_patch_end - &rvwinkle_patch_start) <=
+ BUILD_ASSERT((&reset_patch_end - &reset_patch_start) <=
MAX_RESET_PATCH_SIZE);
- src = &rvwinkle_patch_start;
+ src = &reset_patch_start;
dst = (uint32_t *)0x100;
sav = slw_saved_reset;
- while(src < &rvwinkle_patch_end) {
+ while(src < &reset_patch_end) {
*(sav++) = *(dst);
*(dst++) = *(src++);
}
@@ -170,14 +168,14 @@ static void slw_patch_reset(void)
static void slw_unpatch_reset(void)
{
- extern uint32_t rvwinkle_patch_start;
- extern uint32_t rvwinkle_patch_end;
+ extern uint32_t reset_patch_start;
+ extern uint32_t reset_patch_end;
uint32_t *src, *dst, *sav;
- src = &rvwinkle_patch_start;
+ src = &reset_patch_start;
dst = (uint32_t *)0x100;
sav = slw_saved_reset;
- while(src < &rvwinkle_patch_end) {
+ while(src < &reset_patch_end) {
*(dst++) = *(sav++);
src++;
}
diff --git a/include/skiboot.h b/include/skiboot.h
index f475dd6..1dbe38f 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -196,6 +196,7 @@ extern void __noreturn load_and_boot_kernel(bool is_reboot);
extern void cleanup_tlb(void);
extern void init_shared_sprs(void);
extern void init_replicated_sprs(void);
+extern void setup_reset_vector(void);
/* Various probe routines, to replace with an initcall system */
extern void probe_p7ioc(void);
@@ -271,4 +272,7 @@ extern void fake_rtc_init(void);
/* Assembly in head.S */
extern void enter_pm_state(bool winkle);
+extern uint32_t reset_patch_start;
+extern uint32_t reset_patch_end;
+
#endif /* __SKIBOOT_H */