diff options
Diffstat (limited to 'arch/ppc/kernel')
28 files changed, 1953 insertions, 2891 deletions
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index 8a3a845f1..0bfb26c01 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -14,10 +14,8 @@ .c.o: $(CC) $(CFLAGS) -c $< .S.s: -# $(CPP) $(CFLAGS) -D__ASSEMBLY__ -traditional $< -o $*.s $(CPP) $(CFLAGS) -D__ASSEMBLY__ $< -o $*.s .S.o: -# $(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o $(CPP) $(CFLAGS) -D__ASSEMBLY__ $< -o $*.s $(AS) $(ASFLAGS) -o $*.o $*.s rm $*.s @@ -25,40 +23,25 @@ HOST_CC = gcc OBJS = misc.o setup.o port_io.o irq.o pci.o traps.o stubs.o process.o \ - signal.o ksyms.o time.o syscalls.o \ - support.o ptrace.o # ramdisk_drvr.o + signal.o ksyms.o time.o syscalls.o usercpy.o\ + support.o ptrace.o -all: head.o kernel.o #no_ramdisk.o ramdisk.o +all: head.o kernel.o head.o: head.s head.s: head.S $(TOPDIR)/include/linux/tasks.h ppc_defs.h ppc_defs.h: mk_defs -# simppc mk_defs -- $@ mk_defs $@ -#no_ramdisk.o: no_ramdisk.S - -#ramdisk.o: ramdisk.image mk_ramdisk -# mk_ramdisk ramdisk.image $*.s -# $(AS) -o $@ $*.s -# rm $*.s - -#mk_ramdisk: mk_ramdisk.c -# ${HOST_CC} -o mk_ramdisk mk_ramdisk.c - -mk_defs: mk_defs.c $(TOPDIR)/include/asm/mmu.h $(TOPDIR)/include/asm/processor.h $(TOPDIR)/include/asm/pgtable.h $(TOPDIR)/include/asm/ptrace.h -# cc.ppc ${CFLAGS} -o mk_defs -T ld.script-user -Ttext 0x1000 mk_defs.c - gcc.ppc ${CFLAGS} -o mk_defs mk_defs.c +mk_defs: mk_defs.c + $(HOSTCC) $(CFLAGSINC) -Wl,-static ${CFLAGS} -o mk_defs mk_defs.c kernel.o: $(OBJS) $(LD) -r -o kernel.o $(OBJS) sync -#mkboot: mkboot.c -# ${HOST_CC} -o $@ -Iinclude mkboot.c - dep: $(CPP) -M *.c > .depend diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S index bd6819c34..648c7bccf 100644 --- a/arch/ppc/kernel/head.S +++ b/arch/ppc/kernel/head.S @@ -1,16 +1,15 @@ #include "ppc_asm.tmpl" #include "ppc_defs.h" #include <linux/errno.h> -#define NEWMM +#include <linux/sys.h> +#include <asm/ppc_machine.h> + +#define NEWMM 1 #define SYNC() \ isync; \ sync -/* #define TLB_STATS */ - -/* Keep track of low-level exceptions - rather crude, but informative */ #define STATS - /* * Increment a [64 bit] statistic counter * Uses R2, R3 @@ -40,179 +39,9 @@ mtspr XER,r0; \ stw r3,0(r2) -/* These macros can be used to generate very raw traces of low-level */ -/* operations (where printf, etc. can't help). All they provide is */ -/* some after-the-fact documentation of what took place. Since [in */ -/* most instances] they have no registers to work with, they use the */ -/* hardware "special" registers SPRx for storage. Because of this, */ -/* defining more than one of them simultaneously will yield incorrect */ -/* results and a non-functional system. Note: the trick here is to */ -/* gather some data without disturbing anything - Heisenberg are you watching? */ - -/* CAUTION! Don't turn on more than one of these at once! */ -/* #define DO_TRAP_TRACE */ -/* #define DO_TLB_TRACE */ -/* #define DO_RFI_TRACE */ - -#ifdef DO_RFI_TRACE -#define DO_RFI_TRACE_UNMAPPED(mark) \ - mtspr SPR0,r1; \ - mtspr SPR1,r2; \ - mtspr SPR2,r3; \ - mfcr r3; \ - mtspr SPR3,r3; \ - lis r1,_RFI_ptr@h; \ - ori r1,r1,_RFI_ptr@l; \ - lis r3,0xF000; \ - andc r1,r1,r3; \ - lwz r1,0(r1); \ - andc r1,r1,r3; \ - subi r1,r1,4; \ - lis r2,(mark>>16); \ - ori r2,r2,(mark&0xFFFF); \ - stwu r2,4(r1); \ - mfspr r2,SRR0; \ - stwu r2,4(r1); \ - mfspr r2,SRR1; \ - stwu r2,4(r1); \ - addi r1,r1,4+4; \ - lis r2,_RFI_ptr@h; \ - ori r2,r2,_RFI_ptr@l; \ - andc r2,r2,r3; \ - stw r1,0(r2); \ - mfspr r3,SPR3; \ - mtcrf 0xFF,r3; \ - mfspr r1,SPR0; \ - mfspr r2,SPR1; \ - mfspr r3,SPR2 -#define DO_RFI_TRACE_MAPPED(mark) \ - mtspr SPR0,r1; \ - mtspr SPR1,r2; \ - mtspr SPR2,r3; \ - mfcr r3; \ - mtspr SPR3,r3; \ - lis r1,_RFI_ptr@h; \ - ori r1,r1,_RFI_ptr@l; \ - lwz r1,0(r1); \ - lis r3,0x9000; \ - or r1,r1,r3; \ - subi r1,r1,4; \ - lis r2,(mark>>16); \ - ori r2,r2,(mark&0xFFFF); \ - stwu r2,4(r1); \ - mfspr r2,SRR0; \ - stwu r2,4(r1); \ - mfspr r2,SRR1; \ - stwu r2,4(r1); \ - addi r1,r1,4+4; \ - lis r2,_RFI_ptr@h; \ - ori r2,r2,_RFI_ptr@l; \ - stw r1,0(r2); \ - mfspr r3,SPR3; \ - mtcrf 0xFF,r3; \ - mfspr r1,SPR0; \ - mfspr r2,SPR1; \ - mfspr r3,SPR2 -#else #define DO_RFI_TRACE_UNMAPPED(mark) #define DO_RFI_TRACE_MAPPED(mark) -#endif -#ifdef DO_TRAP_TRACE -#define DEFAULT_TRAP(offset) \ - mtspr SPR0,r1; \ - mtspr SPR1,r2; \ - mtspr SPR2,r3; \ - lis r1,_TRAP_ptr@h; \ - ori r1,r1,_TRAP_ptr@l; \ - lis r3,0xF000; \ - andc r1,r1,r3; \ - lwz r1,0(r1); \ - andc r1,r1,r3; \ - subi r1,r1,4; \ - lis r2,0xCACA; \ - ori r2,r2,offset; \ - stwu r2,4(r1); \ - mfspr r2,SRR0; \ - stwu r2,4(r1); \ - mfspr r2,SRR1; \ - stwu r2,4(r1); \ - mfspr r2,SPR0; \ - stwu r2,4(r1); \ - addi r1,r1,4; \ - lis r2,_TRAP_ptr@h; \ - ori r2,r2,_TRAP_ptr@l; \ - andc r2,r2,r3; \ - stw r1,0(r2); \ - mfspr r1,SPR0; \ - mfspr r2,SPR1; \ - mfspr r3,SPR2; \ - li r13,0; \ - ori r13,r13,HID0_ICE; \ - mtspr HID0,r13; \ - lis r13,0xFFF00000>>16; \ - ori r13,r13,offset; \ - mtlr r13; \ - b hang -#define TRACE_TRAP(offset) \ - mtspr SPR0,r1; \ - mtspr SPR1,r2; \ - mtspr SPR2,r3; \ - mfcr r3; \ - mtspr SPR3,r3; \ - lis r1,_TRAP_ptr@h; \ - ori r1,r1,_TRAP_ptr@l; \ - lis r3,0xF000; \ - andc r1,r1,r3; \ - lwz r1,0(r1); \ - andc r1,r1,r3; \ - subi r1,r1,4; \ - lis r2,0xCABB; \ - ori r2,r2,offset; \ - stwu r2,4(r1); \ - dcbst 0,r1; \ - mfspr r2,SRR0; \ - stwu r2,4(r1); \ - dcbst 0,r1; \ - mfspr r2,SRR1; \ - stwu r2,4(r1); \ - dcbst 0,r1; \ - li r2,offset; \ - cmpi 0,r2,0x0C00; \ - beq 01f; \ - cmpi 0,r2,0x0300; \ - beq 00f; \ - cmpi 0,r2,0x0400; \ - beq 00f; \ - mfspr r2,SPR0; \ - b 02f; \ -00: mfspr r2,DAR; \ - b 02f; \ -01: mr r2,r0; \ -02: stwu r2,4(r1); \ - dcbst 0,r1; \ - addi r1,r1,4; \ - mflr r2; \ - stw r2,0(r1); \ - bl check_trace; \ - lwz r2,0(r1); \ - mtlr r2; \ -02: lis r2,_TRAP_ptr@h; \ - ori r2,r2,_TRAP_ptr@l; \ - oris r1,r1,0x9000; \ - cmp 0,r1,r2; \ - bne 00f; \ - lis r1,_TRAP_TRACE@h; \ - ori r1,r1,_TRAP_TRACE@l; \ -00: lis r3,0xF000; \ - andc r2,r2,r3; \ - stw r1,0(r2); \ - mfspr r1,SPR0; \ - mfspr r2,SPR1; \ - mfspr r3,SPR3; \ - mtcrf 0xFF,r3; \ - mfspr r3,SPR2 -#else #define DEFAULT_TRAP(offset) \ li r13,0; \ ori r13,r13,HID0_ICE; \ @@ -222,7 +51,6 @@ mtlr r13; \ blr #define TRACE_TRAP(offset) -#endif #define DATA_CACHE_OFF() \ mfspr r2,HID0; \ @@ -246,27 +74,147 @@ bdnz 0b /* Validate kernel stack - check for overflow */ -#define CHECK_STACK() +/* all regs are considered scratch since the C function will stomp them */ +#define CHECK_STACK() \ + /*lis r3,current_set@ha; \ + lwz r3,current_set@l(r3); \ + bl _EXTERN(check_stack)*/ +#if 0 #define _CHECK_STACK() \ mtspr SPR0,r3; \ + mtspr SPR1,r4; /* use r3,4 as scratch */ \ lis r2,current_set@ha; \ lwz r2,current_set@l(r2); \ lwz r2,KERNEL_STACK_PAGE(r2); \ - lis r3,sys_stack@h; \ + /* if kernel stack is sys_stack skip check */ \ + /*lis r3,sys_stack@h; \ ori r3,r3,sys_stack@l; \ - cmpl 0,r1,r3; \ - ble 02f; \ - li r3,0x0FFF; \ + cmpl 0,r1,r3;*/ \ + /* check for STACK_MAGIC on kernel stack page */ \ + lis r3, 0xdead; /* STACK_MAGIC */ \ + ori r3,r3,0xbeef; \ + lwz r4,0(r2); /* get *kernel_stack_page */ \ + cmpl 0,r4,r3; \ + bne 01f; \ + /* check that ksp is > kernel page */ \ + /*li r3,0x0FFF; \ andc r2,r2,r3; \ andc r3,r1,r3; \ cmp 0,r3,r2; \ - beq 02f; \ - mr r3,r1; \ + beq 02f;*/ \ + /* check that ksp and kernel stack page are on same page */ \ + cmp 0,r1,r2; \ + bge 02f; \ +01: mr r6,r1; /* setup info for call to bad_stack() */ \ + mr r5,r2; \ bl _EXTERN(bad_stack); \ -02: mfspr r3,SPR0 +02: mfspr r4,SPR1; \ + mfspr r3,SPR0 +#endif + +/* save fp regs if fp is used */ +/* assumes that r1 contains ptr to regs of task and r2 is scratch + -- Cort */ +#define SAVE_FP_REGS() \ + /* check if fp has been used by checking msr_fp bit */ \ + lwz r2,_MSR(r1); \ + andi. r2,r2,MSR_FP; \ + bne 00f; \ + /* floating point has been used -- save fp regs */ \ + lis r2,current_set@h; \ + ori r2,r2,current_set@l; \ + addi r2,r2,TSS; \ + /*mr r2,r1;*/ \ + stfd fr0,TSS_FPR0(r2); \ + stfd fr1,TSS_FPR1(r2); \ + stfd fr2,TSS_FPR2(r2); \ + stfd fr3,TSS_FPR3(r2); \ + stfd fr4,TSS_FPR4(r2); \ + stfd fr5,TSS_FPR5(r2); \ + stfd fr6,TSS_FPR6(r2); \ + stfd fr7,TSS_FPR7(r2); \ + stfd fr8,TSS_FPR8(r2); \ + stfd fr9,TSS_FPR9(r2); \ + stfd fr10,TSS_FPR10(r2); \ + stfd fr11,TSS_FPR11(r2); \ + stfd fr12,TSS_FPR12(r2); \ + stfd fr13,TSS_FPR13(r2); \ + stfd fr14,TSS_FPR14(r2); \ + stfd fr15,TSS_FPR15(r2); \ + stfd fr16,TSS_FPR16(r2); \ + stfd fr17,TSS_FPR17(r2); \ + stfd fr18,TSS_FPR18(r2); \ + stfd fr19,TSS_FPR19(r2); \ + stfd fr20,TSS_FPR20(r2); \ + stfd fr21,TSS_FPR21(r2); \ + stfd fr22,TSS_FPR22(r2); \ + stfd fr23,TSS_FPR23(r2); \ + stfd fr24,TSS_FPR24(r2); \ + stfd fr25,TSS_FPR25(r2); \ + stfd fr26,TSS_FPR26(r2); \ + stfd fr27,TSS_FPR27(r2); \ + stfd fr28,TSS_FPR28(r2); \ + stfd fr29,TSS_FPR29(r2); \ + stfd fr30,TSS_FPR30(r2); \ + stfd fr31,TSS_FPR31(r2); \ +00: + -/* Save all registers on kernel stack during an exception */ -#define SAVE_REGS(mark) \ +/* restores fp regs if fp has been used -- always restores fpscr */ +/* assumes that r1 contains ptr to regs, r2 is scratch and srr1 holds + what will become the msr when this process executes -- Cort*/ +#define RESTORE_FP_REGS(mark) \ + /* check if restoring from _switch() */ \ + li r2, mark; \ + cmpi 0,r2,0x0f0f; \ + bne 00f; /* only need to save if called from _switch() with 0x0f0f */\ + /* check if fp has been used by checking msr_fp bit */ \ + /* srr1 contains msr */ \ + mfspr r2,SRR1; \ + andi. r2,r2,MSR_FP; \ + bne 00f; \ + /* floating point has been used -- restore fp regs */ \ + /* Hey, Rocky! Watch me pull fp regs from my stack! */ \ + lis r2,current_set@h; \ + ori r2,r2,current_set@l; \ + addi r2,r2,TSS; \ + /*mr r2,r1;*/\ + lfd fr0,TSS_FPR0(r2); \ + lfd fr1,TSS_FPR1(r2); \ + lfd fr2,TSS_FPR2(r2); \ + lfd fr3,TSS_FPR3(r2); \ + lfd fr4,TSS_FPR4(r2); \ + lfd fr5,TSS_FPR5(r2); \ + lfd fr6,TSS_FPR6(r2); \ + lfd fr7,TSS_FPR7(r2); \ + lfd fr8,TSS_FPR8(r2); \ + lfd fr9,TSS_FPR9(r2); \ + lfd fr10,TSS_FPR10(r2); \ + lfd fr11,TSS_FPR11(r2); \ + lfd fr12,TSS_FPR12(r2); \ + lfd fr13,TSS_FPR13(r2); \ + lfd fr14,TSS_FPR14(r2); \ + lfd fr15,TSS_FPR15(r2); \ + lfd fr16,TSS_FPR16(r2); \ + lfd fr17,TSS_FPR17(r2); \ + lfd fr18,TSS_FPR18(r2); \ + lfd fr19,TSS_FPR19(r2); \ + lfd fr20,TSS_FPR20(r2); \ + lfd fr21,TSS_FPR21(r2); \ + lfd fr22,TSS_FPR22(r2); \ + lfd fr23,TSS_FPR23(r2); \ + lfd fr24,TSS_FPR24(r2); \ + lfd fr25,TSS_FPR25(r2); \ + lfd fr26,TSS_FPR26(r2); \ + lfd fr27,TSS_FPR27(r2); \ + lfd fr28,TSS_FPR28(r2); \ + lfd fr29,TSS_FPR29(r2); \ + lfd fr30,TSS_FPR30(r2); \ + lfd fr31,TSS_FPR31(r2); \ +00: + +/* save all registers */ +#define SAVE_ALL_REGS(mark) \ subi r1,r1,INT_FRAME_SIZE; /* Make room for frame */ \ stmw r3,GPR3(r1); /* Save R3..R31 */ \ stw r3,ORIG_GPR3(r1); \ @@ -287,10 +235,6 @@ stw r2,_CCR(r1); \ mfspr r2,XER; \ stw r2,_XER(r1); \ - stfd fr0,FPR0(r1); \ - stfd fr1,FPR1(r1); \ - stfd fr2,FPR2(r1); \ - stfd fr3,FPR3(r1); \ mffs fr0; \ stfd fr0,FPCSR(r1); \ lis r2,_break_lwarx@h; \ @@ -304,9 +248,11 @@ li r2,0; \ stw r2,RESULT(r1) + +/* save registers clobbered by a page fault handler */ #define SAVE_PAGE_FAULT_REGS(offset) \ mfspr r2,DAR; \ - stw r2,_DAR(r1); \ + stw r2,_DAR(r1); \ mfspr r2,DSISR; \ stw r2,_DSISR(r1); \ mfspr r2,PVR; /* Check for 603/603e */ \ @@ -328,7 +274,7 @@ mfspr r2,DCMP; \ stw r2,_DCMP(r1); \ 24: - + #define SAVE_INT_REGS(mark) \ mtspr SPR0,r1; /* Save current stack pointer */ \ mtspr SPR1,r2; /* Scratch */ \ @@ -375,7 +321,7 @@ mtspr SRR1,r2; \ SYNC(); \ rfi; \ -20: SAVE_REGS(mark); \ +20: SAVE_ALL_REGS(mark); \ CHECK_STACK() #define RETURN_FROM_INT(mark) \ @@ -412,7 +358,10 @@ bl _EXTERN(flush_instruction_cache); */ \ 05: lis r3,current_set@ha; /* need to save kernel stack pointer */ \ lwz r3,current_set@l(r3); \ - addi r4,r1,INT_FRAME_SIZE; /* size of frame */ \ + /*addi r4,r1,INT_FRAME_SIZE*/; /* size of frame */ \ + lwz r4, KERNEL_STACK_PAGE(r3); \ + addi r4,r4,KERNEL_STACK_SIZE; /* reset stack pointer to top of stack page */ \ + /* stack isn't 0'd so show_task():sched.c shows highwater of stack */ \ stw r4,TSS+KSP(r3); \ lwz r4,STATE(r3); /* If state != 0, can't run */ \ cmpi 0,r4,0; \ @@ -442,20 +391,18 @@ mtlr r2; \ lwz r2,_XER(r1); \ mtspr XER,r2; \ - lwz r2,_CCR(r1); \ - mtcrf 0xFF,r2; \ lfd fr0,FPCSR(r1); \ mtfsf 0xFF,fr0; \ - lfd fr0,FPR0(r1); \ - lfd fr1,FPR1(r1); \ - lfd fr2,FPR2(r1); \ - lfd fr3,FPR3(r1); \ + RESTORE_FP_REGS(mark) ; \ + lwz r2,_CCR(r1); \ + mtcrf 0xFF,r2; \ lwz r0,GPR0(r1); \ lwz r2,GPR2(r1); \ lwz r1,GPR1(r1); \ SYNC(); \ rfi + _TEXT() /* * This code may be executed by a bootstrap process. If so, the @@ -578,35 +525,6 @@ _ORG(0x1000) /* Note: It is *unsafe* to use the TRACE TRAP macro here since there */ /* could be a 'trace' in progress when the TLB miss occurs. */ /* TRACE_TRAP(0x1000) */ -#ifdef TLB_STATS - lis r2,DataLoadTLB_trace_ptr@h - ori r2,r2,DataLoadTLB_trace_ptr@l - lis r3,0xF000 - andc r2,r2,r3 - lwz r1,0(r2) - andc r1,r1,r3 - li r0,0x1000 - stw r0,0(r1) - mftbu r0 - stw r0,4(r1) - mftb r0 - stw r0,8(r1) - mfspr r0,IMISS - mfspr r3,SRR1 - extrwi r3,r3,1,14 - or r0,r0,r3 - stw r0,12(r1) - addi r1,r1,16 - mfcr r0 - cmpl 0,r1,r2 - blt 00f - lis r1,DataLoadTLB_trace_buf@h - ori r1,r1,DataLoadTLB_trace_buf@l - lis r3,0xF000 - andc r1,r1,r3 -00: mtcrf 0xFF,r0 - stw r1,0(r2) -#endif b InstructionTLBMiss /* @@ -614,41 +532,6 @@ _ORG(0x1000) */ _ORG(0x1100) /* TRACE_TRAP(0x1100) */ -#ifdef TLB_STATS - lis r2,DataLoadTLB_trace_ptr@h - ori r2,r2,DataLoadTLB_trace_ptr@l - lis r3,0xF000 - andc r2,r2,r3 - lwz r1,0(r2) - andc r1,r1,r3 - li r0,0x1100 - stw r0,0(r1) - mftbu r0 - stw r0,4(r1) - mftb r0 - stw r0,8(r1) - mfspr r0,DMISS - mfspr r3,SRR1 - extrwi r3,r3,1,14 - or r0,r0,r3 - stw r0,12(r1) - addi r1,r1,16 - mfcr r0 - cmpl 0,r1,r2 - blt 00f - lis r1,DataLoadTLB_trace_buf@h - ori r1,r1,DataLoadTLB_trace_buf@l - lis r3,0xF000 - andc r1,r1,r3 -00: mtcrf 0xFF,r0 - stw r1,0(r2) - .data -DataLoadTLB_trace_buf: - .space 64*1024*4 -DataLoadTLB_trace_ptr: - .long DataLoadTLB_trace_buf - .text -#endif b DataLoadTLBMiss /* @@ -656,35 +539,6 @@ DataLoadTLB_trace_ptr: */ _ORG(0x1200) /* TRACE_TRAP(0x1200) */ -#ifdef TLB_STATS - lis r2,DataLoadTLB_trace_ptr@h - ori r2,r2,DataLoadTLB_trace_ptr@l - lis r3,0xF000 - andc r2,r2,r3 - lwz r1,0(r2) - andc r1,r1,r3 - li r0,0x1200 - stw r0,0(r1) - mftbu r0 - stw r0,4(r1) - mftb r0 - stw r0,8(r1) - mfspr r0,DMISS - mfspr r3,SRR1 - extrwi r3,r3,1,14 - or r0,r0,r3 - stw r0,12(r1) - addi r1,r1,16 - mfcr r0 - cmpl 0,r1,r2 - blt 00f - lis r1,DataLoadTLB_trace_buf@h - ori r1,r1,DataLoadTLB_trace_buf@l - lis r3,0xF000 - andc r1,r1,r3 -00: mtcrf 0xFF,r0 - stw r1,0(r2) -#endif b DataStoreTLBMiss _ORG(0x1300) @@ -718,16 +572,40 @@ _ORG(0x4000) #endif +/* changed to use r3 as residual pointer (as firmware does), that's all -- Cort */ /* * Hardware reset [actually from bootstrap] * Initialize memory management & call secondary init * Registers initialized by bootstrap: * R11: Start of command line string * R12: End of command line string + * R28: Residual data + * R29: Total Memory Size * R30: 'BeBx' if this is a BeBox */ Reset: lis r7,0xF000 /* To mask upper 4 bits */ +/* set pointer to residual data */ + lis r1,resptr@h + ori r1,r1,resptr@l + andc r1,r1,r7 +/* changed to use r3 as residual pointer (as firmware does) -- Cort */ +/* this is only a ptr, the actual data is copied in mmu_init */ + stw r3,0(r1) + +/* Copy argument string */ + li r0,0 /* Null terminate string */ + stb r0,0(r12) + lis r1,cmd_line@h + ori r1,r1,cmd_line@l + andc r1,r1,r7 /* No MMU yet - need unmapped address */ + subi r1,r1,1 + subi r11,r11,1 +00: lbzu r0,1(r11) + cmpi 0,r0,0 + stbu r0,1(r1) + bne 00b + #define IS_BE_BOX 0x42654278 /* 'BeBx' */ lis r1,isBeBox@h ori r1,r1,isBeBox@l @@ -751,21 +629,19 @@ Reset: andc r5,r5,r7 /* Tell CPU #1 where to go */ 00: stw r2,0(r1) stw r30,4(r1) -/* Copy argument string */ - li r0,0 /* Null terminate string */ - stb r0,0(r12) - lis r1,cmd_line@h - ori r1,r1,cmd_line@l - andc r1,r1,r7 /* No MMU yet - need unmapped address */ - subi r1,r1,1 - subi r11,r11,1 -00: lbzu r0,1(r11) - cmpi 0,r0,0 - stbu r0,1(r1) - bne 00b + + +#if 0 lis r1,sys_stack@h ori r1,r1,sys_stack@l +#else + lis r1,init_kernel_stack@h + ori r1,r1,init_kernel_stack@l +#endif + addi r1,r1,0x1000 /* top of stack */ +#if 0 li r2,0x0FFF /* Mask stack address down to page boundary */ +#endif andc r1,r1,r2 subi r1,r1,INT_FRAME_SIZE /* Padding for first frame */ li r2,0 /* TOC pointer for nanokernel */ @@ -782,6 +658,13 @@ Reset: 00: stwu r0,4(r3) cmp 0,r3,r4 blt 00b +#if 0 +/* Save total memory size (passed from bootstrap) */ + lis r3,_TotalMemory@h + ori r3,r3,_TotalMemory@l + andc r3,r3,r7 /* make unmapped address */ + stw r29,0(r3) +#endif /* Initialize BAT registers */ lis r3,BAT0@h ori r3,r3,BAT0@l @@ -816,7 +699,7 @@ Reset: lwz r0,4(r3) mtspr IBAT2L,r0 mtspr DBAT2L,r0 -#if 0 +#if 1 lis r3,BAT3@h ori r3,r3,BAT3@l andc r3,r3,r7 /* make unmapped address */ @@ -837,7 +720,7 @@ Reset: DO_RFI_TRACE_UNMAPPED(0xDEAD0000) SYNC rfi /* enables MMU */ -10: bl _EXTERN(MMU_init) /* initialize MMU environment */ +10: bl _EXTERN(MMU_init) /* initialize MMU environment */ DO_RFI_TRACE_MAPPED(0xDEAD0100) /* Withdraw BAT2->RAM mapping */ lis r7,0xF000 /* To mask upper 4 bits */ @@ -1017,14 +900,17 @@ MachineCheck: * Data Access exception */ DataAccess: -/* TRACE_TRAP(0x0300) */ SAVE_INT_REGS(0x0300) - SAVE_PAGE_FAULT_REGS(0x0300) - BUMP(__Data_Page_Faults) - mr r3,r1 /* Set pointer to saved regs */ +#if 1 + mfspr r3, DAR + mfspr r4, DSISR + li r5, 0 /* not a text fault */ + mr r6, r1 + bl _EXTERN(new_page_fault) +#else + SAVE_PAGE_FAULT_REGS(0x0D00) + mr r3,r1 bl _EXTERN(DataAccessException) -#if 0 - bl _EXTERN(flush_instruction_cache) #endif RETURN_FROM_INT(0x0300) @@ -1032,14 +918,17 @@ DataAccess: * Instruction Access Exception */ InstructionAccess: -/* TRACE_TRAP(0x0400) */ SAVE_INT_REGS(0x0400) - SAVE_PAGE_FAULT_REGS(0x0400) - BUMP(__Instruction_Page_Faults) - mr r3,r1 /* Set pointer to saved regs */ +#if 1 + mfspr r3, SPR2 /* srr0 was saved here */ + mfspr r4, SPR3 /* srr1 was saved here */ + li r5, 1 /* a text fault */ + mr r6, r1 + bl _EXTERN(new_page_fault) +#else + SAVE_PAGE_FAULT_REGS(0x0D00) + mr r3,r1 bl _EXTERN(InstructionAccessException) -#if 0 - bl _EXTERN(flush_instruction_cache) #endif RETURN_FROM_INT(0x0400) @@ -1090,17 +979,18 @@ SingleStep: * Floating point [not available, etc] */ FloatingPointCheck: - TRACE_TRAP(0x0800) SAVE_INT_REGS(0x0800) mr r3,r1 /* Set pointer to saved regs */ bl _EXTERN(FloatingPointCheckException) - RETURN_FROM_INT(0x0200) + cmpi 0,r3,MSR_FP /* check if fp was turned on by handler */ + bne 00f + RETURN_FROM_INT(0x0f0f) /* 0xf0f tells to restore fp regs */ +00: RETURN_FROM_INT(0x0200) /* * System Call exception */ SystemCall: -/* TRACE_TRAP(0x0C00) */ SAVE_INT_REGS(0x0C00) lwz r2,_CCR(r1) /* Clear SO bit in CR */ lis r9,0x1000 @@ -1118,13 +1008,21 @@ SystemCall: lwz r2,TASK_FLAGS(r2) andi. r2,r2,PF_TRACESYS bne 50f + lis r2,sys_call_table@h ori r2,r2,sys_call_table@l slwi r0,r0,2 lwzx r2,r2,r0 /* Fetch system call handler [ptr] */ +#if 1 + cmpi 0,r2,0 /* make sure syscall handler not 0 */ + beq 99f + cmpi 0,r0,NR_syscalls<<2 /* make sure syscallnum in bounds */ + bgt 99f +#endif mtlr r2 mr r9,r1 blrl /* Call handler */ + 20: stw r3,RESULT(r1) /* Save result */ cmpi 0,r3,0 bge 30f @@ -1136,10 +1034,6 @@ SystemCall: oris r2,r2,0x1000 stw r2,_CCR(r1) 30: stw r3,GPR3(r1) /* Update return value */ -#if 0 - mr r3,r1 - bl _EXTERN(trace_syscall) -#endif b 99f /* Traced system call support */ 50: bl _EXTERN(syscall_trace) @@ -1171,14 +1065,6 @@ SystemCall: 60: stw r3,GPR3(r1) /* Update return value */ bl _EXTERN(syscall_trace) 99: -#if 0 /* This isn't needed here - already in RETURN_FROM_INT */ - lis r2,kernel_pages_are_copyback@ha - lwz r2,kernel_pages_are_copyback@l(r2) - cmpi 0,r2,0 - beq 00f - bl _EXTERN(flush_instruction_cache) /* Ensure cache coherency */ -00: -#endif RETURN_FROM_INT(0x0C00) /* @@ -1186,36 +1072,6 @@ SystemCall: */ InstructionTLBMiss: BUMP_UNMAPPED(__Instruction_TLB_Misses) -#ifdef DO_TLB_TRACE - lis r1,_TLB_ptr@h - ori r1,r1,_TLB_ptr@l - lis r2,0xF000 - andc r1,r1,r2 - lwz r1,0(r1) - andc r1,r1,r2 - subi r1,r1,4 - lis r2,0xBEBE - ori r2,r2,0x0100 - stwu r2,4(r1) - mfspr r2,SRR0 - stwu r2,4(r1) - mfspr r2,SRR1 - stwu r2,4(r1) - mfspr r2,HASH1 - stwu r2,4(r1) - mfspr r2,HASH2 - stwu r2,4(r1) - mfspr r2,ICMP - stwu r2,4(r1) - mfspr r2,IMISS - stwu r2,4(r1) - addi r1,r1,4+(1*4) - lis r3,_TLB_ptr@h - ori r3,r3,_TLB_ptr@l - lis r2,0xF000 - andc r3,r3,r2 - stw r1,0(r3) -#endif mfctr r0 /* Need to save this - CTR can't be touched! */ mfspr r2,HASH1 /* Get PTE pointer */ mfspr r3,ICMP /* Partial item compare value */ @@ -1256,37 +1112,6 @@ InstructionTLBMiss: * Handle TLB miss for DATA Load operation */ DataLoadTLBMiss: - BUMP_UNMAPPED(__DataLoad_TLB_Misses) -#ifdef DO_TLB_TRACE - lis r1,_TLB_ptr@h - ori r1,r1,_TLB_ptr@l - lis r2,0xF000 - andc r1,r1,r2 - lwz r1,0(r1) - andc r1,r1,r2 - subi r1,r1,4 - lis r2,0xBEBE - ori r2,r2,0x0200 - stwu r2,4(r1) - mfspr r2,SRR0 - stwu r2,4(r1) - mfspr r2,SRR1 - stwu r2,4(r1) - mfspr r2,HASH1 - stwu r2,4(r1) - mfspr r2,HASH2 - stwu r2,4(r1) - mfspr r2,DCMP - stwu r2,4(r1) - mfspr r2,DMISS - stwu r2,4(r1) - addi r1,r1,4+(1*4) - lis r3,_TLB_ptr@h - ori r3,r3,_TLB_ptr@l - lis r2,0xF000 - andc r3,r3,r2 - stw r1,0(r3) -#endif mfctr r0 /* Need to save this - CTR can't be touched! */ mfspr r2,HASH1 /* Get PTE pointer */ mfspr r3,DCMP /* Partial item compare value */ @@ -1325,36 +1150,6 @@ DataLoadTLBMiss: */ DataStoreTLBMiss: BUMP_UNMAPPED(__DataStore_TLB_Misses) -#ifdef DO_TLB_TRACE - lis r1,_TLB_ptr@h - ori r1,r1,_TLB_ptr@l - lis r2,0xF000 - andc r1,r1,r2 - lwz r1,0(r1) - andc r1,r1,r2 - subi r1,r1,4 - lis r2,0xBEBE - ori r2,r2,0x0300 - stwu r2,4(r1) - mfspr r2,SRR0 - stwu r2,4(r1) - mfspr r2,SRR1 - stwu r2,4(r1) - mfspr r2,HASH1 - stwu r2,4(r1) - mfspr r2,HASH2 - stwu r2,4(r1) - mfspr r2,DCMP - stwu r2,4(r1) - mfspr r2,DMISS - stwu r2,4(r1) - addi r1,r1,4+(1*4) - lis r3,_TLB_ptr@h - ori r3,r3,_TLB_ptr@l - lis r2,0xF000 - andc r3,r3,r2 - stw r1,0(r3) -#endif mfctr r0 /* Need to save this - CTR can't be touched! */ mfspr r2,HASH1 /* Get PTE pointer */ mfspr r3,DCMP /* Partial item compare value */ @@ -1531,7 +1326,7 @@ _GLOBAL(flush_page) addi r3,r3,CACHE_LINE_SIZE bdnz 00b blr - + /* * This routine switches between two different tasks. The process * state of one is saved on its kernel stack. Then the state @@ -1543,24 +1338,25 @@ _GLOBAL(flush_page) * of this code; either by coming in via the entry (_switch) * or via "fork" which must set up an environment equivalent * to the "_switch" path. If you change this (or in particular, the - * SAVE_REGS macro), you'll have to change the fork code also. + * SAVE_ALL_REGS macro), you'll have to change the fork code also. * * The code which creates the new task context is in 'copy_thread' * in arch/ppc/kernel/process.c */ _GLOBAL(_switch) - mtspr SPR0,r1 /* SAVE_REGS prologue */ + mtspr SPR0,r1 /* SAVE_ALL_REGS prologue */ mtspr SPR1,r2 mflr r2 /* Return to switch caller */ mtspr SPR2,r2 mfmsr r2 mtspr SPR3,r2 - SAVE_REGS(0x0FF0) + SAVE_ALL_REGS(0x0FF0) + SAVE_FP_REGS() + CHECK_STACK() SYNC() stw r1,KSP(r3) /* Set old stack pointer */ BUMP(__Context_Switches) lwz r1,KSP(r4) /* Load new stack pointer */ - CHECK_STACK() lwz r0,MMU_SEG0(r4) mtsr SR0,r0 lwz r0,MMU_SEG1(r4) @@ -1577,6 +1373,8 @@ _GLOBAL(_switch) mtsr SR6,r0 lwz r0,MMU_SEG7(r4) mtsr SR7,r0 +#if 0 + /* segs 8-15 are shared by everyone -- don't need to be changed */ lwz r0,MMU_SEG8(r4) mtsr SR8,r0 lwz r0,MMU_SEG9(r4) @@ -1593,34 +1391,22 @@ _GLOBAL(_switch) mtsr SR14,r0 lwz r0,MMU_SEG15(r4) mtsr SR15,r0 +#endif + /* no need to invalidate tlb since each process has a distinct + set of vsid's. -- Cort */ +#if 0 tlbia /* Invalidate entire TLB */ BUMP(__TLBIAs) - bl _EXTERN(flush_instruction_cache) -#ifdef TLB_STATS -/* TEMP */ - lis r2,DataLoadTLB_trace_ptr@h - ori r2,r2,DataLoadTLB_trace_ptr@l - lis r3,0x9000 - lwz r4,0(r2) - or r4,r4,r3 - li r0,0 - stw r0,0(r4) - stw r0,4(r4) - stw r0,8(r4) - stw r0,12(r4) - addi r4,r4,4 - cmpl 0,r4,r2 - blt 00f - lis r4,DataLoadTLB_trace_buf@h - ori r4,r4,DataLoadTLB_trace_buf@l -00: stw r4,0(r2) -/* TEMP */ -#endif -#if 0 - lwz r2,_NIP(r1) /* Force TLB/MMU hit */ - lwz r2,0(r2) #endif - RETURN_FROM_INT(0xF000) + /* p5.2 603 users manual - with addr transl. enabled, + the memory access is performed under the control of + the page table entry. I interpret this to mean that + it is tagged with the vsid -- so no need to flush here + since each process has a distinct set of vsid's. + Of course, my intepretation may be wrong. + -- Cort */ + /*bl _EXTERN(flush_instruction_cache)*/ + RETURN_FROM_INT(0x0f0f) /* @@ -1629,50 +1415,16 @@ _GLOBAL(_switch) _GLOBAL(__main) blr -#ifdef DO_TRAP_TRACE -check_trace: - sync /* Force all writes out */ - lwz r2,-8(r1) - andi. r2,r2,MSR_PR - bne 99f - lwz r2,-32(r1) - lwz r3,-16(r1) - cmp 0,r2,r3 - bne 99f - andi. r2,r2,0x7FFF - cmpi 0,r2,0x0C00 - bge 99f - lwz r2,-32+4(r1) - lwz r3,-16+4(r1) - cmp 0,r2,r3 - bne 99f - lwz r2,-32+8(r1) - lwz r3,-16+8(r1) - cmp 0,r2,r3 - bne 99f - lwz r2,-32(r1) - lwz r3,-16(r1) - cmp 0,r2,r3 - bne 99f - andi. r2,r2,0x7FFF - cmpi 0,r2,0x0600 - beq 00f - lwz r2,-32+12(r1) - lwz r3,-16+12(r1) - cmp 0,r2,r3 - bne 99f -00: li r2,0x7653 - stw r2,0(r1) - b 00b -99: blr -#endif - .data .globl sdata sdata: .space 2*4096 + +#if 0 +_GLOBAL(sys_stack) sys_stack: - .space 2*4096 + .space 4096 +#endif CPU1_stack: .globl empty_zero_page @@ -1689,32 +1441,40 @@ swapper_pg_dir: */ .globl cmd_line cmd_line: - .space 512 - + .space 512 + #ifdef STATS /* * Miscellaneous statistics - gathered just for performance info */ - .globl _INTR_stats _INTR_stats: + .globl __Instruction_TLB_Misses __Instruction_TLB_Misses: .long 0,0 /* Instruction TLB misses */ + .globl __DataLoad_TLB_Misses __DataLoad_TLB_Misses: .long 0,0 /* Data [load] TLB misses */ + .globl __DataStore_TLB_Misses __DataStore_TLB_Misses: .long 0,0 /* Data [store] TLB misses */ + .globl __Instruction_Page_Faults __Instruction_Page_Faults: .long 0,0 /* Instruction page faults */ + .globl __Data_Page_Faults __Data_Page_Faults: .long 0,0 /* Data page faults */ + .globl __Cache_Flushes __Cache_Flushes: .long 0,0 /* Explicit cache flushes */ + .globl __Context_Switches __Context_Switches: .long 0,0 /* Context switches */ + .globl __Hardware_Interrupts __Hardware_Interrupts: .long 0,0 /* I/O interrupts (disk, timer, etc) */ .globl __TLBIAs + .globl __TLBIAs __TLBIAs: .long 0,0 /* TLB cache forceably flushed */ .globl __TLBIEs @@ -1722,33 +1482,14 @@ __TLBIEs: .long 0,0 /* Specific TLB entry flushed */ #endif + .globl _TotalMemory +_TotalMemory: + .long 0,0 + /* * This location is used to break any outstanding "lock"s when * changing contexts. */ _break_lwarx: .long 0 - -/* - * Various trace buffers - */ -#ifdef DO_TRAP_TRACE - .data -_TRAP_TRACE: .space 32*1024 -_TRAP_ptr: .long _TRAP_TRACE - .text -#endif - -#ifdef DO_TLB_TRACE - .data -_TLB_TRACE: .space 128*1024 -_TLB_ptr: .long _TLB_TRACE - .text -#endif - -#ifdef DO_RFI_TRACE - .data -_RFI_DATA: .space 128*1024 -_RFI_ptr: .long _RFI_DATA - .text -#endif + diff --git a/arch/ppc/kernel/include/elf/ChangeLog b/arch/ppc/kernel/include/elf/ChangeLog deleted file mode 100644 index b4e7bd3ad..000000000 --- a/arch/ppc/kernel/include/elf/ChangeLog +++ /dev/null @@ -1,155 +0,0 @@ -Tue Jun 20 10:18:28 1995 Jeff Law (law@snake.cs.utah.edu) - - * hppa.h (CPU_PA_RISC1_0): Protect from redefinitions. - (CPU_PA_RISC1_1): Likewise. - -Wed Mar 8 18:14:37 1995 Michael Meissner <meissner@tiktok.cygnus.com> - - * ppc.h: New file for PowerPC support. - -Tue Feb 14 13:59:13 1995 Michael Meissner <meissner@tiktok.cygnus.com> - - * common.h (EM_PPC): Use official value of 20, not 17. - (EM_PPC_OLD): Define this to be the old value of EM_PPC. - - -Tue Jan 24 09:40:59 1995 Michael Meissner <meissner@tiktok.cygnus.com> - - * common.h (EM_PPC): New macro, PowerPC machine id. - -Tue Jan 17 10:51:38 1995 Ian Lance Taylor <ian@sanguine.cygnus.com> - - * mips.h (SHT_MIPS_MSYM, SHT_MIPS_DWARF, SHT_MIPS_EVENTS): Define. - - -Mon Oct 17 13:43:59 1994 Ian Lance Taylor <ian@sanguine.cygnus.com> - - * internal.h (Elf_Internal_Shdr): Remove rawdata and size fields. - Add bfd_section field. - -Tue May 24 16:11:50 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) - - * mips.h (Elf32_External_gptab): Define. - -Mon May 16 13:22:04 1994 Jeff Law (law@snake.cs.utah.edu) - - * common.h (EM_HPPA): Delete. - (EM_PARISC): Add. - * hppa.h: New file. - -Mon May 9 13:27:03 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) - - * common.h (SHN_LORESERVE): Rename from SHN_LORESERV. - (ELF32_R_TYPE, ELF32_R_INFO): Don't rely on size of unsigned char. - (ELF64_R_TYPE): Don't rely on size of unsigned long. - -Mon Apr 25 15:53:09 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) - - * internal.h (Elf_Internal_Shdr): Use PTR, not void *. - -Fri Mar 11 00:34:59 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) - - * mips.h (SHN_MIPS_TEXT, SHN_MIPS_DATA): Define. - -Sat Mar 5 14:08:54 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de) - - * internal.h: Remove Elf32_*, Elf64_* typedefs. These names - cause conflicts with system headers, e.g. link.h in gdb/solib.c. - Combine 32- and 64-bit versions of *_Internal_Dyn. - * common.h: Replace uses of Elf64_Word, Elf64_Xword typedefs - by their expansion. - * mips.h: Replace uses of Elf32_Word, Elf32_Sword, Elf32_Addr - typedefs by their expansion. Add DT_MIPS_RLD_MAP definition. - -Fri Feb 18 10:39:54 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) - - * common.h (EM_CYGNUS_POWERPC): Define. This may be temporary, - depending upon how quickly I can find a real PowerPC ABI. - -Mon Feb 7 08:27:13 1994 Jim Kingdon (kingdon@lioth.cygnus.com) - - * internal.h: Change HOST_64_BIT to BFD_HOST_64_BIT. - -Wed Feb 2 14:12:18 1994 Jim Kingdon (kingdon@lioth.cygnus.com) - - * common.h: Add comments regarding value of EM_HPPA and how to - pick an unofficial value. - -Wed Nov 17 17:14:26 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) - - * mips.h (SHT_MIPS_OPTIONS): Define. - -Mon Nov 8 17:57:00 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) - - * mips.h: Added some more MIPS ABI macro definitions. - -Wed Nov 3 22:07:17 1993 Ken Raeburn (raeburn@rtl.cygnus.com) - - * common.h (EM_MIPS_RS4_BE): New macro. - -Tue Oct 12 07:28:18 1993 Ian Lance Taylor (ian@cygnus.com) - - * mips.h: New file. MIPS ABI specific information. - -Mon Jun 21 13:13:43 1993 Ken Raeburn (raeburn@poseidon.cygnus.com) - - * internal.h: Combined 32- and 64-bit versions of all structures - except *_Internal_Dyn. This will simply the assembler interface, - and some bfd code. - -Tue May 25 02:00:16 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) - - * external.h, internal.h, common.h: Added 64-bit versions of some - structures and macros. Renamed old versions to put "32" in the - name. Some are unchanged. - -Thu Apr 29 12:12:20 1993 Ken Raeburn (raeburn@deneb.cygnus.com) - - * common.h (EM_HPPA, NT_VERSION, STN_UNDEF, DT_*): New macros. - * external.h (Elf_External_Dyn): New type. - - * internal.h (Elf_Internal_Shdr): New field `size'. - (Elf_Internal_Dyn): New type. - -Tue Apr 20 16:03:45 1993 Fred Fish (fnf@cygnus.com) - - * dwarf.h (LANG_CHILL): Change value to one randomly picked in - the user defined range, to reduce probability of collisions. - -Sun Nov 15 09:34:02 1992 Fred Fish (fnf@cygnus.com) - - * dwarf.h (AT_src_coords): Whitespace change only. - * dwarf.h (AT_body_begin, AT_body_end, LANG_MODULA2): - Add from latest gcc. - * dwarf.h (LANG_CHILL): Add as GNU extension. - -Sat Aug 1 13:46:53 1992 Fred Fish (fnf@cygnus.com) - - * dwarf.h: Replace with current version from gcc distribution. - -Fri Jun 19 19:05:09 1992 John Gilmore (gnu at cygnus.com) - - * internal.h: Add real struct tags to all the Type_Defs, so they - can be used in prototypes where the Type_Defs are not known. - -Fri Apr 3 20:58:58 1992 Mark Eichin (eichin at cygnus.com) - - * common.h: added ELF_R_{SYM,TYPE,INFO} for handling relocation - info - added EM_MIPS, and corrected value of EM_860 based on System V ABI - manual. - - * external.h: added Elf_External_{Rel,Rela}. - - * internal.h: added Elf_Internal_{Rel,Rela}. - added rawdata to Elf_Internal_Shdr. - -Sat Nov 30 20:43:59 1991 Steve Chamberlain (sac at rtl.cygnus.com) - - * common.h, dwarf.h, external.h, internal.h, ChangeLog; moved from - ../elf-<foo> - - -Local Variables: -version-control: never -End: diff --git a/arch/ppc/kernel/include/elf/common.h b/arch/ppc/kernel/include/elf/common.h deleted file mode 100644 index a9bce87d6..000000000 --- a/arch/ppc/kernel/include/elf/common.h +++ /dev/null @@ -1,232 +0,0 @@ -/* ELF support for BFD. - Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc. - - Written by Fred Fish @ Cygnus Support, from information published - in "UNIX System V Release 4, Programmers Guide: ANSI C and - Programming Support Tools". - -This file is part of BFD, the Binary File Descriptor library. - -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. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - - -/* This file is part of ELF support for BFD, and contains the portions - that are common to both the internal and external representations. - For example, ELFMAG0 is the byte 0x7F in both the internal (in-memory) - and external (in-file) representations. */ - - -/* Fields in e_ident[] */ - -#define EI_MAG0 0 /* File identification byte 0 index */ -#define ELFMAG0 0x7F /* Magic number byte 0 */ - -#define EI_MAG1 1 /* File identification byte 1 index */ -#define ELFMAG1 'E' /* Magic number byte 1 */ - -#define EI_MAG2 2 /* File identification byte 2 index */ -#define ELFMAG2 'L' /* Magic number byte 2 */ - -#define EI_MAG3 3 /* File identification byte 3 index */ -#define ELFMAG3 'F' /* Magic number byte 3 */ - -#define EI_CLASS 4 /* File class */ -#define ELFCLASSNONE 0 /* Invalid class */ -#define ELFCLASS32 1 /* 32-bit objects */ -#define ELFCLASS64 2 /* 64-bit objects */ - -#define EI_DATA 5 /* Data encoding */ -#define ELFDATANONE 0 /* Invalid data encoding */ -#define ELFDATA2LSB 1 /* 2's complement, little endian */ -#define ELFDATA2MSB 2 /* 2's complement, big endian */ - -#define EI_VERSION 6 /* File version */ - -#define EI_PAD 7 /* Start of padding bytes */ - - -/* Values for e_type, which identifies the object file type */ - -#define ET_NONE 0 /* No file type */ -#define ET_REL 1 /* Relocatable file */ -#define ET_EXEC 2 /* Executable file */ -#define ET_DYN 3 /* Shared object file */ -#define ET_CORE 4 /* Core file */ -#define ET_LOPROC 0xFF00 /* Processor-specific */ -#define ET_HIPROC 0xFFFF /* Processor-specific */ - -/* Values for e_machine, which identifies the architecture */ - -#define EM_NONE 0 /* No machine */ -#define EM_M32 1 /* AT&T WE 32100 */ -#define EM_SPARC 2 /* SUN SPARC */ -#define EM_386 3 /* Intel 80386 */ -#define EM_68K 4 /* Motorola m68k family */ -#define EM_88K 5 /* Motorola m88k family */ -#define EM_860 7 /* Intel 80860 */ -#define EM_MIPS 8 /* MIPS R3000 (officially, big-endian only) */ - -#define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */ - -#define EM_SPARC64 11 /* SPARC v9 (not official) 64-bit */ - -#define EM_PARISC 15 /* HPPA */ -#define EM_PPC 20 /* PowerPC */ - -/* If it is necessary to assign new unofficial EM_* values, please pick large - random numbers (0x8523, 0xa7f2, etc.) to minimize the chances of collision - with official or non-GNU unofficial values. */ - -/* Cygnus PowerPC ELF backend. Written in the absence of an ABI. */ -#define EM_CYGNUS_POWERPC 0x9025 - -/* Old version of PowerPC, this should be removed shortly. */ -#define EM_PPC_OLD 17 - - -/* Values for e_version */ - -#define EV_NONE 0 /* Invalid ELF version */ -#define EV_CURRENT 1 /* Current version */ - -/* Values for program header, p_type field */ - -#define PT_NULL 0 /* Program header table entry unused */ -#define PT_LOAD 1 /* Loadable program segment */ -#define PT_DYNAMIC 2 /* Dynamic linking information */ -#define PT_INTERP 3 /* Program interpreter */ -#define PT_NOTE 4 /* Auxiliary information */ -#define PT_SHLIB 5 /* Reserved, unspecified semantics */ -#define PT_PHDR 6 /* Entry for header table itself */ -#define PT_LOPROC 0x70000000 /* Processor-specific */ -#define PT_HIPROC 0x7FFFFFFF /* Processor-specific */ - -/* Program segment permissions, in program header p_flags field */ - -#define PF_X (1 << 0) /* Segment is executable */ -#define PF_W (1 << 1) /* Segment is writable */ -#define PF_R (1 << 2) /* Segment is readable */ -#define PF_MASKPROC 0xF0000000 /* Processor-specific reserved bits */ - -/* Values for section header, sh_type field */ - -#define SHT_NULL 0 /* Section header table entry unused */ -#define SHT_PROGBITS 1 /* Program specific (private) data */ -#define SHT_SYMTAB 2 /* Link editing symbol table */ -#define SHT_STRTAB 3 /* A string table */ -#define SHT_RELA 4 /* Relocation entries with addends */ -#define SHT_HASH 5 /* A symbol hash table */ -#define SHT_DYNAMIC 6 /* Information for dynamic linking */ -#define SHT_NOTE 7 /* Information that marks file */ -#define SHT_NOBITS 8 /* Section occupies no space in file */ -#define SHT_REL 9 /* Relocation entries, no addends */ -#define SHT_SHLIB 10 /* Reserved, unspecified semantics */ -#define SHT_DYNSYM 11 /* Dynamic linking symbol table */ -#define SHT_LOPROC 0x70000000 /* Processor-specific semantics, lo */ -#define SHT_HIPROC 0x7FFFFFFF /* Processor-specific semantics, hi */ -#define SHT_LOUSER 0x80000000 /* Application-specific semantics */ -#define SHT_HIUSER 0x8FFFFFFF /* Application-specific semantics */ - -/* Values for section header, sh_flags field */ - -#define SHF_WRITE (1 << 0) /* Writable data during execution */ -#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ -#define SHF_EXECINSTR (1 << 2) /* Executable machine instructions */ -#define SHF_MASKPROC 0xF0000000 /* Processor-specific semantics */ - -/* Values of note segment descriptor types for core files. */ - -#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ -#define NT_FPREGSET 2 /* Contains copy of fpregset struct */ -#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ - -/* Values of note segment descriptor types for object files. */ -/* (Only for hppa right now. Should this be moved elsewhere?) */ - -#define NT_VERSION 1 /* Contains a version string. */ - -/* These three macros disassemble and assemble a symbol table st_info field, - which contains the symbol binding and symbol type. The STB_ and STT_ - defines identify the binding and type. */ - -#define ELF_ST_BIND(val) (((unsigned int)(val)) >> 4) -#define ELF_ST_TYPE(val) ((val) & 0xF) -#define ELF_ST_INFO(bind,type) (((bind) << 4) + ((type) & 0xF)) - -#define STN_UNDEF 0 /* undefined symbol index */ - -#define STB_LOCAL 0 /* Symbol not visible outside obj */ -#define STB_GLOBAL 1 /* Symbol visible outside obj */ -#define STB_WEAK 2 /* Like globals, lower precedence */ -#define STB_LOPROC 13 /* Application-specific semantics */ -#define STB_HIPROC 15 /* Application-specific semantics */ - -#define STT_NOTYPE 0 /* Symbol type is unspecified */ -#define STT_OBJECT 1 /* Symbol is a data object */ -#define STT_FUNC 2 /* Symbol is a code object */ -#define STT_SECTION 3 /* Symbol associated with a section */ -#define STT_FILE 4 /* Symbol gives a file name */ -#define STT_LOPROC 13 /* Application-specific semantics */ -#define STT_HIPROC 15 /* Application-specific semantics */ - -/* Special section indices, which may show up in st_shndx fields, among - other places. */ - -#define SHN_UNDEF 0 /* Undefined section reference */ -#define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */ -#define SHN_LOPROC 0xFF00 /* Begin range of appl-specific */ -#define SHN_HIPROC 0xFF1F /* End range of appl-specific */ -#define SHN_ABS 0xFFF1 /* Associated symbol is absolute */ -#define SHN_COMMON 0xFFF2 /* Associated symbol is in common */ -#define SHN_HIRESERVE 0xFFFF /* End range of reserved indices */ - -/* relocation info handling macros */ - -#define ELF32_R_SYM(i) ((i) >> 8) -#define ELF32_R_TYPE(i) ((i) & 0xff) -#define ELF32_R_INFO(s,t) (((s) << 8) + ((t) & 0xff)) - -#define ELF64_R_SYM(i) ((i) >> 32) -#define ELF64_R_TYPE(i) ((i) & 0xffffffff) -#define ELF64_R_INFO(s,t) (((bfd_vma) (s) << 32) + (bfd_vma) (t)) - -/* Dynamic section tags */ - -#define DT_NULL 0 -#define DT_NEEDED 1 -#define DT_PLTRELSZ 2 -#define DT_PLTGOT 3 -#define DT_HASH 4 -#define DT_STRTAB 5 -#define DT_SYMTAB 6 -#define DT_RELA 7 -#define DT_RELASZ 8 -#define DT_RELAENT 9 -#define DT_STRSZ 10 -#define DT_SYMENT 11 -#define DT_INIT 12 -#define DT_FINI 13 -#define DT_SONAME 14 -#define DT_RPATH 15 -#define DT_SYMBOLIC 16 -#define DT_REL 17 -#define DT_RELSZ 18 -#define DT_RELENT 19 -#define DT_PLTREL 20 -#define DT_DEBUG 21 -#define DT_TEXTREL 22 -#define DT_JMPREL 23 -#define DT_LOPROC 0x70000000 -#define DT_HIPROC 0x7fffffff diff --git a/arch/ppc/kernel/include/elf/dwarf.h b/arch/ppc/kernel/include/elf/dwarf.h deleted file mode 100644 index bc9723ae0..000000000 --- a/arch/ppc/kernel/include/elf/dwarf.h +++ /dev/null @@ -1,314 +0,0 @@ -/* Declarations and definitions of codes relating to the DWARF symbolic - debugging information format. - - Written by Ron Guilmette (rfg@ncd.com) - -Copyright (C) 1992 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC 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, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* This file is derived from the DWARF specification (a public document) - Revision 1.0.1 (April 8, 1992) developed by the UNIX International - Programming Languages Special Interest Group (UI/PLSIG) and distributed - by UNIX International. Copies of this specification are available from - UNIX International, 20 Waterview Boulevard, Parsippany, NJ, 07054. -*/ - -/* Tag names and codes. */ - -enum dwarf_tag { - TAG_padding = 0x0000, - TAG_array_type = 0x0001, - TAG_class_type = 0x0002, - TAG_entry_point = 0x0003, - TAG_enumeration_type = 0x0004, - TAG_formal_parameter = 0x0005, - TAG_global_subroutine = 0x0006, - TAG_global_variable = 0x0007, - /* 0x0008 -- reserved */ - /* 0x0009 -- reserved */ - TAG_label = 0x000a, - TAG_lexical_block = 0x000b, - TAG_local_variable = 0x000c, - TAG_member = 0x000d, - /* 0x000e -- reserved */ - TAG_pointer_type = 0x000f, - TAG_reference_type = 0x0010, - TAG_compile_unit = 0x0011, - TAG_string_type = 0x0012, - TAG_structure_type = 0x0013, - TAG_subroutine = 0x0014, - TAG_subroutine_type = 0x0015, - TAG_typedef = 0x0016, - TAG_union_type = 0x0017, - TAG_unspecified_parameters = 0x0018, - TAG_variant = 0x0019, - TAG_common_block = 0x001a, - TAG_common_inclusion = 0x001b, - TAG_inheritance = 0x001c, - TAG_inlined_subroutine = 0x001d, - TAG_module = 0x001e, - TAG_ptr_to_member_type = 0x001f, - TAG_set_type = 0x0020, - TAG_subrange_type = 0x0021, - TAG_with_stmt = 0x0022, - - /* GNU extensions */ - - TAG_format_label = 0x8000, /* for FORTRAN 77 and Fortran 90 */ - TAG_namelist = 0x8001, /* For Fortran 90 */ - TAG_function_template = 0x8002, /* for C++ */ - TAG_class_template = 0x8003 /* for C++ */ -}; - -#define TAG_lo_user 0x8000 /* implementation-defined range start */ -#define TAG_hi_user 0xffff /* implementation-defined range end */ -#define TAG_source_file TAG_compile_unit /* for backward compatibility */ - -/* Form names and codes. */ - -enum dwarf_form { - FORM_ADDR = 0x1, - FORM_REF = 0x2, - FORM_BLOCK2 = 0x3, - FORM_BLOCK4 = 0x4, - FORM_DATA2 = 0x5, - FORM_DATA4 = 0x6, - FORM_DATA8 = 0x7, - FORM_STRING = 0x8 -}; - -/* Attribute names and codes. */ - -enum dwarf_attribute { - AT_sibling = (0x0010|FORM_REF), - AT_location = (0x0020|FORM_BLOCK2), - AT_name = (0x0030|FORM_STRING), - AT_fund_type = (0x0050|FORM_DATA2), - AT_mod_fund_type = (0x0060|FORM_BLOCK2), - AT_user_def_type = (0x0070|FORM_REF), - AT_mod_u_d_type = (0x0080|FORM_BLOCK2), - AT_ordering = (0x0090|FORM_DATA2), - AT_subscr_data = (0x00a0|FORM_BLOCK2), - AT_byte_size = (0x00b0|FORM_DATA4), - AT_bit_offset = (0x00c0|FORM_DATA2), - AT_bit_size = (0x00d0|FORM_DATA4), - /* (0x00e0|FORM_xxxx) -- reserved */ - AT_element_list = (0x00f0|FORM_BLOCK4), - AT_stmt_list = (0x0100|FORM_DATA4), - AT_low_pc = (0x0110|FORM_ADDR), - AT_high_pc = (0x0120|FORM_ADDR), - AT_language = (0x0130|FORM_DATA4), - AT_member = (0x0140|FORM_REF), - AT_discr = (0x0150|FORM_REF), - AT_discr_value = (0x0160|FORM_BLOCK2), - /* (0x0170|FORM_xxxx) -- reserved */ - /* (0x0180|FORM_xxxx) -- reserved */ - AT_string_length = (0x0190|FORM_BLOCK2), - AT_common_reference = (0x01a0|FORM_REF), - AT_comp_dir = (0x01b0|FORM_STRING), - AT_const_value_string = (0x01c0|FORM_STRING), - AT_const_value_data2 = (0x01c0|FORM_DATA2), - AT_const_value_data4 = (0x01c0|FORM_DATA4), - AT_const_value_data8 = (0x01c0|FORM_DATA8), - AT_const_value_block2 = (0x01c0|FORM_BLOCK2), - AT_const_value_block4 = (0x01c0|FORM_BLOCK4), - AT_containing_type = (0x01d0|FORM_REF), - AT_default_value_addr = (0x01e0|FORM_ADDR), - AT_default_value_data2 = (0x01e0|FORM_DATA2), - AT_default_value_data4 = (0x01e0|FORM_DATA4), - AT_default_value_data8 = (0x01e0|FORM_DATA8), - AT_default_value_string = (0x01e0|FORM_STRING), - AT_friends = (0x01f0|FORM_BLOCK2), - AT_inline = (0x0200|FORM_STRING), - AT_is_optional = (0x0210|FORM_STRING), - AT_lower_bound_ref = (0x0220|FORM_REF), - AT_lower_bound_data2 = (0x0220|FORM_DATA2), - AT_lower_bound_data4 = (0x0220|FORM_DATA4), - AT_lower_bound_data8 = (0x0220|FORM_DATA8), - AT_private = (0x0240|FORM_STRING), - AT_producer = (0x0250|FORM_STRING), - AT_program = (0x0230|FORM_STRING), - AT_protected = (0x0260|FORM_STRING), - AT_prototyped = (0x0270|FORM_STRING), - AT_public = (0x0280|FORM_STRING), - AT_pure_virtual = (0x0290|FORM_STRING), - AT_return_addr = (0x02a0|FORM_BLOCK2), - AT_abstract_origin = (0x02b0|FORM_REF), - AT_start_scope = (0x02c0|FORM_DATA4), - AT_stride_size = (0x02e0|FORM_DATA4), - AT_upper_bound_ref = (0x02f0|FORM_REF), - AT_upper_bound_data2 = (0x02f0|FORM_DATA2), - AT_upper_bound_data4 = (0x02f0|FORM_DATA4), - AT_upper_bound_data8 = (0x02f0|FORM_DATA8), - AT_virtual = (0x0300|FORM_STRING), - - /* GNU extensions. */ - - AT_sf_names = (0x8000|FORM_DATA4), - AT_src_info = (0x8010|FORM_DATA4), - AT_mac_info = (0x8020|FORM_DATA4), - AT_src_coords = (0x8030|FORM_DATA4), - AT_body_begin = (0x8040|FORM_ADDR), - AT_body_end = (0x8050|FORM_ADDR) -}; - -#define AT_lo_user 0x8000 /* implementation-defined range start */ -#define AT_hi_user 0xffff /* implementation-defined range end */ - -/* Location atom names and codes. */ - -enum dwarf_location_atom { - OP_REG = 0x01, - OP_BASEREG = 0x02, - OP_ADDR = 0x03, - OP_CONST = 0x04, - OP_DEREF2 = 0x05, - OP_DEREF4 = 0x06, - OP_ADD = 0x07 -}; - -#define OP_LO_USER 0x80 /* implementation-defined range start */ -#define OP_HI_USER 0xff /* implementation-defined range end */ - -/* Fundamental type names and codes. */ - -enum dwarf_fundamental_type { - FT_char = 0x0001, - FT_signed_char = 0x0002, - FT_unsigned_char = 0x0003, - FT_short = 0x0004, - FT_signed_short = 0x0005, - FT_unsigned_short = 0x0006, - FT_integer = 0x0007, - FT_signed_integer = 0x0008, - FT_unsigned_integer = 0x0009, - FT_long = 0x000a, - FT_signed_long = 0x000b, - FT_unsigned_long = 0x000c, - FT_pointer = 0x000d, /* an alias for (void *) */ - FT_float = 0x000e, - FT_dbl_prec_float = 0x000f, - FT_ext_prec_float = 0x0010, /* breaks "classic" svr4 SDB */ - FT_complex = 0x0011, /* breaks "classic" svr4 SDB */ - FT_dbl_prec_complex = 0x0012, /* breaks "classic" svr4 SDB */ - /* 0x0013 -- reserved */ - FT_void = 0x0014, - FT_boolean = 0x0015, /* breaks "classic" svr4 SDB */ - FT_ext_prec_complex = 0x0016, /* breaks "classic" svr4 SDB */ - FT_label = 0x0017, - - /* GNU extensions - The low order byte must indicate the size (in bytes) for the type. - All of these types will probably break "classic" svr4 SDB */ - - FT_long_long = 0x8008, - FT_signed_long_long = 0x8108, - FT_unsigned_long_long = 0x8208, - - FT_int8 = 0x9001, - FT_signed_int8 = 0x9101, - FT_unsigned_int8 = 0x9201, - FT_int16 = 0x9302, - FT_signed_int16 = 0x9402, - FT_unsigned_int16 = 0x9502, - FT_int32 = 0x9604, - FT_signed_int32 = 0x9704, - FT_unsigned_int32 = 0x9804, - FT_int64 = 0x9908, - FT_signed_int64 = 0x9a08, - FT_unsigned_int64 = 0x9b08, - - FT_real32 = 0xa004, - FT_real64 = 0xa108, - FT_real96 = 0xa20c, - FT_real128 = 0xa310 -}; - -#define FT_lo_user 0x8000 /* implementation-defined range start */ -#define FT_hi_user 0xffff /* implementation defined range end */ - -/* Type modifier names and codes. */ - -enum dwarf_type_modifier { - MOD_pointer_to = 0x01, - MOD_reference_to = 0x02, - MOD_const = 0x03, - MOD_volatile = 0x04 -}; - -#define MOD_lo_user 0x80 /* implementation-defined range start */ -#define MOD_hi_user 0xff /* implementation-defined range end */ - -/* Array ordering names and codes. */ - -enum dwarf_array_dim_ordering { - ORD_row_major = 0, - ORD_col_major = 1 -}; - -/* Array subscript format names and codes. */ - -enum dwarf_subscr_data_formats { - FMT_FT_C_C = 0x0, - FMT_FT_C_X = 0x1, - FMT_FT_X_C = 0x2, - FMT_FT_X_X = 0x3, - FMT_UT_C_C = 0x4, - FMT_UT_C_X = 0x5, - FMT_UT_X_C = 0x6, - FMT_UT_X_X = 0x7, - FMT_ET = 0x8 -}; - -/* Derived from above for ease of use. */ - -#define FMT_CODE(_FUNDAMENTAL_TYPE_P, _UB_CONST_P, _LB_CONST_P) \ - (((_FUNDAMENTAL_TYPE_P) ? 0 : 4) \ - | ((_UB_CONST_P) ? 0 : 2) \ - | ((_LB_CONST_P) ? 0 : 1)) - -/* Source language names and codes. */ - -enum dwarf_source_language { - LANG_C89 = 0x00000001, - LANG_C = 0x00000002, - LANG_ADA83 = 0x00000003, - LANG_C_PLUS_PLUS = 0x00000004, - LANG_COBOL74 = 0x00000005, - LANG_COBOL85 = 0x00000006, - LANG_FORTRAN77 = 0x00000007, - LANG_FORTRAN90 = 0x00000008, - LANG_PASCAL83 = 0x00000009, - LANG_MODULA2 = 0x0000000a, - - /* GNU extensions */ - - LANG_CHILL = 0x00009af3 /* random value for GNU Chill */ -}; - -#define LANG_lo_user 0x00008000 /* implementation-defined range start */ -#define LANG_hi_user 0x0000ffff /* implementation-defined range end */ - -/* Names and codes for GNU "macinfo" extension. */ - -enum dwarf_macinfo_record_type { - MACINFO_start = 's', - MACINFO_resume = 'r', - MACINFO_define = 'd', - MACINFO_undef = 'u' -}; diff --git a/arch/ppc/kernel/include/elf/external.h b/arch/ppc/kernel/include/elf/external.h deleted file mode 100644 index f2ab63e1e..000000000 --- a/arch/ppc/kernel/include/elf/external.h +++ /dev/null @@ -1,190 +0,0 @@ -/* ELF support for BFD. - Copyright (C) 1991, 1992 Free Software Foundation, Inc. - - Written by Fred Fish @ Cygnus Support, from information published - in "UNIX System V Release 4, Programmers Guide: ANSI C and - Programming Support Tools". - -This file is part of BFD, the Binary File Descriptor library. - -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. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - - -/* This file is part of ELF support for BFD, and contains the portions - that describe how ELF is represented externally by the BFD library. - I.E. it describes the in-file representation of ELF. It requires - the elf-common.h file which contains the portions that are common to - both the internal and external representations. */ - -/* The 64-bit stuff is kind of random. Perhaps someone will publish a - spec someday. */ - -/* ELF Header (32-bit implementations) */ - -typedef struct { - unsigned char e_ident[16]; /* ELF "magic number" */ - unsigned char e_type[2]; /* Identifies object file type */ - unsigned char e_machine[2]; /* Specifies required architecture */ - unsigned char e_version[4]; /* Identifies object file version */ - unsigned char e_entry[4]; /* Entry point virtual address */ - unsigned char e_phoff[4]; /* Program header table file offset */ - unsigned char e_shoff[4]; /* Section header table file offset */ - unsigned char e_flags[4]; /* Processor-specific flags */ - unsigned char e_ehsize[2]; /* ELF header size in bytes */ - unsigned char e_phentsize[2]; /* Program header table entry size */ - unsigned char e_phnum[2]; /* Program header table entry count */ - unsigned char e_shentsize[2]; /* Section header table entry size */ - unsigned char e_shnum[2]; /* Section header table entry count */ - unsigned char e_shstrndx[2]; /* Section header string table index */ -} Elf32_External_Ehdr; - -typedef struct { - unsigned char e_ident[16]; /* ELF "magic number" */ - unsigned char e_type[2]; /* Identifies object file type */ - unsigned char e_machine[2]; /* Specifies required architecture */ - unsigned char e_version[4]; /* Identifies object file version */ - unsigned char e_entry[8]; /* Entry point virtual address */ - unsigned char e_phoff[8]; /* Program header table file offset */ - unsigned char e_shoff[8]; /* Section header table file offset */ - unsigned char e_flags[4]; /* Processor-specific flags */ - unsigned char e_ehsize[2]; /* ELF header size in bytes */ - unsigned char e_phentsize[2]; /* Program header table entry size */ - unsigned char e_phnum[2]; /* Program header table entry count */ - unsigned char e_shentsize[2]; /* Section header table entry size */ - unsigned char e_shnum[2]; /* Section header table entry count */ - unsigned char e_shstrndx[2]; /* Section header string table index */ -} Elf64_External_Ehdr; - -/* Program header */ - -typedef struct { - unsigned char p_type[4]; /* Identifies program segment type */ - unsigned char p_offset[4]; /* Segment file offset */ - unsigned char p_vaddr[4]; /* Segment virtual address */ - unsigned char p_paddr[4]; /* Segment physical address */ - unsigned char p_filesz[4]; /* Segment size in file */ - unsigned char p_memsz[4]; /* Segment size in memory */ - unsigned char p_flags[4]; /* Segment flags */ - unsigned char p_align[4]; /* Segment alignment, file & memory */ -} Elf32_External_Phdr; - -typedef struct { - unsigned char p_type[4]; /* Identifies program segment type */ - unsigned char p_flags[4]; /* Segment flags */ - unsigned char p_offset[8]; /* Segment file offset */ - unsigned char p_vaddr[8]; /* Segment virtual address */ - unsigned char p_paddr[8]; /* Segment physical address */ - unsigned char p_filesz[8]; /* Segment size in file */ - unsigned char p_memsz[8]; /* Segment size in memory */ - unsigned char p_align[8]; /* Segment alignment, file & memory */ -} Elf64_External_Phdr; - -/* Section header */ - -typedef struct { - unsigned char sh_name[4]; /* Section name, index in string tbl */ - unsigned char sh_type[4]; /* Type of section */ - unsigned char sh_flags[4]; /* Miscellaneous section attributes */ - unsigned char sh_addr[4]; /* Section virtual addr at execution */ - unsigned char sh_offset[4]; /* Section file offset */ - unsigned char sh_size[4]; /* Size of section in bytes */ - unsigned char sh_link[4]; /* Index of another section */ - unsigned char sh_info[4]; /* Additional section information */ - unsigned char sh_addralign[4]; /* Section alignment */ - unsigned char sh_entsize[4]; /* Entry size if section holds table */ -} Elf32_External_Shdr; - -typedef struct { - unsigned char sh_name[4]; /* Section name, index in string tbl */ - unsigned char sh_type[4]; /* Type of section */ - unsigned char sh_flags[8]; /* Miscellaneous section attributes */ - unsigned char sh_addr[8]; /* Section virtual addr at execution */ - unsigned char sh_offset[8]; /* Section file offset */ - unsigned char sh_size[8]; /* Size of section in bytes */ - unsigned char sh_link[4]; /* Index of another section */ - unsigned char sh_info[4]; /* Additional section information */ - unsigned char sh_addralign[8]; /* Section alignment */ - unsigned char sh_entsize[8]; /* Entry size if section holds table */ -} Elf64_External_Shdr; - -/* Symbol table entry */ - -typedef struct { - unsigned char st_name[4]; /* Symbol name, index in string tbl */ - unsigned char st_value[4]; /* Value of the symbol */ - unsigned char st_size[4]; /* Associated symbol size */ - unsigned char st_info[1]; /* Type and binding attributes */ - unsigned char st_other[1]; /* No defined meaning, 0 */ - unsigned char st_shndx[2]; /* Associated section index */ -} Elf32_External_Sym; - -typedef struct { - unsigned char st_name[4]; /* Symbol name, index in string tbl */ - unsigned char st_info[1]; /* Type and binding attributes */ - unsigned char st_other[1]; /* No defined meaning, 0 */ - unsigned char st_shndx[2]; /* Associated section index */ - unsigned char st_value[8]; /* Value of the symbol */ - unsigned char st_size[8]; /* Associated symbol size */ -} Elf64_External_Sym; - -/* Note segments */ - -typedef struct { - unsigned char namesz[4]; /* Size of entry's owner string */ - unsigned char descsz[4]; /* Size of the note descriptor */ - unsigned char type[4]; /* Interpretation of the descriptor */ - char name[1]; /* Start of the name+desc data */ -} Elf_External_Note; - -/* Relocation Entries */ -typedef struct { - unsigned char r_offset[4]; /* Location at which to apply the action */ - unsigned char r_info[4]; /* index and type of relocation */ -} Elf32_External_Rel; - -typedef struct { - unsigned char r_offset[4]; /* Location at which to apply the action */ - unsigned char r_info[4]; /* index and type of relocation */ - unsigned char r_addend[4]; /* Constant addend used to compute value */ -} Elf32_External_Rela; - -typedef struct { - unsigned char r_offset[8]; /* Location at which to apply the action */ - unsigned char r_info[8]; /* index and type of relocation */ -} Elf64_External_Rel; - -typedef struct { - unsigned char r_offset[8]; /* Location at which to apply the action */ - unsigned char r_info[8]; /* index and type of relocation */ - unsigned char r_addend[8]; /* Constant addend used to compute value */ -} Elf64_External_Rela; - -/* dynamic section structure */ - -typedef struct { - unsigned char d_tag[4]; /* entry tag value */ - union { - unsigned char d_val[4]; - unsigned char d_ptr[4]; - } d_un; -} Elf32_External_Dyn; - -typedef struct { - unsigned char d_tag[8]; /* entry tag value */ - union { - unsigned char d_val[8]; - unsigned char d_ptr[8]; - } d_un; -} Elf64_External_Dyn; diff --git a/arch/ppc/kernel/include/elf/hppa.h b/arch/ppc/kernel/include/elf/hppa.h deleted file mode 100644 index e3f70d23d..000000000 --- a/arch/ppc/kernel/include/elf/hppa.h +++ /dev/null @@ -1,90 +0,0 @@ -/* HPPA ELF support for BFD. - Copyright (C) 1993, 1994 Free Software Foundation, Inc. - -This file is part of BFD, the Binary File Descriptor library. - -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. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* This file holds definitions specific to the HPPA ELF ABI. Note - that most of this is not actually implemented by BFD. */ - -/* Processor specific flags for the ELF header e_flags field. */ - -/* Target processor IDs to be placed in the low 16 bits of the flags - field. Note these names are shared with SOM, and therefore do not - follow ELF naming conventions. */ - -/* PA 1.0 big endian. */ -#ifndef CPU_PA_RISC1_0 -#define CPU_PA_RISC1_0 0x0000020b -#endif - -/* PA 1.1 big endian. */ -#ifndef CPU_PA_RISC1_1 -#define CPU_PA_RISC1_1 0x00000210 -#endif - -/* PA 1.0 little endian (unsupported) is 0x0000028b. */ -/* PA 1.1 little endian (unsupported) is 0x00000290. */ - -/* Trap null address dereferences. */ -#define ELF_PARISC_TRAPNIL 0x00010000 - -/* .PARISC.archext section is present. */ -#define EF_PARISC_EXT 0x00020000 - -/* Processor specific section types. */ - -/* Holds the global offset table, a table of pointers to external - data. */ -#define SHT_PARISC_GOT SHT_LOPROC+0 - -/* Nonloadable section containing information in architecture - extensions used by the code. */ -#define SHT_PARISC_ARCH SHT_LOPROC+1 - -/* Section in which $global$ is defined. */ -#define SHT_PARISC_GLOBAL SHT_LOPROC+2 - -/* Section holding millicode routines (mul, div, rem, dyncall, etc. */ -#define SHT_PARISC_MILLI SHT_LOPROC+3 - -/* Section holding unwind information for use by debuggers. */ -#define SHT_PARISC_UNWIND SHT_LOPROC+4 - -/* Section holding the procedure linkage table. */ -#define SHT_PARISC_PLT SHT_LOPROC+5 - -/* Short initialized and uninitialized data. */ -#define SHT_PARISC_SDATA SHT_LOPROC+6 -#define SHT_PARISC_SBSS SHT_LOPROC+7 - -/* Optional section holding argument location/relocation info. */ -#define SHT_PARISC_SYMEXTN SHT_LOPROC+8 - -/* Option section for linker stubs. */ -#define SHT_PARISC_STUBS SHT_LOPROC+9 - -/* Processor specific section flags. */ - -/* This section is near the global data pointer and thus allows short - addressing modes to be used. */ -#define SHF_PARISC_SHORT 0x20000000 - -/* Processor specific symbol types. */ - -/* Millicode function entry point. */ -#define STT_PARISC_MILLICODE STT_LOPROC+0 - diff --git a/arch/ppc/kernel/include/elf/internal.h b/arch/ppc/kernel/include/elf/internal.h deleted file mode 100644 index fb6302937..000000000 --- a/arch/ppc/kernel/include/elf/internal.h +++ /dev/null @@ -1,173 +0,0 @@ -/* ELF support for BFD. - Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc. - - Written by Fred Fish @ Cygnus Support, from information published - in "UNIX System V Release 4, Programmers Guide: ANSI C and - Programming Support Tools". - -This file is part of BFD, the Binary File Descriptor library. - -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. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - - -/* This file is part of ELF support for BFD, and contains the portions - that describe how ELF is represented internally in the BFD library. - I.E. it describes the in-memory representation of ELF. It requires - the elf-common.h file which contains the portions that are common to - both the internal and external representations. */ - - -/* NOTE that these structures are not kept in the same order as they appear - in the object file. In some cases they've been reordered for more optimal - packing under various circumstances. */ - -/* ELF Header */ - -#define EI_NIDENT 16 /* Size of e_ident[] */ - -typedef struct elf_internal_ehdr { - unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ - bfd_vma e_entry; /* Entry point virtual address */ - bfd_signed_vma e_phoff; /* Program header table file offset */ - bfd_signed_vma e_shoff; /* Section header table file offset */ - unsigned long e_version; /* Identifies object file version */ - unsigned long e_flags; /* Processor-specific flags */ - unsigned short e_type; /* Identifies object file type */ - unsigned short e_machine; /* Specifies required architecture */ - unsigned short e_ehsize; /* ELF header size in bytes */ - unsigned short e_phentsize; /* Program header table entry size */ - unsigned short e_phnum; /* Program header table entry count */ - unsigned short e_shentsize; /* Section header table entry size */ - unsigned short e_shnum; /* Section header table entry count */ - unsigned short e_shstrndx; /* Section header string table index */ -} Elf_Internal_Ehdr; - -#define elf32_internal_ehdr elf_internal_ehdr -#define Elf32_Internal_Ehdr Elf_Internal_Ehdr -#define elf64_internal_ehdr elf_internal_ehdr -#define Elf64_Internal_Ehdr Elf_Internal_Ehdr - -/* Program header */ - -struct elf_internal_phdr { - unsigned long p_type; /* Identifies program segment type */ - unsigned long p_flags; /* Segment flags */ - bfd_vma p_offset; /* Segment file offset */ - bfd_vma p_vaddr; /* Segment virtual address */ - bfd_vma p_paddr; /* Segment physical address */ - bfd_vma p_filesz; /* Segment size in file */ - bfd_vma p_memsz; /* Segment size in memory */ - bfd_vma p_align; /* Segment alignment, file & memory */ -}; - -typedef struct elf_internal_phdr Elf_Internal_Phdr; -#define elf32_internal_phdr elf_internal_phdr -#define Elf32_Internal_Phdr Elf_Internal_Phdr -#define elf64_internal_phdr elf_internal_phdr -#define Elf64_Internal_Phdr Elf_Internal_Phdr - -/* Section header */ - -typedef struct elf_internal_shdr { - unsigned int sh_name; /* Section name, index in string tbl */ - unsigned int sh_type; /* Type of section */ - bfd_vma sh_flags; /* Miscellaneous section attributes */ - bfd_vma sh_addr; /* Section virtual addr at execution */ - bfd_size_type sh_size; /* Size of section in bytes */ - bfd_size_type sh_entsize; /* Entry size if section holds table */ - unsigned long sh_link; /* Index of another section */ - unsigned long sh_info; /* Additional section information */ - file_ptr sh_offset; /* Section file offset */ - unsigned int sh_addralign; /* Section alignment */ - - /* The internal rep also has some cached info associated with it. */ - asection * bfd_section; /* Associated BFD section. */ - PTR contents; /* Section contents. */ -} Elf_Internal_Shdr; - -#define elf32_internal_shdr elf_internal_shdr -#define Elf32_Internal_Shdr Elf_Internal_Shdr -#define elf64_internal_shdr elf_internal_shdr -#define Elf64_Internal_Shdr Elf_Internal_Shdr - -/* Symbol table entry */ - -struct elf_internal_sym { - bfd_vma st_value; /* Value of the symbol */ - bfd_vma st_size; /* Associated symbol size */ - unsigned long st_name; /* Symbol name, index in string tbl */ - unsigned char st_info; /* Type and binding attributes */ - unsigned char st_other; /* No defined meaning, 0 */ - unsigned short st_shndx; /* Associated section index */ -}; - -typedef struct elf_internal_sym Elf_Internal_Sym; - -#define elf32_internal_sym elf_internal_sym -#define elf64_internal_sym elf_internal_sym -#define Elf32_Internal_Sym Elf_Internal_Sym -#define Elf64_Internal_Sym Elf_Internal_Sym - -/* Note segments */ - -typedef struct elf_internal_note { - unsigned long namesz; /* Size of entry's owner string */ - unsigned long descsz; /* Size of the note descriptor */ - unsigned long type; /* Interpretation of the descriptor */ - char name[1]; /* Start of the name+desc data */ -} Elf_Internal_Note; -#define Elf32_Internal_Note Elf_Internal_Note -#define elf32_internal_note elf_internal_note - -/* Relocation Entries */ - -typedef struct elf_internal_rel { - bfd_vma r_offset; /* Location at which to apply the action */ - /* This needs to support 64-bit values in elf64. */ - bfd_vma r_info; /* index and type of relocation */ -} Elf_Internal_Rel; - -#define elf32_internal_rel elf_internal_rel -#define Elf32_Internal_Rel Elf_Internal_Rel -#define elf64_internal_rel elf_internal_rel -#define Elf64_Internal_Rel Elf_Internal_Rel - -typedef struct elf_internal_rela { - bfd_vma r_offset; /* Location at which to apply the action */ - bfd_vma r_info; /* Index and Type of relocation */ - bfd_signed_vma r_addend; /* Constant addend used to compute value */ -} Elf_Internal_Rela; - -#define elf32_internal_rela elf_internal_rela -#define elf64_internal_rela elf_internal_rela -#define Elf32_Internal_Rela Elf_Internal_Rela -#define Elf64_Internal_Rela Elf_Internal_Rela - -/* dynamic section structure */ - -typedef struct elf_internal_dyn { - /* This needs to support 64-bit values in elf64. */ - bfd_vma d_tag; /* entry tag value */ - union { - /* This needs to support 64-bit values in elf64. */ - bfd_vma d_val; - bfd_vma d_ptr; - } d_un; -} Elf_Internal_Dyn; - -#define elf32_internal_dyn elf_internal_dyn -#define elf64_internal_dyn elf_internal_dyn -#define Elf32_Internal_Dyn Elf_Internal_Dyn -#define Elf64_Internal_Dyn Elf_Internal_Dyn diff --git a/arch/ppc/kernel/include/elf/mips.h b/arch/ppc/kernel/include/elf/mips.h deleted file mode 100644 index f6beff71c..000000000 --- a/arch/ppc/kernel/include/elf/mips.h +++ /dev/null @@ -1,267 +0,0 @@ -/* MIPS ELF support for BFD. - Copyright (C) 1993, 1994 Free Software Foundation, Inc. - - By Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>, from - information in the System V Application Binary Interface, MIPS - Processor Supplement. - -This file is part of BFD, the Binary File Descriptor library. - -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. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* This file holds definitions specific to the MIPS ELF ABI. Note - that most of this is not actually implemented by BFD. */ - -/* Processor specific flags for the ELF header e_flags field. */ - -/* At least one .noreorder directive appears in the source. */ -#define EF_MIPS_NOREORDER 0x00000001 - -/* File contains position independent code. */ -#define EF_MIPS_PIC 0x00000002 - -/* Code in file uses the standard calling sequence for calling - position independent code. */ -#define EF_MIPS_CPIC 0x00000004 - -/* Four bit MIPS architecture field. */ -#define EF_MIPS_ARCH 0xf0000000 - -/* -mips1 code. */ -#define E_MIPS_ARCH_1 0x00000000 - -/* -mips2 code. */ -#define E_MIPS_ARCH_2 0x10000000 - -/* -mips3 code. */ -#define E_MIPS_ARCH_3 0x20000000 - -/* Processor specific section indices. These sections do not actually - exist. Symbols with a st_shndx field corresponding to one of these - values have a special meaning. */ - -/* Defined and allocated common symbol. Value is virtual address. If - relocated, alignment must be preserved. */ -#define SHN_MIPS_ACOMMON 0xff00 - -/* Defined and allocated text symbol. Value is virtual address. - Occur in the dynamic symbol table of Alpha OSF/1 and Irix 5 executables. */ -#define SHN_MIPS_TEXT 0xff01 - -/* Defined and allocated data symbol. Value is virtual address. - Occur in the dynamic symbol table of Alpha OSF/1 and Irix 5 executables. */ -#define SHN_MIPS_DATA 0xff02 - -/* Small common symbol. */ -#define SHN_MIPS_SCOMMON 0xff03 - -/* Small undefined symbol. */ -#define SHN_MIPS_SUNDEFINED 0xff04 - -/* Processor specific section types. */ - -/* Section contains the set of dynamic shared objects used when - statically linking. */ -#define SHT_MIPS_LIBLIST 0x70000000 - -/* I'm not sure what this is, but it's used on Irix 5. */ -#define SHT_MIPS_MSYM 0x70000001 - -/* Section contains list of symbols whose definitions conflict with - symbols defined in shared objects. */ -#define SHT_MIPS_CONFLICT 0x70000002 - -/* Section contains the global pointer table. */ -#define SHT_MIPS_GPTAB 0x70000003 - -/* Section contains microcode information. The exact format is - unspecified. */ -#define SHT_MIPS_UCODE 0x70000004 - -/* Section contains some sort of debugging information. The exact - format is unspecified. It's probably ECOFF symbols. */ -#define SHT_MIPS_DEBUG 0x70000005 - -/* Section contains register usage information. */ -#define SHT_MIPS_REGINFO 0x70000006 - -/* Section contains miscellaneous options (used on Irix). */ -#define SHT_MIPS_OPTIONS 0x7000000d - -/* DWARF debugging section (used on Irix 6). */ -#define SHT_MIPS_DWARF 0x7000001e - -/* Events section. This appears on Irix 6. I don't know what it - means. */ -#define SHT_MIPS_EVENTS 0x70000021 - -/* A section of type SHT_MIPS_LIBLIST contains an array of the - following structure. The sh_link field is the section index of the - string table. The sh_info field is the number of entries in the - section. */ -typedef struct -{ - /* String table index for name of shared object. */ - unsigned long l_name; - /* Time stamp. */ - unsigned long l_time_stamp; - /* Checksum of symbol names and common sizes. */ - unsigned long l_checksum; - /* String table index for version. */ - unsigned long l_version; - /* Flags. */ - unsigned long l_flags; -} Elf32_Lib; - -/* The l_flags field of an Elf32_Lib structure may contain the - following flags. */ - -/* Require an exact match at runtime. */ -#define LL_EXACT_MATCH 0x00000001 - -/* Ignore version incompatibilities at runtime. */ -#define LL_IGNORE_INT_VER 0x00000002 - -/* A section of type SHT_MIPS_CONFLICT is an array of indices into the - .dynsym section. Each element has the following type. */ -typedef unsigned long Elf32_Conflict; - -/* A section of type SHT_MIPS_GPTAB contains information about how - much GP space would be required for different -G arguments. This - information is only used so that the linker can provide informative - suggestions as to the best -G value to use. The sh_info field is - the index of the section for which this information applies. The - contents of the section are an array of the following union. The - first element uses the gt_header field. The remaining elements use - the gt_entry field. */ -typedef union -{ - struct - { - /* -G value actually used for this object file. */ - unsigned long gt_current_g_value; - /* Unused. */ - unsigned long gt_unused; - } gt_header; - struct - { - /* If this -G argument has been used... */ - unsigned long gt_g_value; - /* ...this many GP section bytes would be required. */ - unsigned long gt_bytes; - } gt_entry; -} Elf32_gptab; - -/* The external version of Elf32_gptab. */ - -typedef union -{ - struct - { - unsigned char gt_current_g_value[4]; - unsigned char gt_unused[4]; - } gt_header; - struct - { - unsigned char gt_g_value[4]; - unsigned char gt_bytes[4]; - } gt_entry; -} Elf32_External_gptab; - -/* A section of type SHT_MIPS_REGINFO contains the following - structure. */ -typedef struct -{ - /* Mask of general purpose registers used. */ - unsigned long ri_gprmask; - /* Mask of co-processor registers used. */ - unsigned long ri_cprmask[4]; - /* GP register value for this object file. */ - long ri_gp_value; -} Elf32_RegInfo; - -/* The external version of the Elf_RegInfo structure. */ -typedef struct -{ - unsigned char ri_gprmask[4]; - unsigned char ri_cprmask[4][4]; - unsigned char ri_gp_value[4]; -} Elf32_External_RegInfo; - -/* MIPS ELF .reginfo swapping routines. */ -extern void bfd_mips_elf32_swap_reginfo_in - PARAMS ((bfd *, const Elf32_External_RegInfo *, Elf32_RegInfo *)); -extern void bfd_mips_elf32_swap_reginfo_out - PARAMS ((bfd *, const Elf32_RegInfo *, Elf32_External_RegInfo *)); - -/* Processor specific section flags. */ - -/* This section must be in the global data area. */ -#define SHF_MIPS_GPREL 0x10000000 - -/* Processor specific program header types. */ - -/* Register usage information. Identifies one .reginfo section. */ -#define PT_MIPS_REGINFO 0x70000000 - -/* Processor specific dynamic array tags. */ - -/* 32 bit version number for runtime linker interface. */ -#define DT_MIPS_RLD_VERSION 0x70000001 - -/* Time stamp. */ -#define DT_MIPS_TIME_STAMP 0x70000002 - -/* Checksum of external strings and common sizes. */ -#define DT_MIPS_ICHECKSUM 0x70000003 - -/* Index of version string in string table. */ -#define DT_MIPS_IVERSION 0x70000004 - -/* 32 bits of flags. */ -#define DT_MIPS_FLAGS 0x70000005 - -/* Base address of the segment. */ -#define DT_MIPS_BASE_ADDRESS 0x70000006 - -/* Address of .conflict section. */ -#define DT_MIPS_CONFLICT 0x70000008 - -/* Address of .liblist section. */ -#define DT_MIPS_LIBLIST 0x70000009 - -/* Number of local global offset table entries. */ -#define DT_MIPS_LOCAL_GOTNO 0x7000000a - -/* Number of entries in the .conflict section. */ -#define DT_MIPS_CONFLICTNO 0x7000000b - -/* Number of entries in the .liblist section. */ -#define DT_MIPS_LIBLISTNO 0x70000010 - -/* Number of entries in the .dynsym section. */ -#define DT_MIPS_SYMTABNO 0x70000011 - -/* Index of first external dynamic symbol not referenced locally. */ -#define DT_MIPS_UNREFEXTNO 0x70000012 - -/* Index of first dynamic symbol in global offset table. */ -#define DT_MIPS_GOTSYM 0x70000013 - -/* Number of page table entries in global offset table. */ -#define DT_MIPS_HIPAGENO 0x70000014 - -/* Address of run time loader map, used for debugging. */ -#define DT_MIPS_RLD_MAP 0x70000016 diff --git a/arch/ppc/kernel/include/elf/ppc.h b/arch/ppc/kernel/include/elf/ppc.h deleted file mode 100644 index b4907acb7..000000000 --- a/arch/ppc/kernel/include/elf/ppc.h +++ /dev/null @@ -1,32 +0,0 @@ -/* MIPS PPC support for BFD. - Copyright (C) 1995 Free Software Foundation, Inc. - - By Michael Meissner, Cygnus Support, <meissner@cygnus.com>, from information - in the System V Application Binary Interface, PowerPC Processor Supplement - and the PowerPC Embedded Application Binary Interface (eabi). - -This file is part of BFD, the Binary File Descriptor library. - -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. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* This file holds definitions specific to the PPC ELF ABI. Note - that most of this is not actually implemented by BFD. */ - -/* Processor specific flags for the ELF header e_flags field. */ - -#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ - - /* CYGNUS local bits below */ -#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag */ diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c index 27d146479..41d453186 100644 --- a/arch/ppc/kernel/irq.c +++ b/arch/ppc/kernel/irq.c @@ -3,6 +3,7 @@ * * Copyright (C) 1992 Linus Torvalds * Adapted from arch/i386 by Gary Thomas + * Modified by Cort Dougan (cort@cs.nmt.edu) * * This file contains the code used by various IRQ handling routines: * asking for different IRQ's should be done through these routines @@ -30,6 +31,24 @@ #include <asm/irq.h> #include <asm/bitops.h> +inline int get_irq_list(char *); +void check_irq(void); +void BeBox_CPU1(void); +void BeBox_state(void); +int BeBox_irq(void); +void show_BeBox_state(void); +void BeBox_enable_irq(int ); +void BeBox_disable_irq(int ); +void BeBox_init_IRQ(void); +void _do_bottom_half(void); +static _NOP(void); +static _delay(void); +void hard_disk_LED(int state); + + +#define SHOW_IRQ +#undef SHOW_IRQ + /* * For the BeBox, interrupt numbers are 0..15 for 8259 PIC interrupts * and 16..31 for other BeBox motherboard type interrupts. @@ -52,7 +71,8 @@ void disable_irq(unsigned int irq_nr) } else { mask = 1 << (irq_nr & 7); - if (irq_nr < 8) { + if (irq_nr < 8) + { cache_21 |= mask; outb(cache_21,0x21); } else @@ -120,150 +140,202 @@ static struct irq_action irq_action[32] = { { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL } }; -int get_irq_list(char *buf) + +inline int get_irq_list(char *buf) { - int i, len = 0; - struct irq_action * action = irq_action; - - for (i = 0; i < 132; i++, action++) { - if (!action->handler) - continue; - len += sprintf(buf+len, "%2d: %8d %c %s\n", - i, kstat.interrupts[i], - (action->flags & SA_INTERRUPT) ? '+' : ' ', - action->name); - } - return len; + int i, len = 0; + struct irq_action * action = irq_action; + + for (i = 0; i < 32; i++, action++) { + if (!action->handler) + continue; + len += sprintf(buf+len, "%2d: %8d %c %s\n", + i, kstat.interrupts[i], + (action->flags & SA_INTERRUPT) ? '+' : ' ', + action->name); + } + return len; } -asmlinkage void handle_IRQ(struct pt_regs *regs) +inline void +process_IRQ(int irq, int _irq, struct pt_regs *regs) { - int irq, _irq, s; + struct irq_action *action; + atomic_inc(&intr_count); + if (irq < 16) + { + /* Mask interrupt */ + if (irq > 7) + { + cache_A1 |= (1<<(irq-8)); + outb(cache_A1, 0xA1); + } else + { + cache_21 |= (1<<irq); + outb(cache_21, 0x21); + } + } + action = irq + irq_action; + kstat.interrupts[irq]++; + /* TEMP */ + /* On the Nobis, the keyboard interrupt "edge" gets lost - why? */ + if (irq == 0) + { + static int count; + if (++count == 500) + { + if (inb(0x64) & 0x01) + { struct irq_action *action; - intr_count++; - if (!isBeBox[0] || ((irq = BeBox_irq()) < 16)) - { - /* Figure out IRQ#, etc. */ - outb(0x0C, 0x20); /* Poll interrupt controller */ - irq = _irq = inb(0x20); - irq &= 0x07; /* Caution! */ - if (irq == 2) - { /* Cascaded interrupt -> IRQ8..IRQ15 */ - outb(0x0C, 0xA0); - irq = (_irq = inb(0xA0)) & 0x07; - irq += 8; - } - /* Mask interrupt & Issue EOI to interrupt controller */ - if (irq > 7) - { - cache_A1 |= (1<<(irq-8)); - outb(cache_A1, 0xA1); -#if 0 - outb(0x20, 0xA0); - /* Need to ack cascade controller as well */ - outb(0x20, 0x20); -#else - outb(0x60|(irq-8), 0xA0); /* Specific EOI */ - /* Need to ack cascade controller as well */ - outb(0x62, 0x20); -#endif - } else - { - cache_21 |= (1<<irq); - outb(cache_21, 0x21); - outb(0x20, 0x20); - } - } - action = irq + irq_action; - kstat.interrupts[irq]++; - if (action->handler) - { - action->handler(irq, action->dev_id, regs); - } else - { - printk("Bogus interrupt #%d/%x, PC: %x\n", irq, _irq, regs->nip); - } - if (_disable_interrupts() && !action->notified) - { - action->notified = 1; - printk("*** WARNING! %s handler [IRQ %d] turned interrupts on!\n", action->name, irq); - } - if (irq < 16) - { - if (!(action->flags & SA_ONESHOT)) - { - /* Re-enable interrupt */ - if (irq > 7) - { - cache_A1 &= ~(1<<(irq-8)); - outb(cache_A1, 0xA1); - } else - { - cache_21 &= ~(1<<irq); - outb(cache_21, 0x21); - } - } - } else + action = irq_action + 1; /* Keyboard */ + printk("Reset KBD, KBSTAT = %x, ELCR = %x/%x, MASK = %x/%x\n", + inb(0x64), inb(0x4D0), inb(0x4D1), cache_21, cache_A1); + action->handler(1, action->dev_id, regs); + } + count = 0; + } + } + if (action->handler) + { + action->handler(irq, action->dev_id, regs); + } else + { + printk("Bogus interrupt %d/%x, pc %x regs %x\n", + irq, _irq,regs->nip,regs); +#if 0 + printk("BeBox[] = %x/%x\n", isBeBox[0], isBeBox[1]); + show_BeBox_state(); + cnpause(); +#endif + } + if (_disable_interrupts() && !action->notified) + { + action->notified = 1; + printk("*** WARNING! %s handler [IRQ %d] turned interrupts on!\n", + action->name, irq); + } + if (irq < 16) + { + /* Issue EOI to interrupt controller */ + if (irq > 7) + { + outb(0xE0|(irq-8), 0xA0); + outb(0xE2, 0x20); + } else + { + outb(0xE0|irq, 0x20); + } + if (!(action->flags & SA_ONESHOT)) + { + /* Re-enable interrupt */ + if (irq > 7) + { + cache_A1 &= ~(1<<(irq-8)); + outb(cache_A1, 0xA1); + } else + { + cache_21 &= ~(1<<irq); + outb(cache_21, 0x21); + } + } + } else + { + BeBox_enable_irq(irq); + } + atomic_dec(&intr_count); +} + +asmlinkage inline void handle_IRQ(struct pt_regs *regs) +{ + int irq, _irq, s; + struct irq_action *action; + static int _ints; + + if (!isBeBox[0] || ((irq = BeBox_irq()) < 16)) + { + /* Figure out IRQ#, etc. */ + outb(0x0C, 0x20); /* Poll interrupt controller */ + irq = _irq = inb(0x20); + irq &= 0x07; /* Caution! */ + if (irq == 2) + { /* Cascaded interrupt -> IRQ8..IRQ15 */ + outb(0x0C, 0xA0); + irq = (_irq = inb(0xA0)) & 0x07; + irq += 8; + } + } + process_IRQ(irq, _irq, regs); + + /* Sometimes, the cascaded IRQ controller get's "stuck" */ + if ((irq == 0) && (_ints++ == 100)) + { + _ints = 0; + outb(0x0A, 0xA0); _irq = inb(0xA0); + if (_irq & ~cache_A1) + { /* Figure out which IRQs are present */ + _irq &= ~cache_A1; + for (irq = 0; irq < 7; irq++) + { + if (_irq & (1<<irq)) { - BeBox_enable_irq(irq); +#if 0 + printk("Dropped IRQ #%d\n", irq+8); +#endif + process_IRQ(irq+8, _irq, regs); } - intr_count--; + } + } + } } /* - * This routine gets called when the SCSI times out on an operation. - * I don't know why this happens, but every so often it does and it - * seems to be a problem with the interrupt controller [state]. It - * happens a lot when there is also network activity (both devices - * are on the PCI bus with interrupts on the cascaded controller). - * Re-initializing the interrupt controller [which might lose some - * pending edge detected interrupts] seems to fix it. + * Display current IRQ state */ -check_irq() + +void +show_irq_state(void) +{ + unsigned char state_21, state_A1; + outb(0x0A, 0x20); state_21 = inb(0x20); + outb(0x0A, 0xA0); state_A1 = inb(0xA0); + printk("IRQ State = %x/%x, Edge = %x/%x, Processor = %d\n", state_21, state_A1, inb(0x4D0), inb(0x4D1), _Processor); +} + +/* + * Initialize interrupt controllers to a well-known state. + */ + +static void +reset_int_controllers(void) { - int s; - unsigned char _a0, _a1, _20, _21; - if (isBeBox[0]) - { - return; - } - s = _disable_interrupts(); - _a1 = inb(0xA1); - _21 = inb(0x21); - outb(0x0C, 0x20); _20 = inb(0x20); - outb(0x0C, 0xA0); _a0 = inb(0xA0); -#if 0 - printk("IRQ 0x20 = %x, 0x21 = %x/%x, 0xA0 = %x, 0xA1 = %x/%x\n", - _20, _21, cache_21, _a0, _a1, cache_A1); -#endif - /* Reset interrupt controller - see if this fixes it! */ /* Initialize interrupt controllers */ outb(0x11, 0x20); /* Start init sequence */ outb(0x40, 0x21); /* Vector base */ outb(0x04, 0x21); /* Cascade (slave) on IRQ2 */ outb(0x01, 0x21); /* Select 8086 mode */ outb(0xFF, 0x21); /* Mask all */ - outb(0x00, 0x4D0); /* All edge triggered */ outb(0x11, 0xA0); /* Start init sequence */ outb(0x48, 0xA1); /* Vector base */ outb(0x02, 0xA1); /* Cascade (slave) on IRQ2 */ outb(0x01, 0xA1); /* Select 8086 mode */ outb(0xFF, 0xA1); /* Mask all */ +#if 0 + outb(0x00, 0x4D0); /* All edge triggered */ outb(0xCF, 0x4D1); /* Trigger mode */ +#endif outb(cache_A1, 0xA1); outb(cache_21, 0x21); enable_irq(2); /* Enable cascade interrupt */ - _enable_interrupts(s); } int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, const char * devname, void *dev_id) + unsigned long irqflags, const char * devname, void *dev_id) { struct irq_action * action; unsigned long flags; -#if 0 -_printk("Request IRQ #%d, Handler: %x\n", irq, handler); +#ifdef SHOW_IRQ +if (irq) printk("Request IRQ #%d, Handler: %x\n", irq, handler); #endif if (irq > 15) { @@ -374,24 +446,33 @@ int probe_irq_off (unsigned long irqs) void init_IRQ(void) { - int i; - - /* set the clock to 100 Hz */ - outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */ - outb_p(LATCH & 0xff , 0x40); /* LSB */ - outb(LATCH >> 8 , 0x40); /* MSB */ - if (request_irq(2, no_action, SA_INTERRUPT, "cascade", NULL)) - printk("Unable to get IRQ2 for cascade\n"); - request_region(0x20,0x20,"pic1"); - request_region(0xa0,0x20,"pic2"); - - /* Set up PCI interrupts */ - route_PCI_interrupts(); - - if (isBeBox[0]) - { - BeBox_init_IRQ(); - } + int i; + + if ((_get_PVR()>>16) == 1) /* PPC 601 */ + { /* Nobis? */ + reset_int_controllers(); + } +#define TIMER0_COUNT 0x40 +#define TIMER_CONTROL 0x43 + /* set the clock to 100 Hz */ + outb_p(0x34,TIMER_CONTROL); /* binary, mode 2, LSB/MSB, ch 0 */ + outb_p(LATCH & 0xff , TIMER0_COUNT); /* LSB */ + outb(LATCH >> 8 , TIMER0_COUNT); /* MSB */ + if (request_irq(2, no_action, SA_INTERRUPT, "cascade", NULL)) + printk("Unable to get IRQ2 for cascade\n"); + request_region(0x20,0x20,"pic1"); + request_region(0xa0,0x20,"pic2"); + + /* Make sure IRQ2 (cascade) interrupt is "level" based */ + outb(inb(0x4D0)|0x04, 0x4D0); /* IRQ2 level based */ + + /* Set up PCI interrupts */ + route_PCI_interrupts(); + + if (isBeBox[0]) + { + BeBox_init_IRQ(); + } } /* @@ -399,11 +480,18 @@ void init_IRQ(void) * is called whenever an interrupt needs non-interrupt-time service. */ -_do_bottom_half() +void _do_bottom_half(void) { - _enable_interrupts(1); - do_bottom_half(); - _disable_interrupts(); + _enable_interrupts(1); + do_bottom_half(); + _disable_interrupts(); +} + +void hard_disk_LED(int state) +{ + if (_Processor == _PROC_IBM) { + outb(state, IBM_HDD_LED); + } } @@ -416,6 +504,11 @@ _do_bottom_half() #define INT_SOURCE (volatile unsigned long *)(BeBox_IO_page+0x2F0) #define CPU_RESET (volatile unsigned long *)(BeBox_IO_page+0x4F0) +#define _CPU0_INT_MASK (volatile unsigned long *)(0xA0000000+0x0F0) +#define _CPU1_INT_MASK (volatile unsigned long *)(0xA0000000+0x1F0) +#define _INT_SOURCE (volatile unsigned long *)(0xA0000000+0x2F0) +#define _CPU_RESET (volatile unsigned long *)(0xA0000000+0x4F0) + #define CPU_HRESET 0x20000000 #define CPU_SRESET 0x40000000 @@ -454,12 +547,12 @@ volatile int CPU1_alive; volatile int CPU1_trace; static -_NOP() +_NOP(void) { } static -_delay() +_delay(void) { int i; for (i = 0; i < 100; i++) _NOP(); @@ -486,12 +579,6 @@ printk("CPU #1 not there? - CPU Status: %x, Trace: %x\n", *CPU_RESET, CPU1_trace _delay(); } printk("CPU #1 running!\n"); -#if 0 -/* Temp - for SCSI */ - *(unsigned char *)0x81000038 = 0x00; - *(unsigned char *)0x8080103C = 0xFF; - *(unsigned char *)0x8080100D = 0x32; -#endif } void @@ -516,6 +603,16 @@ printk("/%x\n", *CPU0_INT_MASK); _enable_interrupts(s); } +void +show_BeBox_state(void) +{ + unsigned long cpu0_int_mask; + unsigned long int_state; + cpu0_int_mask = (*CPU0_INT_MASK & 0x0FFFFFFC) & ~INT_8259; + int_state = cpu0_int_mask & *INT_SOURCE; + printk("Ints[%x] = %x, Mask[%x] = %x/%x, State = %x\n", INT_SOURCE, *INT_SOURCE, CPU0_INT_MASK, *CPU0_INT_MASK, cpu0_int_mask, int_state); +} + int BeBox_irq(void) { @@ -542,12 +639,12 @@ printk("Can't find BeBox IRQ!\n"); return (0); } -BeBox_state() +void BeBox_state(void) { printk("Int state = %x, CPU0 mask = %x, CPU1 mask = %x\n", *INT_SOURCE, *CPU0_INT_MASK, *CPU1_INT_MASK); } -BeBox_CPU1() +void BeBox_CPU1(void) { CPU1_alive++; while (1) ; diff --git a/arch/ppc/kernel/ksyms.c b/arch/ppc/kernel/ksyms.c index a0d3ec66e..b59b8964e 100644 --- a/arch/ppc/kernel/ksyms.c +++ b/arch/ppc/kernel/ksyms.c @@ -1,14 +1,4 @@ #include <linux/module.h> #include <linux/smp.h> -static struct symbol_table arch_symbol_table = { -#include <linux/symtab_begin.h> - /* platform dependent support */ -#include <linux/symtab_end.h> -}; - -void arch_syms_export(void) -{ - register_symtab(&arch_symbol_table); -} - +/* platform dependent support */ diff --git a/arch/ppc/kernel/ld.script-user b/arch/ppc/kernel/ld.script-user deleted file mode 100644 index 910d34ad3..000000000 --- a/arch/ppc/kernel/ld.script-user +++ /dev/null @@ -1,75 +0,0 @@ -OUTPUT_ARCH(powerpc) -SEARCH_DIR(libc); SEARCH_DIR(../sa_test/libc); -SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); -/* Do we need any of these for elf? - __DYNAMIC = 0; */ -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - . = + SIZEOF_HEADERS; - .interp : { *(.interp) } - .hash : { *(.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .rel.text : { *(.rel.text) } - .rela.text : { *(.rela.text) } - .rel.data : { *(.rel.data) } - .rela.data : { *(.rela.data) } - .rel.rodata : { *(.rel.rodata) } - .rela.rodata : { *(.rela.rodata) } - .rel.got : { *(.rel.got) } - .rela.got : { *(.rela.got) } - .rel.ctors : { *(.rel.ctors) } - .rela.ctors : { *(.rela.ctors) } - .rel.dtors : { *(.rel.dtors) } - .rela.dtors : { *(.rela.dtors) } - .rel.bss : { *(.rel.bss) } - .rela.bss : { *(.rela.bss) } - .rel.plt : { *(.rel.plt) } - .rela.plt : { *(.rela.plt) } - .init : { *(.init) } =0 - .plt : { *(.plt) } - .text : - { - *(.text) - } - _etext = .; - PROVIDE (etext = .); - .fini : { *(.fini) } =0 - .ctors : { *(.ctors) } - .dtors : { *(.dtors) } - .rodata : { *(.rodata) } - .rodata1 : { *(.rodata1) } - /* Read-write section, merged into data segment: */ -/* . = (. + 0x0FFF) & 0xFFFFF000; */ - .data : - { - *(.data) - CONSTRUCTORS - } - .data1 : { *(.data1) } - .got : { *(.got.plt) *(.got) } - .dynamic : { *(.dynamic) } - /* We want the small data sections together, so single-instruction offsets - can access them all, and initialized data all before uninitialized, so - we can shorten the on-disk segment size. */ - .sdata : { *(.sdata) } - _edata = .; - PROVIDE (edata = .); - __bss_start = .; - .sbss : { *(.sbss) *(.scommon) } - .bss : - { - *(.dynbss) - *(.bss) - *(COMMON) - } - _end = . ; - PROVIDE (end = .); - /* These are needed for ELF backends which have not yet been - converted to the new style linker. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - /* These must appear regardless of . */ -} - diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index 7d84bdc89..e137e1171 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -3,9 +3,12 @@ * set of code at specific locations, based on function */ -#include <linux/sys.h> #include "ppc_asm.tmpl" - +#include <linux/sys.h> +#include <asm/errno.h> +#include "ppc_defs.h" +#include <asm/processor.h> + /* Keep track of low-level exceptions - rather crude, but informative */ #define STATS @@ -23,6 +26,7 @@ addze r3,r3; \ stw r3,0(r2) +/*#ifdef CONFIG_603*/ /* This instruction is not implemented on the PPC 603 */ #define tlbia \ li r4,64; \ @@ -31,9 +35,195 @@ 0: tlbie r4; \ addi r4,r4,0x1000; \ bdnz 0b +/*#endif*/ /* CONFIG_603*/ _TEXT() +#define CPU_CTL 0x80000092 +_GLOBAL(hard_reset_now) + mfmsr r3 /* Disable interrupts */ + li r4,0 + ori r4,r4,MSR_EE + andc r3,r3,r4 + ori r3,r3,MSR_IP /* Set FLASH/ROM interrupt handlers */ + sync + mtmsr r3 + lis r3,CPU_CTL>>16 + ori r3,r3,(CPU_CTL&0xFFFF) + lbz r4,0(r3) /* Turn on SRESET */ + li r5,1 + andc r4,r4,r5 /* Make sure we go from 0->1 */ + stb r4,0(r3) + ori r4,r4,1 + stb r4,0(r3) /* This should do it! */ +99: nop + b 99b + +#if 0 +/* + unsigned short + le16_to_cpu(unsigned short val) +*/ +_GLOBAL(le16_to_cpu) + lis r4,_le_scratch@h + ori r4,r4,_le_scratch@l + sth r3,0(r4) + li r5,0 + lhbrx r3,r4,r5 + blr +_GLOBAL(le32_to_cpu) + lis r4,_le_scratch@h + ori r4,r4,_le_scratch@l + stw r3,0(r4) + li r5,0 + lwbrx r3,r4,r5 + blr +_GLOBAL(_le_scratch) + .space 4 +#endif +#if 1 +/* +extern int __put_user_8(char, char *); +extern int __put_user_16(short, short *); +extern int __put_user_32(long, long *); +*/ +_GLOBAL(__put_user_8) + /* setup exception stuff */ + lis r2,current_set@ha + lwz r2,current_set@l(r2) + /* increment excount */ + lwz r6,TSS+TSS_EXCOUNT(r2) + addi r6,r6,1 + stw r6,TSS+TSS_EXCOUNT(r2) + /* set expc */ + lis r6,1f@h + ori r6,r6,1f@l + stw r6,TSS+TSS_EXPC(r2) + + stb r3,0(r4) + li r3,0 /* successful return */ + li r6,0 + stw r6,TSS+TSS_EXCOUNT(r2) + blr +1: li r3,-EFAULT /* bad access */ + li r6,0 + stw r6,TSS+TSS_EXCOUNT(r2) + blr + +_GLOBAL(__put_user_16) + /* setup exception stuff */ + lis r2,current_set@ha + lwz r2,current_set@l(r2) + /* increment excount */ + lwz r6,TSS+TSS_EXCOUNT(r2) + addi r6,r6,1 + stw r6,TSS+TSS_EXCOUNT(r2) + /* set expc */ + lis r6,1f@h + ori r6,r6,1f@l + stw r6,TSS+TSS_EXPC(r2) + + sth r3,0(r4) + li r3,0 /* successful return */ + li r6,0 + stw r6,TSS+TSS_EXCOUNT(r2) + blr +1: li r3,-EFAULT /* bad access */ + li r6,0 + stw r6,TSS+TSS_EXCOUNT(r2) + blr + +_GLOBAL(__put_user_32) + /* setup exception stuff */ + lis r2,current_set@ha + lwz r2,current_set@l(r2) + /* increment excount */ + lwz r6,TSS+TSS_EXCOUNT(r2) + addi r6,r6,1 + stw r6,TSS+TSS_EXCOUNT(r2) + /* set expc */ + lis r6,1f@h + ori r6,r6,1f@l + stw r6,TSS+TSS_EXPC(r2) + + stw r3,0(r4) + li r3,0 /* successful return */ + li r6,0 + stw r6,TSS+TSS_EXCOUNT(r2) + blr +1: li r3,-EFAULT /* bad access */ + li r6,0 + stw r6,TSS+TSS_EXCOUNT(r2) + blr + +_GLOBAL(__get_user_8) + /* setup exception stuff */ + lis r2,current_set@ha + lwz r2,current_set@l(r2) + /* increment excount */ + lwz r6,TSS+TSS_EXCOUNT(r2) + addi r6,r6,1 + stw r6,TSS+TSS_EXCOUNT(r2) + /* set expc */ + lis r6,1f@h + ori r6,r6,1f@l + stw r6,TSS+TSS_EXPC(r2) + + lbz r3,0(r4) + li r4,0 /* successful return */ + li r6,0 + stw r6,TSS+TSS_EXCOUNT(r2) + blr +1: li r4,-EFAULT /* bad access */ + li r6,0 + stw r6,TSS+TSS_EXCOUNT(r2) + blr + +_GLOBAL(__get_user_16) + /* setup exception stuff */ + lis r2,current_set@ha + lwz r2,current_set@l(r2) + /* increment excount */ + lwz r6,TSS+TSS_EXCOUNT(r2) + addi r6,r6,1 + stw r6,TSS+TSS_EXCOUNT(r2) + /* set expc */ + lis r6,1f@h + ori r6,r6,1f@l + stw r6,TSS+TSS_EXPC(r2) + + lhz r3,0(r4) + li r4,0 /* successful return */ + li r6,0 + stw r6,TSS+TSS_EXCOUNT(r2) + blr +1: li r4,-EFAULT /* bad access */ + li r6,0 + stw r6,TSS+TSS_EXCOUNT(r2) + blr + +_GLOBAL(__get_user_32) + /* setup exception stuff */ + lis r2,current_set@ha + lwz r2,current_set@l(r2) + /* increment excount */ + lwz r6,TSS+TSS_EXCOUNT(r2) + addi r6,r6,1 + stw r6,TSS+TSS_EXCOUNT(r2) + /* set expc */ + lis r6,1f@h + ori r6,r6,1f@l + stw r6,TSS+TSS_EXPC(r2) + lwz r3,0(r4) + li r4,0 /* successful return */ + li r6,0 + stw r6,TSS+TSS_EXCOUNT(r2) + blr +1: li r4,-EFAULT /* bad access */ + li r6,0 + stw r6,TSS+TSS_EXCOUNT(r2) + blr +#endif /* * Disable interrupts * rc = _disable_interrupts() @@ -418,7 +608,9 @@ _GLOBAL(__ashldi3) _GLOBAL(abort) .long 0 - + +/* in include/asm/string.h now -- Cort */ +#if 0 _GLOBAL(bzero) #define bufp r3 #define len r4 @@ -447,7 +639,9 @@ _GLOBAL(bzero) 20: stbu pat,1(bufp) /* Store value */ bdnz 20b /* Loop [based on counter] */ 99: blr +#endif + _GLOBAL(abs) cmpi 0,r3,0 bge 10f @@ -474,18 +668,22 @@ _GLOBAL(_get_PVR) * Create a kernel thread * __kernel_thread(flags, fn, arg) */ -#if 0 +#if 1 #define SYS_CLONE 120 _GLOBAL(__kernel_thread) __kernel_thread: li r0,SYS_CLONE sc - cmpi 0,r3,0 - bnelr - mtlr r4 - mr r3,r5 + cmpi 0,r3,0 /* parent or child? */ + bnelr /* return if parent */ + mtlr r4 /* fn addr in lr */ + mr r3,r5 /* load arg and call fn */ blr + li 0, 1 /* exit after child exits */ + li 3, 0 + sc #endif + /* Why isn't this a) automatic, b) written in 'C'? */ .data .align 4 @@ -655,5 +853,7 @@ sys_call_table: .long sys_sched_rr_get_interval .long sys_nanosleep .long sys_mremap - .space (NR_syscalls-163)*4 + .long SYMBOL_NAME(sys_setresuid) + .long SYMBOL_NAME(sys_getresuid) + .space (NR_syscalls-165)*4 diff --git a/arch/ppc/kernel/mk_defs.c b/arch/ppc/kernel/mk_defs.c index e63e5c04a..5e6789a1d 100644 --- a/arch/ppc/kernel/mk_defs.c +++ b/arch/ppc/kernel/mk_defs.c @@ -25,6 +25,8 @@ main(int argc, char *argv[]) FILE *out; struct task_struct task; struct thread_struct tss; + int i; + char s[256]; struct pt_regs regs; if (!(out = fopen(argv[1], "w"))) { @@ -62,6 +64,8 @@ main(int argc, char *argv[]) put_line(out, "MMU_SEG13", (int)&tss.segs[13]-(int)&tss); put_line(out, "MMU_SEG14", (int)&tss.segs[14]-(int)&tss); put_line(out, "MMU_SEG15", (int)&tss.segs[15]-(int)&tss); + put_line(out, "TSS_EXPC", (int)&tss.expc-(int)&tss); + put_line(out, "TSS_EXCOUNT", (int)&tss.excount-(int)&tss); put_line(out, "TSS_FPR0", (int)&tss.fpr[0]-(int)&tss); put_line(out, "TSS_FPR1", (int)&tss.fpr[1]-(int)&tss); put_line(out, "TSS_FPR2", (int)&tss.fpr[2]-(int)&tss); @@ -94,6 +98,7 @@ main(int argc, char *argv[]) put_line(out, "TSS_FPR29", (int)&tss.fpr[29]-(int)&tss); put_line(out, "TSS_FPR30", (int)&tss.fpr[30]-(int)&tss); put_line(out, "TSS_FPR31", (int)&tss.fpr[31]-(int)&tss); + put_line(out, "TSS_FP_USED", (int)&tss.fp_used-(int)&tss); /* Interrupt register frame */ put_line(out, "INT_FRAME_SIZE", sizeof(regs)); put_line(out, "GPR0", (int)®s.gpr[0]-(int)®s); @@ -128,14 +133,19 @@ main(int argc, char *argv[]) put_line(out, "GPR29", (int)®s.gpr[29]-(int)®s); put_line(out, "GPR30", (int)®s.gpr[30]-(int)®s); put_line(out, "GPR31", (int)®s.gpr[31]-(int)®s); - put_line(out, "FPR0", (int)®s.fpr[0]-(int)®s); - put_line(out, "FPR1", (int)®s.fpr[1]-(int)®s); - put_line(out, "FPR2", (int)®s.fpr[2]-(int)®s); - put_line(out, "FPR3", (int)®s.fpr[3]-(int)®s); +#if 0 + for ( i = 0 ; i <= 31 ; i++) + { + sprintf(s,"FPR%d",i); + put_line(out, s, (int)®s.fpr[i]-(int)®s); + } +#endif put_line(out, "FPCSR", (int)®s.fpcsr-(int)®s); /* Note: these symbols include "_" because they overlap with special register names */ put_line(out, "_NIP", (int)®s.nip-(int)®s); put_line(out, "_MSR", (int)®s.msr-(int)®s); + /* put_line(out, "_SRR1", (int)®s.srr1-(int)®s); + put_line(out, "_SRR0", (int)®s.srr0-(int)®s); */ put_line(out, "_CTR", (int)®s.ctr-(int)®s); put_line(out, "_LINK", (int)®s.link-(int)®s); put_line(out, "_CCR", (int)®s.ccr-(int)®s); diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index ff50a6c5e..74f796792 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c @@ -145,7 +145,38 @@ static char BeBox_pci_IRQ_routes[] = 15 /* Line 4 */ }; -/* #define PCI_DEBUG */ +/* IBM Nobis */ +static char Nobis_pci_IRQ_map[16] = + { + 0, /* Slot 0 - unused */ + 0, /* Slot 1 - unused */ + 0, /* Slot 2 - unused */ + 0, /* Slot 3 - unused */ + 0, /* Slot 4 - unused */ + 0, /* Slot 5 - unused */ + 0, /* Slot 6 - unused */ + 0, /* Slot 7 - unused */ + 0, /* Slot 8 - unused */ + 0, /* Slot 9 - unused */ + 0, /* Slot 10 - unused */ + 0, /* Slot 11 - unused */ + 3, /* Slot 12 - SCSI */ + 0, /* Slot 13 - unused */ + 0, /* Slot 14 - unused */ + 0, /* Slot 15 - unused */ + }; + +static char Nobis_pci_IRQ_routes[] = + { + 0, /* Line 0 - Unused */ + 13, /* Line 1 */ + 13, /* Line 2 */ + 13, /* Line 3 */ + 13 /* Line 4 */ + }; + +#define PCI_DEBUG +#undef PCI_DEBUG #ifdef PCI_STATS int PCI_conversions[2]; @@ -460,6 +491,11 @@ void route_PCI_interrupts(void) Motherboard_map = BeBox_pci_IRQ_map; Motherboard_routes = BeBox_pci_IRQ_routes; } else + if ((_get_PVR()>>16) == 1) + { /* Nobis */ + Motherboard_map = Nobis_pci_IRQ_map; + Motherboard_routes = Nobis_pci_IRQ_routes; + } else { /* Motorola hardware */ switch (inb(0x800) & 0xF0) { diff --git a/arch/ppc/kernel/port_io.c b/arch/ppc/kernel/port_io.c index 3693112b2..e886705e1 100644 --- a/arch/ppc/kernel/port_io.c +++ b/arch/ppc/kernel/port_io.c @@ -141,3 +141,9 @@ unsigned char outb_p(unsigned char val,int port) { return (outb(val,port)); } unsigned short outw_p(unsigned short val,int port) { return (outw(val,port)); } unsigned long outl_p(unsigned long val,int port) { return (outl(val,port)); } + +/* makes writing to the ibm acorn power management stuff easier -- Cort */ +/* args in forn of PA.B as in tech spec for ibm carolina */ +void ibm_write(unsigned char val,unsigned int port) +{ +} diff --git a/arch/ppc/kernel/ppc_asm.tmpl b/arch/ppc/kernel/ppc_asm.tmpl index b6fa91a3c..5d357be22 100644 --- a/arch/ppc/kernel/ppc_asm.tmpl +++ b/arch/ppc/kernel/ppc_asm.tmpl @@ -17,6 +17,8 @@ _EXTERN(n): #else #define _EXTERN(n) n +#define SYMBOL_NAME(x) x + #define _GLOBAL(n)\ .globl n;\ n: diff --git a/arch/ppc/kernel/ppc_defs.h b/arch/ppc/kernel/ppc_defs.h deleted file mode 100644 index 1965f83e1..000000000 --- a/arch/ppc/kernel/ppc_defs.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * WARNING! This file is automatically generated - DO NOT EDIT! - */ -#define STATE 0 -#define COUNTER 4 -#define BLOCKED 16 -#define SIGNAL 12 -#define KERNEL_STACK_PAGE 88 -#define TSS 528 -#define KSP 0 -#define LAST_PC 72 -#define USER_STACK 76 -#define PT_REGS 340 -#define PF_TRACESYS 32 -#define TASK_FLAGS 20 -#define MMU_SEG0 8 -#define MMU_SEG1 12 -#define MMU_SEG2 16 -#define MMU_SEG3 20 -#define MMU_SEG4 24 -#define MMU_SEG5 28 -#define MMU_SEG6 32 -#define MMU_SEG7 36 -#define MMU_SEG8 40 -#define MMU_SEG9 44 -#define MMU_SEG10 48 -#define MMU_SEG11 52 -#define MMU_SEG12 56 -#define MMU_SEG13 60 -#define MMU_SEG14 64 -#define MMU_SEG15 68 -#define TSS_FPR0 80 -#define TSS_FPR1 88 -#define TSS_FPR2 96 -#define TSS_FPR3 104 -#define TSS_FPR4 112 -#define TSS_FPR5 120 -#define TSS_FPR6 128 -#define TSS_FPR7 136 -#define TSS_FPR8 144 -#define TSS_FPR9 152 -#define TSS_FPR10 160 -#define TSS_FPR11 168 -#define TSS_FPR12 176 -#define TSS_FPR13 184 -#define TSS_FPR14 192 -#define TSS_FPR15 200 -#define TSS_FPR16 208 -#define TSS_FPR17 216 -#define TSS_FPR18 224 -#define TSS_FPR19 232 -#define TSS_FPR20 240 -#define TSS_FPR21 248 -#define TSS_FPR22 256 -#define TSS_FPR23 264 -#define TSS_FPR24 272 -#define TSS_FPR25 280 -#define TSS_FPR26 288 -#define TSS_FPR27 296 -#define TSS_FPR28 304 -#define TSS_FPR29 312 -#define TSS_FPR30 320 -#define TSS_FPR31 328 -#define INT_FRAME_SIZE 384 -#define GPR0 56 -#define GPR1 60 -#define GPR2 64 -#define GPR3 68 -#define GPR4 72 -#define GPR5 76 -#define GPR6 80 -#define GPR7 84 -#define GPR8 88 -#define GPR9 92 -#define GPR10 96 -#define GPR11 100 -#define GPR12 104 -#define GPR13 108 -#define GPR14 112 -#define GPR15 116 -#define GPR16 120 -#define GPR17 124 -#define GPR18 128 -#define GPR19 132 -#define GPR20 136 -#define GPR21 140 -#define GPR22 144 -#define GPR23 148 -#define GPR24 152 -#define GPR25 156 -#define GPR26 160 -#define GPR27 164 -#define GPR28 168 -#define GPR29 172 -#define GPR30 176 -#define GPR31 180 -#define FPR0 248 -#define FPR1 256 -#define FPR2 264 -#define FPR3 272 -#define FPCSR 280 -#define _NIP 184 -#define _MSR 188 -#define _CTR 192 -#define _LINK 196 -#define _CCR 200 -#define _XER 204 -#define _DAR 208 -#define _DSISR 212 -#define _HASH1 216 -#define _HASH2 220 -#define _IMISS 224 -#define _DMISS 228 -#define _ICMP 232 -#define _DCMP 236 -#define ORIG_GPR3 240 -#define RESULT 244 -#define TRAP 288 -#define MARKER 292 diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c index 11ddb7678..8dc0e61ca 100644 --- a/arch/ppc/kernel/process.c +++ b/arch/ppc/kernel/process.c @@ -3,6 +3,7 @@ * * Copyright (C) 1995 Linus Torvalds * Adapted for PowerPC by Gary Thomas + * Modified by Cort Dougan (cort@cs.nmt.edu) */ /* @@ -13,73 +14,157 @@ #include <linux/sched.h> #include <linux/kernel.h> #include <linux/mm.h> +#include <linux/smp.h> +#include <linux/smp_lock.h> #include <linux/stddef.h> #include <linux/unistd.h> #include <linux/ptrace.h> #include <linux/malloc.h> -#include <linux/ldt.h> #include <linux/user.h> #include <linux/a.out.h> #include <asm/pgtable.h> -#include <asm/segment.h> +#include <asm/uaccess.h> #include <asm/system.h> #include <asm/io.h> #include <asm/ppc_machine.h> +int dump_fpu(void); +void hard_reset_now(void); +void switch_to(struct task_struct *, struct task_struct *); +void copy_thread(int,unsigned long,unsigned long,struct task_struct *, + struct pt_regs *); +void print_backtrace(unsigned long *); int -dump_fpu() +dump_fpu(void) { - return (1); + return (1); } + +/* check to make sure the kernel stack is healthy */ +int check_stack(struct task_struct *tsk) +{ + extern unsigned long init_kernel_stack[PAGE_SIZE/sizeof(long)]; + int ret = 0; + int i; + + /* skip check in init_kernel_task -- swapper */ + if ( tsk->kernel_stack_page == (unsigned long)&init_kernel_stack ) + return; + /* check bounds on stack -- above/below kstack page */ + if ( (tsk->tss.ksp-1 & KERNEL_STACK_MASK) != tsk->kernel_stack_page ) + { + printk("check_stack(): not in bounds %s/%d ksp %x/%x\n", + tsk->comm,tsk->pid,tsk->tss.ksp,tsk->kernel_stack_page); + ret |= 1; + } + + /* check for magic on kstack */ + if ( *(unsigned long *)(tsk->kernel_stack_page) != STACK_MAGIC) + { + printk("check_stack(): no magic %s/%d ksp %x/%x magic %x\n", + tsk->comm,tsk->pid,tsk->tss.ksp,tsk->kernel_stack_page, + *(unsigned long *)(tsk->kernel_stack_page)); + ret |= 2; + } + +#ifdef KERNEL_STACK_BUFFER + /* check extra padding page under kernel stack */ + for ( i = PAGE_SIZE/sizeof(long) ; i >= 1; i--) + { + struct pt_regs *regs; + + if ( *((unsigned long *)(tsk->kernel_stack_page)-1) ) + { + printk("check_stack(): padding touched %s/%d ksp %x/%x value %x/%d\n", + tsk->comm,tsk->pid,tsk->tss.ksp,tsk->kernel_stack_page, + *(unsigned long *)(tsk->kernel_stack_page-i),i*sizeof(long)); + regs = (struct pt_regs *)(tsk->kernel_stack_page-(i*sizeof(long))); + printk("marker %x trap %x\n", regs->marker,regs->trap); + print_backtrace((unsigned long *)(tsk->tss.ksp)); + + ret |= 4; + break; + } + } +#endif + +#if 0 + if (ret) + panic("bad stack"); +#endif + return(ret); +} + + void switch_to(struct task_struct *prev, struct task_struct *new) { struct pt_regs *regs; struct thread_struct *new_tss, *old_tss; int s = _disable_interrupts(); - regs = new->tss.ksp; + regs = (struct pt_regs *)(new->tss.ksp); +#if 1 + check_stack(prev); + check_stack(new); +#endif + /* if a process has used fp 15 times, then turn + on the fpu for good otherwise turn it on with the fp + exception handler as needed. + skip this for kernel tasks. + -- Cort */ + if ( (regs->msr & MSR_FP)&&(regs->msr & MSR_PR)&&(new->tss.fp_used < 15) ) + { #if 0 - printk("Task %x(%d) -> %x(%d)", current, current->pid, new, new->pid); - printk(" - IP: %x, SR: %x, SP: %x\n", regs->nip, regs->msr, regs); + printk("turning off fpu: %s/%d fp_used %d\n", + new->comm,new->pid,new->tss.fp_used); +#endif + regs->msr = regs->msr & ~MSR_FP; + } +#if 0 + printk("%s/%d -> %s/%d\n",prev->comm,prev->pid,new->comm,new->pid); #endif new_tss = &new->tss; old_tss = ¤t->tss; - current_set[0] = new; /* FIX ME! */ + current_set[0] = new; _switch(old_tss, new_tss); -#if 0 - printk("Back in task %x(%d)\n", current, current->pid); -#endif _enable_interrupts(s); } +asmlinkage int sys_debug(unsigned long r3) +{ + lock_kernel(); + if (!strcmp(current->comm,"crashme")) + printk("sys_debug(): r3 (syscall) %d\n", r3); + unlock_kernel(); + return 0; +} + asmlinkage int sys_idle(void) { + int ret = -EPERM; + + lock_kernel(); if (current->pid != 0) - return -EPERM; + goto out; /* endless idle loop with no priority at all */ current->counter = -100; for (;;) { schedule(); } -} - -void hard_reset_now(void) -{ - halt(); + ret = 0; +out: + unlock_kernel(); + return ret; } void show_regs(struct pt_regs * regs) { - _panic("show_regs"); } -/* - * Free current thread data structures etc.. - */ void exit_thread(void) { } @@ -96,30 +181,34 @@ release_thread(struct task_struct *t) /* * Copy a thread.. */ -void copy_thread(int nr, unsigned long clone_flags, unsigned long usp, +int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, struct task_struct * p, struct pt_regs * regs) { int i; SEGREG *segs; struct pt_regs * childregs; -#if 0 -printk("copy thread - NR: %d, Flags: %x, USP: %x, Task: %x, Regs: %x\n", nr, clone_flags, usp, p, regs); -#endif + /* Construct segment registers */ - segs = p->tss.segs; + segs = (SEGREG *)(p->tss.segs); for (i = 0; i < 8; i++) { segs[i].ks = 0; segs[i].kp = 1; +#if 0 segs[i].vsid = i | (nr << 4); +#else + segs[i].vsid = i | ((nr * 10000) << 4); +#endif } if ((p->mm->context == 0) || (p->mm->count == 1)) { - p->mm->context = (nr<<4); -#if 0 -printk("Setting MM[%x] Context = %x Task = %x Current = %x/%x\n", p->mm, p->mm->context, p, current, current->mm); +#if 0 + p->mm->context = ((nr)<<4); +#else + p->mm->context = ((nr*10000)<<4); #endif } + /* Last 8 are shared with kernel & everybody else... */ for (i = 8; i < 16; i++) { @@ -127,22 +216,23 @@ printk("Setting MM[%x] Context = %x Task = %x Current = %x/%x\n", p->mm, p->mm-> segs[i].kp = 1; segs[i].vsid = i; } + /* Copy registers */ -#ifdef STACK_HAS_TWO_PAGES - childregs = ((struct pt_regs *) (p->kernel_stack_page + 2*PAGE_SIZE)) - 2; -#else - childregs = ((struct pt_regs *) (p->kernel_stack_page + 1*PAGE_SIZE)) - 2; -#endif + childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 2; + *childregs = *regs; /* STRUCT COPY */ childregs->gpr[3] = 0; /* Result from fork() */ - p->tss.ksp = childregs; + p->tss.ksp = (unsigned long)(childregs); if (usp >= (unsigned long)regs) { /* Stack is in kernel space - must adjust */ - childregs->gpr[1] = childregs+1; + childregs->gpr[1] = (long)(childregs+1); } else { /* Provided stack is in user space */ childregs->gpr[1] = usp; } + p->tss.fp_used = 0; + + return 0; } /* @@ -152,43 +242,17 @@ void dump_thread(struct pt_regs * regs, struct user * dump) { } -#if 0 -/* - * Do necessary setup to start up a newly executed thread. - */ -void start_thread(struct pt_regs * regs, unsigned long eip, unsigned long esp) -{ - regs->nip = eip; - regs->gpr[1] = esp; - regs->msr = MSR_USER; -#if 0 -{ - int len; - len = (unsigned long)0x80000000 - esp; - if (len > 128) len = 128; - printk("Start thread [%x] at PC: %x, SR: %x, SP: %x\n", regs, eip, regs->msr, esp); - dump_buf(esp, len); - dump_buf(eip, 0x80); -} -#endif -} -#endif asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs) { - return do_fork(SIGCHLD, regs->gpr[1], regs); + int ret; + + lock_kernel(); + ret = do_fork(SIGCHLD, regs->gpr[1], regs); + unlock_kernel(); + return ret; } -/* - * sys_execve() executes a new program. - * - * This works due to the PowerPC calling sequence: the first 6 args - * are gotten from registers, while the rest is on the stack, so - * we get a0-a5 for free, and then magically find "struct pt_regs" - * on the stack for us.. - * - * Don't do this at home. - */ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5, struct pt_regs *regs) @@ -196,12 +260,31 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, int error; char * filename; - error = getname((char *) a0, &filename); - if (error) + lock_kernel(); + /* getname does it's own verification of the address + when it calls get_max_filename() but + it will assume it's valid if get_fs() == KERNEL_DS + which is always true on the ppc so we check + it here + + this doesn't completely check any of these data structures, + it just makes sure that the 1st long is in a good area + and from there we assume that it's safe then + -- Cort + */ + /* works now since get_fs/set_fs work properly */ +#if 0 + if ( verify_area(VERIFY_READ,(void *)a0,1) + && verify_area(VERIFY_READ,(void *)a1,1) + && verify_area(VERIFY_READ,(void *)a2,1) + ) { -printk("Error getting EXEC name: %d\n", error); - return error; + return -EFAULT; } +#endif + error = getname((char *) a0, &filename); + if (error) + goto out; flush_instruction_cache(); error = do_execve(filename, (char **) a1, (char **) a2, regs); #if 0 @@ -211,30 +294,32 @@ printk("EXECVE - file = '%s', error = %d\n", filename, error); } #endif putname(filename); +out: + unlock_kernel(); return error; } -/* - * This doesn't actually work correctly like this: we need to do the - * same stack setups that fork() does first. - */ asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs) { unsigned long clone_flags = p1; int res; + + lock_kernel(); res = do_fork(clone_flags, regs->gpr[1], regs); + unlock_kernel(); return res; } void print_backtrace(unsigned long *sp) { +#if 0 int cnt = 0; printk("... Call backtrace:\n"); - while (*sp) + while (verify_area(VERIFY_READ,sp,sizeof(long)) && *sp) { printk("%08X ", sp[1]); - sp = *sp; + sp = (unsigned long *)*sp; if (++cnt == 8) { printk("\n"); @@ -242,17 +327,19 @@ print_backtrace(unsigned long *sp) if (cnt > 32) break; } printk("\n"); +#endif } void print_user_backtrace(unsigned long *sp) { +#if 0 int cnt = 0; printk("... [User] Call backtrace:\n"); - while (valid_addr(sp) && *sp) + while (verify_area(VERIFY_READ,sp,sizeof(long)) && *sp) { printk("%08X ", sp[1]); - sp = *sp; + sp = (unsigned long *)*sp; if (++cnt == 8) { printk("\n"); @@ -260,11 +347,23 @@ print_user_backtrace(unsigned long *sp) if (cnt > 16) break; } printk("\n"); +#endif } void print_kernel_backtrace(void) { +#if 0 unsigned long *_get_SP(void); print_backtrace(_get_SP()); +#endif +} +inline void start_thread(struct pt_regs * regs, + unsigned long eip, unsigned long esp) +{ + regs->nip = eip; + regs->gpr[1] = esp; + regs->msr = MSR_USER; + set_fs(USER_DS); } + diff --git a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c index dc4012f57..2d960c8cd 100644 --- a/arch/ppc/kernel/ptrace.c +++ b/arch/ppc/kernel/ptrace.c @@ -7,6 +7,7 @@ * * Adapted from 'linux/arch/m68k/kernel/ptrace.c' * PowerPC version by Gary Thomas (gdt@linuxppc.org) + * Modified by Cort Dougan (cort@cs.nmt.edu) * * This file is subject to the terms and conditions of the GNU General * Public License. See the file README.legal in the main directory of @@ -17,6 +18,8 @@ #include <linux/kernel.h> #include <linux/sched.h> #include <linux/mm.h> +#include <linux/smp.h> +#include <linux/smp_lock.h> #include <linux/errno.h> #include <linux/ptrace.h> #include <linux/user.h> @@ -264,7 +267,7 @@ static struct vm_area_struct * find_extend_vma(struct task_struct * tsk, unsigne struct vm_area_struct * vma; addr &= PAGE_MASK; - vma = find_vma(tsk,addr); + vma = find_vma(tsk->mm,addr); if (!vma) return NULL; if (vma->vm_start <= addr) @@ -375,34 +378,37 @@ static int write_long(struct task_struct * tsk, unsigned long addr, asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; - struct user * dummy; - - dummy = NULL; + struct user * dummy = NULL; + int ret = -EPERM; + lock_kernel(); if (request == PTRACE_TRACEME) { /* are we already being traced? */ if (current->flags & PF_PTRACED) - return -EPERM; + goto out; /* set the ptrace bit in the process flags. */ current->flags |= PF_PTRACED; - return 0; + ret = 0; + goto out; } if (pid == 1) /* you may not mess with init */ - return -EPERM; + goto out; + ret = -ESRCH; if (!(child = get_task(pid))) - return -ESRCH; + goto out; + ret = -EPERM; if (request == PTRACE_ATTACH) { if (child == current) - return -EPERM; + goto out; if ((!child->dumpable || (current->uid != child->euid) || (current->uid != child->uid) || (current->gid != child->egid) || (current->gid != child->gid)) && !suser()) - return -EPERM; + goto out; /* the same process cannot be attached many times */ if (child->flags & PF_PTRACED) - return -EPERM; + goto out; child->flags |= PF_PTRACED; if (child->p_pptr != current) { REMOVE_LINKS(child); @@ -410,73 +416,75 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) SET_LINKS(child); } send_sig(SIGSTOP, child, 1); - return 0; + ret = 0; + goto out; } + ret = -ESRCH; if (!(child->flags & PF_PTRACED)) - return -ESRCH; + goto out; if (child->state != TASK_STOPPED) { if (request != PTRACE_KILL) - return -ESRCH; + goto out; } if (child->p_pptr != current) - return -ESRCH; + goto out; switch (request) { /* If I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: { unsigned long tmp; - int res; - res = read_long(child, addr, &tmp); - if (res < 0) - return res; - res = verify_area(VERIFY_WRITE, (void *) data, sizeof(long)); - if (!res) + ret = read_long(child, addr, &tmp); + if (ret < 0) + goto out; + ret = verify_area(VERIFY_WRITE, (void *) data, sizeof(long)); + if (!ret) put_user(tmp, (unsigned long *) data); - return res; + goto out; } /* read the word at location addr in the USER area. */ case PTRACE_PEEKUSR: { unsigned long tmp; - int res; if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) return -EIO; - res = verify_area(VERIFY_WRITE, (void *) data, + ret = verify_area(VERIFY_WRITE, (void *) data, sizeof(long)); - if (res) - return res; + if (ret) + goto out; tmp = 0; /* Default return condition */ addr = addr >> 2; /* temporary hack. */ - if (addr < PT_FPR0) { + if (addr < PT_FPR0) tmp = get_reg(child, addr); - } #if 0 else if (addr >= PT_FPR0 && addr < PT_FPR31) tmp = child->tss.fpr[addr - PT_FPR0]; #endif else - return -EIO; - put_user(tmp,(unsigned long *) data); - return 0; + ret = -EIO; + if(!ret) + put_user(tmp,(unsigned long *) data); + goto out; } /* If I and D space are separate, this will have to be fixed. */ case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKEDATA: - return write_long(child,addr,data); + ret = write_long(child,addr,data); + goto out; case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ + ret = -EIO; if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) - return -EIO; + goto out; addr = addr >> 2; /* temporary hack. */ if (addr == PT_ORIG_R3) - return -EIO; + goto out; #if 0 /* Let this check be in 'put_reg' */ if (addr == PT_SR) { data &= SR_MASK; @@ -486,22 +494,24 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) #endif if (addr < PT_FPR0) { if (put_reg(child, addr, data)) - return -EIO; - return 0; + goto out; + ret = 0; + goto out; } #if 0 - if (addr >= 21 && addr < 48) - { + if (addr >= 21 && addr < 48) { child->tss.fp[addr - 21] = data; - return 0; + ret = 0; + goto out; } #endif - return -EIO; + goto out; case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ + ret = -EIO; if ((unsigned long) data >= NSIG) - return -EIO; + goto out; if (request == PTRACE_SYSCALL) child->flags |= PF_TRACESYS; else @@ -510,7 +520,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) wake_up_process(child); /* make sure the single step bit is not set. */ clear_single_step(child); - return 0; + ret = 0; + goto out; } /* @@ -519,29 +530,33 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) * exit. */ case PTRACE_KILL: { + ret = 0; if (child->state == TASK_ZOMBIE) /* already dead */ - return 0; + goto out; wake_up_process(child); child->exit_code = SIGKILL; /* make sure the single step bit is not set. */ clear_single_step(child); - return 0; + goto out; } case PTRACE_SINGLESTEP: { /* set the trap flag. */ + ret = -EIO; if ((unsigned long) data >= NSIG) - return -EIO; + goto out; child->flags &= ~PF_TRACESYS; set_single_step(child); wake_up_process(child); child->exit_code = data; /* give it a chance to run. */ - return 0; + ret = 0; + goto out; } case PTRACE_DETACH: { /* detach a process that was attached. */ + ret = -EIO; if ((unsigned long) data >= NSIG) - return -EIO; + goto out; child->flags &= ~(PF_PTRACED|PF_TRACESYS); wake_up_process(child); child->exit_code = data; @@ -550,19 +565,25 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) SET_LINKS(child); /* make sure the single step bit is not set. */ clear_single_step(child); - return 0; + ret = 0; + goto out; } default: - return -EIO; + ret = -EIO; + goto out; } +out: + unlock_kernel(); + return ret; } asmlinkage void syscall_trace(void) { + lock_kernel(); if ((current->flags & (PF_PTRACED|PF_TRACESYS)) != (PF_PTRACED|PF_TRACESYS)) - return; + goto out; current->exit_code = SIGTRAP; current->state = TASK_STOPPED; notify_parent(current); @@ -575,5 +596,6 @@ asmlinkage void syscall_trace(void) if (current->exit_code) current->signal |= (1 << (current->exit_code - 1)); current->exit_code = 0; - return; +out: + unlock_kernel(); } diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 6f330b052..25f03cc11 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -3,6 +3,7 @@ * * Copyright (C) 1995 Linus Torvalds * Adapted from 'alpha' version by Gary Thomas + * Modified by Cort Dougan (cort@cs.nmt.edu) */ /* @@ -17,23 +18,22 @@ #include <linux/unistd.h> #include <linux/ptrace.h> #include <linux/malloc.h> -#include <linux/ldt.h> #include <linux/user.h> #include <linux/a.out.h> #include <linux/tty.h> #include <linux/major.h> -#define SIO_CONFIG_RA 0x398 -#define SIO_CONFIG_RD 0x399 - +#include <asm/mmu.h> +#include <asm/processor.h> +#include <asm/residual.h> +#include <asm/io.h> #include <asm/pgtable.h> extern unsigned long *end_of_DRAM; extern PTE *Hash; extern unsigned long Hash_size, Hash_mask; - -char sda_root[] = "root=/dev/sda1"; -extern int root_mountflags; +extern int probingmem; +unsigned long empty_zero_page[1024]; unsigned char aux_device_present; #ifdef CONFIG_BLK_DEV_RAM @@ -42,6 +42,14 @@ extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */ extern int rd_image_start; /* starting block # of image */ #endif +#undef HASHSTATS + +extern unsigned long isBeBox[]; + +/* copy of the residual data */ +RESIDUAL res; +unsigned long resptr = 0; /* ptr to residual data from hw */ + /* * The format of "screen_info" is strange, and due to early * i386-setup code. This is just enough to make the console @@ -51,196 +59,351 @@ extern int rd_image_start; /* starting block # of image */ -- Cort */ struct screen_info screen_info = { - 0, 25, /* orig-x, orig-y */ - { 0, 0 }, /* unused */ - 0, /* orig-video-page */ - 0, /* orig-video-mode */ - 80, /* orig-video-cols */ - 0,0,0, /* ega_ax, ega_bx, ega_cx */ - 25, /* orig-video-lines */ - 1, /* orig-video-isVGA */ - 16 /* orig-video-points */ + 0, 25, /* orig-x, orig-y */ + { 0, 0 }, /* unused */ + 0, /* orig-video-page */ + 0, /* orig-video-mode */ + 80, /* orig-video-cols */ + 0,0,0, /* ega_ax, ega_bx, ega_cx */ + 25, /* orig-video-lines */ + 1, /* orig-video-isVGA */ + 16 /* orig-video-points */ }; unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end) { - return memory_start; + return memory_start; } -unsigned long find_end_of_memory(void) +#ifdef HASHSTATS +unsigned long *hashhits; +#endif + +extern unsigned long _TotalMemory; +/* find the physical size of RAM and setup hardware hash table */ +unsigned long *find_end_of_memory(void) { - unsigned char dram_size = inb(0x0804); - unsigned long total; - extern BAT BAT2; -printk("DRAM Size = %x\n", dram_size); -printk("Config registers = %x/%x/%x/%x\n", inb(0x0800), inb(0x0801), inb(0x0802), inb(0x0803)); - switch (dram_size & 0x07) - { - case 0: - total = 0x08000000; /* 128M */ - break; - case 1: - total = 0x02000000; /* 32M */ - break; - case 2: - total = 0x00800000; /* 8M */ - break; - case 3: - total = 0x00400000; /* 4M - can't happen! */ - break; - case 4: - total = 0x10000000; /* 256M */ - break; - case 5: - total = 0x04000000; /* 64M */ - break; - case 6: - total = 0x01000000; /* 16M */ - break; - case 7: - total = 0x04000000; /* Can't happen */ - break; - } - switch ((dram_size>>4) & 0x07) - { - case 0: - total += 0x08000000; /* 128M */ - break; - case 1: - total += 0x02000000; /* 32M */ - break; - case 2: - total += 0x00800000; /* 8M */ - break; - case 3: - total += 0x00000000; /* Module not present */ - break; - case 4: - total += 0x10000000; /* 256M */ - break; - case 5: - total += 0x04000000; /* 64M */ - break; - case 6: - total += 0x01000000; /* 16M */ - break; - case 7: - total += 0x00000000; /* Module not present */ - break; - } -/* TEMP */ total = 0x01000000; -/* _cnpause(); */ -/* CAUTION!! This can be done more elegantly! */ - if (total < 0x01000000) - { - Hash_size = HASH_TABLE_SIZE_64K; - Hash_mask = HASH_TABLE_MASK_64K; - } else - { - Hash_size = HASH_TABLE_SIZE_128K; - Hash_mask = HASH_TABLE_MASK_128K; - } - switch(total) - { - case 0x01000000: -/* BAT2[0][1] = BL_16M;*/ - break; - default: - printk("WARNING: setup.c: find_end_of_memory() unknown total ram size %x\n", total); - break; - } - - Hash = (PTE *)((total-Hash_size)+KERNELBASE); - bzero(Hash, Hash_size); - return ((unsigned long)Hash); + extern BAT BAT2; + _TotalMemory = res.TotalMemory; + + if (_TotalMemory == 0 ) + { + printk("Ramsize from residual data was 0 -- Probing for value\n"); + /* this needs be done differently since the bats actually map + addresses beyond physical memory! -- Cort */ +#if 0 + probingmem = 1; + while ( probingmem ) + { + _TotalMemory += 0x00800000; /* 8M */ + *(unsigned long *)_TotalMemory+KERNELBASE; + } + _TotalMemory -= 0x00800000; +#else + _TotalMemory = 0x03000000; +#endif + printk("Ramsize probed to be %dM\n", _TotalMemory>>20); + } + + /* setup BAT2 mapping so that it covers kernelbase to kernelbase+ramsize */ + switch(_TotalMemory) + { + case 0x01000000: /* 16M */ + BAT2.batu.bl = BL_16M; + Hash_size = HASH_TABLE_SIZE_128K; + Hash_mask = HASH_TABLE_MASK_128K; + break; + case 0x00800000: /* 8M */ + BAT2.batu.bl = BL_8M; + Hash_size = HASH_TABLE_SIZE_64K; + Hash_mask = HASH_TABLE_MASK_64K; + break; + case 0x01800000: /* 24M */ + case 0x02000000: /* 32M */ + BAT2.batu.bl = BL_32M; + Hash_size = HASH_TABLE_SIZE_256K; + Hash_mask = HASH_TABLE_MASK_256K; + break; + case 0x03000000: /* 48M */ + case 0x04000000: /* 64M */ + BAT2.batu.bl = BL_64M; + Hash_size = HASH_TABLE_SIZE_512K; + Hash_mask = HASH_TABLE_MASK_512K; + break; + case 0x05000000: /* 80M */ + BAT2.batu.bl = BL_128M; + Hash_size = HASH_TABLE_SIZE_1M; + Hash_mask = HASH_TABLE_MASK_1M; + break; + default: + printk("WARNING: setup.c: find_end_of_memory() unknown total ram size %x\n", + _TotalMemory); + break; + } + + Hash = (PTE *)((_TotalMemory-Hash_size)+KERNELBASE); + bzero(Hash, Hash_size); + + +#ifdef HASHSTATS + hashhits = (unsigned long *)Hash - (Hash_size/sizeof(struct _PTE))/2; + bzero(hashhits, (Hash_size/sizeof(struct _PTE))/2); + return ((unsigned long *)hashhits); +#else + return ((unsigned long *)Hash); +#endif } int size_memory; -/* #define DEFAULT_ROOT_DEVICE 0x0200 /* fd0 */ -#define DEFAULT_ROOT_DEVICE 0x0801 /* sda1 */ +/* + * This is set up by the setup-routine at boot-time + */ +#define EXT_MEM_K (*(unsigned short *) (PARAM+2)) +#ifdef CONFIG_APM +#define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+64)) +#endif +#define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80)) +#define SCREEN_INFO (*(struct screen_info *) (PARAM+0)) +#define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2)) +#define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8)) +#define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC)) +#define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF)) +#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210)) +#define KERNEL_START (*(unsigned long *) (PARAM+0x214)) +#define INITRD_START (*(unsigned long *) (PARAM+0x218)) +#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c)) +#define COMMAND_LINE ((char *) (PARAM+2048)) +#define COMMAND_LINE_SIZE 256 + +#define RAMDISK_IMAGE_START_MASK 0x07FF +#define RAMDISK_PROMPT_FLAG 0x8000 +#define RAMDISK_LOAD_FLAG 0x4000 + +static char command_line[COMMAND_LINE_SIZE] = { 0, }; + char saved_command_line[COMMAND_LINE_SIZE]; -void setup_arch(char **cmdline_p, - unsigned long * memory_start_p, unsigned long * memory_end_p) + +void +setup_arch(char **cmdline_p, unsigned long * memory_start_p, + unsigned long * memory_end_p) { - extern int _end; - extern char cmd_line[]; - unsigned char reg; - - /* Set up floppy in PS/2 mode */ - outb(0x09, SIO_CONFIG_RA); - reg = inb(SIO_CONFIG_RD); - reg = (reg & 0x3F) | 0x40; - outb(reg, SIO_CONFIG_RD); - outb(reg, SIO_CONFIG_RD); /* Have to write twice to change! */ - ROOT_DEV = to_kdev_t(DEFAULT_ROOT_DEVICE); - /*ROOT_DEV = MKDEV(UNNAMED_MAJOR, 255);*/ /* nfs */ - aux_device_present = 0xaa; + extern int _end; + extern char cmd_line[]; + unsigned char reg; + extern int panic_timeout; + char inf[512]; + int i; + + if (isBeBox[0]) + _Processor = _PROC_Be; + else + { + if (strncmp(res.VitalProductData.PrintableModel,"IBM",3)) + { + _Processor = _PROC_Motorola; + } + else + _Processor = _PROC_IBM; + } + + get_cpuinfo(&inf); + printk("%s",inf); + + /* Set up floppy in PS/2 mode */ + outb(0x09, SIO_CONFIG_RA); + reg = inb(SIO_CONFIG_RD); + reg = (reg & 0x3F) | 0x40; + outb(reg, SIO_CONFIG_RD); + outb(reg, SIO_CONFIG_RD); /* Have to write twice to change! */ + + switch ( _Processor ) + { + case _PROC_IBM: + ROOT_DEV = to_kdev_t(0x0301); /* hda1 */ + break; + case _PROC_Motorola: + ROOT_DEV = to_kdev_t(0x0801); /* sda1 */ + break; + } + aux_device_present = 0xaa; + + panic_timeout = 300; /* reboot on panic */ + +#if 0 + /* get root via nfs from charon -- was only used for testing */ + ROOT_DEV = MKDEV(UNNAMED_MAJOR, 255); /* nfs */ /*nfsaddrs=myip:serverip:gateip:netmaskip:clientname*/ strcpy(cmd_line, - "nfsaddrs=129.138.6.13:129.138.6.90:129.138.6.1:255.255.255.0:pandora"); - /* strcpy(cmd_line,"root=/dev/sda1");*/ - *cmdline_p = cmd_line; - *memory_start_p = (unsigned long) &_end; - *memory_end_p = (unsigned long *)end_of_DRAM; - size_memory = *memory_end_p - KERNELBASE; /* Relative size of memory */ + "nfsaddrs=129.138.6.101:129.138.6.90:129.138.6.1:255.255.255.0:gordito nfsroot=/joplin/ppc/root/"); +#endif + *cmdline_p = cmd_line; + *memory_start_p = (unsigned long) &_end; + (unsigned long *)*memory_end_p = (unsigned long *)end_of_DRAM; + size_memory = *memory_end_p - KERNELBASE; /* Relative size of memory */ #ifdef CONFIG_BLK_DEV_RAM rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); - rd_prompt = 0; - rd_doload = 0; +#if 1 + rd_prompt = 1; + rd_doload = 1; rd_image_start = 0; -#endif +#endif +#endif + + /* Save unparsed command line copy for /proc/cmdline */ + memcpy(saved_command_line, cmd_line,strlen(cmd_line)+1); + printk("Command line: %s\n", cmd_line); } asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on) { - return -EIO; + return -EIO; } -#if 0 -extern char builtin_ramdisk_image; -extern long builtin_ramdisk_size; -void -builtin_ramdisk_init(void) -{ - if ((ROOT_DEV == to_kdev_t(DEFAULT_ROOT_DEVICE)) && (builtin_ramdisk_size != 0)) - { - rd_preloaded_init(&builtin_ramdisk_image, builtin_ramdisk_size); - } else - { /* Not ramdisk - assume root needs to be mounted read only */ - root_mountflags |= MS_RDONLY; - } -} -#endif -#define MAJOR(n) (((n)&0xFF00)>>8) -#define MINOR(n) ((n)&0x00FF) int get_cpuinfo(char *buffer) { - int pvr = _get_PVR(); - char *model; - switch (pvr>>16) - { - case 3: - model = "603"; - break; - case 4: - model = "604"; - break; - case 6: - model = "603e"; - break; - case 7: - model = "603ev"; - break; - default: - model = "unknown"; - break; - } - return sprintf(buffer, "PowerPC %s rev %d.%d\n", model, MAJOR(pvr), MINOR(pvr)); + extern unsigned long loops_per_sec; + int i; + int pvr = _get_PVR(); + int len; + char *model; + unsigned long full = 0, overflow = 0; + unsigned int ti; + PTE *ptr; + + switch (pvr>>16) + { + case 3: + model = "603"; + break; + case 4: + model = "604"; + break; + case 6: + model = "603e"; + break; + case 7: + model = "603ev"; + break; + default: + model = "unknown"; + break; + } + +#ifdef __SMP__ +#define CD(X) (cpu_data[n].X) +#else +#define CD(X) (X) +#define CPUN 0 +#endif + + len = sprintf(buffer, "PowerPC %s/%dMHz revision %d.%d %s\n", + model, + (res.VitalProductData.ProcessorHz > 1024) ? + res.VitalProductData.ProcessorHz>>20 : + res.VitalProductData.ProcessorHz, + MAJOR(pvr), MINOR(pvr), + (inb(IBM_EQUIP_PRESENT) & 2) ? "" : "upgrade"); +#if 1 + if ( res.VitalProductData.PrintableModel[0] ) + len += sprintf(buffer+len,"%s\n",res.VitalProductData.PrintableModel); + + len += sprintf(buffer+len,"Bus %dMHz\n", + (res.VitalProductData.ProcessorBusHz > 1024) ? + res.VitalProductData.ProcessorBusHz>>20 : + res.VitalProductData.ProcessorBusHz); + + /* make sure loops_per_sec has been setup -- ie not at boottime -- Cort */ + if ( CD(loops_per_sec+2500)/500000 > 0) + len += sprintf(buffer+len, + "bogomips: %lu.%02lu\n", + CD(loops_per_sec+2500)/500000, + (CD(loops_per_sec+2500)/5000) % 100); + + + len += sprintf(buffer+len,"Total Ram: %dM Hash Table: %dkB (%dk buckets)\n", + _TotalMemory>>20, Hash_size>>10, + (Hash_size/(sizeof(PTE)*8)) >> 10); + + for ( i = 0 ; (res.ActualNumMemories) && (i < MAX_MEMS) ; i++ ) + { + if (i == 0) + len += sprintf(buffer+len,"SIMM Banks: "); + if ( res.Memories[i].SIMMSize != 0 ) + len += sprintf(buffer+len,"%d:%dM ",i, + (res.Memories[i].SIMMSize > 1024) ? + res.Memories[i].SIMMSize>>20 : + res.Memories[i].SIMMSize); + if ( i == MAX_MEMS-1) + len += sprintf(buffer+len,"\n"); + } + + /* TLB */ + len += sprintf(buffer+len,"TLB"); + switch(res.VitalProductData.TLBAttrib) + { + case CombinedTLB: + len += sprintf(buffer+len,": %d entries\n", + res.VitalProductData.TLBSize); + break; + case SplitTLB: + len += sprintf(buffer+len,": (split I/D) %d/%d entries\n", + res.VitalProductData.I_TLBSize, + res.VitalProductData.D_TLBSize); + break; + case NoneTLB: + len += sprintf(buffer+len,": not present\n"); + break; + } + + /* L1 */ + len += sprintf(buffer+len,"L1: "); + switch(res.VitalProductData.CacheAttrib) + { + case CombinedCAC: + len += sprintf(buffer+len,"%dkB LineSize\n", + res.VitalProductData.CacheSize, + res.VitalProductData.CacheLineSize); + break; + case SplitCAC: + len += sprintf(buffer+len,"(split I/D) %dkB/%dkB Linesize %dB/%dB\n", + res.VitalProductData.I_CacheSize, + res.VitalProductData.D_CacheSize, + res.VitalProductData.D_CacheLineSize, + res.VitalProductData.D_CacheLineSize); + break; + case NoneCAC: + len += sprintf(buffer+len,"not present\n"); + break; + } + + /* L2 */ + if ( (inb(IBM_EQUIP_PRESENT) & 1) == 0) /* l2 present */ + { + int size; + + len += sprintf(buffer+len,"L2: %dkB %s\n", + ((inb(IBM_L2_STATUS) >> 5) & 1) ? 512 : 256, + (inb(IBM_SYS_CTL) & 64) ? "enabled" : "disabled"); + } + else + { + len += sprintf(buffer+len,"L2: not present\n"); + } +#if 0 + len+= sprintf(buffer+len,"Equip register %x\n", + inb(IBM_EQUIP_PRESENT)); + len+= sprintf(buffer+len,"L2Status register %x\n", + inb(IBM_L2_STATUS)); +#endif +#endif + + + return len; } diff --git a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c index 18a0a10d9..ba8864251 100644 --- a/arch/ppc/kernel/signal.c +++ b/arch/ppc/kernel/signal.c @@ -3,16 +3,20 @@ * * Copyright (C) 1991, 1992 Linus Torvalds * Adapted for PowerPC by Gary Thomas + * Modified by Cort Dougan (cort@cs.nmt.edu) */ #include <linux/sched.h> #include <linux/mm.h> +#include <linux/smp.h> +#include <linux/smp_lock.h> #include <linux/kernel.h> #include <linux/signal.h> #include <linux/errno.h> #include <linux/wait.h> #include <linux/ptrace.h> #include <linux/unistd.h> +#include <asm/uaccess.h> #define _S(nr) (1<<((nr)-1)) @@ -26,7 +30,9 @@ asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options); asmlinkage int sys_sigsuspend(unsigned long set, int p2, int p3, int p4, int p6, int p7, struct pt_regs *regs) { unsigned long mask; + int ret = -EINTR; + lock_kernel(); mask = current->blocked; current->blocked = set & _BLOCKABLE; regs->gpr[3] = -EINTR; @@ -37,25 +43,32 @@ printk("Task: %x[%d] - SIGSUSPEND at %x, Mask: %x\n", current, current->pid, reg current->state = TASK_INTERRUPTIBLE; schedule(); if (do_signal(mask,regs)) - return -EINTR; + goto out; } +out: + unlock_kernel(); + return ret; } -/* - * This sets regs->esp even though we don't actually use sigstacks yet.. - */ asmlinkage int sys_sigreturn(struct pt_regs *regs) { struct sigcontext_struct *sc; struct pt_regs *int_regs; - int signo; + int signo, ret; + + lock_kernel(); +#if 1 + if (verify_area(VERIFY_READ, (void *) regs->gpr[1], sizeof(sc)) + || (regs->gpr[1] >=KERNELBASE)) + goto badframe; +#endif sc = (struct sigcontext_struct *)regs->gpr[1]; current->blocked = sc->oldmask & _BLOCKABLE; int_regs = sc->regs; signo = sc->signal; sc++; /* Pop signal 'context' */ - if (sc == (struct sigcontext_struct *)(int_regs)) - { /* Last stacked signal */ + if (sc == (struct sigcontext_struct *)(int_regs)) { + /* Last stacked signal */ #if 0 /* This doesn't work - it blows away the return address! */ memcpy(regs, int_regs, sizeof(*regs)); @@ -72,16 +85,24 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs) regs->nip -= 4; /* Back up & retry system call */ regs->result = 0; } - return (regs->result); - } else - { /* More signals to go */ + ret = (regs->result); + } else { /* More signals to go */ regs->gpr[1] = (unsigned long)sc; regs->gpr[3] = sc->signal; regs->gpr[4] = sc->regs; regs->link = (unsigned long)((sc->regs)+1); regs->nip = sc->handler; - return (sc->signal); + ret = sc->signal; } + goto out; + +badframe: + /*printk("sys_sigreturn(): badstack regs %x cur %s/%d\n", + regs,current->comm,current->pid);*/ + do_exit(SIGSEGV); +out: + unlock_kernel(); + return ret; } @@ -96,27 +117,24 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs) */ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) { - unsigned long mask = ~current->blocked; + unsigned long mask; unsigned long handler_signal = 0; unsigned long *frame = NULL; - unsigned long *trampoline; - unsigned long *regs_ptr; + unsigned long *trampoline, *regs_ptr; unsigned long nip = 0; unsigned long signr; - int bitno; struct sigcontext_struct *sc; struct sigaction * sa; - int s = _disable_interrupts(); + int bitno, s, ret; + + lock_kernel(); + mask = ~current->blocked; while ((signr = current->signal & mask)) { -#if 0 - signr = ffz(~signr); /* Compute bit # */ -#else for (bitno = 0; bitno < 32; bitno++) - { - if (signr & (1<<bitno)) break; - } + if (signr & (1<<bitno)) + break; signr = bitno; -#endif + current->signal &= ~(1<<signr); /* Clear bit */ sa = current->sig->action + signr; signr++; @@ -157,7 +175,7 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) current->state = TASK_STOPPED; current->exit_code = signr; if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & - SA_NOCLDSTOP)) + SA_NOCLDSTOP)) notify_parent(current); schedule(); continue; @@ -174,27 +192,33 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) do_exit(signr); } } - /* - * OK, we're invoking a handler - */ + + /* handle signal */ if ((int)regs->orig_gpr3 >= 0) { if ((int)regs->result == -ERESTARTNOHAND || - ((int)regs->result == -ERESTARTSYS && !(sa->sa_flags & SA_RESTART))) + ((int)regs->result == -ERESTARTSYS && + !(sa->sa_flags & SA_RESTART))) (int)regs->result = -EINTR; } handler_signal |= 1 << (signr-1); mask &= ~sa->sa_mask; } + ret = 0; if (!handler_signal) /* no handler will be called - return 0 */ - { - _enable_interrupts(s); - return 0; - } + goto out; + nip = regs->nip; frame = (unsigned long *) regs->gpr[1]; + /* Build trampoline code on stack */ frame -= 2; trampoline = frame; +#if 1 + /* verify stack is valid for writing regs struct */ + if (verify_area(VERIFY_WRITE,(void *)frame, sizeof(long)*2+sizeof(*regs)) + || (frame >= KERNELBASE )) + goto badframe; +#endif trampoline[0] = 0x38007777; /* li r0,0x7777 */ trampoline[1] = 0x44000002; /* sc */ frame -= sizeof(*regs) / sizeof(long); @@ -202,12 +226,19 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) memcpy(regs_ptr, regs, sizeof(*regs)); signr = 1; sa = current->sig->action; + for (mask = 1 ; mask ; sa++,signr++,mask += mask) { if (mask > handler_signal) break; if (!(mask & handler_signal)) continue; + frame -= sizeof(struct sigcontext_struct) / sizeof(long); +#if 1 + if (verify_area(VERIFY_WRITE,(void *)frame, + sizeof(struct sigcontext_struct)/sizeof(long))) + goto badframe; +#endif sc = (struct sigcontext_struct *)frame; nip = (unsigned long) sa->sa_handler; #if 0 /* Old compiler */ @@ -226,14 +257,27 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) regs->link = (unsigned long)trampoline; regs->nip = nip; regs->gpr[1] = (unsigned long)sc; - /* The DATA cache must be flushed here to insure coherency */ - /* between the DATA & INSTRUCTION caches. Since we just */ - /* created an instruction stream using the DATA [cache] space */ - /* and since the instruction cache will not look in the DATA */ - /* cache for new data, we have to force the data to go on to */ - /* memory and flush the instruction cache to force it to look */ - /* there. The following function performs this magic */ + + /* The DATA cache must be flushed here to insure coherency + * between the DATA & INSTRUCTION caches. Since we just + * created an instruction stream using the DATA [cache] space + * and since the instruction cache will not look in the DATA + * cache for new data, we have to force the data to go on to + * memory and flush the instruction cache to force it to look + * there. The following function performs this magic + */ flush_instruction_cache(); - _enable_interrupts(s); - return 1; + ret = 1; + goto out; + +badframe: +#if 0 + printk("do_signal(): badstack signr %d frame %x regs %x cur %s/%d\n", + signr, frame, regs, current->comm, current->pid); +#endif + do_exit(SIGSEGV); + +out: + unlock_kernel(); + return ret; } diff --git a/arch/ppc/kernel/stubs.c b/arch/ppc/kernel/stubs.c index b7af6dd44..30f028279 100644 --- a/arch/ppc/kernel/stubs.c +++ b/arch/ppc/kernel/stubs.c @@ -1,59 +1,58 @@ -#include <linux/in.h> +/*#include <linux/in.h>*/ +#include <linux/autoconf.h> +#include <linux/smp.h> +#include <linux/smp_lock.h> -void sys_iopl(void) { _panic("sys_iopl"); } -void sys_vm86(void) { _panic("sys_vm86"); } -void sys_modify_ldt(void) { _panic("sys_modify_ldt"); } - -void sys_ipc(void) {_panic("sys_ipc"); } -void sys_newselect(void) {_panic("sys_newselect"); } - -halt() -{ - printk("\n...Halt!\n"); - abort(); -} - -_panic(char *msg) +void sys_iopl(void) { - printk("Panic: %s\n", msg); - printk("Panic: %s\n", msg); - abort(); + lock_kernel(); + panic("sys_iopl"); + unlock_kernel(); } - -_warn(char *msg) +void sys_vm86(void) { - printk("*** Warning: %s UNIMPLEMENTED!\n", msg); + lock_kernel(); + panic("sys_vm86"); + unlock_kernel(); } - - -void -saved_command_line(void) +void sys_modify_ldt(void) { - panic("saved_command_line"); + lock_kernel(); + panic("sys_modify_ldt"); + unlock_kernel(); } -void -KSTK_EIP(void) +void sys_ipc(void) { - panic("KSTK_EIP"); + lock_kernel(); + panic("sys_ipc"); + unlock_kernel(); } -void -KSTK_ESP(void) +void sys_newselect(void) { - panic("KSTK_ESP"); + lock_kernel(); + panic("sys_newselect"); + unlock_kernel(); } +#ifndef CONFIG_MODULES void scsi_register_module(void) { + lock_kernel(); panic("scsi_register_module"); + unlock_kernel(); } void scsi_unregister_module(void) { + lock_kernel(); panic("scsi_unregister_module"); + unlock_kernel(); } +#endif + diff --git a/arch/ppc/kernel/syscalls.c b/arch/ppc/kernel/syscalls.c index 7dd34510c..9d18c45ab 100644 --- a/arch/ppc/kernel/syscalls.c +++ b/arch/ppc/kernel/syscalls.c @@ -2,6 +2,7 @@ * linux/arch/ppc/kernel/sys_ppc.c * * Adapted from the i386 version by Gary Thomas + * Modified by Cort Dougan (cort@cs.nmt.edu) * * This file contains various random system calls that * have a non-standard calling sequence on the Linux/PPC @@ -11,11 +12,14 @@ #include <linux/errno.h> #include <linux/sched.h> #include <linux/mm.h> +#include <linux/smp.h> +#include <linux/smp_lock.h> #include <linux/sem.h> #include <linux/msg.h> #include <linux/shm.h> #include <linux/stat.h> #include <linux/mman.h> +#include <asm/uaccess.h> /* * sys_pipe() is the normal C calling standard for creating @@ -24,30 +28,35 @@ asmlinkage int sys_pipe(unsigned long * fildes) { int error; + + lock_kernel(); error = verify_area(VERIFY_WRITE,fildes,8); if (error) - return error; + goto out; error = do_pipe(fildes); - if (error) - return error; - return 0; +out: + unlock_kernel(); + return error; } asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, int prot, int flags, int fd, off_t offset) { struct file * file = NULL; + int ret = -EBADF; + lock_kernel(); if (!(flags & MAP_ANONYMOUS)) { if (fd >= NR_OPEN || !(file = current->files->fd[fd])) - return -EBADF; + goto out; } flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - return do_mmap(file, addr, len, prot, flags, offset); + ret = do_mmap(file, addr, len, prot, flags, offset); +out: + unlock_kernel(); + return ret; } -#if 0 /* * Perform the select(nd, in, out, ex, tv) and mmap() system * calls. Linux/i386 didn't use to be able to handle more than @@ -58,20 +67,30 @@ asmlinkage int old_mmap(unsigned long *buffer) { int error; unsigned long flags; + long a,b,c,d,e; struct file * file = NULL; + lock_kernel(); error = verify_area(VERIFY_READ, buffer, 6*sizeof(long)); if (error) - return error; - flags = get_user(buffer+3); + goto out; + get_user(flags,buffer+3); if (!(flags & MAP_ANONYMOUS)) { - unsigned long fd = get_user(buffer+4); + unsigned long fd; + get_user(fd,buffer+4); + error = -EBADF; if (fd >= NR_OPEN || !(file = current->files->fd[fd])) - return -EBADF; + goto out; } flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - return do_mmap(file, get_user(buffer), get_user(buffer+1), - get_user(buffer+2), flags, get_user(buffer+5)); + error = -EFAULT; + if ( get_user(a,buffer) || get_user(b,buffer+1) || + get_user(c,buffer+2)||get_user(d,buffer+5) ) + goto out; + error = do_mmap(file,a,b,c, flags, d); +out: + unlock_kernel(); + return error; } extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); @@ -84,16 +103,21 @@ asmlinkage int old_select(unsigned long *buffer) fd_set *exp; struct timeval *tvp; + lock_kernel(); n = verify_area(VERIFY_READ, buffer, 5*sizeof(unsigned long)); if (n) - return n; - n = get_user(buffer); - inp = (fd_set *) get_user(buffer+1); - outp = (fd_set *) get_user(buffer+2); - exp = (fd_set *) get_user(buffer+3); - tvp = (struct timeval *) get_user(buffer+4); - return sys_select(n, inp, outp, exp, tvp); + goto out; + get_user(n,buffer); + get_user(inp,buffer+1); + get_user(outp,buffer+2); + get_user(exp,buffer+3); + get_user(tvp,buffer+4); + n = sys_select(n, inp, outp, exp, tvp); +out: + unlock_kernel(); + return n; } +#if 0 /* * sys_ipc() is the de-multiplexer for the SysV IPC calls.. @@ -102,57 +126,68 @@ asmlinkage int old_select(unsigned long *buffer) */ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth) { - int version; + int version, ret; + lock_kernel(); version = call >> 16; /* hack for backward compatibility */ call &= 0xffff; if (call <= SEMCTL) switch (call) { case SEMOP: - return sys_semop (first, (struct sembuf *)ptr, second); + ret = sys_semop (first, (struct sembuf *)ptr, second); + goto out; case SEMGET: - return sys_semget (first, second, third); + ret = sys_semget (first, second, third); + goto out; case SEMCTL: { union semun fourth; - int err; + ret = -EINVAL; if (!ptr) - return -EINVAL; - if ((err = verify_area (VERIFY_READ, ptr, sizeof(long)))) - return err; + goto out; + if ((ret = verify_area (VERIFY_READ, ptr, sizeof(long)))) + goto out; fourth.__pad = (void *) get_fs_long(ptr); - return sys_semctl (first, second, third, fourth); + ret = sys_semctl (first, second, third, fourth); + goto out; } default: - return -EINVAL; + ret = -EINVAL; + goto out; } if (call <= MSGCTL) switch (call) { case MSGSND: - return sys_msgsnd (first, (struct msgbuf *) ptr, - second, third); + ret = sys_msgsnd (first, (struct msgbuf *) ptr, + second, third); + goto out; case MSGRCV: switch (version) { case 0: { struct ipc_kludge tmp; - int err; + ret = -EINVAL; if (!ptr) - return -EINVAL; - if ((err = verify_area (VERIFY_READ, ptr, sizeof(tmp)))) - return err; + goto out; + if ((ret = verify_area (VERIFY_READ, ptr, sizeof(tmp)))) + goto out; memcpy_fromfs (&tmp,(struct ipc_kludge *) ptr, sizeof (tmp)); - return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third); + ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third); + goto out; } case 1: default: - return sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third); + ret = sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third); + goto out; } case MSGGET: - return sys_msgget ((key_t) first, second); + ret = sys_msgget ((key_t) first, second); + goto out; case MSGCTL: - return sys_msgctl (first, second, (struct msqid_ds *) ptr); + ret = sys_msgctl (first, second, (struct msqid_ds *) ptr); + goto out; default: - return -EINVAL; + ret = -EINVAL; + goto out; } if (call <= SHMCTL) switch (call) { @@ -160,29 +195,39 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, switch (version) { case 0: default: { ulong raddr; - int err; - if ((err = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong)))) - return err; - err = sys_shmat (first, (char *) ptr, second, &raddr); - if (err) - return err; + if ((ret = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong)))) + goto out; + ret = sys_shmat (first, (char *) ptr, second, &raddr); + if (ret) + goto out; put_fs_long (raddr, (ulong *) third); - return 0; + ret = 0; + goto out; } case 1: /* iBCS2 emulator entry point */ + ret = -EINVAL; if (get_fs() != get_ds()) - return -EINVAL; - return sys_shmat (first, (char *) ptr, second, (ulong *) third); + goto out; + ret = sys_shmat (first, (char *) ptr, second, (ulong *) third); + goto out; } case SHMDT: - return sys_shmdt ((char *)ptr); + ret = sys_shmdt ((char *)ptr); + goto out; case SHMGET: - return sys_shmget (first, second, third); + ret = sys_shmget (first, second, third); + goto out; case SHMCTL: - return sys_shmctl (first, second, (struct shmid_ds *) ptr); + ret = sys_shmctl (first, second, (struct shmid_ds *) ptr); + goto out; default: - return -EINVAL; + ret = -EINVAL; + goto out; } - return -EINVAL; + else + ret = -EINVAL; +out: + unlock_kernel(); + return ret; } #endif diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c index a0e2e0534..cdcad8204 100644 --- a/arch/ppc/kernel/time.c +++ b/arch/ppc/kernel/time.c @@ -24,6 +24,7 @@ #include <asm/io.h> #include <asm/nvram.h> #include <asm/mc146818rtc.h> +#include <asm/processor.h> #include <linux/timex.h> #include <linux/config.h> @@ -43,6 +44,13 @@ static inline int CMOS_READ(int addr) return (inb(NVRAM_DATA)); } +static inline int CMOS_WRITE(int addr, int val) +{ + outb(addr>>8, NVRAM_AS1); + outb(addr, NVRAM_AS0); + return (outb(val, NVRAM_DATA)); +} + /* This function must be called with interrupts disabled * It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs * @@ -138,9 +146,110 @@ void do_settimeofday(struct timeval *tv) time_state = TIME_BAD; time_maxerror = 0x70000000; time_esterror = 0x70000000; + set_rtc(xtime.tv_sec); sti(); } +static int month_days[12] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +#define FEBRUARY 2 +#define STARTOFTIME 1970 +#define SECDAY 86400L +#define SECYR (SECDAY * 365) +#define leapyear(year) ((year) % 4 == 0) +#define days_in_year(a) (leapyear(a) ? 366 : 365) +#define days_in_month(a) (month_days[(a) - 1]) + +struct _tm +{ + int tm_sec; + int tm_min; + int tm_hour; + int tm_day; + int tm_month; + int tm_year; +}; + +static _to_tm(int tim, struct _tm * tm) +{ + register int i; + register long hms, day; + + day = tim / SECDAY; + hms = tim % SECDAY; + + /* Hours, minutes, seconds are easy */ + tm->tm_hour = hms / 3600; + tm->tm_min = (hms % 3600) / 60; + tm->tm_sec = (hms % 3600) % 60; + + /* Number of years in days */ + for (i = STARTOFTIME; day >= days_in_year(i); i++) + day -= days_in_year(i); + tm->tm_year = i; + + /* Number of months in days left */ + if (leapyear(tm->tm_year)) + days_in_month(FEBRUARY) = 29; + for (i = 1; day >= days_in_month(i); i++) + day -= days_in_month(i); + days_in_month(FEBRUARY) = 28; + tm->tm_month = i; + + /* Days are what is left over (+1) from all that. */ + tm->tm_day = day + 1; +} + +/* + * Set the time into the CMOS + */ +static void set_rtc(unsigned long nowtime) +{ + int retval = 0; + struct _tm tm; + unsigned char save_control, save_freq_select; + + /*if (_Processor != _PROC_IBM) return;*/ + + _to_tm(nowtime, &tm); + + /* tell the clock it's being set */ + save_control = CMOS_MCRTC_READ(MCRTC_CONTROL); + CMOS_MCRTC_WRITE((save_control|MCRTC_SET), MCRTC_CONTROL); + /* stop and reset prescaler */ + save_freq_select = CMOS_MCRTC_READ(MCRTC_FREQ_SELECT); + CMOS_MCRTC_WRITE((save_freq_select|MCRTC_DIV_RESET2), MCRTC_FREQ_SELECT); + + printk("Set RTC H:M:S M/D/Y %d:%02d:%02d %d/%d/%d\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_month, tm.tm_day, tm.tm_year); + if (!(save_control & MCRTC_DM_BINARY) || MCRTC_ALWAYS_BCD) { + BIN_TO_BCD(tm.tm_sec); + BIN_TO_BCD(tm.tm_min); + BIN_TO_BCD(tm.tm_hour); + BIN_TO_BCD(tm.tm_month); + BIN_TO_BCD(tm.tm_day); + BIN_TO_BCD(tm.tm_year); + } + + CMOS_MCRTC_WRITE(tm.tm_sec, MCRTC_SECONDS); + CMOS_MCRTC_WRITE(tm.tm_min, MCRTC_MINUTES); + CMOS_MCRTC_WRITE(tm.tm_hour, MCRTC_HOURS); + CMOS_MCRTC_WRITE(tm.tm_month, MCRTC_MONTH); + CMOS_MCRTC_WRITE(tm.tm_day, MCRTC_MINUTES); + CMOS_MCRTC_WRITE(tm.tm_year - 1900, MCRTC_MINUTES); + + /* The following flags have to be released exactly in this order, + * otherwise the DS12887 (popular MC146818A clone with integrated + * battery and quartz) will not reset the oscillator and will not + * update precisely 500 ms later. You won't find this mentioned in + * the Dallas Semiconductor data sheets, but who believes data + * sheets anyway ... -- Markus Kuhn + */ + CMOS_MCRTC_WRITE(save_control, MCRTC_CONTROL); + CMOS_MCRTC_WRITE(save_freq_select, MCRTC_FREQ_SELECT); +} /* * In order to set the CMOS clock precisely, set_rtc_mmss has to be @@ -156,17 +265,19 @@ static int set_rtc_mmss(unsigned long nowtime) unsigned char save_control, save_freq_select; #ifdef __powerpc__ +printk("%s: %d - set TOD\n", __FILE__, __LINE__); return (-1); /* Not implemented */ #else - save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ - CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); +printk("%s: %d - set TOD\n", __FILE__, __LINE__); + save_control = CMOS_MCRTC_READ(MCRTC_CONTROL); /* tell the clock it's being set */ + CMOS_MCRTC_WRITE((save_control|MCRTC_SET), MCRTC_CONTROL); - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ - CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); + save_freq_select = CMOS_MCRTC_READ(MCRTC_FREQ_SELECT); /* stop and reset prescaler */ + CMOS_MCRTC_WRITE((save_freq_select|MCRTC_DIV_RESET2), MCRTC_FREQ_SELECT); - cmos_minutes = CMOS_READ(RTC_MINUTES); - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) + cmos_minutes = CMOS_MCRTC_READ(MCRTC_MINUTES); + if (!(save_control & MCRTC_DM_BINARY) || MCRTC_ALWAYS_BCD) BCD_TO_BIN(cmos_minutes); /* @@ -182,12 +293,12 @@ return (-1); /* Not implemented */ real_minutes %= 60; if (abs(real_minutes - cmos_minutes) < 30) { - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + if (!(save_control & MCRTC_DM_BINARY) || MCRTC_ALWAYS_BCD) { BIN_TO_BCD(real_seconds); BIN_TO_BCD(real_minutes); } - CMOS_WRITE(real_seconds,RTC_SECONDS); - CMOS_WRITE(real_minutes,RTC_MINUTES); + CMOS_MCRTC_WRITE(real_seconds,MCRTC_SECONDS); + CMOS_MCRTC_WRITE(real_minutes,MCRTC_MINUTES); } else retval = -1; @@ -198,8 +309,8 @@ return (-1); /* Not implemented */ * the Dallas Semiconductor data sheets, but who believes data * sheets anyway ... -- Markus Kuhn */ - CMOS_WRITE(save_control, RTC_CONTROL); - CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + CMOS_MCRTC_WRITE(save_control, MCRTC_CONTROL); + CMOS_MCRTC_WRITE(save_freq_select, MCRTC_FREQ_SELECT); return retval; #endif @@ -214,27 +325,42 @@ static long last_rtc_update = 0; */ static inline void timer_interrupt(int irq, void *dev, struct pt_regs * regs) { - do_timer(regs); - - /* - * If we have an externally synchronized Linux clock, then update - * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be - * called as close as possible to 500 ms before the new second starts. - */ - if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 && - xtime.tv_usec > 500000 - (tick >> 1) && - xtime.tv_usec < 500000 + (tick >> 1)) - if (set_rtc_mmss(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ -#if 0 - /* As we return to user mode fire off the other CPU schedulers.. this is - basically because we don't yet share IRQ's around. This message is - rigged to be safe on the 386 - basically its a hack, so don't look - closely for now.. */ - smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); -#endif + static int timeints = 0; + + do_timer(regs); + + /* + * If we have an externally synchronized Linux clock, then update + * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be + * called as close as possible to 500 ms before the new second starts. + */ + if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 && + xtime.tv_usec > 500000 - (tick >> 1) && + xtime.tv_usec < 500000 + (tick >> 1)) + if (set_rtc_mmss(xtime.tv_sec) == 0) + last_rtc_update = xtime.tv_sec; + else + last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ + + + /* use hard disk LED as a heartbeat instead -- much more useful + -- Cort */ + switch(timeints) + { + /* act like an actual heart beat -- ie thump-thump-pause... */ + case 0: + case 20: + hard_disk_LED(1); + break; + case 7: + case 27: + hard_disk_LED(0); + break; + case 100: + timeints = -1; + break; + } + timeints++; } /* Converts Gregorian date to seconds since 1970-01-01 00:00:00. @@ -270,49 +396,52 @@ static inline unsigned long mktime(unsigned int year, unsigned int mon, unsigned long get_cmos_time(void) { - unsigned int year, mon, day, hour, min, sec; - int i; - - if (isBeBox[0]) - { -#ifndef __powerpc__ - /* The Linux interpretation of the CMOS clock register contents: - * When the Update-In-Progress (UIP) flag goes from 1 to 0, the - * RTC registers show the second which has precisely just started. - * Let's hope other operating systems interpret the RTC the same way. - */ - /* read RTC exactly on falling edge of update flag */ - for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ - if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) - break; - for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ - if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) - break; -#endif - do { /* Isn't this overkill ? UIP above should guarantee consistency */ - sec = CMOS_MCRTC_READ(MCRTC_SECONDS); - min = CMOS_MCRTC_READ(MCRTC_MINUTES); - hour = CMOS_MCRTC_READ(MCRTC_HOURS); - day = CMOS_MCRTC_READ(MCRTC_DAY_OF_MONTH); - mon = CMOS_MCRTC_READ(MCRTC_MONTH); - year = CMOS_MCRTC_READ(MCRTC_YEAR); - } while (sec != CMOS_MCRTC_READ(MCRTC_SECONDS)); - } else + unsigned int year, mon, day, hour, min, sec; + int i; + + if (_Processor == _PROC_IBM) + { + do { /* Isn't this overkill ? UIP above should guarantee consistency */ + sec = CMOS_MCRTC_READ(MCRTC_SECONDS); + min = CMOS_MCRTC_READ(MCRTC_MINUTES); + hour = CMOS_MCRTC_READ(MCRTC_HOURS); + day = CMOS_MCRTC_READ(MCRTC_DAY_OF_MONTH); + mon = CMOS_MCRTC_READ(MCRTC_MONTH); + year = CMOS_MCRTC_READ(MCRTC_YEAR); + } while (sec != CMOS_MCRTC_READ(MCRTC_SECONDS)); + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hour); + BCD_TO_BIN(day); + BCD_TO_BIN(mon); + BCD_TO_BIN(year); + } else + if (_Processor == _PROC_Be) + { + do { /* Isn't this overkill ? UIP above should guarantee consistency */ + sec = CMOS_MCRTC_READ(MCRTC_SECONDS); + min = CMOS_MCRTC_READ(MCRTC_MINUTES); + hour = CMOS_MCRTC_READ(MCRTC_HOURS); + day = CMOS_MCRTC_READ(MCRTC_DAY_OF_MONTH); + mon = CMOS_MCRTC_READ(MCRTC_MONTH); + year = CMOS_MCRTC_READ(MCRTC_YEAR); + } while (sec != CMOS_MCRTC_READ(MCRTC_SECONDS)); + } else { /* Motorola PowerStack etc. */ - do { /* Isn't this overkill ? UIP above should guarantee consistency */ - sec = CMOS_READ(RTC_SECONDS); - min = CMOS_READ(RTC_MINUTES); - hour = CMOS_READ(RTC_HOURS); - day = CMOS_READ(RTC_DAY_OF_MONTH); - mon = CMOS_READ(RTC_MONTH); - year = CMOS_READ(RTC_YEAR); - } while (sec != CMOS_READ(RTC_SECONDS)); - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); + do { /* Isn't this overkill ? UIP above should guarantee consistency */ + sec = CMOS_READ(RTC_SECONDS); + min = CMOS_READ(RTC_MINUTES); + hour = CMOS_READ(RTC_HOURS); + day = CMOS_READ(RTC_DAY_OF_MONTH); + mon = CMOS_READ(RTC_MONTH); + year = CMOS_READ(RTC_YEAR); + } while (sec != CMOS_READ(RTC_SECONDS)); + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hour); + BCD_TO_BIN(day); + BCD_TO_BIN(mon); + BCD_TO_BIN(year); } #if 0 printk("CMOS TOD - M/D/Y H:M:S = %d/%d/%d %d:%02d:%02d\n", mon, day, year, hour, min, sec); @@ -324,13 +453,13 @@ printk("CMOS TOD - M/D/Y H:M:S = %d/%d/%d %d:%02d:%02d\n", mon, day, year, hour, void time_init(void) { - void (*irq_handler)(int, struct pt_regs *); - xtime.tv_sec = get_cmos_time(); - xtime.tv_usec = 0; - - /* If we have the CPU hardware time counters, use them */ - irq_handler = timer_interrupt; - if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL) != 0) - panic("Could not allocate timer IRQ!"); + void (*irq_handler)(int, struct pt_regs *); + xtime.tv_sec = get_cmos_time(); + xtime.tv_usec = 0; + + /* If we have the CPU hardware time counters, use them */ + irq_handler = timer_interrupt; + if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL) != 0) + panic("Could not allocate timer IRQ!"); } diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index e9f5e8e5b..a637e0acb 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -3,6 +3,7 @@ * * Copyright (C) 1995 Gary Thomas * Adapted for PowerPC by Gary Thomas + * Modified by Cort Dougan (cort@cs.nmt.edu) */ /* @@ -17,7 +18,6 @@ #include <linux/unistd.h> #include <linux/ptrace.h> #include <linux/malloc.h> -#include <linux/ldt.h> #include <linux/user.h> #include <linux/a.out.h> @@ -40,44 +40,62 @@ trap_init(void) void _exception(int signr, struct pt_regs *regs) { -/* dump_regs(regs);*/ - force_sig(signr, current); - if (!user_mode(regs)) - { - printk("Failure in kernel at PC: %x, MSR: %x\n", regs->nip, regs->msr); - while (1) ; - } + /* dump_regs(regs);*/ + force_sig(signr, current); + if (!user_mode(regs)) + { + printk("Failure in kernel at PC: %x, MSR: %x\n", regs->nip, regs->msr); + while (1) ; + } } MachineCheckException(struct pt_regs *regs) { -/* printk("Machine check at PC: %x[%x], SR: %x\n", regs->nip, va_to_phys(regs->nip), regs->msr);*/ - _exception(SIGSEGV, regs); + printk("Machine check at PC: %x[%x], SR: %x\n", regs->nip, va_to_phys(regs->nip), regs->msr); + _exception(SIGSEGV, regs); } ProgramCheckException(struct pt_regs *regs) { -/* printk("Program check at PC: %x[%x], SR: %x\n", regs->nip, va_to_phys(regs->nip), regs->msr);*/ - if (current->flags & PF_PTRACED) - { - _exception(SIGTRAP, regs); - } else - { - _exception(SIGILL, regs); - } +#if 0 + printk("Program check at PC: %x[%x], SR: %x\n", + regs->nip, va_to_phys(regs->nip), regs->msr); + #endif + if (current->flags & PF_PTRACED) + { + _exception(SIGTRAP, regs); + } else + { + _exception(SIGILL, regs); + } } SingleStepException(struct pt_regs *regs) { -/* printk("Single step at PC: %x[%x], SR: %x\n", regs->nip, va_to_phys(regs->nip), regs->msr);*/ regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */ _exception(SIGTRAP, regs); } FloatingPointCheckException(struct pt_regs *regs) { -/* printk("Floating point check at PC: %x[%x], SR: %x\n", regs->nip, va_to_phys(regs->nip), regs->msr);*/ - _exception(SIGFPE, regs); + /* if fpu already on -- then exception was generated by an error */ + if ( (unsigned long)(regs->msr) & (unsigned long)MSR_FP ) + { + _exception(SIGFPE, regs); + return 0; + } + +#if 0 + printk("fpu off -- turning on: %s pc %x fpscr %x msr %x ksp %x r1 %x\n", + current->comm,regs->nip,regs->fpcsr,regs->msr,regs,regs->gpr[1]); +#endif + + /* if the fpu is off then turn it on and return */ + regs->msr |= MSR_FP; + current->tss.fp_used++; + /* tells return_from_int to restore fp regs since fp was turned on + see head.S -- Cort */ + return MSR_FP; } AlignmentException(struct pt_regs *regs) @@ -88,11 +106,20 @@ AlignmentException(struct pt_regs *regs) _exception(SIGBUS, regs); } -bad_stack(struct pt_regs *regs) + +/* see CHECK_STACK macro in head.S for argument definitions */ +bad_stack(unsigned int r3, unsigned int r4, unsigned int r5, unsigned int r6) { -/* printk("Kernel stack overflow at PC: %x[%x], SR: %x\n", regs->nip, va_to_phys(regs->nip), regs->msr); - dump_regs(regs);*/ - while (1) ; + /* r6 (was r1) kernel stack pointer */ + /* r5 (was r2) kernel stack page */ + /* r4 kernel stack magic */ + /* r3 stack magic or ksp masked to page boundary */ + printk("bad_stack(): Kernel stack bad.\n"); + printk("ksp %x kpage %x stack magic %x r3 %x\n", + r6,r5,r4,r3); + printk("current: %s/%d\n", + current->comm,current->pid); + while(1); } dump_regs(struct pt_regs *regs) diff --git a/arch/ppc/kernel/usercpy.c b/arch/ppc/kernel/usercpy.c new file mode 100644 index 000000000..7ef0f2280 --- /dev/null +++ b/arch/ppc/kernel/usercpy.c @@ -0,0 +1,116 @@ +#include <linux/types.h> +#include <asm/string.h> +#include <asm/errno.h> +#include <linux/sched.h> + +/* + * bad data accesses from these functions should be handled specially + * since they are to user areas and may or may not be valid. + * on error -EFAULT should be returned. -- Cort + */ +int __copy_tofrom_user_failure(void) +{ + current->tss.excount = 0; + return -EFAULT; +} + +int __copy_tofrom_user(unsigned long to, unsigned long from, int size) +{ + /* setup exception handling stuff */ + current->tss.excount++; + current->tss.expc = (unsigned long )__copy_tofrom_user_failure; + + if (memcpy( (void *)to, (void *)from, (size_t) size) == -EFAULT ) + { + /* take down exception handler stuff */ + current->tss.excount = 0; + return -EFAULT; + } + current->tss.excount = 0; + return 0; /* successful return */ +} + +/* Just like strncpy except in the return value: + * + * -EFAULT if an exception occurs before the terminator is copied. + * N if the buffer filled. + * + * Otherwise the length of the string is returned. + */ +asmlinkage int __strncpy_from_user_failure(void) +{ + current->tss.excount = 0; + return -EFAULT; +} + +int __strncpy_from_user(unsigned long dest, unsigned long src, int count) +{ + int i = 0; + /* setup exception handling stuff */ + current->tss.excount++; + current->tss.expc = (unsigned long )__strncpy_from_user_failure; + + while ( i != count ) + { + *(char *)(dest+i) = *(char *)(src+i); + if ( *(char *)(src+i) == 0 ) + { + return i; + } + i++; + } + *(char *)(dest+i) = (char)0; + /* take down exception handler stuff */ + current->tss.excount = 0; + return i; +} + +int __clear_user_failure(void) +{ + current->tss.excount = 0; + return -EFAULT; +} +int __clear_user(unsigned long addr, int size) +{ + /* setup exception handling stuff */ + current->tss.excount++; + current->tss.expc = (unsigned long )__clear_user_failure; + + if ((int)memset((void *)addr,(int)0, (__kernel_size_t)size) == -EFAULT ) + { + /* take down exception handler stuff */ + current->tss.excount = 0; + return -EFAULT; + } + /* take down exception handler stuff */ + current->tss.excount = 0; + return size; +} + +/* + * Return the length of the string including the NUL terminator + * (strlen+1) or zero if an error occured. + */ +size_t strlen_user_failure(void) +{ + current->tss.excount = 0; + return -EFAULT; +} +size_t strlen_user(char * s) +{ + size_t i; + /* setup exception handling stuff */ + current->tss.excount++; + current->tss.expc = (unsigned long )strlen_user_failure; + + i = strlen(s)+1; + + if ( i == -EFAULT) + return -EFAULT; + + /* take down exception handler stuff */ + current->tss.excount = 0; + + return(i); +} + |