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