diff options
Diffstat (limited to 'arch/powerpc/kernel/misc_32.S')
-rw-r--r-- | arch/powerpc/kernel/misc_32.S | 113 |
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 | ||
1021 | relocate_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 | |||
1041 | 1: | ||
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 | |||
1055 | 0: /* top, read another word for the indirection page */ | ||
1056 | lwzu r0, 4(r3) | ||
1057 | |||
1058 | 1: | ||
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 | |||
1066 | 2: /* 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 | |||
1074 | 2: /* are we done? */ | ||
1075 | rlwinm. r7, r0, 0, 29, 29 /* IND_DONE (1<<2) */ | ||
1076 | beq 2f | ||
1077 | b 3f | ||
1078 | |||
1079 | 2: /* 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 | ||
1089 | 9: | ||
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 | |||
1102 | 3: | ||
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 | |||
1114 | 1: b 1b | ||
1115 | |||
1116 | relocate_new_kernel_end: | ||
1117 | |||
1118 | .globl relocate_new_kernel_size | ||
1119 | relocate_new_kernel_size: | ||
1120 | .long relocate_new_kernel_end - relocate_new_kernel | ||
1121 | #endif | ||