/*
* Boot code and exception vectors for Book3E processors
*
* Copyright (C) 2007 Ben. Herrenschmidt (benh@kernel.crashing.org), IBM Corp.
*
* 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 <linux/threads.h>
#include <asm/reg.h>
#include <asm/page.h>
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
#include <asm/cputable.h>
#include <asm/setup.h>
#include <asm/thread_info.h>
#include <asm/exception-64e.h>
#include <asm/bug.h>
#include <asm/irqflags.h>
#include <asm/ptrace.h>
#include <asm/ppc-opcode.h>
#include <asm/mmu.h>
/* XXX This will ultimately add space for a special exception save
* structure used to save things like SRR0/SRR1, SPRGs, MAS, etc...
* when taking special interrupts. For now we don't support that,
* special interrupts from within a non-standard level will probably
* blow you up
*/
#define SPECIAL_EXC_FRAME_SIZE INT_FRAME_SIZE
/* Exception prolog code for all exceptions */
#define EXCEPTION_PROLOG(n, type, addition) \
mtspr SPRN_SPRG_##type##_SCRATCH,r13; /* get spare registers */ \
mfspr r13,SPRN_SPRG_PACA; /* get PACA */ \
std r10,PACA_EX##type+EX_R10(r13); \
std r11,PACA_EX##type+EX_R11(r13); \
mfcr r10; /* save CR */ \
addition; /* additional code for that exc. */ \
std r1,PACA_EX##type+EX_R1(r13); /* save old r1 in the PACA */ \
stw r10,PACA_EX##type+EX_CR(r13); /* save old CR in the PACA */ \
mfspr r11,SPRN_##type##_SRR1;/* what are we coming from */ \
type##_SET_KSTACK; /* get special stack if necessary */\
andi. r10,r11,MSR_PR; /* save stack pointer */ \
beq 1f; /* branch around if supervisor */ \
ld r1,PACAKSAVE(r13); /* get kernel stack coming from usr */\
1: cmpdi cr1,r1,0; /* check if SP makes sense */ \
bge- cr1,exc_##n##_bad_stack;/* bad stack (TODO: out of line) */ \
mfspr r10,SPRN_##type##_SRR0; /* read SRR0 before touching stack */
/* Exception type-specific macros */
#define GEN_SET_KSTACK \
subi r1,r1,INT_FRAME_SIZE; /* alloc frame on kernel stack */
#define SPRN_GEN_SRR0 SPRN_SRR0
#define SPRN_GEN_SRR1 SPRN_SRR1
#define CRIT_SET_KSTACK \
ld r1,PACA_CRIT_STACK(r13); \
subi r1,r1,SPECIAL_EXC_FRAME_SIZE;
#define SPRN_CRIT_SRR0 SPRN_CSRR0
#define SPRN_CRIT_SRR1 SPRN_CSRR1
#define DBG_SET_KSTACK \
ld r1,PACA_DBG_STACK(r13); \
subi r1,r1,SPECIAL_EXC_FRAME_SIZE;
#define SPRN_DBG_SRR0 SPRN_DSRR0
#define SPRN_DBG_SRR1 SPRN_DSRR1
#define MC_SET_KSTACK \
ld r1,PACA_MC_STACK(r13); \
subi r1,r1,SPECIAL_EXC_FRAME_SIZE;
#define SPRN_MC_SRR0 SPRN_MCSRR0
#define SPRN_MC_SRR1 SPRN_MCSRR1
#define NORMAL_EXCEPTION_PROLOG(n, addition) \
EXCEPTION_PROLOG(n, GEN, addition##_GEN)
#define CRIT_EXCEPTION_PROLOG(n, addition) \
EXCEPTION_PROLOG(n, CRIT, addition##_CRIT)
#define DBG_EXCEPTION_PROLOG(n, addition) \
EXCEPTION_PROLOG(n, DBG, addition##_DBG)
#define MC_EXCEPTION_PROLOG(n, addition) \
EXCEPTION_PROLOG(n, MC, addition##_MC)
/* Variants of the "addition" argument for the prolog
*/
#define PROLOG_ADDITION_NONE_GEN
#define PROLOG_ADDITION_NONE_CRIT
#define PROLOG_ADDITION_NONE_DBG
#define PROLOG_ADDITION_NONE_MC
#define PROLOG_ADDITION_MASKABLE_GEN \
lbz r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */ \
cmpwi cr0,r11,0; /* yes -> go out of line */ \
beq masked_interrupt_book3e;
#define PROLOG_ADDITION_2REGS_GEN \
std r14,PACA_EXGEN+EX_R14(r13); \
std r15,PACA_EXGEN+EX_R15(r13)
#define PROLOG_ADDITION_1REG_GEN \
std r14,PACA_EXGEN+EX_R14(r13);
#define PROLOG_ADDITION_2REGS_CRIT \
std r14,PACA_EXCRIT+EX_R14(r13); \