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 23relocate_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 37 mtspr SPRN_SRR1, r8 38 addi r8, r4, 1f - relocate_new_kernel 39 mtspr SPRN_SRR0, r8 40 sync 41 rfi 42 431: 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 570: /* top, read another word for the indirection page */ 58 lwzu r0, 4(r3) 59 601: 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 682: /* 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 762: /* are we done? */ 77 rlwinm. r7, r0, 0, 29, 29 /* IND_DONE (1<<2) */ 78 beq 2f 79 b 3f 80 812: /* 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 919: 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 1043: 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 1161: b 1b 117 118relocate_new_kernel_end: 119 120 .globl relocate_new_kernel_size 121relocate_new_kernel_size: 122 .long relocate_new_kernel_end - relocate_new_kernel 123