Ticket #11: user_mode.diff
File user_mode.diff, 46.8 KB (added by , 14 years ago) |
---|
-
hexo/include/hexo/interrupt.h
103 103 104 104 /************************************************************ exceptions */ 105 105 106 #define CPU_EXCEPTION_ILLEGAL_INS 0x1 107 #define CPU_EXCEPTION_DATA_ERROR 0x2 108 #define CPU_EXCEPTION_INS_ERROR 0x3 109 #define CPU_EXCEPTION_DATA_ALIGN 0x4 110 #define CPU_EXCEPTION_OTHER 0x5 111 112 106 113 /** CPU exception handler function template 107 114 @see cpu_exception_handler_t 108 115 @showcontent -
hexo/include/hexo/asm.h
1 /* 2 * This file is part of MutekH. 3 * 4 * MutekH is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU Lesser General Public License as published 6 * by the Free Software Foundation; version 2.1 of the License. 7 * 8 * MutekH is distributed in the hope that it will be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * Lesser General Public License for more details. 12 * 13 * You should have received a copy of the GNU Lesser General Public 14 * License along with MutekH; if not, write to the Free Software 15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 16 * 02110-1301 USA 17 * 18 * Copyright (c) UPMC, Lip6, SoC 19 * Nicolas Pouillon <nipo@ssji.net>, 2010 20 */ 21 22 #ifndef HEXO_ASM_H_ 23 #define HEXO_ASM_H_ 24 25 #define ASM_STR_(x) #x 26 #define ASM_STR(x) ASM_STR_(x) 27 28 #define FUNC_START(x) \ 29 "\t.globl " #x " \n" \ 30 "\t.func " #x " \n" \ 31 "\t.type " #x ", %function \n" \ 32 #x ": \n" 33 34 #define FUNC_END(x) \ 35 "\t.endfunc \n" \ 36 "\t.size " #x ", .-" #x " \n" 37 38 #endif -
hexo/user_mode.c
Property changes on: hexo/include/hexo/asm.h ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:keywords + "Author Date Id Rev URL Revision" Added: svn:eol-style + native
1 /* 2 * This file is part of MutekH. 3 * 4 * MutekH is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU Lesser General Public License as published 6 * by the Free Software Foundation; version 2.1 of the License. 7 * 8 * MutekH is distributed in the hope that it will be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * Lesser General Public License for more details. 12 * 13 * You should have received a copy of the GNU Lesser General Public 14 * License along with MutekH; if not, write to the Free Software 15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 16 * 02110-1301 USA 17 * 18 * Copyright (c) UPMC, Lip6, SoC 19 * Nicolas Pouillon <nipo@ssji.net>, 2010 20 */ 21 22 #include <hexo/types.h> 23 #include <hexo/local.h> 24 25 /** 26 Pointer to base of kernel stack associated to a user-mode thread 27 */ 28 CONTEXT_LOCAL uintptr_t context_kstack; -
hexo/Makefile
Property changes on: hexo/user_mode.c ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:keywords + "Author Date Id Rev URL Revision" Added: svn:eol-style + native
8 8 objs += ipi.o 9 9 endif 10 10 11 ifeq ($(CONFIG_CPU_USER), defined) 12 objs += user_mode.o 13 endif 14 11 15 ifeq ($(CONFIG_HEXO_IRQ), defined) 12 16 objs += interrupt.o 13 17 endif -
cpu/ppc/exception.c
15 15 along with MutekH; if not, write to the Free Software Foundation, 16 16 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 17 18 Copyright (c) Nicolas Pouillon <nipo@ssji.net>, 2009 19 18 Copyright (c) 2009-2010, Nicolas Pouillon <nipo@ssji.net> 20 19 */ 21 20 21 #include <hexo/asm.h> 22 #include <hexo/interrupt.h> 23 24 #define GET_SPRREL(name, rd, rt, spr) \ 25 "mfspr " #rt ", " #spr " \n\t" \ 26 "lwz " #rd ", " name "(" #rt ") \n\t" 27 #define GET_ABS(name, rd, rt) \ 28 "lis " #rt ", " name "@ha \n\t" \ 29 "lwz " #rd ", " name "@l(" #rt ") \n\t" 30 #define LA(rd, name) \ 31 "lis " #rd ", (" #name ")@h \n\t" \ 32 "ori " #rd ", " #rd ", (" #name ")@l\n\t" 33 34 #ifdef CONFIG_SMP 35 # define CPULOCAL_GET(name, rd, rt) GET_SPRREL(name, rd, rt, 0x105) 36 #else 37 # define CPULOCAL_GET(name, rd, rt) GET_ABS(name, rd) 38 #endif 39 40 #define CONTEXTLOCAL_GET(name, rd, rt) GET_SPRREL(name, rd, rt, 0x104) 41 42 43 #define SPRG0 "0x110" 44 #define SPRG1 "0x111" 45 46 #define DO_REG_2_3(op, n, off) \ 47 #op " 2, " #off "+4* 0(" #n ") \n\t" \ 48 #op " 3, " #off "+4* 1(" #n ") \n\t" 49 50 #define DO_REG_4_12(op, n, off) \ 51 #op " 4, " #off "+4* 0(" #n ") \n\t" \ 52 #op " 5, " #off "+4* 1(" #n ") \n\t" \ 53 #op " 6, " #off "+4* 2(" #n ") \n\t" \ 54 #op " 7, " #off "+4* 3(" #n ") \n\t" \ 55 #op " 8, " #off "+4* 4(" #n ") \n\t" \ 56 #op " 9, " #off "+4* 5(" #n ") \n\t" \ 57 #op " 10, " #off "+4* 6(" #n ") \n\t" \ 58 #op " 11, " #off "+4* 7(" #n ") \n\t" \ 59 #op " 12, " #off "+4* 8(" #n ") \n\t" 60 61 #define DO_REG_2_12(op, n, off) \ 62 DO_REG_2_3(op, n, off) \ 63 DO_REG_4_12(op, n, off+8) 64 65 22 66 /* 23 ".section \".ppc_special." #name "\",\"ax\",@progbits \n\t" 24 ".globl ppc_special_" #name "_entry \n\t" 25 ".type ppc_special_" #name "_entry, @function \n" 26 "ppc_special_" #name "_entry: \n\t" 27 "stwu 1, -16(1) \n\t" 28 "stw 0, 8(1) \n\t" 29 "mflr 0 \n\t" 30 "stw 0, 12(1) \n\t" 31 "bl " #func "\n\t" 32 "lwz 0, 12(1) \n\t" 33 "mtlr 0 \n\t" 34 "lwz 0, 8(1) \n\t" 35 "addi 1, 1, 16 \n\t" 36 #ret_ins "\n\t" 37 ".size ppc_special_" #name "_entry, .-ppc_special_" #name "_entry \n\t" 38 */ 67 (cls / tls are r/o for user, no need to restore) 39 68 40 #define SAVE_REG_2_12(n, off) \ 41 "stw 2, " #off "+4* 0(" #n ") \n\t" \42 "stw 3, " #off "+4* 1(" #n ") \n\t" \43 "stw 4, " #off "+4* 2(" #n ") \n\t" \44 "stw 5, " #off "+4* 3(" #n ") \n\t" \45 "stw 6, " #off "+4* 4(" #n ") \n\t" \46 "stw 7, " #off "+4* 5(" #n ") \n\t" \47 "stw 8, " #off "+4* 6(" #n ") \n\t" \48 "stw 9, " #off "+4* 7(" #n ") \n\t" \49 "stw 10, " #off "+4* 8(" #n ") \n\t" \50 "stw 11, " #off "+4* 9(" #n ") \n\t" \51 "stw 12, " #off "+4*10(" #n ") \n\t"69 Whatever the exception, we need to: 70 * copy r0, r1 -> sprg0, sprg1 71 * save cr to r0 72 * get cpu "previous" mode 73 * if from kernel 74 * copy back r1 from sprg1 75 * if from user 76 * get task's kernel stack to r1 77 * reserve 32+5 registers 78 * put cr (r0) 79 * put exception type in r0 80 * put srr0/2 (PC), srr1/3 (msr) 52 81 53 #define RESTORE_REG_2_12(n, off) \ 54 "lwz 2, " #off "+4* 0(" #n ") \n\t" \55 "lwz 3, " #off "+4* 1(" #n ") \n\t" \56 "lwz 4, " #off "+4* 2(" #n ") \n\t" \57 "lwz 5, " #off "+4* 3(" #n ") \n\t" \58 "lwz 6, " #off "+4* 4(" #n ") \n\t" \59 "lwz 7, " #off "+4* 5(" #n ") \n\t" \60 "lwz 8, " #off "+4* 6(" #n ") \n\t" \61 "lwz 9, " #off "+4* 7(" #n ") \n\t" \62 "lwz 10, " #off "+4* 8(" #n ") \n\t" \63 "lwz 11, " #off "+4* 9(" #n ") \n\t" \64 "lwz 12, " #off "+4*10(" #n ") \n\t"82 Generic part: 83 * put ctr, lr 84 * put sprg[01] on stack 85 * put gpr 2-12 on stack 86 * (put gpr 13-31 on stack) 87 * handle exception 88 * restore ctr, cr, lr, srr0 (PC), srr1 (msr) 89 * (restore gpr 13-31) 90 * restore gpr 2-12 91 * load r0 from *sp 92 * load sp from *sp 93 * rfi 65 94 66 #ifdef CONFIG_SMP 67 # define GET_HANDLER_ADDRESS(name, rd, rt, spr) \ 68 "mfspr " #rt ", " #spr " \n\t" \ 69 "lwz " #rd ", " name "(" #rt ") \n\t" 95 stack layout: 96 0 1 2 3 4 5 6 37 97 [sp] [ctr] [lr] [cr] [srr0/pc] [srr1/msr] [r0 .. r31] 98 */ 99 100 #if defined(CONFIG_USER_MODE) 101 # define GET_STACK_SAVE_CR \ 102 /* put msr in cr and do bit test (user mode) */ \ 103 "mf" #msr_srr " 1 \n\t" \ 104 "mtcr 1 \n\t" \ 105 "bt 17, 1f \n\t" \ 106 /* from kernel */ \ 107 "mfspr 1, " SPRG1 " \n\t" \ 108 "stwu 1, -38*4(1) \n\t" \ 109 "stw 0, 3 *4(1) \n\t" \ 110 "b 2f \n\t" \ 111 "1: \n\t" \ 112 CONTEXTLOCAL_GET("context_kstack", 1, 1) \ 113 "addi 1, -38*4(1) \n\t" \ 114 /* save cr */ \ 115 "stw 0, 3 *4(1) \n\t" \ 116 /* save old sp */ \ 117 "mfspr 0, " SPRG1 " \n\t" \ 118 "stw 0, 0 *4(1) \n\t" \ 119 "2: \n\t" 70 120 #else 71 # define GET_HANDLER_ADDRESS(name, rd, rt, foo) \ 72 "lis " #rt ", " name "@ha \n\t" \ 73 "lwz " #rd ", " name "@l(" #rt ") \n\t" 121 # define GET_STACK_SAVE_CR \ 122 "stwu 1, -38*4(1) \n\t" \ 123 /* save cr */ \ 124 "stw 0, 3 *4(1) \n\t" 74 125 #endif 75 126 76 # define GET_CPULOCAL_HANDLER_ADDRESS(name, rd, rt) GET_HANDLER_ADDRESS(name, rd, rt, 0x105) 77 # define GET_CONTEXTLOCAL_HANDLER_ADDRESS(name, rd, rt) GET_HANDLER_ADDRESS(name, rd, rt, 0x104) 127 #define prepare_exception(pc_srr, msr_srr) \ 128 "mtspr " SPRG0 ", 0 \n\t" \ 129 "mtspr " SPRG1 ", 1 \n\t" \ 130 "mfcr 0 \n\t" \ 131 GET_STACK_SAVE_CR \ 132 /* pc */ \ 133 "mf" #pc_srr " 0 \n\t" \ 134 "stw 0, 4 *4(1) \n\t" \ 135 /* srr1 */ \ 136 "mf" #msr_srr " 0 \n\t" \ 137 "stw 0, 5 *4(1) \n\t" \ 138 /* ctr */ \ 139 "mfctr 0 \n\t" \ 140 "stw 0, 1 *4(1) \n\t" 78 141 79 #define HANDLE_EXCEPTION(eno, srr02) \ 80 /* r1 -> @0 */ \ 81 "stwu 1,-4*22(1) \n\t" \ 82 /* r0 -> @3 */ \ 83 "stw 0, 4* 7(1) \n\t" \ 84 /* lr -> @19 */ \ 85 "mflr 0 \n\t" \ 86 "stw 0, 4*19(1) \n\t" \ 87 /* cr -> @21 */ \ 88 "mfcr 0 \n\t" \ 89 "stw 0, 4*21(1) \n\t" \ 90 /* r2-r12 -> @8-18 */ \ 91 SAVE_REG_2_12(1, 32) \ 92 \ 93 /* ctr -> @20 */ \ 94 "mfctr 0 \n\t" \ 95 "stw 0, 4*20(1) \n\t" \ 96 \ 97 GET_CPULOCAL_HANDLER_ADDRESS("cpu_exception_handler", 0, 3) \ 98 "mtctr 0 \n\t" \ 99 \ 100 /* Put handler arguments: */ \ 101 /* a0: type */ \ 102 /* a1: execptr (srr) */ \ 103 /* a2: dataptr (dear) */ \ 104 /* a3: regtable (sp + 7*4) */ \ 105 /* a4: sp (sp + 22*4) */ \ 106 "li 3, " #eno " \n\t" \ 107 "mfsrr" #srr02 " 4 \n\t" \ 108 "mfspr 5, 981 \n\t" \ 109 "addi 6, 1, 4* 7 \n\t" \ 110 "addi 7, 1, 4*22 \n\t" \ 111 \ 112 "bctrl \n\t" \ 113 \ 114 /* ctr -> @20 */ \ 115 "lwz 0, 4*20(1) \n\t" \ 116 "mtctr 0 \n\t" \ 117 \ 118 /* r2-r12 -> @8-18 */ \ 119 RESTORE_REG_2_12(1, 32) \ 120 \ 121 /* lr -> @19 */ \ 122 "lwz 0, 4*19(1) \n\t" \ 123 "mtlr 0 \n\t" \ 124 \ 125 /* cr -> @21 */ \ 126 "lwz 0, 4*21(1) \n\t" \ 127 "mtcr 0 \n\t" \ 128 \ 129 /* r0 -> @7 */ \ 130 "lwz 0, 4* 7(1) \n\t" \ 131 /* r1 -> @0 */ \ 132 "addi 1, 1, 4*18 \n\t" 142 #define handle_exception(name) \ 143 LA(0, exception_common) \ 144 "mtctr 0 \n\t" \ 145 /* exc type */ \ 146 "li 0, " ASM_STR(name) " \n\t" \ 147 "bctr \n\t" 133 148 134 asm( 135 ".section .excep,\"ax\",@progbits \n" 149 #define CRASH(x, y) \ 150 prepare_exception(x, y) \ 151 handle_exception(CPU_EXCEPTION_OTHER) 136 152 137 /* critical interrupt (critical, async) */ 138 ".org 0x100\n" 153 #define handle_interrupt(no) \ 154 LA(0, interrupt_common) \ 155 "mtctr 0 \n\t" \ 156 "li 0, " #no " \n\t" \ 157 "bctr \n\t" 139 158 140 /* machine check (critical, async, imprecise) */ 141 ".org 0x200\n" 142 ".globl ppc_special_machine_check_entry \n\t" 143 ".type ppc_special_machine_check_entry, @function \n" 144 "ppc_special_machine_check_entry: \n\t" 145 HANDLE_EXCEPTION(3, 2) 146 "rfci \n\t" 147 ".size ppc_special_machine_check_entry, .-ppc_special_machine_check_entry \n\t" 159 #define handle_syscall() \ 160 LA(0, syscall_common) \ 161 "mtctr 0 \n\t" 148 162 149 /* data storage */ 150 ".org 0x300\n" 151 ".globl ppc_special_data_storage_entry \n\t" 152 ".type ppc_special_data_storage_entry, @function \n" 153 "ppc_special_data_storage_entry: \n\t" 154 HANDLE_EXCEPTION(4, 0) 155 "rfi \n\t" 156 ".size ppc_special_data_storage_entry, .-ppc_special_data_storage_entry \n\t" 163 asm(".section .text,\"ax\",@progbits \n" 157 164 158 /* instr storage */ 159 ".org 0x400\n" 160 ".globl ppc_special_instr_storage_entry \n\t" 161 ".type ppc_special_instr_storage_entry, @function \n" 162 "ppc_special_instr_storage_entry: \n\t" 163 HANDLE_EXCEPTION(5, 0) 164 "rfi \n\t" 165 ".size ppc_special_instr_storage_entry, .-ppc_special_instr_storage_entry \n\t" 165 FUNC_START(exception_common) 166 DO_REG_2_12(stw, 1, 8*4) 167 /* lr */ 168 "mflr 3 \n\t" 169 "stw 3, 2 *4(1) \n\t" 170 /* r0 */ 171 "mfspr 3, " SPRG0 " \n\t" 172 "stw 3, 6 *4(1) \n\t" 173 /* r1 */ 174 "mfspr 3, " SPRG1 " \n\t" 175 "stw 3, 7 *4(1) \n\t" 176 /* Put handler arguments: */ 177 /* a0: type */ 178 /* a1: execptr (srr) */ 179 /* a2: dataptr (dear) */ 180 /* a3: regtable (sp + 6*4) */ 181 /* a4: sp (sp + 22*4) */ 182 "or 3, 0, 0 \n\t" 183 "lwz 4, 4 *4(1) \n\t" 184 "addi 6, 1, 6*4 \n\t" 185 "lwz 7, 7 *4(1) \n\t" 166 186 167 /* external (async) */ 168 ".org 0x500\n" 169 ".globl ppc_special_external_entry \n\t" 170 ".type ppc_special_external_entry, @function \n" 171 "ppc_special_external_entry: \n\t" 172 /* r1 -> @0 */ 173 "stwu 1,-4*18(1) \n\t" 174 /* r0 -> @3 */ 175 "stw 0, 4* 3(1) \n\t" 176 /* lr -> @15 */ 177 "mflr 0 \n\t" 178 "stw 0, 4*15(1) \n\t" 179 /* cr -> @17 */ 180 "mfcr 0 \n\t" 181 "stw 0, 4*17(1) \n\t" 182 /* r2-r12 -> @4-14 */ 183 SAVE_REG_2_12(1, 16) 187 /* 188 * dont use 0 as 3rd arg, or you'll get crappy things, 189 * hijack r5 and do mfdear afterwards 190 */ 191 CPULOCAL_GET("cpu_exception_handler", 0, 5) 192 "mtctr 0 \n\t" 193 "mfdear 5 \n\t" 184 194 185 /* ctr -> @16 */ 186 "mfctr 0 \n\t" 187 "stw 0, 4*16(1) \n\t" 195 /* Call the exception handler */ 196 "bctrl \n\t" 197 "b back_from_exception \n\t" 198 FUNC_END(exception_common) 188 199 189 GET_CPULOCAL_HANDLER_ADDRESS("cpu_interrupt_handler", 0, 3)190 "mtctr 0 \n\t"191 200 192 GET_CPULOCAL_HANDLER_ADDRESS("cpu_interrupt_handler_arg", 3, 3)193 201 194 /* interrupt line is 0 */ 195 "li 4, 0 \n\t" 202 FUNC_START(interrupt_common) 203 DO_REG_2_12(stw, 1, 8*4) 204 /* lr */ 205 "mflr 3 \n\t" 206 "stw 3, 2 *4(1) \n\t" 207 /* r0 */ 208 "mfspr 3, " SPRG0 " \n\t" 209 "stw 3, 6 *4(1) \n\t" 210 /* r1 */ 211 "mfspr 3, " SPRG1 " \n\t" 212 "stw 3, 7 *4(1) \n\t" 213 /* Put handler arguments: */ 214 /* a0: priv */ 215 /* a1: irq */ 196 216 197 "bctrl \n\t" 217 CPULOCAL_GET("cpu_interrupt_handler", 5, 5) 218 CPULOCAL_GET("cpu_interrupt_handler_arg", 3, 3) 219 "or 4, 0, 0 \n\t" 220 "mtctr 5 \n\t" 198 221 199 /* ctr -> @16 */ 200 "lwz 0, 4*16(1) \n\t" 201 "mtctr 0 \n\t" 222 /* Call the interrupt handler */ 223 "bctrl \n\t" 224 "b back_from_exception \n\t" 225 FUNC_END(interrupt_common) 202 226 203 /* r2-r12 -> @4-14 */204 RESTORE_REG_2_12(1, 16)205 227 206 /* lr -> @15 */207 "lwz 0, 4*15(1) \n\t"208 "mtlr 0 \n\t"209 228 210 /* cr -> @17 */ 211 "lwz 0, 4*17(1) \n\t" 212 "mtcr 0 \n\t" 229 FUNC_START(syscall_common) 230 DO_REG_2_12(stw, 1, 8*4) 231 /* ctr */ 232 "mfctr 3 \n\t" 233 "stw 3, 1 *4(1) \n\t" 234 /* lr */ 235 "mflr 3 \n\t" 236 "stw 3, 2 *4(1) \n\t" 237 /* r0 */ 238 "mfspr 3, " SPRG0 " \n\t" 239 "stw 3, 6 *4(1) \n\t" 240 /* r1 */ 241 "mfspr 3, " SPRG1 " \n\t" 242 "stw 3, 7 *4(1) \n\t" 243 /* Put handler arguments: */ 244 /* a0: number */ 245 /* a1: regtable */ 213 246 214 /* r0 -> @3 */ 215 "lwz 0, 4* 3(1) \n\t" 216 /* r1 -> @0 */ 217 "addi 1, 1, 4*18 \n\t" 247 CPULOCAL_GET("cpu_syscall_handler", 5, 5) 248 "mtctr 5 \n\t" 218 249 219 "rfi\n\t"220 ".size ppc_special_external_entry, .-ppc_special_external_entry\n\t"250 "li 3, 0 \n\t" 251 "addi 6, 1, 6*4 \n\t" 221 252 253 /* Call the syscall handler */ 254 "bctrl \n\t" 255 "b back_from_syscall \n\t" 256 FUNC_END(syscall_common) 222 257 223 /* alignment */224 ".org 0x600\n"225 ".globl ppc_special_alignment_entry \n\t"226 ".type ppc_special_alignment_entry, @function \n"227 "ppc_special_alignment_entry: \n\t"228 HANDLE_EXCEPTION(2, 0)229 "rfi \n\t"230 ".size ppc_special_alignment_entry, .-ppc_special_alignment_entry \n\t"231 258 232 /* program */233 ".org 0x700\n"234 ".globl ppc_special_program_entry \n\t"235 ".type ppc_special_program_entry, @function \n"236 "ppc_special_program_entry: \n\t"237 HANDLE_EXCEPTION(1, 0)238 "rfi \n\t"239 ".size ppc_special_program_entry, .-ppc_special_program_entry \n\t"240 259 241 /* fpu unusable */242 ".org 0x800\n"243 260 244 /* syscall */245 ".org 0xc00\n"246 ".globl ppc_special_syscall_entry \n\t"247 ".type ppc_special_syscall_entry, @function \n"248 "ppc_special_syscall_entry: \n\t"249 "stwu 1, -4*15(1) \n\t"250 "stw 0, 4* 1(1) \n\t"251 261 252 SAVE_REG_2_12(1, 16) 262 FUNC_START(back_from_exception) 263 DO_REG_4_12(lwz, 1, 10*4) 253 264 254 /* Put syscall number on first arg */ 255 "or 3, 0, 0 \n\t" 256 "mflr 0 \n\t" 257 "stw 0, 4*13(1) \n\t" 265 /* Dont restore reg 4 to 12 for syscall return */ 266 "back_from_syscall: \n\t" 267 DO_REG_2_3(lwz, 1, 8*4) 258 268 259 "mfctr 0 \n\t" 260 "stw 0, 4*14(1) \n\t" 269 /* ctr */ 270 "lwz 0, 1 *4(1) \n\t" 271 "mtctr 0 \n\t" 272 /* lr */ 273 "lwz 0, 2 *4(1) \n\t" 274 "mtlr 0 \n\t" 275 /* cr */ 276 "lwz 0, 3 *4(1) \n\t" 277 "mtcr 0 \n\t" 278 /* srr0 */ 279 "lwz 0, 4 *4(1) \n\t" 280 "mtsrr0 0 \n\t" 281 /* srr1 */ 282 "lwz 0, 5 *4(1) \n\t" 283 "mtsrr1 0 \n\t" 284 /* r0 */ 285 "lwz 0, 6 *4(1) \n\t" 286 /* r1 */ 287 "lwz 1, 7 *4(1) \n\t" 288 "rfi \n\t" 289 FUNC_END(back_from_exception) 290 ); 261 291 262 GET_CONTEXTLOCAL_HANDLER_ADDRESS("cpu_syscall_handler", 0, 3)263 "mtctr 0 \n\t"264 "bctrl \n\t"265 292 266 /* Put register table on second arg */267 /* Table is: sp, r0, r2, r3, ..., r12 */268 "or 4, 1, 1 \n\t"269 "lwz 0, 4*14(1) \n\t"270 "mtctr 0 \n\t"271 293 272 "lwz 0, 4*13(1) \n\t" 273 RESTORE_REG_2_12(1, 16) 294 asm( 295 ".section .excep,\"ax\",@progbits \n" 274 296 275 "mtlr 0 \n\t" 276 "lwz 0, 4(1) \n\t" 277 "lwz 1, 0(1) \n\t" 297 /* critical interrupt (critical, async) */ 298 ".org 0x100\n" 299 FUNC_START(ppc_critical_entry) 300 prepare_exception(srr2, srr3) 301 handle_interrupt(1) 302 FUNC_END(ppc_critical_entry) 278 303 279 "rfi \n\t" 280 ".size ppc_special_syscall_entry, .-ppc_special_syscall_entry \n\t" 304 /* machine check (critical, async, imprecise) */ 305 ".org 0x200\n" 306 FUNC_START(ppc_machine_entry) 307 CRASH(srr2, srr3) 308 FUNC_END(ppc_machine_entry) 281 309 282 /* apu unavailable */ 283 ".org 0xf20\n" 310 /* data storage */ 311 ".org 0x300\n" 312 FUNC_START(ppc_data_storage_entry) 313 prepare_exception(srr0, srr1) 314 handle_exception(CPU_EXCEPTION_DATA_ERROR) 315 FUNC_END(ppc_data_storage_entry) 284 316 285 /* programmable-interval timer (async) */ 286 ".org 0x1000\n" 317 /* instr storage */ 318 ".org 0x400\n" 319 FUNC_START(ppc_instr_storage_entry) 320 prepare_exception(srr0, srr1) 321 handle_exception(CPU_EXCEPTION_INS_ERROR) 322 FUNC_END(ppc_instr_storage_entry) 287 323 288 /* fixed-interval timer (async) */ 289 ".org 0x1010\n" 324 /* external (async) */ 325 ".org 0x500\n" 326 FUNC_START(ppc_external_entry) 327 prepare_exception(srr0, srr1) 328 handle_interrupt(0) 329 FUNC_END(ppc_external_entry) 290 330 291 /* watchdog (critical, async) */292 ".org 0x1020\n"293 331 294 /* data tlb */ 295 ".org 0x1100\n" 332 /* alignment */ 333 ".org 0x600\n" 334 FUNC_START(ppc_align_entry) 335 prepare_exception(srr0, srr1) 336 handle_exception(CPU_EXCEPTION_DATA_ALIGN) 337 FUNC_END(ppc_align_entry) 296 338 297 /* ins tlb */ 298 ".org 0x1200\n" 339 /* program */ 340 ".org 0x700\n" 341 FUNC_START(ppc_program_entry) 342 prepare_exception(srr0, srr1) 343 handle_exception(CPU_EXCEPTION_ILLEGAL_INS) 344 FUNC_END(ppc_program_entry) 299 345 300 /* debug (critical, (a)sync) */ 301 ".org 0x2000\n" 346 /* fpu unusable */ 347 ".org 0x800\n" 348 FUNC_START(ppc_fpu_entry) 349 CRASH(srr0, srr1) 350 FUNC_END(ppc_fpu_entry) 302 351 352 /* syscall */ 353 ".org 0xc00\n" 354 FUNC_START(ppc_syscall_entry) 355 handle_syscall() 356 FUNC_END(ppc_syscall_entry) 357 358 /* apu unavailable */ 359 ".org 0xf20\n" 360 361 /* programmable-interval timer (async) */ 362 ".org 0x1000\n" 363 364 /* fixed-interval timer (async) */ 365 ".org 0x1010\n" 366 367 /* watchdog (critical, async) */ 368 ".org 0x1020\n" 369 370 /* data tlb */ 371 ".org 0x1100\n" 372 373 /* ins tlb */ 374 ".org 0x1200\n" 375 376 /* debug (critical, (a)sync) */ 377 ".org 0x2000\n" 378 303 379 ); 304 380 -
cpu/ppc/notes.rst
1 Special purpose register usage 2 ------------------------------ 3 4 ===== ====== ======================= ========== 5 reg sprn data attributes 6 ===== ====== ======================= ========== 7 sprg0 0x110 exception handler r0 rw 8 ----- ------ ----------------------- ---------- 9 sprg1 0x111 exception handler r1 rw 10 ----- ------ ----------------------- ---------- 11 sprg2 0x112 exception handler r2 rw 12 ----- ------ ----------------------- ---------- 13 sprg4 0x104 task-local-storage base ro, user 14 ----- ------ ----------------------- ---------- 15 sprg4 0x114 task-local-storage base rw 16 ----- ------ ----------------------- ---------- 17 sprg5 0x105 cpu-local-storage base ro, user 18 ----- ------ ----------------------- ---------- 19 sprg5 0x115 cpu-local-storage base rw 20 ----- ------ ----------------------- ---------- -
cpu/ppc/boot.c
19 19 20 20 */ 21 21 22 #include <hexo/asm.h> 23 22 24 #ifdef CONFIG_SOCLIB_MEMCHECK 23 25 # include <arch/mem_checker.h> 24 26 #endif … … 26 28 asm( 27 29 ".section .text,\"ax\",@progbits \n" 28 30 29 ".globl cpu_boot \n" 30 "cpu_boot: \n" 31 FUNC_START(cpu_boot) 31 32 32 33 /* get CPU id and adjust stack */ 33 34 "lis 9, __initial_stack - 8@ha \n" … … 86 87 "la 2, arch_init@l(2) \n" 87 88 "mtctr 2 \n" 88 89 "bctr \n" 90 FUNC_END(cpu_boot) 89 91 ); 90 92 91 93 asm( 92 94 ".section .boot,\"ax\",@progbits \n" 93 95 94 ".globl cpu_boot_pointer \n\t" 95 "cpu_boot_pointer: \n\t" 96 FUNC_START(cpu_boot_pointer) 96 97 "1: \n\t" 97 98 "lis 3, cpu_boot@ha \n\t" 98 99 "la 3, cpu_boot@l(3) \n\t" … … 100 101 "bctr \n\t" 101 102 ".org 0x80-4 \n\t" 102 103 "b 1b \n\t" 104 FUNC_END(cpu_boot_pointer) 103 105 ); 104 106 -
cpu/mips/interrupts.c
16 16 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 17 18 18 Copyright Alexandre Becoulet <alexandre.becoulet@lip6.fr> (c) 2006 19 Copyright (c) 2010, Nicolas Pouillon <nipo@ssji.net> 20 */ 19 21 22 #include <hexo/asm.h> 23 24 #ifdef CONFIG_SMP 25 # define CPU_LOCAL_GET(reg, name) " lw " #reg ", " #name "($27) \n" 26 #else 27 # define CPU_LOCAL_GET(reg, name) " lw " #reg ", " #name "\n" 28 #endif 29 30 #if __mips >= 32 31 # define CPU_ID(reg) \ 32 " mfc0 " #reg ", $15, 1 \n" \ 33 " andi " #reg ", " #reg ", 0x3ff \n" 34 # define STATUS_UM_BIT "0x10" 35 #else 36 # define CPU_ID(reg) \ 37 " mfc0 " #reg ", $15 \n" \ 38 " andi " #reg ", " #reg ", 0x3ff \n" 39 # define STATUS_UM_BIT "0x8" 40 #endif 41 42 // Not in macros: $0, $26 (k0), $27 (k1), $29 (sp) 43 44 // 11 registers (but as we call ABI-compliant func, t* may not be saved) 45 // so only gp and ra must be saved. 46 // Even if we end-up switching threads, switch() will finally save them 47 #define DO_CALLEE_SAVED(op, reg) \ 48 " " #op " $28, 28 * 4(" #reg ") \n" \ 49 " " #op " $31, 31 * 4(" #reg ") \n" 50 /* 51 " " #op " $16, 16 * 4(" #reg ") \n" \ 52 " " #op " $17, 17 * 4(" #reg ") \n" \ 53 " " #op " $18, 18 * 4(" #reg ") \n" \ 54 " " #op " $19, 19 * 4(" #reg ") \n" \ 55 " " #op " $20, 20 * 4(" #reg ") \n" \ 56 " " #op " $21, 21 * 4(" #reg ") \n" \ 57 " " #op " $22, 22 * 4(" #reg ") \n" \ 58 " " #op " $23, 23 * 4(" #reg ") \n" \ 59 " " #op " $30, 30 * 4(" #reg ") \n" \ 20 60 */ 21 61 62 63 // 10 registers 64 #define DO_TEMP_REGS(op, reg) \ 65 " " #op " $8, 8 * 4(" #reg ") \n" \ 66 " " #op " $9, 9 * 4(" #reg ") \n" \ 67 " " #op " $10, 10 * 4(" #reg ") \n" \ 68 " " #op " $11, 11 * 4(" #reg ") \n" \ 69 " " #op " $12, 12 * 4(" #reg ") \n" \ 70 " " #op " $13, 13 * 4(" #reg ") \n" \ 71 " " #op " $14, 14 * 4(" #reg ") \n" \ 72 " " #op " $15, 15 * 4(" #reg ") \n" \ 73 " " #op " $24, 24 * 4(" #reg ") \n" \ 74 " " #op " $25, 25 * 4(" #reg ") \n" 75 76 #define DO_AT_REG(op, reg) \ 77 " " #op " $1, 1 * 4(" #reg ") \n" 78 79 #define DO_RVAL_REGS(op, reg) \ 80 " " #op " $2, 2 * 4(" #reg ") \n" \ 81 " " #op " $3, 3 * 4(" #reg ") \n" 82 83 #define DO_ARG_REGS(op, reg) \ 84 " " #op " $4, 4 * 4(" #reg ") \n" \ 85 " " #op " $5, 5 * 4(" #reg ") \n" \ 86 " " #op " $6, 6 * 4(" #reg ") \n" \ 87 " " #op " $7, 7 * 4(" #reg ") \n" 88 22 89 asm( 23 90 ".section .excep,\"ax\",@progbits \n" 24 91 25 92 ".set push \n" 26 93 ".set noreorder \n" 27 94 " b 1f \n" 28 # 95 #if __mips >= 32 29 96 ".space 0x17c \n" 30 97 #else 31 98 ".space 0x7c \n" 32 99 #endif 33 100 ".set pop \n" 34 101 35 ".globl mips_interrupt_entry \n" 36 ".func mips_interrupt_entry \n" 37 ".type mips_interrupt_entry, %function \n" 38 "mips_interrupt_entry: \n" 102 FUNC_START(mips_interrupt_entry) 39 103 ".set push \n" 40 104 ".set noat \n" 41 105 … … 43 107 44 108 /* restore cpu local storage */ 45 109 #if defined(CONFIG_CPU_USER) 46 # if defined(CONFIG_SMP)47 110 48 # if __mips >= 3249 " mfc0 $26, $15, 1 \n"50 # else51 " mfc0 $26, $15 \n"52 # endif53 54 " andi $26, $26, 0x3ff \n"55 " sll $26, $26, 2 \n"56 " lw $27, cpu_local_storage($26) \n"57 # endif58 59 111 /* event from user mode ? */ 60 112 " mfc0 $26, $12 \n" 61 " andi $26, $26, 0x8\n"113 " andi $26, $26, " STATUS_UM_BIT " \n" 62 114 63 115 ".set noreorder \n" 64 " blez $26, 1f \n" 116 /* zero if from Kernel mode */ 117 " beqz $26, 1f \n" 118 /* abuse the delay slot to get the current SP (sp_user_kernel) */ 65 119 " move $26, $sp \n" 66 120 ".set reorder \n" 67 121 122 # if defined(CONFIG_SMP) 123 /* Restore CLS if we are from user mode */ 124 CPU_ID($26) 125 " sll $26, $26, 2 \n" 126 " lw $27, cpu_local_storage($26) \n" 127 # endif 128 129 /* Get user's SP (sp_user_user) */ 130 " move $26, $sp \n" 131 68 132 /* restore kernel stack ! */ 69 # ifdef CONFIG_SMP 70 " lw $sp, __context_data_base($27) \n" 71 # else 72 " lw $sp, __context_data_base \n" 73 # endif 74 " addiu $sp, %lo(context_kstack) \n" 75 " lw $sp, ($sp) \n" 133 CPU_LOCAL_GET($sp, __context_data_base) 134 " lw $sp, %lo(context_kstack)($sp) \n" 135 "1: \n" 76 136 #else /* !defined(CONFIG_CPU_USER) */ 137 /* Get current SP (sp_user_none) */ 77 138 " move $26, $sp \n" 78 139 #endif 79 140 80 /* save registers usefull to syscall */ 81 "1: \n" 82 " addu $sp, -4*32 \n" 141 /* 142 Either: 143 * We are not handling user mode and $26 is last known sp (sp_user_none) 144 * We are handling user mode 145 * From user mode, $26 is user's sp (sp_user_user) 146 * From kernel mode, $26 is last known sp (sp_user_kernel) 147 */ 148 149 /* save registers useful to syscall */ 83 150 #if defined(CONFIG_LIBELF_RTLD_TLS) 84 151 /* add room for hwrena and tls registers */ 85 " addu $sp, -4*2 \n" 152 " addu $sp, -4*35 \n" 153 #else 154 " addu $sp, -4*33 \n" 86 155 #endif 87 156 " sw $26, 29*4($sp) \n" 88 157 89 " sw $4, 4*4($sp) \n" /* Args regs */ 90 " sw $5, 5*4($sp) \n" /* Args regs */ 91 " sw $6, 6*4($sp) \n" /* Args regs */ 92 " sw $7, 7*4($sp) \n" /* Args regs */ 158 DO_ARG_REGS(sw, $sp) 93 159 94 " sw $31, 31*4($sp) \n" /* Return address regs */95 96 160 /* read and extract cause */ 97 161 " mfc0 $4, $13 \n" 98 162 " andi $6, $4, 0x3c \n" 99 163 100 /* read & save EPC */ 101 " mfc0 $5, $14 \n" 102 " sw $5, 0*4($sp) \n" 164 " mfc0 $5, $12 \n" 165 " sb $5, 32*4($sp) \n" 166 /* Let's say we are in kernel mode, no exception, no irq */ 167 # if __mips >= 32 168 " ori $5, $5, 0x1f \n" 169 " xori $5, $5, 0x1f \n" 170 # else 171 # error Implement me 172 # endif 173 " mtc0 $5, $12 \n" 103 174 104 175 #if defined(CONFIG_LIBELF_RTLD_TLS) 105 176 /* read & save hwrena */ 106 177 " mfc0 $7, $7 \n" 107 " sw $7, 3 2*4($sp) \n"178 " sw $7, 33*4($sp) \n" 108 179 /* read & save tls */ 109 180 " mfc0 $7, $4, 2 \n" 110 " sw $7, 3 3*4($sp) \n"181 " sw $7, 34*4($sp) \n" 111 182 #endif 112 183 184 #if defined(CONFIG_CPU_USER) 185 /* increment the user-mode counter */ 186 CPU_LOCAL_GET($5, __context_data_base) 187 " lw $7, %lo(usermode_counter)($5) \n" 188 " addui $7, $7, 1 \n" 189 " sw $7, %lo(usermode_counter)($5) \n" 190 #endif 191 113 192 " li $7, 32 \n" 114 193 " beq $6, $7, interrupt_sys \n" 115 194 116 195 /* save extra registers for hw interrupts and exceptions only */ 117 196 118 " sw $1, 1*4($sp) \n" /* AT reg */ 197 DO_AT_REG(sw, $sp) 198 DO_RVAL_REGS(sw, $sp) 199 DO_TEMP_REGS(sw, $sp) 200 DO_CALLEE_SAVED(sw, $sp) 119 201 120 " sw $2, 2*4($sp) \n" /* Return value regs */ 121 " sw $3, 3*4($sp) \n" /* Return value regs */ 202 /* read & save EPC */ 203 " mfc0 $5, $14 \n" 204 " sw $5, 0*4($sp) \n" 122 205 123 " sw $8, 8*4($sp) \n" /* Temp regs */124 " sw $9, 9*4($sp) \n" /* Temp regs */125 " sw $10, 10*4($sp) \n" /* Temp regs */126 " sw $11, 11*4($sp) \n" /* Temp regs */127 " sw $12, 12*4($sp) \n" /* Temp regs */128 " sw $13, 13*4($sp) \n" /* Temp regs */129 " sw $14, 14*4($sp) \n" /* Temp regs */130 " sw $15, 15*4($sp) \n" /* Temp regs */131 132 " sw $16, 16*4($sp) \n" /* Callee saved */133 " sw $17, 17*4($sp) \n" /* Callee saved */134 " sw $18, 18*4($sp) \n" /* Callee saved */135 " sw $19, 19*4($sp) \n" /* Callee saved */136 " sw $20, 20*4($sp) \n" /* Callee saved */137 " sw $21, 21*4($sp) \n" /* Callee saved */138 " sw $22, 22*4($sp) \n" /* Callee saved */139 " sw $23, 23*4($sp) \n" /* Callee saved */140 141 " sw $30, 30*4($sp) \n" /* Callee saved */142 143 " sw $24, 24*4($sp) \n" /* Temp regs */144 " sw $25, 25*4($sp) \n" /* Temp regs */145 146 " sw $28, 28*4($sp) \n" /* Save user GP */147 148 206 " beq $6, $0, interrupt_hw \n" 149 207 150 208 /************************************************************* … … 161 219 162 220 " addiu $sp, $sp, -5*4 \n" 163 221 " sw $26, 4*4($sp) \n" 164 #ifdef CONFIG_SMP 165 " lw $1, cpu_exception_handler($27) \n" 166 #else 167 " lw $1, cpu_exception_handler \n" 168 #endif 222 CPU_LOCAL_GET($1, cpu_exception_handler) 169 223 " jalr $1 \n" 170 224 " addiu $sp, $sp, 5*4 \n" 171 225 … … 181 235 " move $4, $0 \n" /* single trap on mips: id = 0 */ 182 236 " addiu $5, $sp, 0 \n" /* register table on stack */ 183 237 " addiu $sp, $sp, -4*4 \n" 184 #ifdef CONFIG_SMP 185 " lw $11, __context_data_base($27) \n" 186 #else 187 " lw $11, __context_data_base \n" 188 #endif 238 CPU_LOCAL_GET($31, __context_data_base) 189 239 " lw $1, cpu_syscall_handler($11) \n" 190 240 " jalr $1 \n" 191 241 " addiu $sp, $sp, 4*4 \n" … … 208 258 " andi $5, $5, 0xff \n" 209 259 210 260 " addiu $sp, $sp, -4*4 \n" 211 #ifdef CONFIG_SMP 212 " lw $1, cpu_interrupt_handler($27) \n" 213 " lw $4, cpu_interrupt_handler_arg($27)\n" 214 #else 215 " lw $1, cpu_interrupt_handler \n" 216 " lw $4, cpu_interrupt_handler_arg \n" 217 #endif 261 CPU_LOCAL_GET($1, cpu_interrupt_handler) 262 CPU_LOCAL_GET($4, cpu_interrupt_handler_arg) 218 263 " jalr $1 \n" 219 264 " addiu $sp, $sp, 4*4 \n" 220 265 … … 225 270 /* restore registers */ 226 271 "return: \n" 227 272 228 " lw $1, 1*4($sp) \n" 273 DO_AT_REG(lw, $sp) 274 DO_ARG_REGS(lw, $sp) 275 DO_TEMP_REGS(lw, $sp) 229 276 230 " lw $4, 4*4($sp) \n" 231 " lw $5, 5*4($sp) \n" 232 " lw $6, 6*4($sp) \n" 233 " lw $7, 7*4($sp) \n" 277 "return_val: \n" 234 278 235 " lw $8, 8*4($sp) \n" 236 " lw $9, 9*4($sp) \n" 237 " lw $10, 10*4($sp) \n" 238 " lw $11, 11*4($sp) \n" 239 " lw $12, 12*4($sp) \n" 240 " lw $13, 13*4($sp) \n" 241 " lw $14, 14*4($sp) \n" 242 " lw $15, 15*4($sp) \n" 279 DO_RVAL_REGS(lw, $sp) 243 280 244 " lw $16, 16*4($sp) \n" 245 " lw $17, 17*4($sp) \n" 246 " lw $18, 18*4($sp) \n" 247 " lw $19, 19*4($sp) \n" 248 " lw $20, 20*4($sp) \n" 249 " lw $21, 21*4($sp) \n" 250 " lw $22, 22*4($sp) \n" 251 " lw $23, 23*4($sp) \n" 281 /* reload lower byte of status */ 282 " lbu $28, 32*4($sp) \n" 283 " mfc0 $31, $12 \n" 284 " ori $31, $31, 0xff \n" 285 " xori $31, $31, 0xff \n" 286 " or $31, $31, $28 \n" 287 " mtc0 $31, $12 \n" 252 288 253 " lw $30, 30*4($sp) \n"254 255 " lw $24, 24*4($sp) \n"256 " lw $25, 25*4($sp) \n"257 258 "return_val: \n"259 260 " lw $2, 2*4($sp) \n" /* Syscall return value */261 " lw $3, 3*4($sp) \n" /* Syscall return value */262 263 289 #if defined(CONFIG_LIBELF_RTLD_TLS) 264 290 /* reload hwrena */ 265 " lw $31, 3 2*4($sp) \n"291 " lw $31, 33*4($sp) \n" 266 292 " mtc0 $31, $7 \n" 267 293 /* reload tls */ 268 " lw $31, 3 3*4($sp) \n"294 " lw $31, 34*4($sp) \n" 269 295 " mtc0 $31, $4, 2 \n" 270 296 #endif 271 297 272 " lw $28, 28*4($sp) \n" /* restore user GP */ 273 " lw $31, 31*4($sp) \n" /* restore return address */ 298 DO_CALLEE_SAVED(lw, $sp) 274 299 275 300 " lw $sp, 29*4($sp) \n" /* restore user stack */ 276 301 … … 285 310 # endif 286 311 287 312 ".set pop \n" 288 ".endfunc \n" 289 ".size mips_interrupt_entry, .-mips_interrupt_entry \n" 313 FUNC_END(mips_interrupt_entry) 290 314 ); 291 315 292 316 // Local Variables: -
cpu/mips/boot.c
19 19 20 20 */ 21 21 22 #include <hexo/asm.h> 23 22 24 #ifdef CONFIG_SOCLIB_MEMCHECK 23 25 # include <arch/mem_checker.h> 24 26 #endif … … 26 28 asm( 27 29 ".section .boot,\"ax\",@progbits \n" 28 30 29 ".globl cpu_boot \n" 30 ".func cpu_boot \n\t" 31 ".type cpu_boot, %function \n\t" 32 "cpu_boot: \n" 31 FUNC_START(cpu_boot) 33 32 34 33 ".set push \n" 35 34 ".set noreorder \n" … … 122 121 #endif 123 122 124 123 ".set pop \n" 125 ".size cpu_boot, .-cpu_boot \n\t" 126 ".endfunc \n\t" 124 FUNC_END(cpu_boot) 127 125 ); 128 126 129 127 // Local Variables: -
cpu/mips/cpu_context.c
7 7 # include <arch/mem_checker.h> 8 8 #endif 9 9 10 #if defined(CONFIG_CPU_USER)11 CONTEXT_LOCAL uintptr_t context_kstack;12 #endif13 14 10 error_t 15 11 cpu_context_bootstrap(struct context_s *context) 16 12 {