| Eric W. Biederman | 70765aa | 2005-06-25 14:58:07 -0700 | [diff] [blame] | 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 | 
| Olaf Hering | ee93b43 | 2005-06-30 02:58:49 -0700 | [diff] [blame] | 37 | mtspr	SPRN_SRR1, r8 | 
| Eric W. Biederman | 70765aa | 2005-06-25 14:58:07 -0700 | [diff] [blame] | 38 | addi	r8, r4, 1f - relocate_new_kernel | 
| Olaf Hering | ee93b43 | 2005-06-30 02:58:49 -0700 | [diff] [blame] | 39 | mtspr	SPRN_SRR0, r8 | 
| Eric W. Biederman | 70765aa | 2005-06-25 14:58:07 -0700 | [diff] [blame] | 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 |  |