iseries_head.s
来自「是关于linux2.5.1的完全源码」· S 代码 · 共 1,513 行 · 第 1/3 页
S
1,513 行
/* * arch/ppc/kernel/iSeries_head.S * * Adapted from arch/ppc/kernel/head.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 iSeries by Mike Corrigan * Updated by Dave Boutcher * * This file contains the low-level support and setup for the * iSeries LPAR platform. * * 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/config.h>#include <asm/processor.h>#include <asm/page.h>#include <asm/mmu.h>#include <asm/pgtable.h>#include <asm/ppc_asm.h>#include <asm/thread_info.h>#include "ppc_defs.h"#include "iSeries_asm.h" .text .globl _stext_stext:/* iSeries LPAR * * In an iSeries partition, the operating system has no direct access * to the hashed page table. The iSeries hypervisor manages the * hashed page table, and is directed by the operating system in the * partition. The partition, Linux in this case, always runs with * MSR.IR and MSR.DR equal to 1. The hypervisor establishes * addressibility for the first 64 MB of memory at 0xC0000000 by * building a hashed page table and setting segment register 12. * * The partition memory is not physically contiguous, nor necessarily * addressable with a 32-bit address. The hypervisor provides functions * which the kernel can use to discover the layout of memory. The * iSeries LPAR specific code in the kernel will build a table that maps * contiguous pseudo-real addresses starting at zero to the actual * physical addresses owned by this partition. In 32-bit mode we will * restrict ourselves to no more than 768 MB (or maybe 1 GB) * * When Linux interrupt handlers get control, the hypervisor has * already saved SRR0 and SRR1 into a control block shared between * the hypervisor and Linux. This is know as the ItLpPaca. The values * in the actual SRR0 and SRR1 are not valid. This requires a change in * the way the SPRG registers are used. The definitions are: * * Register old definition new definition * * SPRG0 temp - used to save gpr reserved for hypervisor * SPRG1 temp - used to save gpr addr of Paca * SPRG2 0 or kernel stack frame temp - used to save gpr * SPRG3 Linux thread Linux thread * * The Paca contains the address of the ItLpPaca. The Paca is known only * to Linux, while the ItLpPaca is shared between Linux and the * hypervisor. * * The value that used to be in SPRG2 will now be saved in the Paca, * as will at least one GPR. */ .globl __start__start: b start_here . = 0x020 /* iSeries LPAR hypervisor expects a 64-bit offset of the hvReleaseData structure (see HvReleaseData.h) at offset 0x20. This is the base for all common control blocks between the hypervisor and the kernel */ .long 0 .long hvReleaseData-KERNELBASE .long 0 .long msChunks-KERNELBASE .long 0 .long pidhash-KERNELBASE /* Pointer to start of embedded System.map */ .long 0 .globl embedded_sysmap_startembedded_sysmap_start: .long 0 /* Pointer to end of embedded System.map */ .long 0 .globl embedded_sysmap_endembedded_sysmap_end: .long 0 . = 0x060 .globl ste_fault_countste_fault_count: .long 0 .globl set_context_countset_context_count: .long 0 .globl yield_countyield_count: .long 0 .globl update_times_countupdate_times_count: .long 0 .globl update_wall_jiffies_countupdate_wall_jiffies_count: .long 0 .globl update_wall_jiffies_ticksupdate_wall_jiffies_ticks: .long 0/* * We assume SPRG1 has the address of the Paca and SPRG3 * has the address of the task's thread_struct. * SPRG2 is used as a scratch register (as required by the * hypervisor). SPRG0 is reserved for the hypervisor. * * The ItLpPaca has the values of SRR0 and SRR1 that the * hypervisor saved at the point of the actual interrupt. * * The Paca contains the value that the non-LPAR PPC Linux Kernel * keeps in SPRG2, which is either zero (if the interrupt * occurred in the kernel) or the address of the available * space on the kernel stack (if the interrupt occurred * in user code).*/#define EXCEPTION_PROLOG_1 \ mtspr SPRG2,r20; /* use SPRG2 as scratch reg */\ mfspr r20,SPRG1; /* get Paca */\ /* must do std not stw because soft disable protects \ * 64-bit register use (in HvCall, maybe others) \ */\ std r21,PACAR21(r20); /* Save GPR21 in Paca */\ std r22,PACAR22(r20); /* Save GPR22 in Paca */\ mfcr r22 /* Get CR */#define EXCEPTION_PROLOG_2 \ lwz r21,PACAKSAVE(r20); /* exception stack to use */\ cmpwi 0,r21,0; /* user mode or kernel */\ bne 1f; /* 0 -> r1, else use PACAKSAVE */\ subi r21,r1,INT_FRAME_SIZE; /* alloc exc. frame */\1: stw r1,GPR1(r21); \ mr r1,r21; \ stw r22,_CCR(r1); /* save CR in stackframe */ \ mflr r22; \ stw r22,_LINK(r1); /* Save LR in stackframe */ \ bl save_regs; /* now save everything else */ \ ld r22,PACALPPACA+LPPACASRR0(r20); /* Get SRR0 from ItLpPaca */\ ld r23,PACALPPACA+LPPACASRR1(r20) /* Get SRR1 from ItLpPaca */#define EXCEPTION_PROLOG_EXIT \ mtcrf 0xff,r22; \ ld r22,PACALPPACA+LPPACASRR0(r20); \ ld r21,PACALPPACA+LPPACASRR1(r20); \ mtspr SRR0,r22; \ mtspr SRR1,r21; \ ld r22,PACAR22(r20); \ ld r21,PACAR21(r20); \ mfspr r20,SPRG2; \ RFI#define EXCEPTION_PROLOG \ EXCEPTION_PROLOG_1; \ EXCEPTION_PROLOG_2/* * Note: code which follows this uses cr0.eq (set if from kernel), * r21, r22 (SRR0), and r23 (SRR1). *//* * Exception vectors. */#define STD_EXCEPTION(n, label, hdlr) \ . = n; \label: \ EXCEPTION_PROLOG; \ addi r3,r1,STACK_FRAME_OVERHEAD; \ li r20,0; /* soft disabled */\ bl transfer_to_handler; \ .long hdlr; \ .long ret_from_except/* System reset */ . = 0x100SystemReset: mfspr r3,SPRG3 /* Get Paca address */ mtspr SPRG1,r3 /* Set Linux SPRG1 -> Paca */ lhz r24,PACAPACAINDEX(r3) /* Get processor # */ cmpi 0,r24,0 /* Are we processor 0? */ beq start_here /* Start up the first processor */ mfspr r4,CTRLF li r5,RUNLATCH andc r4,r4,r5 /* Turn off the run light */ mtspr CTRLT,r41: HMT_LOW#ifdef CONFIG_SMP lbz r23,PACAPROCSTART(r3) /* Test if this processor * should start */ cmpi 0,r23,0 bne secondary_startsecondary_smp_loop: /* Let the Hypervisor know we are alive */ /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */ lis r3,0x8002 rldicr r0,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */ rldicl r3,r3,0,48 /* r3 = r3 & 0x000000000000ffff */ or r3,r3,r0 /* r3 = r3 | r0 */#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 r3,SPRG1 /* Put r3 back */ b 1b /* If SMP not configured, secondaries * loop forever *//* Machine check */ STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)/* Data access exception. */ . = 0x300DataAccess: EXCEPTION_PROLOG mfspr r4,DAR stw r4,_DAR(r1) mfspr r5,DSISR stw r5,_DSISR(r1) andis. r0,r5,0x0020 /* Is this a segment fault? */ bne ste_fault /* Yes - go reload segment regs */ /* This should and with 0xd7ff */ andis. r0,r5,0xa470 /* Can we handle as little fault? */ bne 1f /* */ rlwinm r3,r5,32-15,21,21 /* DSISR_STORE -> _PAGE_RW */ /* * r3 contains the required access permissions * r4 contains the faulting address */ stw r22,_NIP(r1) /* Help with debug if dsi loop */ bl hash_page /* Try to handle as hpte fault */ lwz r4,_DAR(r1) /* Get original DAR */ lwz r5,_DSISR(r1) /* and original DSISR */1: addi r3,r1,STACK_FRAME_OVERHEAD lwz r20,_SOFTE(r1) bl transfer_to_handler .long do_page_fault .long ret_from_except/* Instruction access exception. */ . = 0x400InstructionAccess: EXCEPTION_PROLOG mr r4,r22 mr r5,r23 andis. r0,r23,0x0020 /* Is this a segment fault? */ bne ste_fault /* Yes - go reload segment regs */ andis. r0,r23,0x4000 /* no pte found? */ beq 1f /* if so, try to put a PTE */ li r3,0 bl hash_page /* Try to handle as hpte fault */ mr r4,r22 mr r5,r231: addi r3,r1,STACK_FRAME_OVERHEAD lwz r20,_SOFTE(r1) bl transfer_to_handler .long do_page_fault .long ret_from_except/* External interrupt */ . = 0x500;HardwareInterrupt: EXCEPTION_PROLOG_1 lbz r21,PACAPROCENABLED(r20) cmpi 0,r21,0 bne 1f EXCEPTION_PROLOG_EXIT1: EXCEPTION_PROLOG_2do_pending_int: addi r3,r1,STACK_FRAME_OVERHEAD li r4,0 li r20,0 /* Soft disabled */ bl transfer_to_handler .globl do_IRQ_interceptdo_IRQ_intercept: .long do_IRQ; .long ret_from_intercept/* Alignment exception */ . = 0x600Alignment: EXCEPTION_PROLOG mfspr r4,DAR stw r4,_DAR(r1) mfspr r5,DSISR stw r5,_DSISR(r1) addi r3,r1,STACK_FRAME_OVERHEAD lbz r20,PACAPROCENABLED(r20) /* preserve soft en/disabled */ bl transfer_to_handler .long AlignmentException .long ret_from_except/* Program check exception */ . = 0x700ProgramCheck: EXCEPTION_PROLOG addi r3,r1,STACK_FRAME_OVERHEAD lbz r20,PACAPROCENABLED(r20) /* preserve soft en/disabled */ bl transfer_to_handler .long ProgramCheckException .long ret_from_except/* Floating-point unavailable */ . = 0x800FPUnavailable: EXCEPTION_PROLOG lwz r3,PACAKSAVE(r20) cmpwi 0,r3,0 beq 1f b load_up_fpu1: li r20,0 /* soft disabled */ bl transfer_to_handler /* if from kernel, take a trap */ .long KernelFP .long ret_from_except . = 0x900Decrementer: EXCEPTION_PROLOG_1 lbz r21,PACAPROCENABLED(r20) cmpi 0,r21,0 bne 1f li r21,1 stb r21,PACALPPACA+LPPACADECRINT(r20) lwz r21,PACADEFAULTDECR(r20) mtspr DEC,r21 EXCEPTION_PROLOG_EXIT1: EXCEPTION_PROLOG_2 addi r3,r1,STACK_FRAME_OVERHEAD li r20,0 /* Soft disabled */ bl transfer_to_handler .globl timer_interrupt_intercepttimer_interrupt_intercept: .long timer_interrupt .long ret_from_intercept STD_EXCEPTION(0xa00, Trap_0a, UnknownException) STD_EXCEPTION(0xb00, Trap_0b, UnknownException)/* System call */ . = 0xc00SystemCall: EXCEPTION_PROLOG /* Store r3 to the kernel stack */ stw r3,ORIG_GPR3(r1) lbz r20,PACAPROCENABLED(r20) /* preserve soft en/disabled */ bl transfer_to_handler .long DoSyscall .long ret_from_except/* Single step - not used on 601 */ STD_EXCEPTION(0xd00, SingleStep, SingleStepException)/* STD_EXCEPTION(0xe00, Trap_0e, UnknownException) STD_EXCEPTION(0xf00, Trap_0f, UnknownException)*/ STD_EXCEPTION(0x1300, Trap_13, InstructionBreakpoint)/* STD_EXCEPTION(0x1400, SMI, SMIException) STD_EXCEPTION(0x1500, Trap_15, UnknownException) STD_EXCEPTION(0x1600, Trap_16, UnknownException) STD_EXCEPTION(0x1700, Trap_17, TAUException) STD_EXCEPTION(0x1800, Trap_18, UnknownException) STD_EXCEPTION(0x1900, Trap_19, UnknownException) STD_EXCEPTION(0x1a00, Trap_1a, UnknownException) STD_EXCEPTION(0x1b00, Trap_1b, UnknownException) STD_EXCEPTION(0x1c00, Trap_1c, UnknownException) STD_EXCEPTION(0x1d00, Trap_1d, UnknownException) STD_EXCEPTION(0x1e00, Trap_1e, UnknownException) STD_EXCEPTION(0x1f00, Trap_1f, UnknownException) STD_EXCEPTION(0x2000, RunMode, RunModeException) STD_EXCEPTION(0x2100, Trap_21, UnknownException) STD_EXCEPTION(0x2200, Trap_22, UnknownException) STD_EXCEPTION(0x2300, Trap_23, UnknownException) STD_EXCEPTION(0x2400, Trap_24, UnknownException) STD_EXCEPTION(0x2500, Trap_25, UnknownException) STD_EXCEPTION(0x2600, Trap_26, UnknownException) STD_EXCEPTION(0x2700, Trap_27, UnknownException) STD_EXCEPTION(0x2800, Trap_28, UnknownException) STD_EXCEPTION(0x2900, Trap_29, UnknownException) STD_EXCEPTION(0x2a00, Trap_2a, UnknownException) STD_EXCEPTION(0x2b00, Trap_2b, UnknownException) STD_EXCEPTION(0x2c00, Trap_2c, UnknownException) STD_EXCEPTION(0x2d00, Trap_2d, UnknownException) STD_EXCEPTION(0x2e00, Trap_2e, UnknownException) STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)*/ . = 0x3000 /* This code saves: CTR, XER, DAR, DSISR, SRR0, SRR1, */ /* r0, r2-r13, r20-r24 */ /* It uses R22 as a scratch register */save_regs: ld r22,PACAR21(r20) /* Get GPR21 from Paca */ stw r22,GPR21(r1) /* Save GPR21 in stackframe */ ld r22,PACAR22(r20) /* Get GPR22 from Paca */ stw r22,GPR22(r1) /* Save GPR22 in stackframe */ stw r23,GPR23(r1) /* Save GPR23 in stackframe */ stw r24,GPR24(r1) /* Save GPR24 in stackframe */ mfspr r22,SPRG2 /* Get GPR20 from SPRG2 */ stw r22,GPR20(r1) /* Save GPR20 in stackframe */ mfctr r22 stw r22,_CTR(r1) mfspr r22,XER stw r22,_XER(r1) lbz r22,PACAPROCENABLED(r20)/* Get soft enabled/disabled */ stw r22,_SOFTE(r1) stw r0,GPR0(r1) SAVE_8GPRS(2, r1) SAVE_4GPRS(10, r1) blr ste_fault: bl set_kernel_segregs mfspr r3,SPRG1 li r4,0 stb r4,PACAPROCENABLED(r3) /* Soft disable prevents going to */ /* do_pending_int on recursive fault */ lis r3,ste_fault_count@ha lwz r4,ste_fault_count@l(r3) addi r4,r4,1 stw r4,ste_fault_count@l(r3) mfspr r3,SPRG3 /* get thread */ addi r3,r3,-THREAD /* get 'current' */ lwz r3,MM(r3) /* get mm */ cmpi 0,r3,0 /* if no mm */ beq 1f /* then use context 0 (kernel) */ lwz r3,CONTEXT(r3) /* get context */1: /* set_context kills r0, r3, r4 and CTR */ bl set_context lwz r3,_SOFTE(r1) cmpi 0,r3,0 beq 5f /* skip checks if restoring disabled */ CHECKANYINT(r4,r5,r6) /* if pending interrupts, process them */ bne- do_pending_int5: mfspr r4,SPRG1 stb r3,PACAPROCENABLED(r4) /* Restore enabled/disabled */ b fault_exit /* * This code finishes saving the registers to the exception frame * and jumps to the appropriate handler for the exception, turning * on address translation. * * At this point r0-r13, r20-r24, CCR, CTR, LINK, XER, DAR and DSISR
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?