aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/misc_32.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/misc_32.S')
-rw-r--r--arch/powerpc/kernel/misc_32.S113
1 files changed, 113 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 624a983a9676..01d0d97a16e1 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -5,6 +5,10 @@
5 * Largely rewritten by Cort Dougan (cort@cs.nmt.edu) 5 * Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
6 * and Paul Mackerras. 6 * and Paul Mackerras.
7 * 7 *
8 * kexec bits:
9 * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
10 * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
11 *
8 * This program is free software; you can redistribute it and/or 12 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License 13 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 14 * as published by the Free Software Foundation; either version
@@ -24,6 +28,8 @@
24#include <asm/ppc_asm.h> 28#include <asm/ppc_asm.h>
25#include <asm/thread_info.h> 29#include <asm/thread_info.h>
26#include <asm/asm-offsets.h> 30#include <asm/asm-offsets.h>
31#include <asm/processor.h>
32#include <asm/kexec.h>
27 33
28 .text 34 .text
29 35
@@ -1006,3 +1012,110 @@ _GLOBAL(execve)
1006 */ 1012 */
1007_GLOBAL(__main) 1013_GLOBAL(__main)
1008 blr 1014 blr
1015
1016#ifdef CONFIG_KEXEC
1017 /*
1018 * Must be relocatable PIC code callable as a C function.
1019 */
1020 .globl relocate_new_kernel
1021relocate_new_kernel:
1022 /* r3 = page_list */
1023 /* r4 = reboot_code_buffer */
1024 /* r5 = start_address */
1025
1026 li r0, 0
1027
1028 /*
1029 * Set Machine Status Register to a known status,
1030 * switch the MMU off and jump to 1: in a single step.
1031 */
1032
1033 mr r8, r0
1034 ori r8, r8, MSR_RI|MSR_ME
1035 mtspr SPRN_SRR1, r8
1036 addi r8, r4, 1f - relocate_new_kernel
1037 mtspr SPRN_SRR0, r8
1038 sync
1039 rfi
1040
10411:
1042 /* from this point address translation is turned off */
1043 /* and interrupts are disabled */
1044
1045 /* set a new stack at the bottom of our page... */
1046 /* (not really needed now) */
1047 addi r1, r4, KEXEC_CONTROL_CODE_SIZE - 8 /* for LR Save+Back Chain */
1048 stw r0, 0(r1)
1049
1050 /* Do the copies */
1051 li r6, 0 /* checksum */
1052 mr r0, r3
1053 b 1f
1054
10550: /* top, read another word for the indirection page */
1056 lwzu r0, 4(r3)
1057
10581:
1059 /* is it a destination page? (r8) */
1060 rlwinm. r7, r0, 0, 31, 31 /* IND_DESTINATION (1<<0) */
1061 beq 2f
1062
1063 rlwinm r8, r0, 0, 0, 19 /* clear kexec flags, page align */
1064 b 0b
1065
10662: /* is it an indirection page? (r3) */
1067 rlwinm. r7, r0, 0, 30, 30 /* IND_INDIRECTION (1<<1) */
1068 beq 2f
1069
1070 rlwinm r3, r0, 0, 0, 19 /* clear kexec flags, page align */
1071 subi r3, r3, 4
1072 b 0b
1073
10742: /* are we done? */
1075 rlwinm. r7, r0, 0, 29, 29 /* IND_DONE (1<<2) */
1076 beq 2f
1077 b 3f
1078
10792: /* is it a source page? (r9) */
1080 rlwinm. r7, r0, 0, 28, 28 /* IND_SOURCE (1<<3) */
1081 beq 0b
1082
1083 rlwinm r9, r0, 0, 0, 19 /* clear kexec flags, page align */
1084
1085 li r7, PAGE_SIZE / 4
1086 mtctr r7
1087 subi r9, r9, 4
1088 subi r8, r8, 4
10899:
1090 lwzu r0, 4(r9) /* do the copy */
1091 xor r6, r6, r0
1092 stwu r0, 4(r8)
1093 dcbst 0, r8
1094 sync
1095 icbi 0, r8
1096 bdnz 9b
1097
1098 addi r9, r9, 4
1099 addi r8, r8, 4
1100 b 0b
1101
11023:
1103
1104 /* To be certain of avoiding problems with self-modifying code
1105 * execute a serializing instruction here.
1106 */
1107 isync
1108 sync
1109
1110 /* jump to the entry point, usually the setup routine */
1111 mtlr r5
1112 blrl
1113
11141: b 1b
1115
1116relocate_new_kernel_end:
1117
1118 .globl relocate_new_kernel_size
1119relocate_new_kernel_size:
1120 .long relocate_new_kernel_end - relocate_new_kernel
1121#endif