exception.S 7.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

35 36
#include "exception.h"

37 38 39 40
	.text

	.globl system_reset_iSeries
system_reset_iSeries:
41
	bl	.relative_toc
42
	mfspr	r13,SPRN_SPRG3		/* Get alpaca address */
43
	LOAD_REG_ADDR(r23, alpaca)
44 45 46
	li	r0,ALPACA_SIZE
	sub	r23,r13,r23
	divdu	r23,r23,r0		/* r23 has cpu number */
47
	LOAD_REG_ADDR(r13, paca)
48 49 50
	mulli	r0,r23,PACA_SIZE
	add	r13,r13,r0
	mtspr	SPRN_SPRG3,r13		/* Save it away for the future */
51 52 53
	mfmsr	r24
	ori	r24,r24,MSR_RI
	mtmsrd	r24			/* RI on */
54
	mr	r24,r23
55 56 57 58 59 60 61 62
	cmpwi	0,r24,0			/* Are we processor 0? */
	bne	1f
	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

63
/* Spin on __secondary_hold_spinloop until it is updated by the boot cpu. */
64
/* In the UP case we'll yield() later, and we will not access the paca anyway */
65
#ifdef CONFIG_SMP
66 67
1:
	HMT_LOW
68
	LOAD_REG_ADDR(r23, __secondary_hold_spinloop)
69 70
	ld	r23,0(r23)
	sync
71
	LOAD_REG_ADDR(r3,current_set)
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
	sldi	r28,r24,3		/* get current_set[cpu#] */
	ldx	r3,r3,r28
	addi	r1,r3,THREAD_SIZE
	subi	r1,r1,STACK_FRAME_OVERHEAD

	cmpwi	0,r23,0			/* Keep poking the Hypervisor until */
	bne	2f			/* we're released */
	/* 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 */
	b	1b
#endif

2:
	HMT_LOW
90 91 92 93
#ifdef CONFIG_SMP
	lbz	r23,PACAPROCSTART(r13)	/* Test if this processor
					 * should start */
	sync
94
	LOAD_REG_ADDR(r3,current_set)
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
	sldi	r28,r24,3		/* get current_set[cpu#] */
	ldx	r3,r3,r28
	addi	r1,r3,THREAD_SIZE
	subi	r1,r1,STACK_FRAME_OVERHEAD

	cmpwi	0,r23,0
	beq	iSeries_secondary_smp_loop	/* Loop until told to go */
	b	__secondary_start		/* Loop until told to go */
iSeries_secondary_smp_loop:
	/* 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 */
#else /* CONFIG_SMP */
	/* Yield the processor.  This is required for non-SMP kernels
		which are running on multi-threaded machines. */
	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" */
#endif /* CONFIG_SMP */
	li	r0,-1			/* r0=-1 indicates a Hypervisor call */
	sc				/* Invoke the hypervisor via a system call */
	mfspr	r13,SPRN_SPRG3		/* Put r13 back ???? */
120
	b	2b			/* If SMP not configured, secondaries
121 122
					 * loop forever */

123 124
/***  ISeries-LPAR interrupt handlers ***/

125
	STD_EXCEPTION_ISERIES(machine_check, PACA_EXMC)
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141

	.globl data_access_iSeries
data_access_iSeries:
	mtspr	SPRN_SPRG1,r13
BEGIN_FTR_SECTION
	mtspr	SPRN_SPRG2,r12
	mfspr	r13,SPRN_DAR
	mfspr	r12,SPRN_DSISR
	srdi	r13,r13,60
	rlwimi	r13,r12,16,0x20
	mfcr	r12
	cmpwi	r13,0x2c
	beq	.do_stab_bolted_iSeries
	mtcrf	0x80,r12
	mfspr	r12,SPRN_SPRG2
END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
142 143
	EXCEPTION_PROLOG_1(PACA_EXGEN)
	EXCEPTION_PROLOG_ISERIES_1
144 145 146 147 148
	b	data_access_common

.do_stab_bolted_iSeries:
	mtcrf	0x80,r12
	mfspr	r12,SPRN_SPRG2
149 150
	EXCEPTION_PROLOG_1(PACA_EXSLB)
	EXCEPTION_PROLOG_ISERIES_1
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
	b	.do_stab_bolted

	.globl	data_access_slb_iSeries
data_access_slb_iSeries:
	mtspr	SPRN_SPRG1,r13		/* save r13 */
	mfspr	r13,SPRN_SPRG3		/* get paca address into r13 */
	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)
	mfspr	r10,SPRN_SPRG1
	std	r10,PACA_EXSLB+EX_R13(r13)
	ld	r12,PACALPPACAPTR(r13)
	ld	r12,LPPACASRR1(r12)
	b	.slb_miss_realmode

174
	STD_EXCEPTION_ISERIES(instruction_access, PACA_EXGEN)
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208

	.globl	instruction_access_slb_iSeries
instruction_access_slb_iSeries:
	mtspr	SPRN_SPRG1,r13		/* save r13 */
	mfspr	r13,SPRN_SPRG3		/* get paca address into r13 */
	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)
	mfspr	r10,SPRN_SPRG1
	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)
	mfspr	r10,SPRG1
	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)
209
	EXCEPTION_PROLOG_ISERIES_1
210 211 212
	b	slb_miss_user_common
#endif

213 214 215 216 217 218 219
	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)
220 221 222 223 224

	.globl	system_call_iSeries
system_call_iSeries:
	mr	r9,r13
	mfspr	r13,SPRN_SPRG3
225
	EXCEPTION_PROLOG_ISERIES_1
226 227
	b	system_call_common

228 229 230
	STD_EXCEPTION_ISERIES(single_step, PACA_EXGEN)
	STD_EXCEPTION_ISERIES(trap_0e, PACA_EXGEN)
	STD_EXCEPTION_ISERIES(performance_monitor, PACA_EXGEN)
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256

decrementer_iSeries_masked:
	/* We may not have a valid TOC pointer in here. */
	li	r11,1
	ld	r12,PACALPPACAPTR(r13)
	stb	r11,LPPACADECRINT(r12)
	LOAD_REG_IMMEDIATE(r12, tb_ticks_per_jiffy)
	lwz	r12,0(r12)
	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 */

257 258
_INIT_STATIC(__start_initialization_iSeries)
	/* Clear out the BSS */
259 260
	LOAD_REG_ADDR(r11,__bss_stop)
	LOAD_REG_ADDR(r8,__bss_start)
261 262 263 264 265 266 267 268 269 270
	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:
271
	LOAD_REG_ADDR(r1,init_thread_union)
272 273 274 275 276 277 278 279 280 281
	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