diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-04-19 04:00:00 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-04-19 04:00:00 +0000 |
commit | 46e045034336a2cc90c1798cd7cc07af744ddfd6 (patch) | |
tree | 3b9b51fc482e729f663d25333e77fbed9aaa939a /arch/sparc64/kernel | |
parent | 31dc59d503a02e84c4de98826452acaeb56dc15a (diff) |
Merge with Linux 2.3.99-pre4.
Diffstat (limited to 'arch/sparc64/kernel')
-rw-r--r-- | arch/sparc64/kernel/Makefile | 12 | ||||
-rw-r--r-- | arch/sparc64/kernel/dtlb_base.S | 24 | ||||
-rw-r--r-- | arch/sparc64/kernel/dtlb_prot.S | 8 | ||||
-rw-r--r-- | arch/sparc64/kernel/ebus.c | 14 | ||||
-rw-r--r-- | arch/sparc64/kernel/entry.S | 39 | ||||
-rw-r--r-- | arch/sparc64/kernel/etrap.S | 309 | ||||
-rw-r--r-- | arch/sparc64/kernel/ioctl32.c | 21 | ||||
-rw-r--r-- | arch/sparc64/kernel/itlb_base.S | 26 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_common.c | 161 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_impl.h | 6 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_psycho.c | 25 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_sabre.c | 22 | ||||
-rw-r--r-- | arch/sparc64/kernel/process.c | 57 | ||||
-rw-r--r-- | arch/sparc64/kernel/rtrap.S | 253 | ||||
-rw-r--r-- | arch/sparc64/kernel/semaphore.c | 10 | ||||
-rw-r--r-- | arch/sparc64/kernel/signal.c | 4 | ||||
-rw-r--r-- | arch/sparc64/kernel/signal32.c | 4 | ||||
-rw-r--r-- | arch/sparc64/kernel/smp.c | 96 | ||||
-rw-r--r-- | arch/sparc64/kernel/sparc64_ksyms.c | 9 | ||||
-rw-r--r-- | arch/sparc64/kernel/sys32.S | 188 | ||||
-rw-r--r-- | arch/sparc64/kernel/sys_sparc32.c | 110 | ||||
-rw-r--r-- | arch/sparc64/kernel/sys_sunos32.c | 122 | ||||
-rw-r--r-- | arch/sparc64/kernel/winfixup.S | 28 |
23 files changed, 990 insertions, 558 deletions
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 124776f51..5e37c94b4 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -8,10 +8,10 @@ # Note 2! The CFLAGS definitions are now in the main makefile... .S.s: - $(CPP) -D__ASSEMBLY__ $(AFLAGS) -ansi $< -o $*.s + $(CPP) $(AFLAGS) -ansi $< -o $*.s .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $< -o $*.o + $(CC) $(AFLAGS) -ansi -c $< -o $*.o all: kernel.o head.o init_task.o @@ -54,7 +54,7 @@ endif head.o: head.S ttable.S itlb_base.S dtlb_base.S dtlb_backend.S dtlb_prot.S \ etrap.S rtrap.S winfixup.S entry.S - $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $*.S -o $*.o + $(CC) $(AFLAGS) -ansi -c $*.S -o $*.o # # This is just to get the dependencies... @@ -84,7 +84,7 @@ check_asm: dummy @echo "#undef __SMP__" >> tmp.c @echo "#undef CONFIG_SMP" >> tmp.c @echo "#include <linux/sched.h>" >> tmp.c - $(CC) $(CPPFLAGS) -E tmp.c -o tmp.i + $(CPP) $(CPPFLAGS) tmp.c -o tmp.i @echo "/* Automatically generated. Do not edit. */" > check_asm.c @echo "#include <linux/config.h>" >> check_asm.c @echo "#undef __SMP__" >> check_asm.c @@ -113,7 +113,7 @@ check_asm: dummy @echo "#undef CONFIG_SMP" >> tmp.c @echo "#define CONFIG_SMP 1" >> tmp.c @echo "#include <linux/sched.h>" >> tmp.c - $(CC) $(CPPFLAGS) -D__SMP__ -E tmp.c -o tmp.i + $(CPP) $(CPPFLAGS) -D__SMP__ tmp.c -o tmp.i @echo "/* Automatically generated. Do not edit. */" > check_asm.c @echo "#include <linux/config.h>" >> check_asm.c @echo "#undef CONFIG_SMP" >> check_asm.c @@ -138,7 +138,7 @@ check_asm: dummy @rm -f check_asm check_asm.c @echo -e "\n#else /* SPIN_LOCK_DEBUG */\n" >> asm_offsets.h @echo "#include <linux/sched.h>" > tmp.c - $(CC) $(CPPFLAGS) -D__SMP__ -DSPIN_LOCK_DEBUG -E tmp.c -o tmp.i + $(CPP) $(CPPFLAGS) -D__SMP__ -DSPIN_LOCK_DEBUG tmp.c -o tmp.i @echo "/* Automatically generated. Do not edit. */" > check_asm.c @echo "#include <linux/config.h>" >> check_asm.c @echo "#undef CONFIG_SMP" >> check_asm.c diff --git a/arch/sparc64/kernel/dtlb_base.S b/arch/sparc64/kernel/dtlb_base.S index 0f86bc896..72120b563 100644 --- a/arch/sparc64/kernel/dtlb_base.S +++ b/arch/sparc64/kernel/dtlb_base.S @@ -1,4 +1,4 @@ -/* $Id: dtlb_base.S,v 1.5 2000/01/31 04:59:12 davem Exp $ +/* $Id: dtlb_base.S,v 1.7 2000/03/26 09:13:48 davem Exp $ * dtlb_base.S: Front end to DTLB miss replacement strategy. * This is included directly into the trap table. * @@ -56,19 +56,19 @@ be,pn %xcc, 3f ! Yep, special processing srax %g4, VPTE_SHIFT, %g6 ! Create VPTE offset ldxa [%g3 + %g6] ASI_S, %g5 ! Load VPTE -1: brlz,pt %g5, 2f ! Valid, load into TLB +1: brlz,pt %g5, 9f ! Valid, load into TLB and %g5, (_PAGE_PRESENT|_PAGE_READ), %g4 ! Mask readable bits ba,a,pt %xcc, 4f ! Invalid, branch out /* DTLB ** ICACHE line 2: Quick kernel TLB misses */ -3: brgez,a,pn %g4, 1b ! Kernel virtual map? - ldxa [%g3 + %g6] ASI_N, %g5 ! Yep, load k-vpte - srlx %g4, 40, %g5 ! Else compute phys-kpte - andcc %g5, 1, %g0 ! I/O area? - be,pt %xcc, 2f ! Nope, go and load TLB +3: brlz,pt %g4, 9f ! Kernel virtual map? xor %g2, %g4, %g5 ! Finish bit twiddles - ba,pt %xcc, 2f ! Yes, I/O space, back back - xor %g5, (KERN_IOBITS), %g5 ! After set E, clear CP/CV + ldxa [%g3 + %g6] ASI_N, %g5 ! Yep, load k-vpte + ba,pt %xcc, 1b ! Continue tlb reload + nop +9: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB + retry ! Trap return + nop /* DTLB ** ICACHE line 3: winfixups+real_faults */ 4: cmp %g4, (_PAGE_PRESENT|_PAGE_READ) ! Readable page? @@ -81,14 +81,14 @@ mov TLB_TAG_ACCESS, %g4 ! Prepare for fault processing /* DTLB ** ICACHE line 4: padding */ + ldxa [%g4] ASI_DMMU, %g5 ! Load faulting VA page be,pt %xcc, sparc64_realfault_common ! Jump to normal fault handling - ldxa [%g4] ASI_DMMU, %g5 ! And load faulting VA page + mov FAULT_CODE_DTLB, %g4 ! It was read from DTLB ba,a,pt %xcc, winfix_trampoline ! Call window fixup code 5: or %g5, _PAGE_ACCESSED, %g5 ! Indicate reference or %g5, %g4, %g5 ! Set valid stxa %g5, [%g3 + %g6] ASI_S ! Update PTE table (cant trap) -2: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB - retry ! Trap return + ba,a,pt %xcc, 9b ! Complete tlb miss #undef TAG_CONTEXT_BITS #undef VPTE_SHIFT diff --git a/arch/sparc64/kernel/dtlb_prot.S b/arch/sparc64/kernel/dtlb_prot.S index 73f3596e1..5e99d5d47 100644 --- a/arch/sparc64/kernel/dtlb_prot.S +++ b/arch/sparc64/kernel/dtlb_prot.S @@ -1,4 +1,4 @@ -/* $Id: dtlb_prot.S,v 1.19 2000/01/31 04:59:12 davem Exp $ +/* $Id: dtlb_prot.S,v 1.20 2000/03/26 09:13:48 davem Exp $ * dtlb_prot.S: DTLB protection trap strategy. * This is included directly into the trap table. * @@ -40,15 +40,15 @@ /* PROT ** ICACHE line 3: Real user faults */ 1: rdpr %pstate, %g5 ! Move into alternate globals wrpr %g5, PSTATE_AG|PSTATE_MG, %pstate - rdpr %tl, %g4 ! Need to do a winfixup? - cmp %g4, 1 ! Trap level >1? + rdpr %tl, %g1 ! Need to do a winfixup? + cmp %g1, 1 ! Trap level >1? mov TLB_TAG_ACCESS, %g4 ! Prepare reload of vaddr bgu,pn %xcc, winfix_trampoline ! Yes, perform winfixup ldxa [%g4] ASI_DMMU, %g5 ! Put tagaccess in %g5 ba,pt %xcc, sparc64_realfault_common ! Nope, normal fault /* PROT ** ICACHE line 4: More real fault processing */ - mov 1, %g4 ! Indicate this was a write + mov FAULT_CODE_DTLB | FAULT_CODE_WRITE, %g4 nop nop nop diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index 903bcf445..f64422a0e 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c @@ -1,4 +1,4 @@ -/* $Id: ebus.c,v 1.46 1999/11/19 05:52:48 davem Exp $ +/* $Id: ebus.c,v 1.47 2000/03/25 05:18:10 davem Exp $ * ebus.c: PCI to EBus bridge device. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -278,7 +278,6 @@ void __init ebus_init(void) struct linux_ebus *ebus; struct pci_dev *pdev; struct pcidev_cookie *cookie; - unsigned short pci_command; int nd, ebusnd; int num_ebus = 0; @@ -328,17 +327,6 @@ void __init ebus_init(void) ebus->self = pdev; ebus->parent = pbm = cookie->pbm; - /* Enable BUS Master. */ - pci_read_config_word(pdev, PCI_COMMAND, &pci_command); - pci_command |= PCI_COMMAND_MASTER; - pci_write_config_word(pdev, PCI_COMMAND, pci_command); - - /* Set reasonable cache line size and latency timer values. */ - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); - - /* NOTE: Cache line size is in 32-bit word units. */ - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 64/sizeof(u32)); - ebus_ranges_init(ebus); ebus_intmap_init(ebus); diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 2ab8b70d4..529703dfc 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.113 2000/03/06 22:33:42 davem Exp $ +/* $Id: entry.S,v 1.115 2000/03/29 09:55:30 davem Exp $ * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points. * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -998,12 +998,12 @@ linux_sparc_syscall32: mov %i5, %o5 ! IEU1 srl %i2, 0, %o2 ! IEU0 Group - mov %i0, %l5 ! IEU1 - andcc %l0, 0x20, %g0 ! IEU1 Group + andcc %l0, 0x20, %g0 ! IEU0 Group bne,pn %icc, linux_syscall_trace32 ! CTI - srl %i3, 0, %o3 ! IEU0 + mov %i0, %l5 ! IEU1 call %l7 ! CTI Group brk forced - add %o7, 3f-.-4, %o7 ! IEU0 + srl %i3, 0, %o3 ! IEU0 + ba,a,pt %xcc, 3f /* Linux native and SunOS system calls enter here... */ .align 32 @@ -1032,30 +1032,31 @@ linux_sparc_syscall: mov %i0, %l5 ! IEU0 2: call %l7 ! CTI Group brk forced mov %i5, %o5 ! IEU0 + nop + 3: stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0] ret_sys_call: #ifdef SYSCALL_TRACING call syscall_trace_exit add %sp, STACK_BIAS + REGWIN_SZ, %o1 #endif - ldx [%curptr + AOFF_task_flags], %l6 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %g3 + ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 ! pc = npc sra %o0, 0, %o0 mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %g3 cmp %o0, -ENOIOCTLCMD sllx %g2, 32, %g2 bgeu,pn %xcc, 1f - andcc %l6, 0x20, %l6 - /* System call success, clear Carry condition code. */ - andn %g3, %g2, %g3 + andcc %l0, 0x20, %l6 + andn %g3, %g2, %g3 /* System call success, clear Carry condition code. */ stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE] bne,pn %icc, linux_syscall_trace2 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 ! pc = npc - add %l1, 0x4, %l2 !npc = npc+4 + add %l1, 0x4, %l2 ! npc = npc+4 stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC] - b,pt %xcc, rtrap_clr_l6 + ba,pt %xcc, rtrap_clr_l6 stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC] + 1: /* System call failure, set Carry condition code. * Also, get abs(errno) to return to the process. @@ -1066,15 +1067,14 @@ ret_sys_call: mov 1, %l6 stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE] bne,pn %icc, linux_syscall_trace2 - ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 ! pc = npc - add %l1, 0x4, %l2 !npc = npc+4 - + add %l1, 0x4, %l2 !npc = npc+4 stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC] + b,pt %xcc, rtrap stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC] linux_syscall_trace2: call syscall_trace - add %l1, 0x4, %l2 /* npc = npc+4 */ + nop stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC] ba,pt %xcc, rtrap stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC] @@ -1082,6 +1082,9 @@ linux_syscall_trace2: .align 32 .globl __flushw_user __flushw_user: + rdpr %otherwin, %g1 + brz,pn %g1, 2f + clr %g2 1: save %sp, -128, %sp rdpr %otherwin, %g1 brnz,pt %g1, 1b @@ -1090,4 +1093,4 @@ __flushw_user: brnz,pt %g2, 1b restore %g0, %g0, %g0 2: retl - mov %g3, %o7 + nop diff --git a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S index d243a43b3..b0a8f766d 100644 --- a/arch/sparc64/kernel/etrap.S +++ b/arch/sparc64/kernel/etrap.S @@ -1,4 +1,4 @@ -/* $Id: etrap.S,v 1.42 1999/07/30 09:35:18 davem Exp $ +/* $Id: etrap.S,v 1.43 2000/03/29 09:55:30 davem Exp $ * etrap.S: Preparing for entry into the kernel on Sparc V9. * * Copyright (C) 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -13,6 +13,8 @@ #include <asm/head.h> #define TASK_REGOFF ((PAGE_SIZE<<1)-TRACEREG_SZ-REGWIN_SZ) +#define ETRAP_PSTATE1 (PSTATE_RMO | PSTATE_PRIV) +#define ETRAP_PSTATE2 (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE) /* * On entry, %g7 is return address - 0x4. @@ -20,148 +22,167 @@ */ .text - .align 32 - .globl etrap, etrap_irq, etraptl1 - .globl scetrap - -etrap: rdpr %pil, %g2 ! Single Group -etrap_irq: rdpr %tstate, %g1 ! Single Group - sllx %g2, 20, %g3 ! IEU0 Group - andcc %g1, TSTATE_PRIV, %g0 ! IEU1 - or %g1, %g3, %g1 ! IEU0 Group - bne,a,pn %xcc, 1f ! CTI - sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2 ! IEU1 - sethi %hi(TASK_REGOFF), %g2 ! IEU0 Group - sethi %hi(TSTATE_PEF), %g3 ! IEU1 - or %g2, %lo(TASK_REGOFF), %g2 ! IEU0 Group - and %g1, %g3, %g3 ! IEU1 - brnz,pn %g3, 1f ! CTI+IEU1 Group - add %g6, %g2, %g2 ! IEU0 - wr %g0, 0, %fprs ! Single Group+4bubbles -1: rdpr %tpc, %g3 ! Single Group - stx %g1, [%g2 + REGWIN_SZ + PT_V9_TSTATE] ! Store Group - rdpr %tnpc, %g1 ! Single Group - stx %g3, [%g2 + REGWIN_SZ + PT_V9_TPC] ! Store Group - rd %y, %g3 ! Single Group+4bubbles - stx %g1, [%g2 + REGWIN_SZ + PT_V9_TNPC] ! Store Group - st %g3, [%g2 + REGWIN_SZ + PT_V9_Y] ! Store Group - save %g2, -STACK_BIAS, %sp ! The ordering here is ! Single Group - rdpr %pstate, %g1 ! critical, see winfixup ! Single Group+9bubbles - andn %g6, 0x1f, %l6 ! IEU0 Group - bne,pn %xcc, 3f ! CTI - mov PRIMARY_CONTEXT, %l4 ! IEU1 - rdpr %canrestore, %g3 ! Single Group+4bubbles - rdpr %wstate, %g2 ! Single Group+4bubbles - wrpr %g0, 7, %cleanwin ! Single Group+4bubbles - wrpr %g0, 0, %canrestore ! Single Group+4bubbles - sll %g2, 3, %g2 ! IEU0 Group - mov 1, %l5 ! IEU1 - stb %l5, [%l6 + AOFF_task_thread + AOFF_thread_fpdepth] ! Store - wrpr %g3, 0, %otherwin ! Single Group+4bubbles - wrpr %g2, 0, %wstate ! Single Group+4bubbles - stxa %g0, [%l4] ASI_DMMU ! Store Group - flush %l6 ! Single Group+9bubbles - wr %g0, ASI_AIUS, %asi ! Single Group+4bubbles -2: wrpr %g0, 0x0, %tl ! Single Group+4bubbles - andn %g1, PSTATE_MM, %l1 ! IEU0 Group - mov %g4, %l4 ! IEU1 - mov %g5, %l5 ! IEU0 Group - mov %g7, %l2 ! IEU1 - wrpr %l1, (PSTATE_AG|PSTATE_RMO), %pstate ! Single Group+4bubbles - stx %g1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G1] ! Store Group - stx %g2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G2] ! Store Group - stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G3] ! Store Group - stx %g4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G4] ! Store Group - stx %g5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G5] ! Store Group - stx %g6, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G6] ! Store Group - stx %g7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G7] ! Store Group - stx %i0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0] ! Store Group - stx %i1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1] ! Store Group - stx %i2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2] ! Store Group - stx %i3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I3] ! Store Group - stx %i4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I4] ! Store Group - sethi %uhi(PAGE_OFFSET), %g4 ! IEU0 - stx %i5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I5] ! Store Group - stx %i6, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I6] ! Store Group - sllx %g4, 32, %g4 ! IEU0 - stx %i7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I7] ! Store Group - wrpr %l1, (PSTATE_IE|PSTATE_AG|PSTATE_RMO), %pstate ! Single Group+4bubbles - jmpl %l2 + 0x4, %g0 ! CTI Group - mov %l6, %g6 ! IEU0 - -3: ldub [%l6 + AOFF_task_thread + AOFF_thread_fpdepth], %l5 ! Load Group - add %l6, AOFF_task_thread + AOFF_thread_fpsaved + 1, %l4 ! IEU0 - srl %l5, 1, %l3 ! IEU0 Group - add %l5, 2, %l5 ! IEU1 - stb %l5, [%l6 + AOFF_task_thread + AOFF_thread_fpdepth] ! Store - ba,pt %xcc, 2b ! CTI - stb %g0, [%l4 + %l3] ! Store Group - -etraptl1: rdpr %tstate, %g1 ! Single Group+4bubbles - sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2 ! IEU1 - ba,pt %xcc, 1b ! CTI Group - andcc %g1, TSTATE_PRIV, %g0 ! IEU0 - -scetrap: rdpr %pil, %g2 ! Single Group - rdpr %tstate, %g1 ! Single Group - sllx %g2, 20, %g3 ! IEU0 Group - andcc %g1, TSTATE_PRIV, %g0 ! IEU1 - or %g1, %g3, %g1 ! IEU0 Group - bne,a,pn %xcc, 1f ! CTI - sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2 ! IEU1 - sethi %hi(TASK_REGOFF), %g2 ! IEU0 Group - sethi %hi(TSTATE_PEF), %g3 ! IEU1 - or %g2, %lo(TASK_REGOFF), %g2 ! IEU0 Group - and %g1, %g3, %g3 ! IEU1 - brnz,pn %g3, 1f ! CTI+IEU1 Group - add %g6, %g2, %g2 ! IEU0 - wr %g0, 0, %fprs ! Single Group+4bubbles -1: rdpr %tpc, %g3 ! Single Group - stx %g1, [%g2 + REGWIN_SZ + PT_V9_TSTATE] ! Store Group - rdpr %tnpc, %g1 ! Single Group - stx %g3, [%g2 + REGWIN_SZ + PT_V9_TPC] ! Store Group - stx %g1, [%g2 + REGWIN_SZ + PT_V9_TNPC] ! Store Group - st %g0, [%g2 + REGWIN_SZ + PT_V9_Y] ! Store Group - save %g2, -STACK_BIAS, %sp ! The ordering here is ! Single Group - rdpr %pstate, %g1 ! critical, see winfixup ! Single Group+9bubbles - andn %g6, 0x1f, %l6 ! IEU0 Group - bne,pn %xcc, 2f ! CTI - mov PRIMARY_CONTEXT, %l4 ! IEU1 - rdpr %canrestore, %g3 ! Single Group+4bubbles - rdpr %wstate, %g2 ! Single Group+4bubbles - wrpr %g0, 7, %cleanwin ! Single Group+4bubbles - wrpr %g0, 0, %canrestore ! Single Group+4bubbles - sll %g2, 3, %g2 ! IEU0 Group - wrpr %g3, 0, %otherwin ! Single Group+4bubbles - wrpr %g2, 0, %wstate ! Single Group+4bubbles - stxa %g0, [%l4] ASI_DMMU ! Store Group - flush %l6 ! Single Group+9bubbles - wr %g0, ASI_AIUS, %asi ! Single Group+4bubbles -2: wrpr %g0, 0x0, %tl ! Single Group+4bubbles - andn %g1, PSTATE_MM, %l1 ! IEU0 Group - mov %g4, %l4 ! IEU1 - mov %g5, %l5 ! IEU0 Group - mov %g7, %l2 ! IEU1 - wrpr %l1, (PSTATE_AG|PSTATE_RMO), %pstate ! Single Group+4bubbles - stx %g1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G1] ! Store Group - stx %g2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G2] ! Store Group - stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G3] ! Store Group - stx %g4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G4] ! Store Group - stx %g5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G5] ! Store Group - stx %g6, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G6] ! Store Group - stx %g7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G7] ! Store Group - stx %i0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0] ! Store Group - stx %i1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1] ! Store Group - stx %i2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2] ! Store Group - stx %i3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I3] ! Store Group - stx %i4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I4] ! Store Group - sethi %uhi(PAGE_OFFSET), %g4 ! IEU0 - stx %i5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I5] ! Store Group - stx %i6, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I6] ! Store Group - sllx %g4, 32, %g4 ! IEU0 - stx %i7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I7] ! Store Group - wrpr %l1, (PSTATE_IE|PSTATE_AG|PSTATE_RMO), %pstate ! Single Group+4bubbles - jmpl %l2 + 0x4, %g0 ! CTI Group - mov %l6, %g6 ! IEU0 + .align 64 + .globl etrap, etrap_irq, etraptl1 + +etrap: rdpr %pil, %g2 ! Single Group +etrap_irq: rdpr %tstate, %g1 ! Single Group + sllx %g2, 20, %g3 ! IEU0 Group + andcc %g1, TSTATE_PRIV, %g0 ! IEU1 + or %g1, %g3, %g1 ! IEU0 Group + bne,pn %xcc, 1f ! CTI + sub %sp, REGWIN_SZ+TRACEREG_SZ-STACK_BIAS, %g2 ! IEU1 + wrpr %g0, 7, %cleanwin ! Single Group+4bubbles + + sethi %hi(TASK_REGOFF), %g2 ! IEU0 Group + sethi %hi(TSTATE_PEF), %g3 ! IEU1 + or %g2, %lo(TASK_REGOFF), %g2 ! IEU0 Group + and %g1, %g3, %g3 ! IEU1 + brnz,pn %g3, 1f ! CTI+IEU1 Group + add %g6, %g2, %g2 ! IEU0 + wr %g0, 0, %fprs ! Single Group+4bubbles +1: rdpr %tpc, %g3 ! Single Group + + stx %g1, [%g2 + REGWIN_SZ + PT_V9_TSTATE] ! Store Group + rdpr %tnpc, %g1 ! Single Group + stx %g3, [%g2 + REGWIN_SZ + PT_V9_TPC] ! Store Group + rd %y, %g3 ! Single Group+4bubbles + stx %g1, [%g2 + REGWIN_SZ + PT_V9_TNPC] ! Store Group + st %g3, [%g2 + REGWIN_SZ + PT_V9_Y] ! Store Group + save %g2, -STACK_BIAS, %sp ! Ordering here is critical ! Single Group + mov %g6, %l6 ! IEU0 Group + + bne,pn %xcc, 3f ! CTI + mov PRIMARY_CONTEXT, %l4 ! IEU1 + rdpr %canrestore, %g3 ! Single Group+4bubbles + rdpr %wstate, %g2 ! Single Group+4bubbles + wrpr %g0, 0, %canrestore ! Single Group+4bubbles + sll %g2, 3, %g2 ! IEU0 Group + mov 1, %l5 ! IEU1 + stb %l5, [%l6 + AOFF_task_thread + AOFF_thread_fpdepth] ! Store + + wrpr %g3, 0, %otherwin ! Single Group+4bubbles + wrpr %g2, 0, %wstate ! Single Group+4bubbles + stxa %g0, [%l4] ASI_DMMU ! Store Group + flush %l6 ! Single Group+9bubbles + wr %g0, ASI_AIUS, %asi ! Single Group+4bubbles +2: wrpr %g0, 0x0, %tl ! Single Group+4bubbles + mov %g4, %l4 ! IEU1 + mov %g5, %l5 ! IEU0 Group + + mov %g7, %l2 ! IEU1 + wrpr %g0, ETRAP_PSTATE1, %pstate ! Single Group+4bubbles + stx %g1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G1] ! Store Group + stx %g2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G2] ! Store Group + stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G3] ! Store Group + stx %g4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G4] ! Store Group + stx %g5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G5] ! Store Group + stx %g6, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G6] ! Store Group + + stx %g7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G7] ! Store Group + stx %i0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0] ! Store Group + stx %i1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1] ! Store Group + stx %i2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2] ! Store Group + stx %i3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I3] ! Store Group + stx %i4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I4] ! Store Group + sethi %uhi(PAGE_OFFSET), %g4 ! IEU0 + stx %i5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I5] ! Store Group + + stx %i6, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I6] ! Store Group + sllx %g4, 32, %g4 ! IEU0 + stx %i7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I7] ! Store Group + wrpr %g0, ETRAP_PSTATE2, %pstate ! Single Group+4bubbles + jmpl %l2 + 0x4, %g0 ! CTI Group + mov %l6, %g6 ! IEU0 + nop + nop + +3: ldub [%l6 + AOFF_task_thread + AOFF_thread_fpdepth], %l5 ! Load Group + add %l6, AOFF_task_thread + AOFF_thread_fpsaved + 1, %l4 ! IEU0 + srl %l5, 1, %l3 ! IEU0 Group + add %l5, 2, %l5 ! IEU1 + stb %l5, [%l6 + AOFF_task_thread + AOFF_thread_fpdepth] ! Store + ba,pt %xcc, 2b ! CTI + stb %g0, [%l4 + %l3] ! Store Group + nop + +etraptl1: rdpr %tstate, %g1 ! Single Group+4bubbles + sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2 ! IEU1 + ba,pt %xcc, 1b ! CTI Group + andcc %g1, TSTATE_PRIV, %g0 ! IEU0 + + .align 64 + .globl scetrap +scetrap: rdpr %pil, %g2 ! Single Group + rdpr %tstate, %g1 ! Single Group + sllx %g2, 20, %g3 ! IEU0 Group + andcc %g1, TSTATE_PRIV, %g0 ! IEU1 + or %g1, %g3, %g1 ! IEU0 Group + bne,pn %xcc, 1f ! CTI + sub %sp, (REGWIN_SZ+TRACEREG_SZ-STACK_BIAS), %g2 ! IEU1 + wrpr %g0, 7, %cleanwin ! Single Group+4bubbles + + sllx %g1, 51, %g3 ! IEU0 Group + sethi %hi(TASK_REGOFF), %g2 ! IEU1 + or %g2, %lo(TASK_REGOFF), %g2 ! IEU0 Group + brlz,pn %g3, 1f ! CTI+IEU1 + add %g6, %g2, %g2 ! IEU0 Group + wr %g0, 0, %fprs ! Single Group+4bubbles +1: rdpr %tpc, %g3 ! Single Group + stx %g1, [%g2 + REGWIN_SZ + PT_V9_TSTATE] ! Store Group + + rdpr %tnpc, %g1 ! Single Group + stx %g3, [%g2 + REGWIN_SZ + PT_V9_TPC] ! Store Group + stx %g1, [%g2 + REGWIN_SZ + PT_V9_TNPC] ! Store Group + save %g2, -STACK_BIAS, %sp ! Ordering here is critical ! Single Group + mov %g6, %l6 ! IEU0 Group + bne,pn %xcc, 2f ! CTI + mov ASI_P, %l7 ! IEU1 + rdpr %canrestore, %g3 ! Single Group+4bubbles + + rdpr %wstate, %g2 ! Single Group+4bubbles + wrpr %g0, 0, %canrestore ! Single Group+4bubbles + sll %g2, 3, %g2 ! IEU0 Group + mov PRIMARY_CONTEXT, %l4 ! IEU1 + wrpr %g3, 0, %otherwin ! Single Group+4bubbles + wrpr %g2, 0, %wstate ! Single Group+4bubbles + stxa %g0, [%l4] ASI_DMMU ! Store + flush %l6 ! Single Group+9bubbles + + mov ASI_AIUS, %l7 ! IEU0 Group +2: mov %g4, %l4 ! IEU1 + mov %g5, %l5 ! IEU0 Group + add %g7, 0x4, %l2 ! IEU1 + wrpr %g0, ETRAP_PSTATE1, %pstate ! Single Group+4bubbles + stx %g1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G1] ! Store Group + stx %g2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G2] ! Store Group + sllx %l7, 24, %l7 ! IEU0 + + stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G3] ! Store Group + rdpr %cwp, %l0 ! Single Group + stx %g4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G4] ! Store Group + stx %g5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G5] ! Store Group + stx %g6, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G6] ! Store Group + stx %g7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G7] ! Store Group + or %l7, %l0, %l7 ! IEU0 + sethi %hi(TSTATE_RMO | TSTATE_PEF), %l0 ! IEU1 + + or %l7, %l0, %l7 ! IEU0 Group + wrpr %l2, %tnpc ! Single Group+4bubbles + wrpr %l7, (TSTATE_PRIV | TSTATE_IE), %tstate ! Single Group+4bubbles + stx %i0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0] ! Store Group + stx %i1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1] ! Store Group + stx %i2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2] ! Store Group + stx %i3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I3] ! Store Group + stx %i4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I4] ! Store Group + + sethi %uhi(PAGE_OFFSET), %g4 ! IEU0 + stx %i5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I5] ! Store Group + stx %i6, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I6] ! Store Group + sllx %g4, 32, %g4 ! IEU0 + mov %l6, %g6 ! IEU1 + stx %i7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I7] ! Store Group + done + nop #undef TASK_REGOFF diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index 254e2eb8a..ef07fca85 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.85 2000/03/23 05:25:41 davem Exp $ +/* $Id: ioctl32.c,v 1.87 2000/03/30 02:09:07 davem Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) @@ -2716,6 +2716,25 @@ COMPATIBLE_IOCTL(SG_GET_TIMEOUT) COMPATIBLE_IOCTL(SG_EMULATED_HOST) COMPATIBLE_IOCTL(SG_SET_TRANSFORM) COMPATIBLE_IOCTL(SG_GET_TRANSFORM) +COMPATIBLE_IOCTL(SG_SET_RESERVED_SIZE) +COMPATIBLE_IOCTL(SG_GET_RESERVED_SIZE) +COMPATIBLE_IOCTL(SG_GET_SCSI_ID) +COMPATIBLE_IOCTL(SG_SET_FORCE_LOW_DMA) +COMPATIBLE_IOCTL(SG_GET_LOW_DMA) +COMPATIBLE_IOCTL(SG_SET_FORCE_PACK_ID) +COMPATIBLE_IOCTL(SG_GET_PACK_ID) +COMPATIBLE_IOCTL(SG_GET_NUM_WAITING) +COMPATIBLE_IOCTL(SG_SET_DEBUG) +COMPATIBLE_IOCTL(SG_GET_SG_TABLESIZE) +COMPATIBLE_IOCTL(SG_GET_COMMAND_Q) +COMPATIBLE_IOCTL(SG_SET_COMMAND_Q) +COMPATIBLE_IOCTL(SG_GET_VERSION_NUM) +COMPATIBLE_IOCTL(SG_NEXT_CMD_LEN) +COMPATIBLE_IOCTL(SG_SCSI_RESET) +COMPATIBLE_IOCTL(SG_IO) +COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE) +COMPATIBLE_IOCTL(SG_SET_KEEP_ORPHAN) +COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN) /* PPP stuff */ COMPATIBLE_IOCTL(PPPIOCGFLAGS) COMPATIBLE_IOCTL(PPPIOCSFLAGS) diff --git a/arch/sparc64/kernel/itlb_base.S b/arch/sparc64/kernel/itlb_base.S index 4ef509731..7f0da3d14 100644 --- a/arch/sparc64/kernel/itlb_base.S +++ b/arch/sparc64/kernel/itlb_base.S @@ -1,4 +1,4 @@ -/* $Id: itlb_base.S,v 1.8 2000/01/31 04:59:12 davem Exp $ +/* $Id: itlb_base.S,v 1.9 2000/03/26 09:13:48 davem Exp $ * itlb_base.S: Front end to ITLB miss replacement strategy. * This is included directly into the trap table. * @@ -40,25 +40,25 @@ /* ITLB ** ICACHE line 3: Real faults */ rdpr %tpc, %g5 ! And load faulting VA - clr %g4 ! It was read + mov FAULT_CODE_ITLB, %g4 ! It was read from ITLB sparc64_realfault_common: ! Called by TL0 dtlb_miss too - sethi %hi(1f), %g7 ! Save state - ba,pt %xcc, etrap ! ... -1: or %g7, %lo(1b), %g7 ! ... - mov %l4, %o2 ! Read/Write/No idea - srlx %l5, PAGE_SHIFT, %o1 ! Page align faulting VA - add %sp, STACK_BIAS + REGWIN_SZ, %o0! Compute pt_regs arg - -/* ITLB ** ICACHE line 4: Call fault processing code */ + stb %g4, [%g6 + AOFF_task_thread + AOFF_thread_fault_code] + stx %g5, [%g6 + AOFF_task_thread + AOFF_thread_fault_address] + ba,pt %xcc, etrap ! Save state +1: rd %pc, %g7 ! ... call do_sparc64_fault ! Call fault handler - sllx %o1, PAGE_SHIFT, %o1 ! Finish page alignment - ba,a,pt %xcc, rtrap_clr_l6 ! Restore cpu state - nop + add %sp, STACK_BIAS + REGWIN_SZ, %o0! Compute pt_regs arg + +/* ITLB ** ICACHE line 4: Finish faults + window fixups */ + ba,pt %xcc, rtrap_clr_l6 ! Restore cpu state + nop winfix_trampoline: rdpr %tpc, %g3 ! Prepare winfixup TNPC or %g3, 0x7c, %g3 ! Compute offset to branch wrpr %g3, %tnpc ! Write it into TNPC done ! Do it to it + nop + nop #undef TAG_CONTEXT_BITS #undef VPTE_SHIFT diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index 154ee0181..98b41d079 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c @@ -1,4 +1,4 @@ -/* $Id: pci_common.c,v 1.6 2000/01/06 23:51:49 davem Exp $ +/* $Id: pci_common.c,v 1.7 2000/03/25 05:18:11 davem Exp $ * pci_common.c: PCI controller common support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -565,6 +565,165 @@ void __init pci_fixup_irq(struct pci_pbm_info *pbm, pci_fixup_irq(pbm, pci_bus_b(walk)); } +#undef DEBUG_BUSMASTERING + +static void pdev_setup_busmastering(struct pci_dev *pdev, int is_66mhz) +{ + u16 cmd; + u8 hdr_type, min_gnt, ltimer; + +#ifdef DEBUG_BUSMASTERING + printk("PCI: Checking DEV(%s), ", pdev->name); +#endif + + pci_read_config_word(pdev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MASTER; + pci_write_config_word(pdev, PCI_COMMAND, cmd); + + /* Read it back, if the mastering bit did not + * get set, the device does not support bus + * mastering so we have nothing to do here. + */ + pci_read_config_word(pdev, PCI_COMMAND, &cmd); + if ((cmd & PCI_COMMAND_MASTER) == 0) { +#ifdef DEBUG_BUSMASTERING + printk("no bus mastering...\n"); +#endif + return; + } + + /* Set correct cache line size, 64-byte on all + * Sparc64 PCI systems. Note that the value is + * measured in 32-bit words. + */ +#ifdef DEBUG_BUSMASTERING + printk("set cachelinesize, "); +#endif + pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, + 64 / sizeof(u32)); + + pci_read_config_byte(pdev, PCI_HEADER_TYPE, &hdr_type); + hdr_type &= ~0x80; + if (hdr_type != PCI_HEADER_TYPE_NORMAL) { +#ifdef DEBUG_BUSMASTERING + printk("hdr_type=%x, exit\n", hdr_type); +#endif + return; + } + + /* If the latency timer is already programmed with a non-zero + * value, assume whoever set it (OBP or whoever) knows what + * they are doing. + */ + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, <imer); + if (ltimer != 0) { +#ifdef DEBUG_BUSMASTERING + printk("ltimer was %x, exit\n", ltimer); +#endif + return; + } + + /* XXX Since I'm tipping off the min grant value to + * XXX choose a suitable latency timer value, I also + * XXX considered making use of the max latency value + * XXX as well. Unfortunately I've seen too many bogusly + * XXX low settings for it to the point where it lacks + * XXX any usefulness. In one case, an ethernet card + * XXX claimed a min grant of 10 and a max latency of 5. + * XXX Now, if I had two such cards on the same bus I + * XXX could not set the desired burst period (calculated + * XXX from min grant) without violating the max latency + * XXX bound. Duh... + * XXX + * XXX I blame dumb PC bios implementors for stuff like + * XXX this, most of them don't even try to do something + * XXX sensible with latency timer values and just set some + * XXX default value (usually 32) into every device. + */ + + pci_read_config_byte(pdev, PCI_MIN_GNT, &min_gnt); + + if (min_gnt == 0) { + /* If no min_gnt setting then use a default + * value. + */ + if (is_66mhz) + ltimer = 16; + else + ltimer = 32; + } else { + int shift_factor; + + if (is_66mhz) + shift_factor = 2; + else + shift_factor = 3; + + /* Use a default value when the min_gnt value + * is erroneously high. + */ + if (((unsigned int) min_gnt << shift_factor) > 512 || + ((min_gnt << shift_factor) & 0xff) == 0) { + ltimer = 8 << shift_factor; + } else { + ltimer = min_gnt << shift_factor; + } + } + + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, ltimer); +#ifdef DEBUG_BUSMASTERING + printk("set ltimer to %x\n", ltimer); +#endif +} + +void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm, + struct pci_bus *pbus) +{ + struct list_head *walk; + int all_are_66mhz; + u16 status; + + if (pbm->is_66mhz_capable == 0) { + all_are_66mhz = 0; + goto out; + } + + walk = &pbus->devices; + all_are_66mhz = 1; + for (walk = walk->next; walk != &pbus->devices; walk = walk->next) { + struct pci_dev *pdev = pci_dev_b(walk); + + pci_read_config_word(pdev, PCI_STATUS, &status); + if (!(status & PCI_STATUS_66MHZ)) { + all_are_66mhz = 0; + break; + } + } +out: + pbm->all_devs_66mhz = all_are_66mhz; + + printk("PCI%d(PBM%c): Bus running at %dMHz\n", + pbm->parent->index, + (pbm == &pbm->parent->pbm_A) ? 'A' : 'B', + (all_are_66mhz ? 66 : 33)); +} + +void pci_setup_busmastering(struct pci_pbm_info *pbm, + struct pci_bus *pbus) +{ + struct list_head *walk = &pbus->devices; + int is_66mhz; + + is_66mhz = pbm->is_66mhz_capable && pbm->all_devs_66mhz; + + for (walk = walk->next; walk != &pbus->devices; walk = walk->next) + pdev_setup_busmastering(pci_dev_b(walk), is_66mhz); + + walk = &pbus->children; + for (walk = walk->next; walk != &pbus->children; walk = walk->next) + pci_setup_busmastering(pbm, pci_bus_b(walk)); +} + /* Generic helper routines for PCI error reporting. */ void pci_scan_for_target_abort(struct pci_controller_info *p, struct pci_pbm_info *pbm, diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index eeda574f7..54a8952b8 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h @@ -1,4 +1,4 @@ -/* $Id: pci_impl.h,v 1.5 2000/02/08 05:11:32 jj Exp $ +/* $Id: pci_impl.h,v 1.6 2000/03/25 05:18:11 davem Exp $ * pci_impl.h: Helper definitions for PCI controller support. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) @@ -28,6 +28,10 @@ extern void pci_assign_unassigned(struct pci_pbm_info *pbm, struct pci_bus *pbus); extern void pci_fixup_irq(struct pci_pbm_info *pbm, struct pci_bus *pbus); +extern void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm, + struct pci_bus *pbus); +extern void pci_setup_busmastering(struct pci_pbm_info *pbm, + struct pci_bus *pbus); /* Error reporting support. */ extern void pci_scan_for_target_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 1c8f59f3f..a45fe4740 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -1,4 +1,4 @@ -/* $Id: pci_psycho.c,v 1.14 2000/03/10 02:42:15 davem Exp $ +/* $Id: pci_psycho.c,v 1.15 2000/03/25 05:18:11 davem Exp $ * pci_psycho.c: PSYCHO/U2P specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) @@ -1193,6 +1193,23 @@ static void __init pbm_bridge_reconfigure(struct pci_controller_info *p) pbm_renumber(&p->pbm_A, 0xff); } +static void __init pbm_config_busmastering(struct pci_pbm_info *pbm) +{ + u8 *addr; + + /* Set cache-line size to 64 bytes, this is actually + * a nop but I do it for completeness. + */ + addr = psycho_pci_config_mkaddr(pbm, pbm->pci_first_busno, + 0, PCI_CACHE_LINE_SIZE); + pci_config_write8(addr, 64 / sizeof(u32)); + + /* Set PBM latency timer to 64 PCI clocks. */ + addr = psycho_pci_config_mkaddr(pbm, pbm->pci_first_busno, + 0, PCI_LATENCY_TIMER); + pci_config_write8(addr, 64); +} + static void __init pbm_scan_bus(struct pci_controller_info *p, struct pci_pbm_info *pbm) { @@ -1203,11 +1220,17 @@ static void __init pbm_scan_bus(struct pci_controller_info *p, pci_record_assignments(pbm, pbm->pci_bus); pci_assign_unassigned(pbm, pbm->pci_bus); pci_fixup_irq(pbm, pbm->pci_bus); + pci_determine_66mhz_disposition(pbm, pbm->pci_bus); + pci_setup_busmastering(pbm, pbm->pci_bus); } static void __init psycho_scan_bus(struct pci_controller_info *p) { pbm_bridge_reconfigure(p); + pbm_config_busmastering(&p->pbm_B); + p->pbm_B.is_66mhz_capable = 0; + pbm_config_busmastering(&p->pbm_A); + p->pbm_A.is_66mhz_capable = 1; pbm_scan_bus(p, &p->pbm_B); pbm_scan_bus(p, &p->pbm_A); diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index a10f5f072..a55772179 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -1,4 +1,4 @@ -/* $Id: pci_sabre.c,v 1.15 2000/03/10 02:42:16 davem Exp $ +/* $Id: pci_sabre.c,v 1.16 2000/03/25 05:18:12 davem Exp $ * pci_sabre.c: Sabre specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) @@ -1060,6 +1060,13 @@ static void __init sabre_scan_bus(struct pci_controller_info *p) struct pci_bus *sabre_bus; struct list_head *walk; + /* The APB bridge speaks to the Sabre host PCI bridge + * at 66Mhz, but the front side of APB runs at 33Mhz + * for both segments. + */ + p->pbm_A.is_66mhz_capable = 0; + p->pbm_B.is_66mhz_capable = 0; + /* Unlike for PSYCHO, we can only have one SABRE * in a system. Having multiple SABREs is thus * and error, and as a consequence we do not need @@ -1079,6 +1086,17 @@ static void __init sabre_scan_bus(struct pci_controller_info *p) sabre_bus = pci_scan_bus(p->pci_first_busno, p->pci_ops, &p->pbm_A); + + { + unsigned int devfn; + u8 *addr; + + devfn = PCI_DEVFN(0, 0); + addr = sabre_pci_config_mkaddr(&p->pbm_A, 0, + devfn, PCI_LATENCY_TIMER); + pci_config_write8(addr, 32); + } + apb_init(p, sabre_bus); walk = &sabre_bus->children; @@ -1099,6 +1117,8 @@ static void __init sabre_scan_bus(struct pci_controller_info *p) pci_record_assignments(pbm, pbus); pci_assign_unassigned(pbm, pbus); pci_fixup_irq(pbm, pbus); + pci_determine_66mhz_disposition(pbm, pbus); + pci_setup_busmastering(pbm, pbus); } sabre_register_error_handlers(p); diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index dd71b1e92..8ac030324 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.104 2000/03/01 02:53:32 davem Exp $ +/* $Id: process.c,v 1.105 2000/03/26 09:13:48 davem Exp $ * arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) @@ -451,7 +451,7 @@ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp) { unsigned long fp, distance, rval; - if(!(current->thread.flags & SPARC_FLAG_32BIT)) { + if (!(current->thread.flags & SPARC_FLAG_32BIT)) { csp += STACK_BIAS; psp += STACK_BIAS; __get_user(fp, &(((struct reg_window *)psp)->ins[6])); @@ -466,14 +466,14 @@ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp) distance = fp - psp; rval = (csp - distance); - if(copy_in_user(rval, psp, distance)) + if (copy_in_user(rval, psp, distance)) rval = 0; - else if(current->thread.flags & SPARC_FLAG_32BIT) { - if(put_user(((u32)csp), &(((struct reg_window32 *)rval)->ins[6]))) + else if (current->thread.flags & SPARC_FLAG_32BIT) { + if (put_user(((u32)csp), &(((struct reg_window32 *)rval)->ins[6]))) rval = 0; } else { - if(put_user(((u64)csp - STACK_BIAS), - &(((struct reg_window *)rval)->ins[6]))) + if (put_user(((u64)csp - STACK_BIAS), + &(((struct reg_window *)rval)->ins[6]))) rval = 0; else rval = rval - STACK_BIAS; @@ -488,7 +488,7 @@ static inline void shift_window_buffer(int first_win, int last_win, { int i; - for(i = first_win; i < last_win; i++) { + for (i = first_win; i < last_win; i++) { t->rwbuf_stkptrs[i] = t->rwbuf_stkptrs[i+1]; memcpy(&t->reg_window[i], &t->reg_window[i+1], sizeof(struct reg_window)); @@ -501,11 +501,11 @@ void synchronize_user_stack(void) unsigned long window; flush_user_windows(); - if((window = t->w_saved) != 0) { + if ((window = t->w_saved) != 0) { int winsize = REGWIN_SZ; int bias = 0; - if(t->flags & SPARC_FLAG_32BIT) + if (t->flags & SPARC_FLAG_32BIT) winsize = REGWIN32_SZ; else bias = STACK_BIAS; @@ -515,11 +515,11 @@ void synchronize_user_stack(void) unsigned long sp = (t->rwbuf_stkptrs[window] + bias); struct reg_window *rwin = &t->reg_window[window]; - if(!copy_to_user((char *)sp, rwin, winsize)) { + if (!copy_to_user((char *)sp, rwin, winsize)) { shift_window_buffer(window, t->w_saved - 1, t); t->w_saved--; } - } while(window--); + } while (window--); } } @@ -530,25 +530,29 @@ void fault_in_user_windows(struct pt_regs *regs) int winsize = REGWIN_SZ; int bias = 0; - if(t->flags & SPARC_FLAG_32BIT) + if (t->flags & SPARC_FLAG_32BIT) winsize = REGWIN32_SZ; else bias = STACK_BIAS; + flush_user_windows(); window = t->w_saved; - if(window != 0) { + + if (window != 0) { window -= 1; do { unsigned long sp = (t->rwbuf_stkptrs[window] + bias); struct reg_window *rwin = &t->reg_window[window]; - if(copy_to_user((char *)sp, rwin, winsize)) + if (copy_to_user((char *)sp, rwin, winsize)) goto barf; - } while(window--); + } while (window--); } t->w_saved = 0; return; + barf: + t->w_saved = window + 1; do_exit(SIGILL); } @@ -578,7 +582,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, t->kregs = (struct pt_regs *)(child_trap_frame+sizeof(struct reg_window)); t->cwp = (regs->tstate + 1) & TSTATE_CWP; t->fpsaved[0] = 0; - if(regs->tstate & TSTATE_PRIV) { + + if (regs->tstate & TSTATE_PRIV) { /* Special case, if we are spawning a kernel thread from * a userspace task (via KMOD, NFS, or similar) we must * disable performance counters in the child because the @@ -597,7 +602,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, sizeof(struct reg_window)); t->kregs->u_regs[UREG_G6] = (unsigned long) p; } else { - if(t->flags & SPARC_FLAG_32BIT) { + if (t->flags & SPARC_FLAG_32BIT) { sp &= 0x00000000ffffffffUL; regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; } @@ -607,7 +612,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, unsigned long csp; csp = clone_stackframe(sp, regs->u_regs[UREG_FP]); - if(!csp) + if (!csp) return -EFAULT; t->kregs->u_regs[UREG_FP] = csp; } @@ -621,19 +626,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, /* Set the second return value for the parent. */ regs->u_regs[UREG_I1] = 0; -#if 0 - printk("\ncopy_thread: c(%p[mm(%p:%p)]) p(%p[mm(%p:%p)])\n", - current, current->mm, current->active_mm, - p, p->mm, p->active_mm); - printk("copy_thread: c MM_ctx(%016lx) MM_pgd(%016lx)\n", - (current->mm ? current->mm->context : 0), - (current->mm ? pgd_val(current->mm->pgd[0]) : 0)); - printk("copy_thread: p MM_ctx(%016lx) MM_pgd(%08x)\n", - (p->mm ? p->mm->context : 0), - (p->mm ? pgd_val(p->mm->pgd[0]) : 0)); - printk("copy_thread: c->flags(%x) p->flags(%x) ", - current->thread.flags, p->thread.flags); -#endif + return 0; } diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S index d059a5a28..1c9b6ac3f 100644 --- a/arch/sparc64/kernel/rtrap.S +++ b/arch/sparc64/kernel/rtrap.S @@ -1,4 +1,4 @@ -/* $Id: rtrap.S,v 1.48 2000/02/09 11:15:07 davem Exp $ +/* $Id: rtrap.S,v 1.49 2000/03/29 09:55:31 davem Exp $ * rtrap.S: Preparing for return from trap on Sparc V9. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -14,194 +14,207 @@ #include <asm/processor.h> #define PTREGS_OFF (STACK_BIAS + REGWIN_SZ) +#define RTRAP_PSTATE (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE) +#define RTRAP_PSTATE_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV) +#define RTRAP_PSTATE_AG_IRQOFF (PSTATE_RMO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG) + +#if 0 +#define RTRAP_CHECK call rtrap_check; add %sp, (STACK_BIAS+REGWIN_SZ), %o0; +#else +#define RTRAP_CHECK +#endif .text + .align 32 +__handle_softirq: + call do_softirq + nop + ba,a,pt %xcc, __handle_softirq_continue + nop +__handle_preemption: + call schedule + nop + ba,pt %xcc, __handle_preemption_continue + nop +__handle_user_windows: + wrpr %g0, RTRAP_PSTATE, %pstate + call fault_in_user_windows + add %sp, STACK_BIAS + REGWIN_SZ, %g0 + ba,a,pt %xcc, __handle_user_windows_continue +__handle_perfctrs: + /* Don't forget to preserve user window invariants. */ + wrpr %g0, RTRAP_PSTATE, %pstate + call update_perfctrs + nop + wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate + ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %o2 + brz,pt %o2, __handle_perfctrs_continue + sethi %hi(TSTATE_PEF), %l6 + wrpr %g0, RTRAP_PSTATE, %pstate + + call fault_in_user_windows + add %sp, STACK_BIAS + REGWIN_SZ, %o0 + ba,pt %xcc, __handle_perfctrs_continue + nop +__handle_userfpu: + rd %fprs, %l5 + andcc %l5, FPRS_FEF, %g0 + be,a,pn %icc, __handle_userfpu_continue + andn %l1, %l6, %l1 + ba,a,pt %xcc, __handle_userfpu_continue +__handle_signal: + clr %o0 + mov %l5, %o2 + mov %l6, %o3 + call do_signal + add %sp, STACK_BIAS + REGWIN_SZ, %o1 + ba,pt %xcc, __handle_signal_continue + clr %l6 + nop + + .align 64 .globl rtrap_clr_l6, rtrap rtrap_clr_l6: clr %l6 - /* Fall through */ rtrap: lduw [%g6 + AOFF_task_processor], %l0 sethi %hi(softirq_state), %l2 or %l2, %lo(softirq_state), %l2 sllx %l0, 6, %l0 ldx [%l2 + %l0], %l1 srlx %l1, 32, %l2 - andcc %l1, %l2, %g0 - be,pt %icc, 2f - nop - call do_softirq - nop -2: ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 + + bne,pn %icc, __handle_softirq + ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1 +__handle_softirq_continue: sethi %hi(0xf << 20), %l4 andcc %l1, TSTATE_PRIV, %l3 - and %l1, %l4, %l4 - rdpr %pstate, %l7 - andn %l1, %l4, %l1 - be,pt %icc, to_user - andn %l7, PSTATE_IE, %l7 + bne,pn %icc, to_kernel + andn %l1, %l4, %l1 +to_user: ldx [%g6 + AOFF_task_need_resched], %l0 + + brnz,pn %l0, __handle_preemption +__handle_preemption_continue: + lduw [%g6 + AOFF_task_sigpending], %l0 + brnz,pn %l0, __handle_signal + nop +__handle_signal_continue: +check_user_wins: + wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate + ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %o2 + brnz,pn %o2, __handle_user_windows + sethi %hi(TSTATE_PEF), %l6 + +__handle_user_windows_continue: + RTRAP_CHECK + ldub [%g6 + AOFF_task_thread + AOFF_thread_flags], %l5 + andcc %l5, SPARC_FLAG_PERFCTR, %g0 + bne,pn %xcc, __handle_perfctrs +__handle_perfctrs_continue: + andcc %l1, %l6, %g0 + bne,pn %xcc, __handle_userfpu + stb %g0, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth] ! This is neccessary for non-syscall rtraps only +__handle_userfpu_continue: - ldub [%g6 + AOFF_task_thread + AOFF_thread_fpdepth], %l5 - brz,pt %l5, rt_continue - srl %l5, 1, %o0 - add %g6, AOFF_task_thread + AOFF_thread_fpsaved, %l6 - ldub [%l6 + %o0], %l2 - sub %l5, 2, %l5 - add %g6, AOFF_task_thread + AOFF_thread_gsr, %o1 - andcc %l2, (FPRS_FEF|FPRS_DU), %g0 - be,pt %icc, 2f - and %l2, FPRS_DL, %l6 - andcc %l2, FPRS_FEF, %g0 - be,pn %icc, 5f - sll %o0, 3, %o5 - rd %fprs, %g5 - wr %g5, FPRS_FEF, %fprs - ldub [%o1 + %o0], %g5 - add %g6, AOFF_task_thread + AOFF_thread_xfsr, %o1 - membar #StoreLoad | #LoadLoad - sll %o0, 8, %o2 - add %g6, AOFF_task_fpregs, %o3 - brz,pn %l6, 1f - add %g6, AOFF_task_fpregs+0x40, %o4 - ldda [%o3 + %o2] ASI_BLK_P, %f0 - ldda [%o4 + %o2] ASI_BLK_P, %f16 -1: andcc %l2, FPRS_DU, %g0 - be,pn %icc, 1f - wr %g5, 0, %gsr - add %o2, 0x80, %o2 - ldda [%o3 + %o2] ASI_BLK_P, %f32 - ldda [%o4 + %o2] ASI_BLK_P, %f48 -1: membar #Sync - ldx [%o1 + %o5], %fsr -2: stb %l5, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth] rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 ldx [%sp + PTREGS_OFF + PT_V9_G2], %g2 + ldx [%sp + PTREGS_OFF + PT_V9_G3], %g3 - mov %g6, %o5 ldx [%sp + PTREGS_OFF + PT_V9_G4], %g4 ldx [%sp + PTREGS_OFF + PT_V9_G5], %g5 ldx [%sp + PTREGS_OFF + PT_V9_G6], %g6 ldx [%sp + PTREGS_OFF + PT_V9_G7], %g7 - - wrpr %l7, PSTATE_AG, %pstate + wrpr %g0, RTRAP_PSTATE_AG_IRQOFF, %pstate ldx [%sp + PTREGS_OFF + PT_V9_I0], %i0 ldx [%sp + PTREGS_OFF + PT_V9_I1], %i1 + ldx [%sp + PTREGS_OFF + PT_V9_I2], %i2 ldx [%sp + PTREGS_OFF + PT_V9_I3], %i3 ldx [%sp + PTREGS_OFF + PT_V9_I4], %i4 ldx [%sp + PTREGS_OFF + PT_V9_I5], %i5 ldx [%sp + PTREGS_OFF + PT_V9_I6], %i6 - ldx [%sp + PTREGS_OFF + PT_V9_I7], %i7 - ld [%sp + PTREGS_OFF + PT_V9_Y], %o3 ldx [%sp + PTREGS_OFF + PT_V9_TPC], %l2 ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %o2 + + ld [%sp + PTREGS_OFF + PT_V9_Y], %o3 wr %o3, %g0, %y srl %l4, 20, %l4 wrpr %l4, 0x0, %pil wrpr %g0, 0x1, %tl - wrpr %l1, %g0, %tstate wrpr %l2, %g0, %tpc wrpr %o2, %g0, %tnpc + brnz,pn %l3, kern_rtt mov PRIMARY_CONTEXT, %l7 ldxa [%l7 + %l7] ASI_DMMU, %l0 stxa %l0, [%l7] ASI_DMMU - flush %o5 - + flush %g6 rdpr %wstate, %l1 rdpr %otherwin, %l2 srl %l1, 3, %l1 + wrpr %l2, %g0, %canrestore wrpr %l1, %g0, %wstate wrpr %g0, %g0, %otherwin restore rdpr %canrestore, %g1 - wrpr %g1, 0x0, %cleanwin retry + nop + kern_rtt: restore retry -to_user: ldx [%g6 + AOFF_task_need_resched], %l0 - wrpr %l7, PSTATE_IE, %pstate - orcc %g0, %l0, %g0 - be,a,pt %xcc, check_signal - - lduw [%g6 + AOFF_task_sigpending], %l0 - call schedule - nop - lduw [%g6 + AOFF_task_sigpending], %l0 -check_signal: brz,a,pt %l0, check_user_wins - nop - clr %o0 - mov %l5, %o2 - mov %l6, %o3 - call do_signal - add %sp, STACK_BIAS + REGWIN_SZ, %o1 - clr %l6 - - /* We must not take any traps between here and the actual - * return to user-space. If we do we risk having windows - * saved to the thread struct between the test and the - * actual return from trap. --DaveM - */ -check_user_wins: - wrpr %l7, 0x0, %pstate - ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %o2 - brz,pt %o2, 1f - sethi %hi(TSTATE_PEF), %l6 +to_kernel: ldub [%g6 + AOFF_task_thread + AOFF_thread_fpdepth], %l5 + brz,pt %l5, rt_continue + srl %l5, 1, %o0 + add %g6, AOFF_task_thread + AOFF_thread_fpsaved, %l6 + ldub [%l6 + %o0], %l2 + sub %l5, 2, %l5 - wrpr %l7, PSTATE_IE, %pstate - call fault_in_user_windows - add %sp, STACK_BIAS + REGWIN_SZ, %o0 - /* It is OK to leave interrupts on now because if - * fault_in_user_windows has returned it has left us - * with a clean user stack state. - */ -1: -#if 0 - call rtrap_check - add %sp, STACK_BIAS + REGWIN_SZ, %o0 -#endif - ldub [%g6 + AOFF_task_thread + AOFF_thread_flags], %l5 - andcc %l5, SPARC_FLAG_PERFCTR, %g0 - be,pt %xcc, 1f - nop + add %g6, AOFF_task_thread + AOFF_thread_gsr, %o1 + andcc %l2, (FPRS_FEF|FPRS_DU), %g0 + be,pt %icc, 2f + and %l2, FPRS_DL, %l6 + andcc %l2, FPRS_FEF, %g0 + be,pn %icc, 5f + sll %o0, 3, %o5 + rd %fprs, %g5 - /* Don't forget to preserve user window invariants. */ - wrpr %l7, PSTATE_IE, %pstate - call update_perfctrs - nop - wrpr %l7, 0x0, %pstate - ldub [%g6 + AOFF_task_thread + AOFF_thread_w_saved], %o2 - brz,pt %o2, 1f - sethi %hi(TSTATE_PEF), %l6 - wrpr %l7, PSTATE_IE, %pstate - call fault_in_user_windows - add %sp, STACK_BIAS + REGWIN_SZ, %o0 + wr %g5, FPRS_FEF, %fprs + ldub [%o1 + %o0], %g5 + add %g6, AOFF_task_thread + AOFF_thread_xfsr, %o1 + membar #StoreLoad | #LoadLoad + sll %o0, 8, %o2 + add %g6, AOFF_task_fpregs, %o3 + brz,pn %l6, 1f + add %g6, AOFF_task_fpregs+0x40, %o4 -1: - andcc %l1, %l6, %g0 - be,pt %xcc, rt_continue - stb %g0, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth] ! This is neccessary for non-syscall rtraps only + ldda [%o3 + %o2] ASI_BLK_P, %f0 + ldda [%o4 + %o2] ASI_BLK_P, %f16 +1: andcc %l2, FPRS_DU, %g0 + be,pn %icc, 1f + wr %g5, 0, %gsr + add %o2, 0x80, %o2 + ldda [%o3 + %o2] ASI_BLK_P, %f32 + ldda [%o4 + %o2] ASI_BLK_P, %f48 - rd %fprs, %l5 - andcc %l5, FPRS_FEF, %g0 - be,a,pn %icc, rt_continue - andn %l1, %l6, %l1 +1: membar #Sync + ldx [%o1 + %o5], %fsr +2: stb %l5, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth] ba,pt %xcc, rt_continue nop - 5: wr %g0, FPRS_FEF, %fprs membar #StoreLoad | #LoadLoad sll %o0, 8, %o2 + add %g6, AOFF_task_fpregs+0x80, %o3 add %g6, AOFF_task_fpregs+0xc0, %o4 ldda [%o3 + %o2] ASI_BLK_P, %f32 ldda [%o4 + %o2] ASI_BLK_P, %f48 -1: membar #Sync + membar #Sync wr %g0, FPRS_DU, %fprs ba,pt %xcc, rt_continue stb %l5, [%g6 + AOFF_task_thread + AOFF_thread_fpdepth] diff --git a/arch/sparc64/kernel/semaphore.c b/arch/sparc64/kernel/semaphore.c index 88ab813f3..0919089ef 100644 --- a/arch/sparc64/kernel/semaphore.c +++ b/arch/sparc64/kernel/semaphore.c @@ -1,4 +1,4 @@ -/* $Id: semaphore.c,v 1.2 1999/12/23 17:12:03 jj Exp $ +/* $Id: semaphore.c,v 1.3 2000/03/27 10:38:46 davem Exp $ * Generic semaphore code. Buyer beware. Do your own * specific changes in <asm/semaphore-helper.h> */ @@ -203,7 +203,7 @@ void down_read_failed_biased(struct rw_semaphore *sem) add_wait_queue(&sem->wait, &wait); /* put ourselves at the head of the list */ for (;;) { - if (clear_le_bit(0, &sem->granted)) + if (test_and_clear_le_bit(0, &sem->granted)) break; set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (!test_le_bit(0, &sem->granted)) @@ -221,7 +221,7 @@ void down_write_failed_biased(struct rw_semaphore *sem) add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */ for (;;) { - if (clear_le_bit(1, &sem->granted)) + if (test_and_clear_le_bit(1, &sem->granted)) break; set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); if (!test_le_bit(1, &sem->granted)) @@ -286,11 +286,11 @@ void down_write_failed(struct rw_semaphore *sem) void __rwsem_wake(struct rw_semaphore *sem, unsigned long readers) { if (readers) { - if (set_le_bit(0, &sem->granted)) + if (test_and_set_le_bit(0, &sem->granted)) BUG(); wake_up(&sem->wait); } else { - if (set_le_bit(1, &sem->granted)) + if (test_and_set_le_bit(1, &sem->granted)) BUG(); wake_up(&sem->write_bias_wait); } diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index 79db5bc4e..e7a50c150 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -616,7 +616,9 @@ static inline void read_maps (void) if (map->vm_file != NULL) { dev = map->vm_file->f_dentry->d_inode->i_dev; ino = map->vm_file->f_dentry->d_inode->i_ino; - line = d_path(map->vm_file->f_dentry, buffer, PAGE_SIZE); + line = d_path(map->vm_file->f_dentry, + map->vm_file->f_vfsmnt, + buffer, PAGE_SIZE); } printk(MAPS_LINE_FORMAT, map->vm_start, map->vm_end, str, map->vm_pgoff << PAGE_SHIFT, kdevname(dev), ino); diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index 8df2116e7..423c5f648 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c @@ -1279,7 +1279,9 @@ static inline void read_maps (void) if (map->vm_file != NULL) { dev = map->vm_file->f_dentry->d_inode->i_dev; ino = map->vm_file->f_dentry->d_inode->i_ino; - line = d_path(map->vm_file->f_dentry, buffer, PAGE_SIZE); + line = d_path(map->vm_file->f_dentry, + map->vm_file->f_vfsmnt, + buffer, PAGE_SIZE); } printk(MAPS_LINE_FORMAT, map->vm_start, map->vm_end, str, map->vm_pgoff << PAGE_SHIFT, kdevname(dev), ino); diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 0d5f615cf..e9a180d2a 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -469,52 +469,83 @@ void smp_flush_tlb_all(void) */ void smp_flush_tlb_mm(struct mm_struct *mm) { - u32 ctx = CTX_HWBITS(mm->context); - - if (mm == current->active_mm && - atomic_read(&mm->mm_users) == 1 && - (mm->cpu_vm_mask == (1UL << smp_processor_id()))) - goto local_flush_and_out; + if (CTX_VALID(mm->context)) { + u32 ctx = CTX_HWBITS(mm->context); + int cpu = smp_processor_id(); + + if (mm == current->active_mm && atomic_read(&mm->mm_users) == 1) { + /* See smp_flush_tlb_page for info about this. */ + mm->cpu_vm_mask = (1UL << cpu); + goto local_flush_and_out; + } - smp_cross_call(&xcall_flush_tlb_mm, ctx, 0, 0); + smp_cross_call(&xcall_flush_tlb_mm, ctx, 0, 0); -local_flush_and_out: - __flush_tlb_mm(ctx, SECONDARY_CONTEXT); + local_flush_and_out: + __flush_tlb_mm(ctx, SECONDARY_CONTEXT); + } } void smp_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { - u32 ctx = CTX_HWBITS(mm->context); + if (CTX_VALID(mm->context)) { + u32 ctx = CTX_HWBITS(mm->context); + int cpu = smp_processor_id(); - start &= PAGE_MASK; - end &= PAGE_MASK; - if(mm == current->active_mm && - atomic_read(&mm->mm_users) == 1 && - (mm->cpu_vm_mask == (1UL << smp_processor_id()))) - goto local_flush_and_out; + start &= PAGE_MASK; + end &= PAGE_MASK; - smp_cross_call(&xcall_flush_tlb_range, ctx, start, end); + if (mm == current->active_mm && atomic_read(&mm->mm_users) == 1) { + mm->cpu_vm_mask = (1UL << cpu); + goto local_flush_and_out; + } + + smp_cross_call(&xcall_flush_tlb_range, ctx, start, end); -local_flush_and_out: - __flush_tlb_range(ctx, start, SECONDARY_CONTEXT, end, PAGE_SIZE, (end-start)); + local_flush_and_out: + __flush_tlb_range(ctx, start, SECONDARY_CONTEXT, end, PAGE_SIZE, (end-start)); + } } void smp_flush_tlb_page(struct mm_struct *mm, unsigned long page) { - u32 ctx = CTX_HWBITS(mm->context); - - page &= PAGE_MASK; - if(mm == current->active_mm && - atomic_read(&mm->mm_users) == 1 && - (mm->cpu_vm_mask == (1UL << smp_processor_id()))) { - goto local_flush_and_out; - } + if (CTX_VALID(mm->context)) { + u32 ctx = CTX_HWBITS(mm->context); + int cpu = smp_processor_id(); + + page &= PAGE_MASK; + if (mm == current->active_mm && atomic_read(&mm->mm_users) == 1) { + /* By virtue of being the current address space, and + * having the only reference to it, the following operation + * is safe. + * + * It would not be a win to perform the xcall tlb flush in + * this case, because even if we switch back to one of the + * other processors in cpu_vm_mask it is almost certain that + * all TLB entries for this context will be replaced by the + * time that happens. + */ + mm->cpu_vm_mask = (1UL << cpu); + goto local_flush_and_out; + } else { + /* By virtue of running under the mm->page_table_lock, + * and mmu_context.h:switch_mm doing the same, the following + * operation is safe. + */ + if (mm->cpu_vm_mask == (1UL << cpu)) + goto local_flush_and_out; + } - smp_cross_call(&xcall_flush_tlb_page, ctx, page, 0); + /* OK, we have to actually perform the cross call. Most likely + * this is a cloned mm or kswapd is kicking out pages for a task + * which has run recently on another cpu. + */ + smp_cross_call(&xcall_flush_tlb_page, ctx, page, 0); -local_flush_and_out: - __flush_tlb_page(ctx, page, SECONDARY_CONTEXT); + local_flush_and_out: + __flush_tlb_page(ctx, page, SECONDARY_CONTEXT); + } } /* CPU capture. */ @@ -603,13 +634,16 @@ static inline void sparc64_do_profile(unsigned long pc, unsigned long o7) extern int rwlock_impl_begin, rwlock_impl_end; extern int atomic_impl_begin, atomic_impl_end; extern int __memcpy_begin, __memcpy_end; + extern int __bitops_begin, __bitops_end; if ((pc >= (unsigned long) &atomic_impl_begin && pc < (unsigned long) &atomic_impl_end) || (pc >= (unsigned long) &rwlock_impl_begin && pc < (unsigned long) &rwlock_impl_end) || (pc >= (unsigned long) &__memcpy_begin && - pc < (unsigned long) &__memcpy_end)) + pc < (unsigned long) &__memcpy_end) || + (pc >= (unsigned long) &__bitops_begin && + pc < (unsigned long) &__bitops_end)) pc = o7; pc -= (unsigned long) &_stext; diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 26e11085d..fc7a8cfe5 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.79 2000/03/17 14:41:18 davem Exp $ +/* $Id: sparc64_ksyms.c,v 1.80 2000/03/27 10:38:47 davem Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -170,6 +170,13 @@ EXPORT_SYMBOL_NOVERS(__rwsem_wake); EXPORT_SYMBOL_PRIVATE(atomic_add); EXPORT_SYMBOL_PRIVATE(atomic_sub); +/* Atomic bit operations. */ +EXPORT_SYMBOL_PRIVATE(test_and_set_bit); +EXPORT_SYMBOL_PRIVATE(test_and_clear_bit); +EXPORT_SYMBOL_PRIVATE(test_and_change_bit); +EXPORT_SYMBOL_PRIVATE(test_and_set_le_bit); +EXPORT_SYMBOL_PRIVATE(test_and_clear_le_bit); + EXPORT_SYMBOL(ivector_table); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S index 34db8d056..c97b266be 100644 --- a/arch/sparc64/kernel/sys32.S +++ b/arch/sparc64/kernel/sys32.S @@ -1,4 +1,4 @@ -/* $Id: sys32.S,v 1.11 2000/01/11 17:33:29 jj Exp $ +/* $Id: sys32.S,v 1.12 2000/03/24 04:17:37 davem Exp $ * sys32.S: I-cache tricks for 32-bit compatability layer simple * conversions. * @@ -6,6 +6,8 @@ * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) */ +#include <asm/errno.h> + /* NOTE: call as jump breaks return stack, we have to avoid that */ .text @@ -69,3 +71,187 @@ sys32_mmap2: srl %o5, 0, %o5 jmpl %g1 + %lo(sys_mmap), %g0 sllx %o5, 12, %o5 + + .align 32 + .globl sys32_socketcall +sys32_socketcall: /* %o0=call, %o1=args */ + cmp %o0, 1 + bl,pn %xcc, do_einval + cmp %o0, 17 + bg,pn %xcc, do_einval + sub %o0, 1, %o0 + sllx %o0, 5, %o0 + sethi %hi(__socketcall_table_begin), %g2 + or %g2, %lo(__socketcall_table_begin), %g2 + jmpl %g2 + %o0, %g0 + nop + + /* Each entry is exactly 32 bytes. */ + .align 32 +__socketcall_table_begin: +do_sys_socket: /* sys_socket(int, int, int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_socket), %g1 + ldswa [%o1 + 0x8] %asi, %o2 + jmpl %g1 + %lo(sys_socket), %g0 + ldswa [%o1 + 0x4] %asi, %o1 + nop + nop + nop +do_sys_bind: /* sys_bind(int fd, struct sockaddr *, int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_bind), %g1 + ldswa [%o1 + 0x8] %asi, %o2 + jmpl %g1 + %lo(sys_bind), %g0 + lduwa [%o1 + 0x4] %asi, %o1 + nop + nop + nop +do_sys_connect: /* sys_connect(int, struct sockaddr *, int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_connect), %g1 + ldswa [%o1 + 0x8] %asi, %o2 + jmpl %g1 + %lo(sys_connect), %g0 + lduwa [%o1 + 0x4] %asi, %o1 + nop + nop + nop +do_sys_listen: /* sys_listen(int, int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_listen), %g1 + jmpl %g1 + %lo(sys_listen), %g0 + ldswa [%o1 + 0x4] %asi, %o1 + nop + nop + nop + nop +do_sys_accept: /* sys_accept(int, struct sockaddr *, int *) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_accept), %g1 + lduwa [%o1 + 0x8] %asi, %o2 + jmpl %g1 + %lo(sys_accept), %g0 + lduwa [%o1 + 0x4] %asi, %o1 + nop + nop + nop +do_sys_getsockname: /* sys_getsockname(int, struct sockaddr *, int *) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_getsockname), %g1 + lduwa [%o1 + 0x8] %asi, %o2 + jmpl %g1 + %lo(sys_getsockname), %g0 + lduwa [%o1 + 0x4] %asi, %o1 + nop + nop + nop +do_sys_getpeername: /* sys_getpeername(int, struct sockaddr *, int *) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_getpeername), %g1 + lduwa [%o1 + 0x8] %asi, %o2 + jmpl %g1 + %lo(sys_getpeername), %g0 + lduwa [%o1 + 0x4] %asi, %o1 + nop + nop + nop +do_sys_socketpair: /* sys_socketpair(int, int, int, int *) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_socketpair), %g1 + ldswa [%o1 + 0x8] %asi, %o2 + lduwa [%o1 + 0xc] %asi, %o3 + jmpl %g1 + %lo(sys_socketpair), %g0 + ldswa [%o1 + 0x4] %asi, %o1 + nop + nop +do_sys_send: /* sys_send(int, void *, size_t, unsigned int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_send), %g1 + lduwa [%o1 + 0x8] %asi, %o2 + lduwa [%o1 + 0xc] %asi, %o3 + jmpl %g1 + %lo(sys_send), %g0 + lduwa [%o1 + 0x4] %asi, %o1 + nop + nop +do_sys_recv: /* sys_recv(int, void *, size_t, unsigned int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_recv), %g1 + lduwa [%o1 + 0x8] %asi, %o2 + lduwa [%o1 + 0xc] %asi, %o3 + jmpl %g1 + %lo(sys_recv), %g0 + lduwa [%o1 + 0x4] %asi, %o1 + nop + nop +do_sys_sendto: /* sys32_sendto(int, u32, __kernel_size_t32, unsigned int, u32, int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys32_sendto), %g1 + lduwa [%o1 + 0x8] %asi, %o2 + lduwa [%o1 + 0xc] %asi, %o3 + lduwa [%o1 + 0x10] %asi, %o4 + ldswa [%o1 + 0x14] %asi, %o5 + jmpl %g1 + %lo(sys32_sendto), %g0 + lduwa [%o1 + 0x4] %asi, %o1 +do_sys_recvfrom: /* sys32_recvfrom(int, u32, __kernel_size_t32, unsigned int, u32, u32) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys32_recvfrom), %g1 + lduwa [%o1 + 0x8] %asi, %o2 + lduwa [%o1 + 0xc] %asi, %o3 + lduwa [%o1 + 0x10] %asi, %o4 + lduwa [%o1 + 0x14] %asi, %o5 + jmpl %g1 + %lo(sys32_recvfrom), %g0 + lduwa [%o1 + 0x4] %asi, %o1 +do_sys_shutdown: /* sys_shutdown(int, int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys_shutdown), %g1 + jmpl %g1 + %lo(sys_shutdown), %g0 + ldswa [%o1 + 0x4] %asi, %o1 + nop + nop + nop + nop +do_sys_setsockopt: /* sys32_setsockopt(int, int, int, char *, int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys32_setsockopt), %g1 + ldswa [%o1 + 0x8] %asi, %o2 + lduwa [%o1 + 0xc] %asi, %o3 + ldswa [%o1 + 0x10] %asi, %o4 + jmpl %g1 + %lo(sys32_setsockopt), %g0 + ldswa [%o1 + 0x4] %asi, %o1 + nop +do_sys_getsockopt: /* sys32_getsockopt(int, int, int, u32, u32) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys32_getsockopt), %g1 + ldswa [%o1 + 0x8] %asi, %o2 + lduwa [%o1 + 0xc] %asi, %o3 + lduwa [%o1 + 0x10] %asi, %o4 + jmpl %g1 + %lo(sys32_getsockopt), %g0 + ldswa [%o1 + 0x4] %asi, %o1 + nop +do_sys_sendmsg: /* sys32_sendmsg(int, struct msghdr32 *, unsigned int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys32_sendmsg), %g1 + lduwa [%o1 + 0x8] %asi, %o2 + jmpl %g1 + %lo(sys32_sendmsg), %g0 + lduwa [%o1 + 0x4] %asi, %o1 + nop + nop + nop +do_sys_recvmsg: /* sys32_recvmsg(int, struct msghdr32 *, unsigned int) */ + ldswa [%o1 + 0x0] %asi, %o0 + sethi %hi(sys32_recvmsg), %g1 + lduwa [%o1 + 0x8] %asi, %o2 + jmpl %g1 + %lo(sys32_recvmsg), %g0 + lduwa [%o1 + 0x4] %asi, %o1 + nop + nop + nop +__socketcall_table_end: + +do_einval: + retl + mov -EINVAL, %o0 +do_efault: + retl + mov -EFAULT, %o0 + + .section __ex_table + .align 4 + .word __socketcall_table_begin, 0, __socketcall_table_end, do_efault + .previous diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index d752f1a0d..b1eb160ad 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.141 2000/03/24 01:31:30 davem Exp $ +/* $Id: sys_sparc32.c,v 1.142 2000/03/24 04:17:38 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -1746,8 +1746,8 @@ static int copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel) return 0; } -extern long do_sys_mount(char * dev_name, char * dir_name, unsigned long type_page, - unsigned long new_flags, unsigned long data_page); +extern long do_sys_mount(char * dev_page, char * dir_page, char * type_page, + unsigned long new_flags, char * data_page); #define SMBFS_NAME "smbfs" #define NCPFS_NAME "ncpfs" @@ -1756,6 +1756,8 @@ asmlinkage int sys32_mount(char *dev_name, char *dir_name, char *type, unsigned { unsigned long type_page = 0; unsigned long data_page = 0; + unsigned long dev_page = 0; + unsigned long dir_page = 0; int err, is_smb, is_ncp; is_smb = is_ncp = 0; @@ -1777,19 +1779,32 @@ asmlinkage int sys32_mount(char *dev_name, char *dir_name, char *type, unsigned if (err) goto type_out; + err = copy_mount_stuff_to_kernel(dev_name, &dev_page); + if (err) + goto data_out; + + err = copy_mount_stuff_to_kernel(dir_name, &dir_page); + if (err) + goto dev_out; + if (!is_smb && !is_ncp) { - err = do_sys_mount(dev_name, dir_name, type_page, new_flags, - data_page); + err = do_sys_mount((char*)dev_page, (char*)dir_page, + (char*)type_page, new_flags, (char*)data_page); } else { if (is_ncp) do_ncp_super_data_conv((void *)data_page); else do_smb_super_data_conv((void *)data_page); - err = do_sys_mount(dev_name, dir_name, type_page, new_flags, - data_page); + err = do_sys_mount((char*)dev_page, (char*)dir_page, + (char*)type_page, new_flags, (char*)data_page); } + free_page(dir_page); + +dev_out: + free_page(dev_page); +data_out: free_page(data_page); type_out: @@ -2790,85 +2805,6 @@ asmlinkage int sys32_setsockopt(int fd, int level, int optname, return sys_setsockopt(fd, level, optname, optval, optlen); } -/* Argument list sizes for sys_socketcall */ -#define AL(x) ((x) * sizeof(u32)) -static unsigned char nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), - AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), - AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)}; -#undef AL - -extern asmlinkage int sys_bind(int fd, struct sockaddr *umyaddr, int addrlen); -extern asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen); -extern asmlinkage int sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen); -extern asmlinkage int sys_getsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len); -extern asmlinkage int sys_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len); -extern asmlinkage int sys_send(int fd, void *buff, size_t len, unsigned flags); -extern asmlinkage int sys32_sendto(int fd, u32 buff, __kernel_size_t32 len, - unsigned flags, u32 addr, int addr_len); -extern asmlinkage int sys_recv(int fd, void *ubuf, size_t size, unsigned flags); -extern asmlinkage int sys32_recvfrom(int fd, u32 ubuf, __kernel_size_t32 size, - unsigned flags, u32 addr, u32 addr_len); -extern asmlinkage int sys32_getsockopt(int fd, int level, int optname, - u32 optval, u32 optlen); - -extern asmlinkage int sys_socket(int family, int type, int protocol); -extern asmlinkage int sys_socketpair(int family, int type, int protocol, - int usockvec[2]); -extern asmlinkage int sys_shutdown(int fd, int how); -extern asmlinkage int sys_listen(int fd, int backlog); - -asmlinkage int sys32_socketcall(int call, u32 *args) -{ - u32 a[6]; - u32 a0,a1; - - if (call<SYS_SOCKET||call>SYS_RECVMSG) - return -EINVAL; - if (copy_from_user(a, args, nargs[call])) - return -EFAULT; - a0=a[0]; - a1=a[1]; - - switch(call) - { - case SYS_SOCKET: - return sys_socket(a0, a1, a[2]); - case SYS_BIND: - return sys_bind(a0, (struct sockaddr *)A(a1), a[2]); - case SYS_CONNECT: - return sys_connect(a0, (struct sockaddr *)A(a1), a[2]); - case SYS_LISTEN: - return sys_listen(a0, a1); - case SYS_ACCEPT: - return sys_accept(a0, (struct sockaddr *)A(a1), (int *)A(a[2])); - case SYS_GETSOCKNAME: - return sys_getsockname(a0, (struct sockaddr *)A(a1), (int *)A(a[2])); - case SYS_GETPEERNAME: - return sys_getpeername(a0, (struct sockaddr *)A(a1), (int *)A(a[2])); - case SYS_SOCKETPAIR: - return sys_socketpair(a0, a1, a[2], (int *)A(a[3])); - case SYS_SEND: - return sys_send(a0, (void *)A(a1), a[2], a[3]); - case SYS_SENDTO: - return sys32_sendto(a0, a1, a[2], a[3], a[4], a[5]); - case SYS_RECV: - return sys_recv(a0, (void *)A(a1), a[2], a[3]); - case SYS_RECVFROM: - return sys32_recvfrom(a0, a1, a[2], a[3], a[4], a[5]); - case SYS_SHUTDOWN: - return sys_shutdown(a0,a1); - case SYS_SETSOCKOPT: - return sys32_setsockopt(a0, a1, a[2], (char *)A(a[3]), a[4]); - case SYS_GETSOCKOPT: - return sys32_getsockopt(a0, a1, a[2], a[3], a[4]); - case SYS_SENDMSG: - return sys32_sendmsg(a0, (struct msghdr32 *)A(a1), a[2]); - case SYS_RECVMSG: - return sys32_recvmsg(a0, (struct msghdr32 *)A(a1), a[2]); - } - return -EINVAL; -} - extern void check_pending(int signum); asmlinkage int sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact) @@ -4144,7 +4080,7 @@ asmlinkage long sparc32_open(const char * filename, int flags, int mode) if (fd >= 0) { struct file * f; lock_kernel(); - f = filp_open(tmp, flags, mode, NULL); + f = filp_open(tmp, flags, mode); unlock_kernel(); error = PTR_ERR(f); if (IS_ERR(f)) diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c index a572e4976..291b174ac 100644 --- a/arch/sparc64/kernel/sys_sunos32.c +++ b/arch/sparc64/kernel/sys_sunos32.c @@ -1,4 +1,4 @@ -/* $Id: sys_sunos32.c,v 1.42 2000/03/15 02:43:35 davem Exp $ +/* $Id: sys_sunos32.c,v 1.43 2000/03/26 11:28:53 davem Exp $ * sys_sunos32.c: SunOS binary compatability layer on sparc64. * * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -79,19 +79,17 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 of } retval = -EBADF; if(!(flags & MAP_ANONYMOUS)) { + struct inode * inode; if(fd >= SUNOS_NR_OPEN) goto out; file = fget(fd); if (!file) goto out; - if (file->f_dentry && file->f_dentry->d_inode) { - struct inode * inode = file->f_dentry->d_inode; - if(MAJOR(inode->i_rdev) == MEM_MAJOR && - MINOR(inode->i_rdev) == 5) { - flags |= MAP_ANONYMOUS; - fput(file); - file = NULL; - } + inode = file->f_dentry->d_inode; + if(MAJOR(inode->i_rdev)==MEM_MAJOR && MINOR(inode->i_rdev)==5) { + flags |= MAP_ANONYMOUS; + fput(file); + file = NULL; } } @@ -601,7 +599,7 @@ struct sunos_nfs_mount_args { char *netname; /* server's netname */ }; -extern int do_mount(struct block_device *, const char *, const char *, char *, int, void *); +extern long do_sys_mount(const char *, const char *, char *, int, void *); extern dev_t get_unnamed_dev(void); extern void put_unnamed_dev(dev_t); extern asmlinkage int sys_mount(char *, char *, char *, unsigned long, void *); @@ -627,17 +625,12 @@ sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr) struct inode *inode; struct file *file; - file = fcheck(fd); + file = fget(fd); if(!file) return 0; dentry = file->f_dentry; - if(!dentry) - return 0; - inode = dentry->d_inode; - if(!inode) - return 0; socket = &inode->u.socket_i; local.sin_family = AF_INET; @@ -651,8 +644,10 @@ sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr) sizeof(local)); } while (ret && try_port > (1024 / 2)); - if (ret) + if (ret) { + fput(file); return 0; + } server.sin_family = AF_INET; server.sin_addr = addr->sin_addr; @@ -661,6 +656,7 @@ sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr) /* Call sys_connect */ ret = socket->ops->connect (socket, (struct sockaddr *) &server, sizeof (server), file->f_flags); + fput(file); if (ret < 0) return 0; return 1; @@ -676,12 +672,12 @@ static int get_default (int value, int def_value) } /* XXXXXXXXXXXXXXXXXXXX */ -asmlinkage int sunos_nfs_mount(char *dir_name, int linux_flags, void *data) +static int sunos_nfs_mount(char *dir_name, int linux_flags, void *data) { int server_fd; char *the_name; struct nfs_mount_data linux_nfs_mount; - struct sunos_nfs_mount_args *sunos_mount = data; + struct sunos_nfs_mount_args sunos_mount; /* Ok, here comes the fun part: Linux's nfs mount needs a * socket connection to the server, but SunOS mount does not @@ -689,41 +685,50 @@ asmlinkage int sunos_nfs_mount(char *dir_name, int linux_flags, void *data) * address to create a socket and bind it to a reserved * port on this system */ + if (copy_from_user(&sunos_mount, data, sizeof(sunos_mount)) + return -EFAULT; + server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (server_fd < 0) return -ENXIO; - if (!sunos_nfs_get_server_fd (server_fd, sunos_mount->addr)){ + if (copy_from_user(&linux_nfs_mount.addr,sunos_mount.addr, + sizeof(*sunos_mount.addr)) || + copy_from_user(&linux_nfs_mount.root,sunos_mount.fh, + sizeof(*sunos_mount.fh))) { + sys_close (server_fd); + return -EFAULT; + } + + if (!sunos_nfs_get_server_fd (server_fd, &linux_nfs_mount.addr)){ sys_close (server_fd); return -ENXIO; } /* Now, bind it to a locally reserved port */ linux_nfs_mount.version = NFS_MOUNT_VERSION; - linux_nfs_mount.flags = sunos_mount->flags; - linux_nfs_mount.addr = *sunos_mount->addr; - linux_nfs_mount.root = *sunos_mount->fh; + linux_nfs_mount.flags = sunos_mount.flags; linux_nfs_mount.fd = server_fd; - linux_nfs_mount.rsize = get_default (sunos_mount->rsize, 8192); - linux_nfs_mount.wsize = get_default (sunos_mount->wsize, 8192); - linux_nfs_mount.timeo = get_default (sunos_mount->timeo, 10); - linux_nfs_mount.retrans = sunos_mount->retrans; + linux_nfs_mount.rsize = get_default (sunos_mount.rsize, 8192); + linux_nfs_mount.wsize = get_default (sunos_mount.wsize, 8192); + linux_nfs_mount.timeo = get_default (sunos_mount.timeo, 10); + linux_nfs_mount.retrans = sunos_mount.retrans; - linux_nfs_mount.acregmin = sunos_mount->acregmin; - linux_nfs_mount.acregmax = sunos_mount->acregmax; - linux_nfs_mount.acdirmin = sunos_mount->acdirmin; - linux_nfs_mount.acdirmax = sunos_mount->acdirmax; + linux_nfs_mount.acregmin = sunos_mount.acregmin; + linux_nfs_mount.acregmax = sunos_mount.acregmax; + linux_nfs_mount.acdirmin = sunos_mount.acdirmin; + linux_nfs_mount.acdirmax = sunos_mount.acdirmax; - the_name = getname(sunos_mount->hostname); + the_name = getname(sunos_mount.hostname); if(IS_ERR(the_name)) - return -EFAULT; + return PTR_ERR(the_name); strncpy (linux_nfs_mount.hostname, the_name, 254); linux_nfs_mount.hostname [255] = 0; putname (the_name); - - return do_mount (NULL, "", dir_name, "nfs", linux_flags, &linux_nfs_mount); + + return do_sys_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount); } /* XXXXXXXXXXXXXXXXXXXX */ @@ -733,6 +738,7 @@ sunos_mount(char *type, char *dir, int flags, void *data) int linux_flags = MS_MGC_MSK; /* new semantics */ int ret = -EINVAL; char *dev_fname = 0; + char *dir_page, *type_page; if (!capable (CAP_SYS_ADMIN)) return -EPERM; @@ -751,24 +757,44 @@ sunos_mount(char *type, char *dir, int flags, void *data) linux_flags |= MS_RDONLY; if(flags & SMNT_NOSUID) linux_flags |= MS_NOSUID; - if(strcmp(type, "ext2") == 0) { - dev_fname = (char *) data; - } else if(strcmp(type, "iso9660") == 0) { - dev_fname = (char *) data; - } else if(strcmp(type, "minix") == 0) { - dev_fname = (char *) data; - } else if(strcmp(type, "nfs") == 0) { - ret = sunos_nfs_mount (dir, flags, data); + + dir_page = getname(dir); + ret = PTR_ERR(dir_page); + if (IS_ERR(dir_page)) goto out; - } else if(strcmp(type, "ufs") == 0) { + + type_page = getname(type); + ret = PTR_ERR(type_page); + if (IS_ERR(type_page)) + goto out1; + + if(strcmp(type_page, "ext2") == 0) { + dev_fname = getname(data); + } else if(strcmp(type_page, "iso9660") == 0) { + dev_fname = getname(data); + } else if(strcmp(type_page, "minix") == 0) { + dev_fname = getname(data); + } else if(strcmp(type_page, "nfs") == 0) { + ret = sunos_nfs_mount (dir_page, flags, data); + goto out2 + } else if(strcmp(type_page, "ufs") == 0) { printk("Warning: UFS filesystem mounts unsupported.\n"); ret = -ENODEV; - goto out; - } else if(strcmp(type, "proc")) { + goto out2 + } else if(strcmp(type_page, "proc")) { ret = -ENODEV; - goto out; + goto out2 } - ret = sys_mount(dev_fname, dir, type, linux_flags, NULL); + ret = PTR_ERR(dev_fname); + if (IS_ERR(dev_fname)) + goto out2; + ret = do_sys_mount(dev_fname, dir_page, type_page, linux_flags, NULL); + if (dev_fname) + putname(dev_fname); +out2: + putname(type_page); +out1: + putname(dir_page); out: unlock_kernel(); return ret; diff --git a/arch/sparc64/kernel/winfixup.S b/arch/sparc64/kernel/winfixup.S index 67653fef1..d733de2c1 100644 --- a/arch/sparc64/kernel/winfixup.S +++ b/arch/sparc64/kernel/winfixup.S @@ -1,4 +1,4 @@ -/* $Id: winfixup.S,v 1.28 1999/07/30 09:35:34 davem Exp $ +/* $Id: winfixup.S,v 1.29 2000/03/26 09:13:48 davem Exp $ * * winfixup.S: Handle cases where user stack pointer is found to be bogus. * @@ -31,7 +31,7 @@ fill_fixup: rdpr %tstate, %g1 andcc %g1, TSTATE_PRIV, %g0 - clr %g4 + or %g4, FAULT_CODE_WINFIXUP, %g4 be,pt %xcc, window_scheisse_from_user_common and %g1, TSTATE_CWP, %g1 @@ -69,21 +69,20 @@ fill_fixup: mov %g6, %o7 ! Get current. andn %l1, PSTATE_MM, %l1 ! We want to be in RMO - srlx %g5, PAGE_SHIFT, %o1 ! Fault address + stb %g4, [%g6 + AOFF_task_thread + AOFF_thread_fault_code] + stx %g5, [%g6 + AOFF_task_thread + AOFF_thread_fault_address] wrpr %g0, 0x0, %tl ! Out of trap levels. wrpr %l1, (PSTATE_IE | PSTATE_AG | PSTATE_RMO), %pstate sethi %uhi(PAGE_OFFSET), %g4 ! Prepare page_offset global reg mov %o7, %g6 sllx %g4, 32, %g4 ! and finish it... - clr %o2 /* This is the same as below, except we handle this a bit special * since we must preserve %l5 and %l6, see comment above. */ - sllx %o1, PAGE_SHIFT, %o1 call do_sparc64_fault add %sp, STACK_BIAS + REGWIN_SZ, %o0 - b,pt %xcc, rtrap + ba,pt %xcc, rtrap nop ! yes, nop is correct /* Be very careful about usage of the alternate globals here. @@ -149,22 +148,19 @@ spill_fixup: andcc %g1, TSTATE_PRIV, %g0 saved and %g1, TSTATE_CWP, %g1 - be,a,pn %xcc, window_scheisse_from_user_common - or %g4, 0x4, %g4 ! we know it was a write + be,pn %xcc, window_scheisse_from_user_common + mov FAULT_CODE_WRITE | FAULT_CODE_DTLB | FAULT_CODE_WINFIXUP, %g4 retry + window_scheisse_from_user_common: + stb %g4, [%g6 + AOFF_task_thread + AOFF_thread_fault_code] + stx %g5, [%g6 + AOFF_task_thread + AOFF_thread_fault_address] wrpr %g1, %cwp - sethi %hi(109f), %g7 ba,pt %xcc, etrap -109: or %g7, %lo(109b), %g7 - srlx %l5, PAGE_SHIFT, %o1 - - and %l4, 0x4, %o2 - sllx %o1, PAGE_SHIFT, %o1 + rd %pc, %g7 call do_sparc64_fault add %sp, STACK_BIAS + REGWIN_SZ, %o0 - ba,pt %xcc, rtrap - clr %l6 + ba,a,pt %xcc, rtrap_clr_l6 .globl winfix_mna, fill_fixup_mna, spill_fixup_mna winfix_mna: |