exception.S 8.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/*
 *  Low level routines for legacy iSeries support.
 *
 *  Extracted from head_64.S
 *
 *  PowerPC version
 *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
 *
 *  Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
 *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
 *  Adapted for Power Macintosh by Paul Mackerras.
 *  Low-level exception handlers and MMU support
 *  rewritten by Paul Mackerras.
 *    Copyright (C) 1996 Paul Mackerras.
 *
 *  Adapted for 64bit PowerPC by Dave Engebretsen, Peter Bergner, and
 *    Mike Corrigan {engebret|bergner|mikejc}@us.ibm.com
 *
 *  This file contains the low-level support and setup for the
 *  PowerPC-64 platform, including trap and interrupt dispatch.
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  as published by the Free Software Foundation; either version
 *  2 of the License, or (at your option) any later version.
 */

#include <asm/reg.h>
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/ptrace.h>
33
#include <asm/cputable.h>
34
#include <asm/mmu.h>
35

36 37
#include "exception.h"

38 39 40 41
	.text

	.globl system_reset_iSeries
system_reset_iSeries:
42
	bl	.relative_toc
43
	mfspr	r13,SPRN_SPRG3		/* Get alpaca address */
44
	LOAD_REG_ADDR(r23, alpaca)
45 46
	li	r0,ALPACA_SIZE
	sub	r23,r13,r23
47
	divdu	r24,r23,r0		/* r24 has cpu number */
48 49
	cmpwi	0,r24,0			/* Are we processor 0? */
	bne	1f
50 51 52 53 54
	LOAD_REG_ADDR(r13, boot_paca)
	mtspr	SPRN_SPRG_PACA,r13	/* Save it away for the future */
	mfmsr	r23
	ori	r23,r23,MSR_RI
	mtmsrd	r23			/* RI on */
55 56 57 58 59 60
	b	.__start_initialization_iSeries	/* Start up the first processor */
1:	mfspr	r4,SPRN_CTRLF
	li	r5,CTRL_RUNLATCH	/* Turn off the run light */
	andc	r4,r4,r5
	mtspr	SPRN_CTRLT,r4

61
/* Spin on __secondary_hold_spinloop until it is updated by the boot cpu. */
62
/* In the UP case we'll yield() later, and we will not access the paca anyway */
63
#ifdef CONFIG_SMP
64
iSeries_secondary_wait_paca:
65
	HMT_LOW
66
	LOAD_REG_ADDR(r23, __secondary_hold_spinloop)
67 68
	ld	r23,0(r23)

69 70 71 72
	cmpdi	0,r23,0
	bne	2f			/* go on when the master is ready */

	/* Keep poking the Hypervisor until we're released */
73 74 75 76 77
	/* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
	lis	r3,0x8002
	rldicr	r3,r3,32,15		/* r0 = (r3 << 32) & 0xffff000000000000 */
	li	r0,-1			/* r0=-1 indicates a Hypervisor call */
	sc				/* Invoke the hypervisor via a system call */
78
	b	iSeries_secondary_wait_paca
79 80

2:
81 82 83 84 85 86 87 88
	HMT_MEDIUM
	sync

	LOAD_REG_ADDR(r3, nr_cpu_ids)	/* get number of pacas allocated */
	lwz	r3,0(r3)		/* nr_cpus= or NR_CPUS can limit */
	cmpld	0,r24,r3		/* is our cpu number allocated? */
	bge	iSeries_secondary_yield	/* no, yield forever */

89 90 91 92 93 94 95 96 97 98
	/* Load our paca now that it's been allocated */
	LOAD_REG_ADDR(r13, paca)
	ld	r13,0(r13)
	mulli	r0,r24,PACA_SIZE
	add	r13,r13,r0
	mtspr	SPRN_SPRG_PACA,r13	/* Save it away for the future */
	mfmsr	r23
	ori	r23,r23,MSR_RI
	mtmsrd	r23			/* RI on */

99
iSeries_secondary_smp_loop:
100 101
	lbz	r23,PACAPROCSTART(r13)	/* Test if this processor
					 * should start */
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
	cmpwi	0,r23,0
	bne	3f			/* go on when we are told */

	HMT_LOW
	/* Let the Hypervisor know we are alive */
	/* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
	lis	r3,0x8002
	rldicr	r3,r3,32,15		/* r0 = (r3 << 32) & 0xffff000000000000 */
	li	r0,-1			/* r0=-1 indicates a Hypervisor call */
	sc				/* Invoke the hypervisor via a system call */
	mfspr	r13,SPRN_SPRG_PACA	/* Put r13 back ???? */
	b	iSeries_secondary_smp_loop /* wait for signal to start */

3:
	HMT_MEDIUM
117
	sync
118
	LOAD_REG_ADDR(r3,current_set)
119 120 121 122 123 124
	sldi	r28,r24,3		/* get current_set[cpu#] */
	ldx	r3,r3,r28
	addi	r1,r3,THREAD_SIZE
	subi	r1,r1,STACK_FRAME_OVERHEAD

	b	__secondary_start		/* Loop until told to go */
125 126 127
#endif /* CONFIG_SMP */

iSeries_secondary_yield:
128 129
	/* Yield the processor.  This is required for non-SMP kernels
		which are running on multi-threaded machines. */
130
	HMT_LOW
131 132 133 134 135 136 137
	lis	r3,0x8000
	rldicr	r3,r3,32,15		/* r3 = (r3 << 32) & 0xffff000000000000 */
	addi	r3,r3,18		/* r3 = 0x8000000000000012 which is "yield" */
	li	r4,0			/* "yield timed" */
	li	r5,-1			/* "yield forever" */
	li	r0,-1			/* r0=-1 indicates a Hypervisor call */
	sc				/* Invoke the hypervisor via a system call */
138
	mfspr	r13,SPRN_SPRG_PACA	/* Put r13 back ???? */
139
	b	iSeries_secondary_yield	/* If SMP not configured, secondaries
140 141
					 * loop forever */

142 143
/***  ISeries-LPAR interrupt handlers ***/

144
	STD_EXCEPTION_ISERIES(machine_check, PACA_EXMC)
145 146 147

	.globl data_access_iSeries
data_access_iSeries:
148
	mtspr	SPRN_SPRG_SCRATCH0,r13
149
BEGIN_FTR_SECTION
150 151 152 153 154 155 156 157 158
	mfspr	r13,SPRN_SPRG_PACA
	std	r9,PACA_EXSLB+EX_R9(r13)
	std	r10,PACA_EXSLB+EX_R10(r13)
	mfspr	r10,SPRN_DAR
	mfspr	r9,SPRN_DSISR
	srdi	r10,r10,60
	rlwimi	r10,r9,16,0x20
	mfcr	r9
	cmpwi	r10,0x2c
159
	beq	.do_stab_bolted_iSeries
160 161 162 163 164 165 166 167 168 169
	ld	r10,PACA_EXSLB+EX_R10(r13)
	std	r11,PACA_EXGEN+EX_R11(r13)
	ld	r11,PACA_EXSLB+EX_R9(r13)
	std	r12,PACA_EXGEN+EX_R12(r13)
	mfspr	r12,SPRN_SPRG_SCRATCH0
	std	r10,PACA_EXGEN+EX_R10(r13)
	std	r11,PACA_EXGEN+EX_R9(r13)
	std	r12,PACA_EXGEN+EX_R13(r13)
	EXCEPTION_PROLOG_ISERIES_1
FTR_SECTION_ELSE
170
	EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, 0)
171
	EXCEPTION_PROLOG_ISERIES_1
172
ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_SLB)
173 174 175
	b	data_access_common

.do_stab_bolted_iSeries:
176 177 178 179
	std	r11,PACA_EXSLB+EX_R11(r13)
	std	r12,PACA_EXSLB+EX_R12(r13)
	mfspr	r10,SPRN_SPRG_SCRATCH0
	std	r10,PACA_EXSLB+EX_R13(r13)
180
	EXCEPTION_PROLOG_ISERIES_1
181 182 183 184
	b	.do_stab_bolted

	.globl	data_access_slb_iSeries
data_access_slb_iSeries:
185 186
	mtspr	SPRN_SPRG_SCRATCH0,r13	/* save r13 */
	mfspr	r13,SPRN_SPRG_PACA	/* get paca address into r13 */
187 188 189 190 191 192 193 194 195 196 197
	std	r3,PACA_EXSLB+EX_R3(r13)
	mfspr	r3,SPRN_DAR
	std	r9,PACA_EXSLB+EX_R9(r13)
	mfcr	r9
#ifdef __DISABLED__
	cmpdi	r3,0
	bge	slb_miss_user_iseries
#endif
	std	r10,PACA_EXSLB+EX_R10(r13)
	std	r11,PACA_EXSLB+EX_R11(r13)
	std	r12,PACA_EXSLB+EX_R12(r13)
198
	mfspr	r10,SPRN_SPRG_SCRATCH0
199 200 201 202 203
	std	r10,PACA_EXSLB+EX_R13(r13)
	ld	r12,PACALPPACAPTR(r13)
	ld	r12,LPPACASRR1(r12)
	b	.slb_miss_realmode

204
	STD_EXCEPTION_ISERIES(instruction_access, PACA_EXGEN)
205 206 207

	.globl	instruction_access_slb_iSeries
instruction_access_slb_iSeries:
208 209
	mtspr	SPRN_SPRG_SCRATCH0,r13	/* save r13 */
	mfspr	r13,SPRN_SPRG_PACA	/* get paca address into r13 */
210 211 212 213 214 215 216 217 218 219 220 221
	std	r3,PACA_EXSLB+EX_R3(r13)
	ld	r3,PACALPPACAPTR(r13)
	ld	r3,LPPACASRR0(r3)	/* get SRR0 value */
	std	r9,PACA_EXSLB+EX_R9(r13)
	mfcr	r9
