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.section .init 15 16/* 17 * start is the entry point. r3 points to the DTB 18 */ 19.globl start 20start: 21 FIXUP_ENDIAN 22 /* 23 * We were loaded at QEMU's kernel load address, but we're not 24 * allowed to link there due to how QEMU deals with linker VMAs, 25 * so we just linked at zero. This means the first thing to do is 26 * to find our stack and toc, and then do a relocate. 27 */ 28 bl 0f 290: mflr r31 30 subi r31, r31, 0b - start /* QEMU's kernel load address */ 31 ld r1, (p_stack - start)(r31) 32 ld r2, (p_toc - start)(r31) 33 add r1, r1, r31 34 add r2, r2, r31 35 36 /* save DTB pointer */ 37 std r3, 56(r1) 38 39 /* 40 * Call relocate. relocate is C code, but careful to not use 41 * any global references, as they may use absolute addresses, 42 * which are, obviously, not yet relocated. 43 */ 44 mr r3, r31 45 ld r4, (p_dyn - start)(r31) 46 add r4, r4, r31 47 bl relocate 48 49 /* relocate vector table to base address 0x0 (MSR_IP = 0) */ 50 51 /* source: r4, dest end: r5, destination: r6 */ 52 53 LOAD_REG_ADDR(r4, __start_interrupts) 54 LOAD_REG_ADDR(r5, __end_interrupts) 55 sub r5,r5,r4 56 li r6,0x100 57 58 sub r4,r4,r6 59 add r5,r5,r6 60 addi r6,r6,-8 612: li r0,8 62 mtctr r0 63 /* copy a cache line size */ 643: addi r6,r6,8 65 ldx r0,r6,r4 66 stdx r0,0,r6 67 bdnz 3b 68 dcbst 0,r6 69 /* flush icache */ 70 sync 71 icbi 0,r6 72 cmpld 0,r6,r5 73 blt 2b 74 sync 75 isync 76 77 /* patch sc1 if needed */ 78 bl hcall_have_broken_sc1 79 cmpwi r3, 0 80 beq 1f 81 LOAD_REG_ADDR(r3, hcall) 82 LOAD_REG_IMMEDIATE(r4, SC1_REPLACEMENT) 83 stw r4, 0(r3) 84 85 /* complete setup */ 861: ld r3, 56(r1) 87 bl setup 88 89 /* run the test */ 90 LOAD_REG_ADDR(r5, __argc) 91 LOAD_REG_ADDR(r4, __argv) 92 lwz r3, 0(r5) 93 bl main 94 bl exit 95 b halt 96 97.align 3 98p_stack: .llong stackptr 99p_toc: .llong tocptr 100p_dyn: .llong dynamic_start 101 102.text 103.align 3 104 105.globl hcall 106hcall: 107 sc 1 108 blr 109 110.globl halt 111halt: 1121: b 1b 113 114.globl enter_rtas 115enter_rtas: 116 mflr r0 117 std r0, 16(r1) 118 119 LOAD_REG_ADDR(r10, rtas_return_loc) 120 mtlr r10 121 LOAD_REG_ADDR(r11, rtas_entry) 122 ld r10, 0(r11) 123 124 mfmsr r11 125 LOAD_REG_IMMEDIATE(r9, RTAS_MSR_MASK) 126 and r11, r11, r9 127 mtsrr0 r10 128 mtsrr1 r11 129 rfid 130 b . 131 132rtas_return_loc: 133 FIXUP_ENDIAN 134 ld r0, 16(r1) 135 mtlr r0 136 blr 137 138call_handler: 139 /* save context */ 140 141 /* GPRs */ 142 143 .irp i, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 \ 144 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 145 SAVE_GPR(\i, r1) 146 .endr 147 mfsprg1 r0 148 std r0,GPR1(r1) 149 150 /* lr, xer, ccr */ 151 152 mflr r0 153 std r0,_LINK(r1) 154 155 mfxer r0 156 std r0,_XER(r1) 157 158 mfcr r0 159 std r0,_CCR(r1) 160 161 /* nip and msr */ 162 163 mfsrr0 r0 164 std r0, _NIP(r1) 165 166 mfsrr1 r0 167 std r0, _MSR(r1) 168 169 /* FIXME: build stack frame */ 170 171 /* call generic handler */ 172 173 addi r3,r1,STACK_FRAME_OVERHEAD 174 bl do_handle_exception 175 176 /* restore context */ 177 178 ld r0,_CTR(r1) 179 mtctr r0 180 181 ld r0,_LINK(r1) 182 mtlr r0 183 184 ld r0,_XER(r1) 185 mtxer r0 186 187 ld r0,_CCR(r1) 188 mtcr r0 189 190 ld r0, _NIP(r1) 191 mtsrr0 r0 192 193 ld r0, _MSR(r1) 194 mtsrr1 r0 195 196 .irp i, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 \ 197 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 198 REST_GPR(\i, r1) 199 .endr 200 201 /* restore r1, as we don't need it anymore */ 202 203 REST_GPR(1,r1) 204 205 rfid 206 b . 207 208.section .text.ex 209 210.macro VECTOR vec 211 . = \vec 212 213 mtsprg1 r1 /* save r1 */ 214 mfsprg0 r1 /* get exception stack address */ 215 subi r1,r1, INT_FRAME_SIZE 216 217 /* save r0 and ctr to call generic handler */ 218 219 SAVE_GPR(0,r1) 220 221 mfctr r0 222 std r0,_CTR(r1) 223 224 LOAD_REG_ADDR(r0, call_handler) 225 mtctr r0 226 227 li r0,\vec 228 std r0,_TRAP(r1) 229 230 bctr 231.endm 232 233 . = 0x100 234 .globl __start_interrupts 235__start_interrupts: 236 237VECTOR(0x300) 238VECTOR(0x400) 239VECTOR(0x500) 240VECTOR(0x600) 241VECTOR(0x700) 242VECTOR(0x800) 243VECTOR(0x900) 244 245 .align 7 246 .globl __end_interrupts 247__end_interrupts: 248