summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-04-19 04:00:00 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-04-19 04:00:00 +0000
commit46e045034336a2cc90c1798cd7cc07af744ddfd6 (patch)
tree3b9b51fc482e729f663d25333e77fbed9aaa939a /arch/sparc64/kernel
parent31dc59d503a02e84c4de98826452acaeb56dc15a (diff)
Merge with Linux 2.3.99-pre4.
Diffstat (limited to 'arch/sparc64/kernel')
-rw-r--r--arch/sparc64/kernel/Makefile12
-rw-r--r--arch/sparc64/kernel/dtlb_base.S24
-rw-r--r--arch/sparc64/kernel/dtlb_prot.S8
-rw-r--r--arch/sparc64/kernel/ebus.c14
-rw-r--r--arch/sparc64/kernel/entry.S39
-rw-r--r--arch/sparc64/kernel/etrap.S309
-rw-r--r--arch/sparc64/kernel/ioctl32.c21
-rw-r--r--arch/sparc64/kernel/itlb_base.S26
-rw-r--r--arch/sparc64/kernel/pci_common.c161
-rw-r--r--arch/sparc64/kernel/pci_impl.h6
-rw-r--r--arch/sparc64/kernel/pci_psycho.c25
-rw-r--r--arch/sparc64/kernel/pci_sabre.c22
-rw-r--r--arch/sparc64/kernel/process.c57
-rw-r--r--arch/sparc64/kernel/rtrap.S253
-rw-r--r--arch/sparc64/kernel/semaphore.c10
-rw-r--r--arch/sparc64/kernel/signal.c4
-rw-r--r--arch/sparc64/kernel/signal32.c4
-rw-r--r--arch/sparc64/kernel/smp.c96
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c9
-rw-r--r--arch/sparc64/kernel/sys32.S188
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c110
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c122
-rw-r--r--arch/sparc64/kernel/winfixup.S28
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, &ltimer);
+ 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: