Commit | Line | Data |
---|---|---|
70765aa4 EB |
1 | /* |
2 | * relocate_kernel.S - put the kernel image in place to boot | |
3 | * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com> | |
4 | * | |
5 | * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz | |
6 | * | |
7 | * This source code is licensed under the GNU General Public License, | |
8 | * Version 2. See the file COPYING for more details. | |
9 | */ | |
10 | ||
11 | #include <asm/reg.h> | |
12 | #include <asm/ppc_asm.h> | |
13 | #include <asm/processor.h> | |
14 | ||
15 | #include <asm/kexec.h> | |
16 | ||
17 | #define PAGE_SIZE 4096 /* must be same value as in <asm/page.h> */ | |
18 | ||
19 | /* | |
20 | * Must be relocatable PIC code callable as a C function. | |
21 | */ | |
22 | .globl relocate_new_kernel | |
23 | relocate_new_kernel: | |
24 | /* r3 = page_list */ | |
25 | /* r4 = reboot_code_buffer */ | |
26 | /* r5 = start_address */ | |
27 | ||
28 | li r0, 0 | |
29 | ||
30 | /* | |
31 | * Set Machine Status Register to a known status, | |
32 | * switch the MMU off and jump to 1: in a single step. | |
33 | */ | |
34 | ||
35 | mr r8, r0 | |
36 | ori r8, r8, MSR_RI|MSR_ME | |
ee93b43a | 37 | mtspr SPRN_SRR1, r8 |
70765aa4 | 38 | addi r8, r4, 1f - relocate_new_kernel |
ee93b43a | 39 | mtspr SPRN_SRR0, r8 |
70765aa4 EB |
40 | sync |
41 | rfi | |
42 | ||
43 | 1: | |
44 | /* from this point address translation is turned off */ | |
45 | /* and interrupts are disabled */ | |
46 | ||
47 | /* set a new stack at the bottom of our page... */ | |
48 | /* (not really needed now) */ | |
49 | addi r1, r4, KEXEC_CONTROL_CODE_SIZE - 8 /* for LR Save+Back Chain */ | |
50 | stw r0, 0(r1) | |
51 | ||
52 | /* Do the copies */ | |
53 | li r6, 0 /* checksum */ | |
54 | mr r0, r3 | |
55 | b 1f | |
56 | ||
57 | 0: /* top, read another word for the indirection page */ | |
58 | lwzu r0, 4(r3) | |
59 | ||
60 | 1: | |
61 | /* is it a destination page? (r8) */ | |
62 | rlwinm. r7, r0, 0, 31, 31 /* IND_DESTINATION (1<<0) */ | |
63 | beq 2f | |
64 | ||
65 | rlwinm r8, r0, 0, 0, 19 /* clear kexec flags, page align */ | |
66 | b 0b | |
67 | ||
68 | 2: /* is it an indirection page? (r3) */ | |
69 | rlwinm. r7, r0, 0, 30, 30 /* IND_INDIRECTION (1<<1) */ | |
70 | beq 2f | |
71 | ||
72 | rlwinm r3, r0, 0, 0, 19 /* clear kexec flags, page align */ | |
73 | subi r3, r3, 4 | |
74 | b 0b | |
75 | ||
76 | 2: /* are we done? */ | |
77 | rlwinm. r7, r0, 0, 29, 29 /* IND_DONE (1<<2) */ | |
78 | beq 2f | |
79 | b 3f | |
80 | ||
81 | 2: /* is it a source page? (r9) */ | |
82 | rlwinm. r7, r0, 0, 28, 28 /* IND_SOURCE (1<<3) */ | |
83 | beq 0b | |
84 | ||
85 | rlwinm r9, r0, 0, 0, 19 /* clear kexec flags, page align */ | |
86 | ||
87 | li r7, PAGE_SIZE / 4 | |
88 | mtctr r7 | |
89 | subi r9, r9, 4 | |
90 | subi r8, r8, 4 | |
91 | 9: | |
92 | lwzu r0, 4(r9) /* do the copy */ | |
93 | xor r6, r6, r0 | |
94 | stwu r0, 4(r8) | |
95 | dcbst 0, r8 | |
96 | sync | |
97 | icbi 0, r8 | |
98 | bdnz 9b | |
99 | ||
100 | addi r9, r9, 4 | |
101 | addi r8, r8, 4 | |
102 | b 0b | |
103 | ||
104 | 3: | |
105 | ||
106 | /* To be certain of avoiding problems with self-modifying code | |
107 | * execute a serializing instruction here. | |
108 | */ | |
109 | isync | |
110 | sync | |
111 | ||
112 | /* jump to the entry point, usually the setup routine */ | |
113 | mtlr r5 | |
114 | blrl | |
115 | ||
116 | 1: b 1b | |
117 | ||
118 | relocate_new_kernel_end: | |
119 | ||
120 | .globl relocate_new_kernel_size | |
121 | relocate_new_kernel_size: | |
122 | .long relocate_new_kernel_end - relocate_new_kernel | |
123 |