#include <linux/init.h>
#include <linux/magic.h>
#include <linux/pgtable.h>
#include <linux/sizes.h>
#include <linux/linkage.h>
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/mmu.h>
#include <asm/cache.h>
#include <asm/cputable.h>
#include <asm/thread_info.h>
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
#include <asm/ptrace.h>
#include <asm/code-patching-asm.h>
#include <asm/interrupt.h>
#define RPN_PATTERN 0x00f0
#include "head_32.h"
#define PAGE_SHIFT_512K 19
#define PAGE_SHIFT_8M 23
__HEAD
_GLOBAL(_stext);
_GLOBAL(_start);
.globl __start
__start:
mr r31,r3
bl initial_mmu
turn_on_mmu:
mfmsr r0
ori r0,r0,MSR_DR|MSR_IR
mtspr SPRN_SRR1,r0
lis r0,start_here@h
ori r0,r0,start_here@l
mtspr SPRN_SRR0,r0
rfi
#ifdef CONFIG_PERF_EVENTS
.align 4
.globl itlb_miss_counter
itlb_miss_counter:
.space 4
.globl dtlb_miss_counter
dtlb_miss_counter:
.space 4
.globl instruction_counter
instruction_counter:
.space 4
#endif
EXCEPTION(INTERRUPT_SYSTEM_RESET, Reset, system_reset_exception)
START_EXCEPTION(INTERRUPT_MACHINE_CHECK, MachineCheck)
EXCEPTION_PROLOG INTERRUPT_MACHINE_CHECK MachineCheck handle_dar_dsisr=1
prepare_transfer_to_handler
bl machine_check_exception
b interrupt_return
EXCEPTION(INTERRUPT_EXTERNAL, HardwareInterrupt, do_IRQ)
START_EXCEPTION(INTERRUPT_ALIGNMENT, Alignment)
EXCEPTION_PROLOG INTERRUPT_ALIGNMENT Alignment handle_dar_dsisr=1
prepare_transfer_to_handler
bl alignment_exception
REST_NVGPRS(r1)
b interrupt_return
START_EXCEPTION(INTERRUPT_PROGRAM, ProgramCheck)
EXCEPTION_PROLOG INTERRUPT_PROGRAM ProgramCheck
prepare_transfer_to_handler
bl program_check_exception
REST_NVGPRS(r1)
b interrupt_return
EXCEPTION(INTERRUPT_DECREMENTER, Decrementer, timer_interrupt)
START_EXCEPTION(INTERRUPT_SYSCALL, SystemCall)
SYSCALL_ENTRY INTERRUPT_SYSCALL
EXCEPTION(INTERRUPT_TRACE, SingleStep, single_step_exception)
START_EXCEPTION(INTERRUPT_SOFT_EMU_8xx, SoftEmu)
EXCEPTION_PROLOG INTERRUPT_SOFT_EMU_8xx SoftEmu
prepare_transfer_to_handler
bl emulation_assist_interrupt
REST_NVGPRS(r1)
b interrupt_return
#ifdef CONFIG_8xx_CPU15
#define INVALIDATE_ADJACENT_PAGES_CPU15(addr, tmp) \
addi tmp, addr, PAGE_SIZE; \
tlbie tmp; \
addi tmp, addr, -PAGE_SIZE; \
tlbie tmp
#else
#define INVALIDATE_ADJACENT_PAGES_CPU15(addr, tmp)
#endif
START_EXCEPTION(INTERRUPT_INST_TLB_MISS_8xx, InstructionTLBMiss)
mtspr SPRN_SPRG_SCRATCH2, r10
mtspr SPRN_M_TW, r11
mfspr r10, SPRN_SRR0
INVALIDATE_ADJACENT_PAGES_CPU15(r10, r11)
mtspr SPRN_MD_EPN, r10
mfspr r10, SPRN_M_TWB
lwz r11, 0(r10)
mtspr SPRN_MD_TWC, r11
mfspr r10, SPRN_MD_TWC
lwz r10, 0(r10)
rlwimi r11, r10, 0, _PAGE_GUARDED | _PAGE_ACCESSED
rlwimi r11, r10, 32 - 9, _PMD_PAGE_512K
mtspr SPRN_MI_TWC, r11
rlwinm r10, r10, 0, ~0x0f00
rlwimi r10, r10, 4, 0x0400
ori r10, r10, RPN_PATTERN | 0x200
mtspr SPRN_MI_RPN, r10
0: mfspr r10, SPRN_SPRG_SCRATCH2
mfspr r11, SPRN_M_TW
rfi
patch_site 0b, patch__itlbmiss_exit_1
#ifdef CONFIG_PERF_EVENTS
patch_site 0f, patch__itlbmiss_perf
0: lwz r10, (itlb_miss_counter - PAGE_OFFSET)@l(0)
addi r10, r10, 1
stw r10, (itlb_miss_counter - PAGE_OFFSET)@l(0)
mfspr r10, SPRN_SPRG_SCRATCH2
mfspr r11, SPRN_M_TW
rfi
#endif
START_EXCEPTION(INTERRUPT_DATA_TLB_MISS_8xx, DataStoreTLBMiss)
mtspr SPRN_SPRG_SCRATCH2, r10
mtspr SPRN_M_TW, r11
mfspr r10, SPRN_M_TWB
lwz r11, 0(r10)
mtspr SPRN_MD_TWC, r11
mfspr r10, SPRN_MD_TWC
lwz r10, 0(r10)
rlwimi r11, r10, 0, _PAGE_GUARDED | _PAGE_ACCESSED
rlwimi r11, r10, 32 - 9, _PMD_PAGE_512K
mtspr SPRN_MD_TWC, r11
li r11, RPN_PATTERN
rlwimi r10, r11, 0, 24, 27
mtspr SPRN_MD_RPN, r10
mtspr SPRN_DAR, r11
0: mfspr r10, SPRN_SPRG_SCRATCH2
mfspr r11, SPRN_M_TW
rfi
patch_site 0b, patch__dtlbmiss_exit_1
#ifdef CONFIG_PERF_EVENTS
patch_site 0f, patch__dtlbmiss_perf
0: lwz r10, (dtlb_miss_counter - PAGE_OFFSET)@l(0)
addi r10, r10, 1
stw r10, (dtlb_miss_counter - PAGE_OFFSET)@l(0)
mfspr r10, SPRN_SPRG_SCRATCH2
mfspr r11, SPRN_M_TW
rfi
#endif
START_EXCEPTION(INTERRUPT_INST_TLB_ERROR_8xx, InstructionTLBError)
EXCEPTION_PROLOG INTERRUPT_INST_STORAGE InstructionTLBError
andis. r5,r9,DSISR_SRR1_MATCH_32S@h
andis. r10,r9,SRR1_ISI_NOPT@h
beq+ .Litlbie
tlbie r12
.Litlbie:
stw r12, _DAR(r11)
stw r5, _DSISR(r11)
prepare_transfer_to_handler
bl do_page_fault
b interrupt_return
START_EXCEPTION(INTERRUPT_DATA_TLB_ERROR_8xx, DataTLBError)
EXCEPTION_PROLOG_0 handle_dar_dsisr=1
mfspr r11, SPRN_DAR
cmpwi cr1, r11, RPN_PATTERN
beq- cr1, FixupDAR
DARFixed:
mfspr r11, SPRN_DSISR
rlwinm r11, r11, 0, DSISR_NOHPTE
cmpwi cr1, r11, 0
beq+ cr1, .Ldtlbie
mfspr r11, SPRN_DAR
tlbie r11
rlwinm r11, r11, 16, 0xffff
cmplwi cr1, r11, TASK_SIZE@h
bge- cr1, FixupPGD
.Ldtlbie:
EXCEPTION_PROLOG_1
EXCEPTION_PROLOG_2 INTERRUPT_DATA_STORAGE DataTLBError handle_dar_dsisr=1
prepare_transfer_to_handler
bl do_page_fault
b interrupt_return
#ifdef CONFIG_VMAP_STACK
vmap_stack_overflow_exception
#endif
START_EXCEPTION(INTERRUPT_DATA_BREAKPOINT_8xx, DataBreakpoint)
EXCEPTION_PROLOG_0 handle_dar_dsisr=1
mfspr r11, SPRN_SRR0
cmplwi cr1, r11, (.Ldtlbie - PAGE_OFFSET)@l
cmplwi cr7, r11, (.Litlbie - PAGE_OFFSET)@l
cror 4*cr1+eq, 4*cr1+eq, 4*cr7+eq
bne cr1, 1f
mtcr r10
mfspr r10, SPRN_SPRG_SCRATCH0
mfspr r11, SPRN_SPRG_SCRATCH1
rfi
1: EXCEPTION_PROLOG_1
EXCEPTION_PROLOG_2 INTERRUPT_DATA_BREAKPOINT_8xx DataBreakpoint handle_dar_dsisr=1
mfspr r4,SPRN_BAR
stw r4,_DAR(r11)
prepare_transfer_to_handler
bl do_break
REST_NVGPRS(r1)
b interrupt_return
#ifdef CONFIG_PERF_EVENTS
START_EXCEPTION(INTERRUPT_INST_BREAKPOINT_8xx, InstructionBreakpoint)
mtspr SPRN_SPRG_SCRATCH0, r10
lwz r10, (instruction_counter - PAGE_OFFSET)@l(0)
addi r10, r10, -1
stw r10, (instruction_counter - PAGE_OFFSET)@l(0)
lis r10, 0xffff
ori r10, r10, 0x01
mtspr SPRN_COUNTA, r10
mfspr r10, SPRN_SPRG_SCRATCH0
rfi
#else
EXCEPTION(INTERRUPT_INST_BREAKPOINT_8xx, Trap_1d, unknown_exception)
#endif
EXCEPTION(0x1e00, Trap_1e, unknown_exception)
EXCEPTION(0x1f00, Trap_1f, unknown_exception)
__HEAD
. = 0x2000
FixupPGD:
mtspr SPRN_M_TW, r10
mfspr r10, SPRN_DAR
mtspr SPRN_MD_EPN, r10
mfspr r11, SPRN_M_TWB
lwz r10, 0(r11)
cmpwi cr1, r10, 0
bne cr1, 1f
rlwinm r10, r11, 0, 20, 31
oris r10, r10, (swapper_pg_dir - PAGE_OFFSET)@ha
lwz r10, (swapper_pg_dir - PAGE_OFFSET)@l(r10)
cmpwi cr1, r10, 0
beq cr1, 1f
stw r10, 0(r11)
mfspr r10, SPRN_M_TW
mtcr r10
mfspr r10, SPRN_SPRG_SCRATCH0
mfspr r11, SPRN_SPRG_SCRATCH1
rfi
1:
mfspr r10, SPRN_M_TW
b .Ldtlbie
FixupDAR:
mtspr SPRN_M_TW, r10
mfspr r10, SPRN_SRR0
mtspr SPRN_MD_EPN, r10
rlwinm r11, r10, 16, 0xfff8
cmpli cr1, r11, TASK_SIZE@h
mfspr r11, SPRN_M_TWB
blt+ cr1, 3f
tophys(r11, r10)
mfspr r11, SPRN_M_TWB
rlwinm r11, r11, 0, 20, 31
oris r11, r11, (swapper_pg_dir - PAGE_OFFSET)@h
ori r11, r11, (swapper_pg_dir - PAGE_OFFSET)@l
3:
lwz r11, 0(r11)
rlwinm r11, r11, 0, ~_PMD_PAGE_8M
mtspr SPRN_MD_TWC, r11
mfspr r11, SPRN_MD_TWC
lwz r11, 0(r11)
rlwimi r11, r10, 0, 32 - PAGE_SHIFT, 31
lwz r11,0(r11)
xoris r10, r11, 0x7c00
rlwinm r10, r10, 0, 21, 5
cmpwi cr1, r10, 2028
beq+ cr1, 142f
cmpwi cr1, r10, 940
beq+ cr1, 142f
cmpwi cr1, r10, 108
beq+ cr1, 144f
cmpwi cr1, r10, 172
beq+ cr1, 142f
cmpwi cr1, r10, 1964
beq+ cr1, 142f
141: mfspr r10,SPRN_M_TW
b DARFixed
144: mfspr r10, SPRN_DSISR
rlwinm r10, r10,0,7,5
mtspr SPRN_DSISR, r10
142:
mfctr r10
mtdar r10
rlwinm r10, r11, 24, 24, 28
addi r10, r10, 150f@l
mtctr r10
xor r10, r10, r10
bctr
150:
add r10, r10, r0 ;b 151f
add r10, r10, r1 ;b 151f
add r10, r10, r2 ;b 151f
add r10, r10, r3 ;b 151f
add r10, r10, r4 ;b 151f
add r10, r10, r5 ;b 151f
add r10, r10, r6 ;b 151f
add r10, r10, r7 ;b 151f
add r10, r10, r8 ;b 151f
add r10, r10, r9 ;b 151f
mtctr r11 ;b 154f
mtctr r11 ;b 153f
add r10, r10, r12 ;b 151f
add r10, r10, r13 ;b 151f
add r10, r10, r14 ;b 151f
add r10, r10, r15 ;b 151f
add r10, r10, r16 ;b 151f
add r10, r10, r17 ;b 151f
add r10, r10, r18 ;b 151f
add r10, r10, r19 ;b 151f
add r10, r10, r20 ;b 151f
add r10, r10, r21 ;b 151f
add r10, r10, r22 ;b 151f
add r10, r10, r23 ;b 151f
add r10, r10, r24 ;b 151f
add r10, r10, r25 ;b 151f
add r10, r10, r26 ;b 151f
add r10, r10, r27 ;b 151f
add r10, r10, r28 ;b 151f
add r10, r10, r29 ;b 151f
add r10, r10, r30 ;b 151f
add r10, r10, r31
151:
rlwinm r11,r11,19,24,28
cmpwi cr1, r11, 0
beq cr1, 152f
addi r11, r11, 150b@l
mtctr r11
rlwinm r11,r11,0,16,10
bctr
152:
mfdar r11
mtdar r10
mtctr r11
mfspr r11, SPRN_SPRG_THREAD
stw r10, DAR(r11)
mfspr r10, SPRN_DSISR
stw r10, DSISR(r11)
mfspr r10,SPRN_M_TW
b DARFixed
153: mfspr r11, SPRN_SPRG_SCRATCH1
add r10, r10, r11
mfctr r11
b 151b
154: mfspr r11, SPRN_SPRG_SCRATCH0
add r10, r10, r11
mfctr r11
b 151b
start_here:
lis r2,init_task@h
ori r2,r2,init_task@l
tophys(r4,r2)
addi r4,r4,THREAD
mtspr SPRN_SPRG_THREAD,r4
lis r1,init_thread_union@ha
addi r1,r1,init_thread_union@l
lis r0, STACK_END_MAGIC@h
ori r0, r0, STACK_END_MAGIC@l
stw r0, 0(r1)
li r0,0
stwu r0,THREAD_SIZE-STACK_FRAME_MIN_SIZE(r1)
lis r6, swapper_pg_dir@h
ori r6, r6, swapper_pg_dir@l
tophys(r6,r6)
mtspr SPRN_M_TWB, r6
bl early_init
#ifdef CONFIG_KASAN
bl kasan_early_init
#endif
li r3,0
mr r4,r31
bl machine_init
bl MMU_init
lis r4,2f@h
ori r4,r4,2f@l
tophys(r4,r4)
li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
mtspr SPRN_SRR0,r4
mtspr SPRN_SRR1,r3
rfi
2:
#ifdef CONFIG_PIN_TLB_IMMR
lis r0, MD_TWAM@h
oris r0, r0, 0x1f00
mtspr SPRN_MD_CTR, r0
LOAD_REG_IMMEDIATE(r0, VIRT_IMMR_BASE | MD_EVALID)
tlbie r0
mtspr SPRN_MD_EPN, r0
LOAD_REG_IMMEDIATE(r0, MD_SVALID | MD_PS512K | MD_GUARDED)
mtspr SPRN_MD_TWC, r0
mfspr r0, SPRN_IMMR
rlwinm r0, r0, 0, 0xfff80000
ori r0, r0, 0xf0 | _PAGE_DIRTY | _PAGE_SPS | _PAGE_SH | \
_PAGE_NO_CACHE | _PAGE_PRESENT
mtspr SPRN_MD_RPN, r0
lis r0, (MD_TWAM | MD_RSV4I)@h
mtspr SPRN_MD_CTR, r0
#endif
#ifndef CONFIG_PIN_TLB_TEXT
li r0, 0
mtspr SPRN_MI_CTR, r0
#endif
#if !defined(CONFIG_PIN_TLB_DATA) && !defined(CONFIG_PIN_TLB_IMMR)
lis r0, MD_TWAM@h
mtspr SPRN_MD_CTR, r0
#endif
tlbia
sync
lis r5, abatron_pteptrs@h
ori r5, r5, abatron_pteptrs@l
stw r5, 0xf0(0)
tophys(r5,r5)
lis r6, swapper_pg_dir@h
ori r6, r6, swapper_pg_dir@l
stw r6, 0(r5)
li r4,MSR_KERNEL
lis r3,start_kernel@h
ori r3,r3,start_kernel@l
mtspr SPRN_SRR0,r3
mtspr SPRN_SRR1,r4
rfi
SYM_FUNC_START_LOCAL(initial_mmu)
li r8, 0
mtspr SPRN_MI_CTR, r8
lis r10, MD_TWAM@h
mtspr SPRN_MD_CTR, r10
tlbia
lis r8, MI_APG_INIT@h
ori r8, r8, MI_APG_INIT@l
mtspr SPRN_MI_AP, r8
lis r8, MD_APG_INIT@h
ori r8, r8, MD_APG_INIT@l
mtspr SPRN_MD_AP, r8
lis r8, MI_RSV4I@h
ori r8, r8, 0x1c00
oris r12, r10, MD_RSV4I@h
ori r12, r12, 0x1c00
li r9, 4
mtctr r9
lis r9, KERNELBASE@h
li r10, MI_PS8MEG | _PMD_ACCESSED | MI_SVALID
li r11, MI_BOOTINIT
1:
mtspr SPRN_MI_CTR, r8
addi r8, r8, 0x100
ori r0, r9, MI_EVALID
mtspr SPRN_MI_EPN, r0
mtspr SPRN_MI_TWC, r10
mtspr SPRN_MI_RPN, r11
mtspr SPRN_MD_CTR, r12
addi r12, r12, 0x100
mtspr SPRN_MD_EPN, r0
mtspr SPRN_MD_TWC, r10
mtspr SPRN_MD_RPN, r11
addis r9, r9, 0x80
addis r11, r11, 0x80
bdnz 1b
lis r8, IDC_INVALL@h
mtspr SPRN_IC_CST, r8
mtspr SPRN_DC_CST, r8
lis r8, IDC_ENABLE@h
mtspr SPRN_IC_CST, r8
mtspr SPRN_DC_CST, r8
mfspr r8, SPRN_DER
#ifdef CONFIG_PERF_EVENTS
rlwinm r8, r8, 0, ~0xc
#else
rlwinm r8, r8, 0, ~0x8
#endif
mtspr SPRN_DER, r8
blr
SYM_FUNC_END(initial_mmu)
#ifdef CONFIG_PIN_TLB
_GLOBAL(mmu_pin_tlb)
lis r9, (1f - PAGE_OFFSET)@h
ori r9, r9, (1f - PAGE_OFFSET)@l
mfmsr r10
mflr r11
li r12, MSR_KERNEL & ~(MSR_IR | MSR_DR | MSR_RI)
rlwinm r0, r10, 0, ~MSR_RI
rlwinm r0, r0, 0, ~MSR_EE
mtmsr r0
isync
.align 4
mtspr SPRN_SRR0, r9
mtspr SPRN_SRR1, r12
rfi
1:
li r5, 0
lis r6, MD_TWAM@h
mtspr SPRN_MI_CTR, r5
mtspr SPRN_MD_CTR, r6
tlbia
#ifdef CONFIG_PIN_TLB_TEXT
LOAD_REG_IMMEDIATE(r5, 28 << 8)
LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET)
LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG | _PMD_ACCESSED)
LOAD_REG_IMMEDIATE(r8, 0xf0 | _PAGE_RO | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT)
LOAD_REG_ADDR(r9, _sinittext)
li r0, 4
mtctr r0
2: ori r0, r6, MI_EVALID
mtspr SPRN_MI_CTR, r5
mtspr SPRN_MI_EPN, r0
mtspr SPRN_MI_TWC, r7
mtspr SPRN_MI_RPN, r8
addi r5, r5, 0x100
addis r6, r6, SZ_8M@h
addis r8, r8, SZ_8M@h
cmplw r6, r9
bdnzt lt, 2b
lis r0, MI_RSV4I@h
mtspr SPRN_MI_CTR, r0
#endif
LOAD_REG_IMMEDIATE(r5, 28 << 8 | MD_TWAM)
#ifdef CONFIG_PIN_TLB_DATA
LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET)
LOAD_REG_IMMEDIATE(r7, MI_SVALID | MI_PS8MEG | _PMD_ACCESSED)
li r8, 0
#ifdef CONFIG_PIN_TLB_IMMR
li r0, 3
#else
li r0, 4
#endif
mtctr r0
cmpwi r4, 0
beq 4f
LOAD_REG_ADDR(r9, _sinittext)
2: ori r0, r6, MD_EVALID
ori r12, r8, 0xf0 | _PAGE_RO | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT
mtspr SPRN_MD_CTR, r5
mtspr SPRN_MD_EPN, r0
mtspr SPRN_MD_TWC, r7
mtspr SPRN_MD_RPN, r12
addi r5, r5, 0x100
addis r6, r6, SZ_8M@h
addis r8, r8, SZ_8M@h
cmplw r6, r9
bdnzt lt, 2b
4:
2: ori r0, r6, MD_EVALID
ori r12, r8, 0xf0 | _PAGE_DIRTY | _PAGE_SPS | _PAGE_SH | _PAGE_PRESENT
mtspr SPRN_MD_CTR, r5
mtspr SPRN_MD_EPN, r0
mtspr SPRN_MD_TWC, r7
mtspr SPRN_MD_RPN, r12
addi r5, r5, 0x100
addis r6, r6, SZ_8M@h
addis r8, r8, SZ_8M@h
cmplw r6, r3
bdnzt lt, 2b
#endif
#ifdef CONFIG_PIN_TLB_IMMR
LOAD_REG_IMMEDIATE(r0, VIRT_IMMR_BASE | MD_EVALID)
LOAD_REG_IMMEDIATE(r7, MD_SVALID | MD_PS512K | MD_GUARDED | _PMD_ACCESSED)
mfspr r8, SPRN_IMMR
rlwinm r8, r8, 0, 0xfff80000
ori r8, r8, 0xf0 | _PAGE_DIRTY | _PAGE_SPS | _PAGE_SH | \
_PAGE_NO_CACHE | _PAGE_PRESENT
mtspr SPRN_MD_CTR, r5
mtspr SPRN_MD_EPN, r0
mtspr SPRN_MD_TWC, r7
mtspr SPRN_MD_RPN, r8
#endif
#if defined(CONFIG_PIN_TLB_IMMR) || defined(CONFIG_PIN_TLB_DATA)
lis r0, (MD_RSV4I | MD_TWAM)@h
mtspr SPRN_MD_CTR, r0
#endif
mtspr SPRN_SRR1, r10
mtspr SPRN_SRR0, r11
rfi
#endif