1/* 2 * Entry point and assembler functions for ppc64 tests. 3 * 4 * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com> 5 * 6 * This work is licensed under the terms of the GNU LGPL, version 2. 7 */ 8#include <asm/hcall.h> 9#include <asm/ppc_asm.h> 10#include <asm/rtas.h> 11#include <asm/ptrace.h> 12 13#include "spapr.h" 14 15#define P_HANDLER 0x2ff8 16 17.section .init 18 19/* 20 * start is the entry point. r3 points to the DTB 21 */ 22.globl start 23start: 24 FIXUP_ENDIAN 25 /* Switch to 64-bit mode */ 26 mfmsr r1 27 li r2,1 28 sldi r2,r2,MSR_SF_BIT 29 or r1,r1,r2 30 mtmsrd r1 31 /* 32 * We were loaded at QEMU's kernel load address, but we're not 33 * allowed to link there due to how QEMU deals with linker VMAs, 34 * so we just linked at zero. This means the first thing to do is 35 * to find our stack and toc, and then do a relocate. powernv and 36 * pseries load addresses are not the same, so find the address 37 * dynamically: 38 */ 39 bl 0f 400: mflr r31 41 subi r31, r31, 0b - start /* QEMU's kernel load address */ 42 43 ld r1, (p_stack - start)(r31) 44 ld r2, (p_toc - start)(r31) 45 add r1, r1, r31 46 add r2, r2, r31 47 48 /* Zero backpointers in initial stack frame so backtrace() stops */ 49 li r0,0 50 std r0,0(r1) 51 std r0,16(r1) 52 53 /* save DTB pointer */ 54 std r3, 56(r1) 55 56 /* 57 * Call relocate. relocate is C code, but careful to not use 58 * any global references, as they may use absolute addresses, 59 * which are, obviously, not yet relocated. 60 */ 61 mr r3, r31 62 ld r4, (p_dyn - start)(r31) 63 add r4, r4, r31 64 bl relocate 65 66 /* compute address of call_handler */ 67 68 LOAD_REG_ADDR(r4, call_handler) 69 std r4, P_HANDLER(0) 70 71 /* relocate vector table to base address 0x0 (MSR_IP = 0) */ 72 73 /* source: r4, dest end: r5, destination: r6 */ 74 75 LOAD_REG_ADDR(r4, __start_interrupts) 76 LOAD_REG_ADDR(r5, __end_interrupts) 77 sub r5,r5,r4 78 li r6,0x100 79 80 sub r4,r4,r6 81 add r5,r5,r6 82 addi r6,r6,-8 832: li r0,8 84 mtctr r0 85 /* copy a cache line size */ 863: addi r6,r6,8 87 ldx r0,r6,r4 88 stdx r0,0,r6 89 bdnz 3b 90 dcbst 0,r6 91 /* flush icache */ 92 sync 93 icbi 0,r6 94 cmpld 0,r6,r5 95 blt 2b 96 sync 97 isync 98 99 /* powernv machine does not check broken_sc1 */ 100 mfmsr r3 101 li r4,1 102 sldi r4,r4,MSR_HV_BIT 103 and. r3,r3,r4 104 bne 1f 105 106 /* patch sc1 if needed */ 107 bl hcall_have_broken_sc1 108 cmpwi r3, 0 109 beq 1f 110 LOAD_REG_ADDR(r3, hcall) 111 LOAD_REG_IMMEDIATE(r4, SC1_REPLACEMENT) 112 stw r4, 0(r3) 113 114 /* complete setup */ 1151: ld r3, 56(r1) 116 bl setup 117 118 /* run the test */ 119 LOAD_REG_ADDR(r3, __argc) 120 LOAD_REG_ADDR(r4, __argv) 121 LOAD_REG_ADDR(r5, __environ) 122 lwz r3, 0(r3) 123 bl main 124 bl exit 125 b halt 126 127/* 128 * start_secondary is the secondary entry point. r3 contains the cpu id 129 */ 130.globl start_secondary 131start_secondary: 132 FIXUP_ENDIAN 133 /* Switch to 64-bit mode */ 134 mfmsr r1 135 li r2,1 136 sldi r2,r2,MSR_SF_BIT 137 or r1,r1,r2 138 mtmsrd r1 139 140 bl 0f 1410: mflr r31 142 subi r31, r31, 0b - start /* QEMU's kernel load address */ 143 144 ld r2, (p_toc - start)(r31) 145 146 LOAD_REG_ADDR(r9, cpus) 147 li r8,0 148 li r7,0 1491: add r6,r9,r7 150 ld r6,CPU_SERVER_NO(r6) 151 cmpd r6,r3 152 beq 2f 153 addi r7,r7,SIZEOF_STRUCT_CPU 154 addi r8,r8,1 155 cmpdi r8,MAX_CPUS 156 bne 1b 157 b . 158 1592: add r3,r9,r7 160 ld r1,CPU_STACK(r3) 161 162 /* Zero backpointers in initial stack frame so backtrace() stops */ 163 li r0,0 164 std r0,0(r1) 165 std r0,16(r1) 166 167 bl main_secondary 168 bl exit 169 b halt 170 171.align 3 172p_stack: .llong stackptr 173p_toc: .llong tocptr 174p_dyn: .llong dynamic_start 175 176.text 177start_text: 178.align 3 179p_toc_text: .llong tocptr 180 181.align 3 182.globl hcall 183hcall: 184 sc 1 185 blr 186 187.globl halt 188halt: 1891: b 1b 190 191.globl enter_rtas 192enter_rtas: 193 LOAD_REG_ADDR(r11, rtas_entry) 194 ld r10, 0(r11) 195 196 cmpdi r10,0 197 bne external_rtas 198 199 /* Use H_RTAS directly */ 200 mr r4,r3 201 lis r3,KVMPPC_H_RTAS@h 202 ori r3,r3,KVMPPC_H_RTAS@l 203 b hcall 204 205external_rtas: 206 /* Use external RTAS blob */ 207 mflr r0 208 std r0, 16(r1) 209 210 LOAD_REG_ADDR(r11, rtas_return_loc) 211 mtlr r11 212 213 mfmsr r11 214 LOAD_REG_IMMEDIATE(r9, RTAS_MSR_MASK) 215 and r11, r11, r9 216 mtsrr0 r10 217 mtsrr1 r11 218 rfid 219 b . 220 221rtas_return_loc: 222 FIXUP_ENDIAN 223 ld r0, 16(r1) 224 mtlr r0 225 blr 226 227call_handler: 228 /* save context */ 229 230 /* GPRs */ 231 232 .irp i, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 \ 233 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 234 SAVE_GPR(\i, r1) 235 .endr 236 mfsprg1 r0 237 std r0,GPR1(r1) 238 std r0,0(r1) /* Backchain from interrupt stack to regular stack */ 239 240 /* lr, xer, ccr */ 241 242 mflr r0 243 std r0,_LINK(r1) 244 245 mfxer r0 246 std r0,_XER(r1) 247 248 mfcr r0 249 std r0,_CCR(r1) 250 251 /* restore TOC pointer */ 252 bl 0f 2530: mflr r31 254 subi r31, r31, 0b - start_text 255 ld r2, (p_toc_text - start_text)(r31) 256 257 /* call generic handler */ 258 259 addi r3,r1,STACK_FRAME_OVERHEAD 260 bl do_handle_exception 261 .global do_handle_exception_return 262do_handle_exception_return: 263 264 /* restore context */ 265 266 ld r0,_CTR(r1) 267 mtctr r0 268 269 ld r0,_LINK(r1) 270 mtlr r0 271 272 ld r0,_XER(r1) 273 mtxer r0 274 275 ld r0,_CCR(r1) 276 mtcr r0 277 278 ld r0, _NIP(r1) 279 mtsrr0 r0 280 281 ld r0, _MSR(r1) 282 mtsrr1 r0 283 284 .irp i, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 \ 285 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 286 REST_GPR(\i, r1) 287 .endr 288 289 /* restore r1, as we don't need it anymore */ 290 291 REST_GPR(1,r1) 292 293 rfid 294 b . 295 296.section .text.ex 297 298/* [H]VECTOR must not be more than 8 instructions to fit in 0x20 vectors */ 299.macro VECTOR vec 300 . = \vec 301 302 mtsprg1 r1 /* save r1 */ 303 mfsprg0 r1 /* get struct cpu address */ 304 ld r1,CPU_EXCEPTION_STACK(r1) /* get exception stack address */ 305 subi r1,r1, INT_FRAME_SIZE 306 307 /* save r0 and ctr to call generic handler */ 308 SAVE_GPR(0,r1) 309 310 li r0,\vec 311 std r0,_TRAP(r1) 312 313 b handler_trampoline 314.endm 315 316.macro HVECTOR vec 317 . = \vec 318 319 mtsprg1 r1 /* save r1 */ 320 mfsprg0 r1 /* get struct cpu address */ 321 ld r1,CPU_EXCEPTION_STACK(r1) /* get exception stack address */ 322 subi r1,r1, INT_FRAME_SIZE 323 324 /* save r0 and ctr to call generic handler */ 325 SAVE_GPR(0,r1) 326 327 li r0,\vec 328 std r0,_TRAP(r1) 329 330 b handler_htrampoline 331.endm 332 333 . = 0x100 334 .globl __start_interrupts 335__start_interrupts: 336 337VECTOR(0x100) 338VECTOR(0x200) 339VECTOR(0x300) 340VECTOR(0x380) 341VECTOR(0x400) 342VECTOR(0x480) 343VECTOR(0x500) 344VECTOR(0x600) 345VECTOR(0x700) 346VECTOR(0x800) 347VECTOR(0x900) 348HVECTOR(0x980) 349VECTOR(0xa00) 350VECTOR(0xc00) 351VECTOR(0xd00) 352HVECTOR(0xe00) 353HVECTOR(0xe20) 354HVECTOR(0xe40) 355HVECTOR(0xe60) 356HVECTOR(0xe80) 357HVECTOR(0xea0) 358VECTOR(0xf00) 359VECTOR(0xf20) 360VECTOR(0xf40) 361VECTOR(0xf60) 362HVECTOR(0xf80) 363 364handler_trampoline: 365 mfctr r0 366 std r0,_CTR(r1) 367 368 ld r0, P_HANDLER(0) 369 mtctr r0 370 371 /* nip and msr */ 372 mfsrr0 r0 373 std r0, _NIP(r1) 374 375 mfsrr1 r0 376 std r0, _MSR(r1) 377 378 bctr 379 380handler_htrampoline: 381 mfctr r0 382 std r0,_CTR(r1) 383 384 ld r0, P_HANDLER(0) 385 mtctr r0 386 387 /* nip and msr */ 388 mfspr r0, SPR_HSRR0 389 std r0, _NIP(r1) 390 391 mfspr r0, SPR_HSRR1 392 std r0, _MSR(r1) 393 394 bctr 395 396 .align 7 397 .globl __end_interrupts 398__end_interrupts: 399 .org P_HANDLER 400 .llong 0 401