#ifdef __DISABLED__
	cmpdi	r3,0
	bge	slb_miss_user_iseries
#endif
	std	r10,PACA_EXSLB+EX_R10(r13)
	std	r11,PACA_EXSLB+EX_R11(r13)
	std	r12,PACA_EXSLB+EX_R12(r13)
222
	mfspr	r10,SPRN_SPRG_SCRATCH0
223 224 225 226 227 228 229 230 231 232
	std	r10,PACA_EXSLB+EX_R13(r13)
	ld	r12,PACALPPACAPTR(r13)
	ld	r12,LPPACASRR1(r12)
	b	.slb_miss_realmode

#ifdef __DISABLED__
slb_miss_user_iseries:
	std	r10,PACA_EXGEN+EX_R10(r13)
	std	r11,PACA_EXGEN+EX_R11(r13)
	std	r12,PACA_EXGEN+EX_R12(r13)
233
	mfspr	r10,SPRG_SCRATCH0
234 235 236 237 238
	ld	r11,PACA_EXSLB+EX_R9(r13)
	ld	r12,PACA_EXSLB+EX_R3(r13)
	std	r10,PACA_EXGEN+EX_R13(r13)
	std	r11,PACA_EXGEN+EX_R9(r13)
	std	r12,PACA_EXGEN+EX_R3(r13)
239
	EXCEPTION_PROLOG_ISERIES_1
240 241 242
	b	slb_miss_user_common
#endif

243 244 245 246 247 248 249
	MASKABLE_EXCEPTION_ISERIES(hardware_interrupt)
	STD_EXCEPTION_ISERIES(alignment, PACA_EXGEN)
	STD_EXCEPTION_ISERIES(program_check, PACA_EXGEN)
	STD_EXCEPTION_ISERIES(fp_unavailable, PACA_EXGEN)
	MASKABLE_EXCEPTION_ISERIES(decrementer)
	STD_EXCEPTION_ISERIES(trap_0a, PACA_EXGEN)
	STD_EXCEPTION_ISERIES(trap_0b, PACA_EXGEN)
250 251 252 253

	.globl	system_call_iSeries
system_call_iSeries:
	mr	r9,r13
254
	mfspr	r13,SPRN_SPRG_PACA
255
	EXCEPTION_PROLOG_ISERIES_1
256 257
	b	system_call_common

258 259 260
	STD_EXCEPTION_ISERIES(single_step, PACA_EXGEN)
	STD_EXCEPTION_ISERIES(trap_0e, PACA_EXGEN)
	STD_EXCEPTION_ISERIES(performance_monitor, PACA_EXGEN)
261 262 263 264 265 266

decrementer_iSeries_masked:
	/* We may not have a valid TOC pointer in here. */
	li	r11,1
	ld	r12,PACALPPACAPTR(r13)
	stb	r11,LPPACADECRINT(r12)
267 268
	li	r12,-1
	clrldi	r12,r12,33	/* set DEC to 0x7fffffff */
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
	mtspr	SPRN_DEC,r12
	/* fall through */

hardware_interrupt_iSeries_masked:
	mtcrf	0x80,r9		/* Restore regs */
	ld	r12,PACALPPACAPTR(r13)
	ld	r11,LPPACASRR0(r12)
	ld	r12,LPPACASRR1(r12)
	mtspr	SPRN_SRR0,r11
	mtspr	SPRN_SRR1,r12
	ld	r9,PACA_EXGEN+EX_R9(r13)
	ld	r10,PACA_EXGEN+EX_R10(r13)
	ld	r11,PACA_EXGEN+EX_R11(r13)
	ld	r12,PACA_EXGEN+EX_R12(r13)
	ld	r13,PACA_EXGEN+EX_R13(r13)
	rfid
	b	.	/* prevent speculative execution */

287 288
_INIT_STATIC(__start_initialization_iSeries)
	/* Clear out the BSS */
289 290
	LOAD_REG_ADDR(r11,__bss_stop)
	LOAD_REG_ADDR(r8,__bss_start)
291 292 293 294 295 296 297 298 299 300
	sub	r11,r11,r8		/* bss size			*/
	addi	r11,r11,7		/* round up to an even double word */
	rldicl. r11,r11,61,3		/* shift right by 3		*/
	beq	4f
	addi	r8,r8,-8
	li	r0,0
	mtctr	r11			/* zero this many doublewords	*/
3:	stdu	r0,8(r8)
	bdnz	3b
4:
301
	LOAD_REG_ADDR(r1,init_thread_union)
302 303 304 305 306 307 308 309 310 311
	addi	r1,r1,THREAD_SIZE
	li	r0,0
	stdu	r0,-STACK_FRAME_OVERHEAD(r1)

	bl	.iSeries_early_setup
	bl	.early_setup

	/* relocation is on at this point */

	b	.start_here_common