summaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/Makefile6
-rw-r--r--arch/sparc/ap1000/aplib.c2
-rw-r--r--arch/sparc/ap1000/mpp.c2
-rw-r--r--arch/sparc/ap1000/msc.c2
-rw-r--r--arch/sparc/ap1000/timer.c7
-rw-r--r--arch/sparc/ap1000/tnet.c2
-rw-r--r--arch/sparc/ap1000/util.c4
-rw-r--r--arch/sparc/config.in17
-rw-r--r--arch/sparc/defconfig55
-rw-r--r--arch/sparc/kernel/Makefile27
-rw-r--r--arch/sparc/kernel/entry.S20
-rw-r--r--arch/sparc/kernel/head.S12
-rw-r--r--arch/sparc/kernel/idprom.c10
-rw-r--r--arch/sparc/kernel/irq.c5
-rw-r--r--arch/sparc/kernel/process.c43
-rw-r--r--arch/sparc/kernel/rtrap.S6
-rw-r--r--arch/sparc/kernel/setup.c32
-rw-r--r--arch/sparc/kernel/signal.c224
-rw-r--r--arch/sparc/kernel/smp.c6
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c3
-rw-r--r--arch/sparc/kernel/sun4c_irq.c25
-rw-r--r--arch/sparc/kernel/sun4d_irq.c60
-rw-r--r--arch/sparc/kernel/sun4d_smp.c10
-rw-r--r--arch/sparc/kernel/sun4m_irq.c8
-rw-r--r--arch/sparc/kernel/sun4m_smp.c11
-rw-r--r--arch/sparc/kernel/sun4setup.c74
-rw-r--r--arch/sparc/kernel/sys_sparc.c34
-rw-r--r--arch/sparc/kernel/sys_sunos.c27
-rw-r--r--arch/sparc/kernel/systbls.S19
-rw-r--r--arch/sparc/kernel/time.c159
-rw-r--r--arch/sparc/lib/Makefile17
-rw-r--r--arch/sparc/lib/locks.S74
-rw-r--r--arch/sparc/math-emu/fnegs.c1
-rw-r--r--arch/sparc/mm/Makefile20
-rw-r--r--arch/sparc/mm/fault.c4
-rw-r--r--arch/sparc/mm/io-unit.c15
-rw-r--r--arch/sparc/mm/iommu.c85
-rw-r--r--arch/sparc/mm/srmmu.c40
-rw-r--r--arch/sparc/mm/sun4c.c31
-rw-r--r--arch/sparc/prom/misc.c13
40 files changed, 720 insertions, 492 deletions
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index a4870e117..fa171a7f7 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.34 1998/04/06 16:09:34 jj Exp $
+# $Id: Makefile,v 1.36 1998/06/02 00:36:40 davem Exp $
# sparc/Makefile
#
# Makefile for the architecture dependent flags and dependencies on the
@@ -16,7 +16,7 @@ SHELL =/bin/bash
# debugging of the kernel to get the proper debugging information.
#CFLAGS := $(CFLAGS) -g -pipe -fcall-used-g5 -fcall-used-g7
-CFLAGS := $(CFLAGS) -pipe -fcall-used-g5 -fcall-used-g7
+CFLAGS := $(CFLAGS) -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
#LINKFLAGS = -N -Ttext 0xf0004000
LINKFLAGS = -T arch/sparc/vmlinux.lds
@@ -45,6 +45,8 @@ endif
archclean:
-$(MAKE) -C arch/sparc/boot archclean
+
+archmrproper:
-$(MAKE) -C arch/sparc/math-emu cleansymlinks
archdep:
diff --git a/arch/sparc/ap1000/aplib.c b/arch/sparc/ap1000/aplib.c
index 173191492..2c36a5ae1 100644
--- a/arch/sparc/ap1000/aplib.c
+++ b/arch/sparc/ap1000/aplib.c
@@ -455,7 +455,7 @@ static inline int aplib_poll(unsigned counter)
while (counter == aplib->rbuf_flag1 + aplib->rbuf_flag2) {
tnet_check_completion();
- if (need_resched)
+ if (current->need_resched)
break;
if (signal_pending(current)) break;
}
diff --git a/arch/sparc/ap1000/mpp.c b/arch/sparc/ap1000/mpp.c
index 84ef7f28e..1e6596a07 100644
--- a/arch/sparc/ap1000/mpp.c
+++ b/arch/sparc/ap1000/mpp.c
@@ -28,7 +28,7 @@ static int last_task = 0;
void mpp_schedule(struct cap_request *req)
{
mpp_current_task = req->data[0];
- need_resched = 1;
+ current->need_resched = 1;
mark_bh(TQUEUE_BH);
}
diff --git a/arch/sparc/ap1000/msc.c b/arch/sparc/ap1000/msc.c
index 92c1f2eeb..01337a53a 100644
--- a/arch/sparc/ap1000/msc.c
+++ b/arch/sparc/ap1000/msc.c
@@ -337,7 +337,7 @@ static inline void qbmful_interrupt(void)
#endif
MSC_OUT(MSC_INTR, AP_SET_INTR_MASK << MSC_INTR_QBMFUL_SH);
intr_mask |= (AP_INTR_REQ << MSC_INTR_QBMFUL_SH);
- need_resched = 1;
+ current->need_resched = 1;
block_parallel_tasks = 1;
mark_bh(TQUEUE_BH);
}
diff --git a/arch/sparc/ap1000/timer.c b/arch/sparc/ap1000/timer.c
index 129b4e6d5..567d24067 100644
--- a/arch/sparc/ap1000/timer.c
+++ b/arch/sparc/ap1000/timer.c
@@ -7,7 +7,6 @@
*/
/* routines to control the AP1000 timer chip */
-#include <linux/config.h> /* for CONFIG_PROFILE */
#include <linux/time.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
@@ -74,8 +73,6 @@ void ap_gettimeofday(struct timeval *xt)
last_freerun = new_freerun;
}
-#ifdef CONFIG_PROFILE
-
static void profile_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
if (prof_buffer && current->pid) {
@@ -98,8 +95,6 @@ void ap_profile_init(void)
}
}
-#endif
-
void ap_init_timers(void)
{
extern void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs);
@@ -114,12 +109,10 @@ void ap_init_timers(void)
(SA_INTERRUPT | SA_STATIC_ALLOC),
"timer", NULL);
-#ifdef CONFIG_PROFILE
request_irq(APTIM0_IRQ,
profile_interrupt,
(SA_INTERRUPT | SA_STATIC_ALLOC),
"profile", NULL);
-#endif
ap_clear_clock_irq();
diff --git a/arch/sparc/ap1000/tnet.c b/arch/sparc/ap1000/tnet.c
index 3d30a56a9..777f169f8 100644
--- a/arch/sparc/ap1000/tnet.c
+++ b/arch/sparc/ap1000/tnet.c
@@ -612,7 +612,7 @@ void tnet_send_ip(int cid,struct sk_buff *skb)
static void reschedule(void)
{
- need_resched = 1;
+ current->need_resched = 1;
mark_bh(TQUEUE_BH);
}
diff --git a/arch/sparc/ap1000/util.c b/arch/sparc/ap1000/util.c
index 5185fdea9..abb51426e 100644
--- a/arch/sparc/ap1000/util.c
+++ b/arch/sparc/ap1000/util.c
@@ -42,8 +42,8 @@ int ap_verify_data(char *d,int len)
return res;
}
-/* How many bogo mips in the entire machine
-Dont worry about float because when it gets this big, its irrelevant */
+/* How many BogoMIPS in the entire machine
+Don't worry about float because when it gets this big, it's irrelevant */
int mpp_agg_bogomips(void)
{
return mpp_num_cells()*loops_per_sec/500000; /* cheat in working it out */
diff --git a/arch/sparc/config.in b/arch/sparc/config.in
index 3f0ab09b6..e3aaea31c 100644
--- a/arch/sparc/config.in
+++ b/arch/sparc/config.in
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.54 1998/03/27 06:59:39 davem Exp $
+# $Id: config.in,v 1.58 1998/07/29 05:06:41 davem Exp $
# For a description of the syntax of this configuration file,
# see the Configure script.
#
@@ -36,6 +36,13 @@ if [ "$CONFIG_AP1000" = "y" ]; then
else
bool 'Support for SUN4 machines (disables SUN4[CDM] support)' CONFIG_SUN4
+ mainmenu_option next_comment
+ comment 'Console drivers'
+ bool 'PROM console' CONFIG_PROM_CONSOLE
+ bool 'Support Frame buffer devices' CONFIG_FB
+ source drivers/video/Config.in
+ endmenu
+
# Global things across all Sun machines.
define_bool CONFIG_SBUS y
define_bool CONFIG_SBUSCHAR y
@@ -48,8 +55,7 @@ else
define_bool CONFIG_SUN_AUXIO y
define_bool CONFIG_SUN_IO y
if [ "$CONFIG_SUN4" = "y" ]; then
- bool 'Sun FB drivers appear in PROCFS' SUN_FBS_IN_PROCFS
- bool 'bwtwo support' SUN_FB_BWTWO
+ bool 'Force early PROM Console' CONFIG_SUN4_FORCECONSOLE
else
source drivers/sbus/char/Config.in
source drivers/sbus/audio/Config.in
@@ -179,9 +185,6 @@ endmenu
mainmenu_option next_comment
comment 'Kernel hacking'
-bool 'Kernel profiling support' CONFIG_PROFILE
-if [ "$CONFIG_PROFILE" = "y" ]; then
- int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
-fi
bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
endmenu
+
diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig
index 1abeca2d6..52801ae68 100644
--- a/arch/sparc/defconfig
+++ b/arch/sparc/defconfig
@@ -21,6 +21,27 @@ CONFIG_VT=y
CONFIG_VT_CONSOLE=y
# CONFIG_AP1000 is not set
# CONFIG_SUN4 is not set
+
+#
+# Console drivers
+#
+CONFIG_PROM_CONSOLE=y
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FB_SBUS=y
+CONFIG_FB_CGSIX=y
+CONFIG_FB_BWTWO=y
+CONFIG_FB_CGTHREE=y
+CONFIG_FB_TCX=y
+CONFIG_FB_CGFOURTEEN=y
+CONFIG_FB_LEO=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_MFB=y
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_FONTWIDTH8_ONLY=y
+CONFIG_FONT_SUN8x16=y
+# CONFIG_FBCON_FONTS is not set
CONFIG_SBUS=y
CONFIG_SBUSCHAR=y
CONFIG_SUN_MOUSE=y
@@ -33,20 +54,6 @@ CONFIG_SUN_AUXIO=y
CONFIG_SUN_IO=y
#
-# SBUS Frame Buffer support
-#
-SUN_FBS_IN_PROCFS=y
-CONFIG_SUN_FB_DISPLAY=y
-SUN_FB_CGSIX=y
-SUN_FB_TCX=y
-SUN_FB_CGTHREE=y
-SUN_FB_CGFOURTEEN=y
-SUN_FB_BWTWO=y
-SUN_FB_LEO=y
-TADPOLE_FB_WEITEK=y
-SUN_FB_CREATOR=y
-
-#
# Misc Linux/SPARC drivers
#
CONFIG_SUN_OPENPROMIO=m
@@ -101,10 +108,8 @@ CONFIG_IP_MULTICAST=y
# CONFIG_IP_PNP is not set
CONFIG_IP_FIREWALL=y
# CONFIG_IP_FIREWALL_NETLINK is not set
-# CONFIG_IP_FIREWALL_VERBOSE is not set
# CONFIG_IP_TRANSPARENT_PROXY is not set
# CONFIG_IP_ALWAYS_DEFRAG is not set
-# CONFIG_IP_ACCT is not set
CONFIG_IP_MASQUERADE=y
#
@@ -138,29 +143,30 @@ CONFIG_IPV6=m
#
#
CONFIG_IPX=m
-
-#
-# IPX options
-#
# CONFIG_IPX_INTERN is not set
+# CONFIG_SPX is not set
CONFIG_ATALK=m
CONFIG_X25=m
# CONFIG_LAPB is not set
# CONFIG_BRIDGE is not set
# CONFIG_LLC is not set
+# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_NET_FASTROUTE is not set
# CONFIG_NET_HW_FLOWCONTROL is not set
# CONFIG_CPU_IS_SLOW is not set
CONFIG_NET_SCHED=y
+CONFIG_NETLINK=y
+CONFIG_RTNETLINK=y
CONFIG_NET_SCH_CBQ=m
CONFIG_NET_SCH_CSZ=m
+CONFIG_NET_SCH_PRIO=y
CONFIG_NET_SCH_RED=m
CONFIG_NET_SCH_SFQ=m
+# CONFIG_NET_SCH_TEQL is not set
CONFIG_NET_SCH_TBF=y
-CONFIG_NET_SCH_PFIFO=y
-CONFIG_NET_SCH_PRIO=y
-# CONFIG_NET_PROFILE is not set
+# CONFIG_NET_QOS is not set
+# CONFIG_NET_CLS is not set
#
# ISDN subsystem
@@ -226,7 +232,6 @@ CONFIG_SUNLANCE=y
CONFIG_HAPPYMEAL=m
CONFIG_SUNQE=m
CONFIG_MYRI_SBUS=m
-CONFIG_CDROM=y
#
# Filesystems
@@ -268,6 +273,7 @@ CONFIG_BSD_DISKLABEL=y
CONFIG_SMD_DISKLABEL=y
# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_ADFS_FS is not set
+CONFIG_DEVPTS_FS=y
# CONFIG_MAC_PARTITION is not set
CONFIG_NLS=y
@@ -309,5 +315,4 @@ CONFIG_NLS=y
#
# Kernel hacking
#
-# CONFIG_PROFILE is not set
# CONFIG_MAGIC_SYSRQ is not set
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 53ed6d340..9606064b3 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.43 1998/03/09 14:03:34 jj Exp $
+# $Id: Makefile,v 1.45 1998/07/28 16:52:42 jj Exp $
# Makefile for the linux kernel.
#
# Note! Dependencies are done automagically by 'make dep', which also
@@ -7,24 +7,12 @@
#
# Note 2! The CFLAGS definitions are now in the main makefile...
-ifdef SMP
-
.S.s:
$(CPP) -D__ASSEMBLY__ $(AFLAGS) -ansi $< -o $*.s
.S.o:
$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $< -o $*.o
-else
-
-.S.s:
- $(CPP) -D__ASSEMBLY__ -ansi $< -o $*.s
-
-.S.o:
- $(CC) -D__ASSEMBLY__ -ansi -c $< -o $*.o
-
-endif
-
all: kernel.o head.o init_task.o
O_TARGET := kernel.o
@@ -38,6 +26,10 @@ O_OBJS := entry.o wof.o wuf.o etrap.o rtrap.o traps.o ${IRQ_OBJS} \
OX_OBJS := sparc_ksyms.o
+ifdef CONFIG_SUN4
+O_OBJS += sun4setup.o
+endif
+
ifdef SMP
O_OBJS += trampoline.o smp.o sun4m_smp.o sun4d_smp.o
endif
@@ -46,18 +38,9 @@ ifdef CONFIG_SUN_AUXIO
O_OBJS += auxio.o
endif
-ifdef SMP
-
head.o: head.S
$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $*.S -o $*.o
-else
-
-head.o: head.S
- $(CC) -D__ASSEMBLY__ -ansi -c $*.S -o $*.o
-
-endif
-
check_asm: dummy
@echo "/* Automatically generated. Do not edit. */" > asm_offsets.h
@echo "#ifndef __ASM_OFFSETS_H__" >> asm_offsets.h
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index d393a9543..66ae02054 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.149 1998/03/19 15:36:30 jj Exp $
+/* $Id: entry.S,v 1.152 1998/07/29 16:32:24 jj Exp $
* arch/sparc/kernel/entry.S: Sparc trap low-level entry points.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -335,7 +335,7 @@ smp4m_ticker:
/* Here is where we check for possible SMP IPI passed to us
* on some level other than 15 which is the NMI and only used
- * for cross calls. That has a seperate entry point below.
+ * for cross calls. That has a separate entry point below.
*/
maybe_smp4m_msg:
GET_PROCESSOR_MID(o3, o2)
@@ -1268,6 +1268,22 @@ C_LABEL(sys_pipe):
mov %l5, %o7
.align 4
+ .globl C_LABEL(sys_sigaltstack)
+C_LABEL(sys_sigaltstack):
+ mov %o7, %l5
+ mov %fp, %o2
+ call C_LABEL(do_sigaltstack)
+ mov %l5, %o7
+
+ .align 4
+ .globl C_LABEL(sys_sigstack)
+C_LABEL(sys_sigstack):
+ mov %o7, %l5
+ mov %fp, %o2
+ call C_LABEL(do_sys_sigstack)
+ mov %l5, %o7
+
+ .align 4
.globl C_LABEL(sys_sigpause)
C_LABEL(sys_sigpause):
/* Note: %o0 already has correct value... */
diff --git a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head.S
index 1536a5e55..9c396c928 100644
--- a/arch/sparc/kernel/head.S
+++ b/arch/sparc/kernel/head.S
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.90 1998/03/24 18:12:05 jj Exp $
+/* $Id: head.S,v 1.92 1998/06/10 07:21:55 davem Exp $
* head.S: The initial boot code for the Sparc port of Linux.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -403,7 +403,7 @@ C_LABEL(trapbase_cpu3):
BAD_TRAP(0xfc) BAD_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
#endif
- .align 4096
+ .align PAGE_SIZE
/* This was the only reasonable way I could think of to properly align
* these page-table data structures.
@@ -585,7 +585,7 @@ srmmu_remap:
bnz srmmu_nviking ! is in mbus mode
nop
- rd %psr, %g3 ! DONT TOUCH %g3
+ rd %psr, %g3 ! DO NOT TOUCH %g3
andn %g3, PSR_ET, %g2
wr %g2, 0x0, %psr
WRITE_PAUSE
@@ -596,10 +596,10 @@ srmmu_remap:
set AC_M_CTPR, %g4
lda [%g4] ASI_M_MMUREGS, %g4
sll %g4, 0x4, %g4 ! We use this below
- ! DONT TOUCH %g4
+ ! DO NOT TOUCH %g4
/* Set the AC bit in the Viking's MMU control reg. */
- lda [%g0] ASI_M_MMUREGS, %g5 ! DONT TOUCH %g5
+ lda [%g0] ASI_M_MMUREGS, %g5 ! DO NOT TOUCH %g5
set 0x8000, %g6 ! AC bit mask
or %g5, %g6, %g6 ! Or it in...
sta %g6, [%g0] ASI_M_MMUREGS ! Close your eyes...
@@ -1040,7 +1040,7 @@ sun4c_continue_boot:
* No, it doesn't work, have to play the save/readCWP/restore trick.
*/
- wr %g0, 0x0, %wim ! so we dont get a trap
+ wr %g0, 0x0, %wim ! so we do not get a trap
WRITE_PAUSE
save
diff --git a/arch/sparc/kernel/idprom.c b/arch/sparc/kernel/idprom.c
index f8dbee4ca..a7d5dcd8c 100644
--- a/arch/sparc/kernel/idprom.c
+++ b/arch/sparc/kernel/idprom.c
@@ -1,10 +1,11 @@
-/* $Id: idprom.c,v 1.22 1996/11/13 05:09:25 davem Exp $
+/* $Id: idprom.c,v 1.23 1998/07/28 16:52:44 jj Exp $
* idprom.c: Routines to load the idprom into kernel addresses and
* interpret the data contained within.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/init.h>
@@ -12,6 +13,10 @@
#include <asm/oplib.h>
#include <asm/idprom.h>
#include <asm/machines.h> /* Fun with Sun released architectures. */
+#ifdef CONFIG_SUN4
+#include <asm/sun4paddr.h>
+extern void sun4setup(void);
+#endif
struct idprom *idprom;
static struct idprom idprom_buffer;
@@ -98,4 +103,7 @@ __initfunc(void idprom_init(void))
idprom->id_ethaddr[0], idprom->id_ethaddr[1],
idprom->id_ethaddr[2], idprom->id_ethaddr[3],
idprom->id_ethaddr[4], idprom->id_ethaddr[5]);
+#ifdef CONFIG_SUN4
+ sun4setup();
+#endif
}
diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c
index b29eca496..d2d27d90a 100644
--- a/arch/sparc/kernel/irq.c
+++ b/arch/sparc/kernel/irq.c
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.85 1998/03/09 14:03:40 jj Exp $
+/* $Id: irq.c,v 1.86 1998/06/04 09:54:49 jj Exp $
* arch/sparc/kernel/irq.c: Interrupt request handling routines. On the
* Sparc the IRQ's are basically 'cast in stone'
* and you are supposed to probe the prom's device
@@ -584,9 +584,6 @@ int request_irq(unsigned int irq,
if (!handler)
return -EINVAL;
- if (irqflags & SA_DCOOKIE)
- dev_id = ((struct devid_cookie *)dev_id)->real_dev_id;
-
action = *(cpu_irq + irq_action);
if (action) {
if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
index 8d4c29e62..c52674431 100644
--- a/arch/sparc/kernel/process.c
+++ b/arch/sparc/kernel/process.c
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.110 1998/04/08 16:15:51 jj Exp $
+/* $Id: process.c,v 1.118 1998/08/04 20:48:47 davem Exp $
* linux/arch/sparc/kernel/process.c
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -26,6 +26,7 @@
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/reboot.h>
+#include <linux/delay.h>
#include <asm/auxio.h>
#include <asm/oplib.h>
@@ -40,8 +41,8 @@
#include <asm/elf.h>
extern void fpsave(unsigned long *, unsigned long *, void *, unsigned long *);
-extern void srmmu_check_pgt_cache(void);
+struct task_struct *last_task_used_math = NULL;
struct task_struct *current_set[NR_CPUS] = {&init_task, };
#ifndef __SMP__
@@ -92,9 +93,8 @@ asmlinkage int sys_idle(void)
}
}
restore_flags(flags);
- check_pgt_cache();
- } else
- srmmu_check_pgt_cache();
+ }
+ check_pgt_cache();
schedule();
}
ret = 0;
@@ -113,18 +113,10 @@ int cpu_idle(void *unused)
current->priority = -100;
while(1) {
srmmu_check_pgt_cache();
- /*
- * tq_scheduler currently assumes we're running in a process
- * context (ie that we hold the kernel lock..)
- */
- if (tq_scheduler) {
- lock_kernel();
- run_task_queue(&tq_scheduler);
- unlock_kernel();
- }
+ run_task_queue(&tq_scheduler);
/* endless idle loop with no priority at all */
current->counter = -100;
- if(!smp_commenced || need_resched)
+ if(!smp_commenced || current->need_resched)
schedule();
}
}
@@ -143,18 +135,18 @@ asmlinkage int sys_idle(void)
extern char reboot_command [];
#ifdef CONFIG_SUN_CONSOLE
-extern void console_restore_palette (void);
+extern void (*prom_palette)(int);
extern int serial_console;
#endif
void machine_halt(void)
{
sti();
- udelay(8000);
+ mdelay(8);
cli();
#ifdef CONFIG_SUN_CONSOLE
- if (!serial_console)
- console_restore_palette ();
+ if (!serial_console && prom_palette)
+ prom_palette (1);
#endif
prom_halt();
panic("Halt failed!");
@@ -165,14 +157,14 @@ void machine_restart(char * cmd)
char *p;
sti();
- udelay(8000);
+ mdelay(8);
cli();
p = strchr (reboot_command, '\n');
if (p) *p = 0;
#ifdef CONFIG_SUN_CONSOLE
- if (!serial_console)
- console_restore_palette ();
+ if (!serial_console && prom_palette)
+ prom_palette (1);
#endif
if (cmd)
prom_reboot(cmd);
@@ -332,9 +324,6 @@ void show_thread(struct thread_struct *tss)
printk("fsr: 0x%08lx fpqdepth: 0x%08lx\n", tss->fsr, tss->fpqdepth);
/* XXX missing: fpqueue */
- printk("sstk_info.stack: 0x%08lx sstk_info.status: 0x%08lx\n",
- (unsigned long)tss->sstk_info.the_stack,
- (unsigned long)tss->sstk_info.cur_status);
printk("flags: 0x%08lx current_ds: 0x%08lx\n", tss->flags, tss->current_ds.seg);
show_regwindow((struct reg_window *)tss->ksp);
@@ -368,8 +357,6 @@ void exit_thread(void)
void flush_thread(void)
{
current->tss.w_saved = 0;
- current->tss.sstk_info.cur_status = 0;
- current->tss.sstk_info.the_stack = 0;
/* No new signal delivery by default */
current->tss.new_signal = 0;
@@ -539,7 +526,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
* This is a clone() call with supplied user stack.
* Set some valid stack frames to give to the child.
*/
- childstack = (struct sparc_stackf *) sp;
+ childstack = (struct sparc_stackf *) (sp & ~0x7UL);
parentstack = (struct sparc_stackf *) regs->u_regs[UREG_FP];
#if 0
diff --git a/arch/sparc/kernel/rtrap.S b/arch/sparc/kernel/rtrap.S
index 3c0d311ba..231f696d7 100644
--- a/arch/sparc/kernel/rtrap.S
+++ b/arch/sparc/kernel/rtrap.S
@@ -1,4 +1,4 @@
-/* $Id: rtrap.S,v 1.50 1998/02/05 14:18:43 jj Exp $
+/* $Id: rtrap.S,v 1.51 1998/07/26 03:02:38 davem Exp $
* rtrap.S: Return from Sparc trap low-level code.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -61,14 +61,14 @@ ret_trap_entry:
C_LABEL(ret_trap_lockless_ipi):
andcc %t_psr, PSR_PS, %g0
be 1f
- sethi %hi(C_LABEL(need_resched)), %twin_tmp1
+ nop
wr %t_psr, 0x0, %psr
b ret_trap_kernel
nop
1:
- ld [%twin_tmp1 + %lo(C_LABEL(need_resched))], %g2
+ ld [%curptr + AOFF_task_need_resched], %g2
orcc %g2, %g0, %g0
be signal_p
ld [%curptr + AOFF_task_sigpending], %g2
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
index b5625cd12..257b1c086 100644
--- a/arch/sparc/kernel/setup.c
+++ b/arch/sparc/kernel/setup.c
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.93 1998/03/09 14:03:18 jj Exp $
+/* $Id: setup.c,v 1.99 1998/07/28 16:52:45 jj Exp $
* linux/arch/sparc/kernel/setup.c
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -47,7 +47,7 @@
struct screen_info screen_info = {
0, 0, /* orig-x, orig-y */
- { 0, 0, }, /* unused */
+ 0, /* unused */
0, /* orig-video-page */
0, /* orig-video-mode */
128, /* orig-video-cols */
@@ -66,9 +66,10 @@ unsigned int phys_bytes_of_ram, end_of_phys_memory;
*/
extern unsigned long trapbase;
+extern int serial_console;
extern void breakpoint(void);
#if CONFIG_SUN_CONSOLE
-extern void console_restore_palette(void);
+void (*prom_palette)(int);
#endif
asmlinkage void sys_sync(void); /* it's really int */
@@ -90,7 +91,8 @@ void prom_sync_me(void)
"nop\n\t" : : "r" (&trapbase));
#ifdef CONFIG_SUN_CONSOLE
- console_restore_palette ();
+ if (prom_palette)
+ prom_palette(1);
#endif
prom_printf("PROM SYNC COMMAND...\n");
show_free_areas();
@@ -120,7 +122,6 @@ unsigned int boot_flags;
#define BOOTME_KGDB 0xc
#ifdef CONFIG_SUN_CONSOLE
-extern char *console_fb_path;
static int console_fb = 0;
#endif
static unsigned long memory_size __initdata = 0;
@@ -218,9 +219,17 @@ __initfunc(static void boot_flags_init(char *commands))
} else if (!strncmp (commands, "ttyb", 4)) {
console_fb = 3;
prom_printf ("Using /dev/ttyb as console.\n");
+#if defined(CONFIG_PROM_CONSOLE)
+ } else if (!strncmp (commands, "prom", 4)) {
+ char *p;
+
+ for (p = commands - 8; *p && *p != ' '; p++)
+ *p = ' ';
+ conswitchp = &prom_con;
+ console_fb = 1;
+#endif
} else {
console_fb = 1;
- console_fb_path = commands;
}
} else
#endif
@@ -323,6 +332,9 @@ __initfunc(void setup_arch(char **cmdline_p,
switch(sparc_cpu_model) {
case sun4:
printk("SUN4\n");
+#ifdef CONFIG_SUN4_FORCECONSOLE
+ register_console(&prom_console);
+#endif
packed = 0;
break;
case sun4c:
@@ -354,6 +366,11 @@ __initfunc(void setup_arch(char **cmdline_p,
break;
};
+#ifdef CONFIG_DUMMY_CONSOLE
+ conswitchp = &dummy_con;
+#elif defined(CONFIG_PROM_CONSOLE)
+ conswitchp = &prom_con;
+#endif
boot_flags_init(*cmdline_p);
idprom_init();
@@ -412,7 +429,6 @@ __initfunc(void setup_arch(char **cmdline_p,
*memory_start_p = sun_serial_setup(*memory_start_p); /* set this up ASAP */
#endif
{
- extern int serial_console; /* in console.c, of course */
#if !CONFIG_SUN_SERIAL
serial_console = 0;
#else
@@ -466,6 +482,8 @@ __initfunc(void setup_arch(char **cmdline_p,
init_task.mm->context = (unsigned long) NO_CONTEXT;
init_task.tss.kregs = &fake_swapper_regs;
+ if (serial_console)
+ conswitchp = NULL;
}
asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c
index efdb362a4..357d30af5 100644
--- a/arch/sparc/kernel/signal.c
+++ b/arch/sparc/kernel/signal.c
@@ -1,4 +1,4 @@
-/* $Id: signal.c,v 1.79 1998/04/04 07:11:41 davem Exp $
+/* $Id: signal.c,v 1.82 1998/07/31 05:18:51 jj Exp $
* linux/arch/sparc/kernel/signal.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
@@ -85,6 +85,7 @@ struct rt_signal_frame {
sigset_t mask;
__siginfo_fpu_t *fpu_save;
unsigned int insns [2];
+ stack_t stack;
__siginfo_fpu_t fpu_state;
};
@@ -187,9 +188,10 @@ asmlinkage void do_rt_sigsuspend(sigset_t *uset, size_t sigsetsize,
}
}
-static inline void
+static inline int
restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu)
{
+ int err;
#ifdef __SMP__
if (current->flags & PF_USEDFPU)
regs->psr &= ~PSR_EF;
@@ -202,15 +204,16 @@ restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu)
current->used_math = 1;
current->flags &= ~PF_USEDFPU;
- copy_from_user(&current->tss.float_regs[0], &fpu->si_float_regs[0],
+ err = copy_from_user(&current->tss.float_regs[0], &fpu->si_float_regs[0],
(sizeof(unsigned long) * 32));
- __get_user(current->tss.fsr, &fpu->si_fsr);
- __get_user(current->tss.fpqdepth, &fpu->si_fpqdepth);
+ err |= __get_user(current->tss.fsr, &fpu->si_fsr);
+ err |= __get_user(current->tss.fpqdepth, &fpu->si_fpqdepth);
if (current->tss.fpqdepth != 0)
- copy_from_user(&current->tss.fpqueue[0],
+ err |= copy_from_user(&current->tss.fpqueue[0],
&fpu->si_fpqueue[0],
((sizeof(unsigned long) +
(sizeof(unsigned long *)))*16));
+ return err;
}
static inline void do_new_sigreturn (struct pt_regs *regs)
@@ -218,6 +221,8 @@ static inline void do_new_sigreturn (struct pt_regs *regs)
struct new_signal_frame *sf;
unsigned long up_psr, pc, npc;
sigset_t set;
+ __siginfo_fpu_t *fpu_save;
+ int err;
sf = (struct new_signal_frame *) regs->u_regs [UREG_FP];
@@ -228,29 +233,33 @@ static inline void do_new_sigreturn (struct pt_regs *regs)
if (((uint) sf) & 3)
goto segv_and_exit;
- __get_user(pc, &sf->info.si_regs.pc);
- __get_user(npc, &sf->info.si_regs.npc);
+ err = __get_user(pc, &sf->info.si_regs.pc);
+ err |= __get_user(npc, &sf->info.si_regs.npc);
if ((pc | npc) & 3)
goto segv_and_exit;
/* 2. Restore the state */
up_psr = regs->psr;
- copy_from_user(regs, &sf->info.si_regs, sizeof (struct pt_regs));
+ err |= copy_from_user(regs, &sf->info.si_regs, sizeof (struct pt_regs));
/* User can only change condition codes and FPU enabling in %psr. */
regs->psr = (up_psr & ~(PSR_ICC | PSR_EF))
| (regs->psr & (PSR_ICC | PSR_EF));
- if (sf->fpu_save)
- restore_fpu_state(regs, sf->fpu_save);
+ err |= __get_user(fpu_save, &sf->fpu_save);
+
+ if (fpu_save)
+ err |= restore_fpu_state(regs, sf->fpu_save);
/* This is pretty much atomic, no amount locking would prevent
* the races which exist anyways.
*/
- if (__get_user(set.sig[0], &sf->info.si_mask) ||
- copy_from_user(&set.sig[1], &sf->extramask,
- (_NSIG_WORDS-1) * sizeof(unsigned int)))
+ err |= __get_user(set.sig[0], &sf->info.si_mask);
+ err |= copy_from_user(&set.sig[1], &sf->extramask,
+ (_NSIG_WORDS-1) * sizeof(unsigned int));
+
+ if (err)
goto segv_and_exit;
sigdelsetmask(&set, ~_BLOCKABLE);
@@ -271,6 +280,7 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
struct sigcontext *scptr;
unsigned long pc, npc, psr;
sigset_t set;
+ int err;
synchronize_user_stack();
@@ -284,8 +294,8 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
(((unsigned long) scptr) & 3))
goto segv_and_exit;
- __get_user(pc, &scptr->sigc_pc);
- __get_user(npc, &scptr->sigc_npc);
+ err = __get_user(pc, &scptr->sigc_pc);
+ err |= __get_user(npc, &scptr->sigc_npc);
if((pc | npc) & 3)
goto segv_and_exit;
@@ -293,10 +303,12 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
/* This is pretty much atomic, no amount locking would prevent
* the races which exist anyways.
*/
- if (__get_user(set.sig[0], &scptr->sigc_mask) ||
- /* Note that scptr + 1 points to extramask */
- copy_from_user(&set.sig[1], scptr + 1,
- (_NSIG_WORDS - 1) * sizeof(unsigned int)))
+ err |= __get_user(set.sig[0], &scptr->sigc_mask);
+ /* Note that scptr + 1 points to extramask */
+ err |= copy_from_user(&set.sig[1], scptr + 1,
+ (_NSIG_WORDS - 1) * sizeof(unsigned int));
+
+ if (err)
goto segv_and_exit;
sigdelsetmask(&set, ~_BLOCKABLE);
@@ -305,26 +317,24 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
recalc_sigpending(current);
spin_unlock_irq(&current->sigmask_lock);
- __get_user(current->tss.sstk_info.cur_status, &scptr->sigc_onstack);
- current->tss.sstk_info.cur_status &= 1;
-
regs->pc = pc;
regs->npc = npc;
- __get_user(regs->u_regs[UREG_FP], &scptr->sigc_sp);
- __get_user(regs->u_regs[UREG_I0], &scptr->sigc_o0);
- __get_user(regs->u_regs[UREG_G1], &scptr->sigc_g1);
+ err = __get_user(regs->u_regs[UREG_FP], &scptr->sigc_sp);
+ err |= __get_user(regs->u_regs[UREG_I0], &scptr->sigc_o0);
+ err |= __get_user(regs->u_regs[UREG_G1], &scptr->sigc_g1);
/* User can only change condition codes in %psr. */
- __get_user(psr, &scptr->sigc_psr);
+ err |= __get_user(psr, &scptr->sigc_psr);
+ if (err)
+ goto segv_and_exit;
+
regs->psr &= ~(PSR_ICC);
regs->psr |= (psr & PSR_ICC);
return;
segv_and_exit:
- /* Ugh, we need to grab master lock in these rare cases ;-( */
- lock_kernel();
- do_exit(SIGSEGV);
+ send_sig(SIGSEGV, current, 1);
}
asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
@@ -333,6 +343,8 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
unsigned int psr, pc, npc;
__siginfo_fpu_t *fpu_save;
sigset_t set;
+ stack_t st;
+ int err;
synchronize_user_stack();
sf = (struct rt_signal_frame *) regs->u_regs[UREG_FP];
@@ -340,40 +352,35 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
(((unsigned long) sf) & 0x03))
goto segv;
- get_user(pc, &sf->regs.pc);
- __get_user(npc, &sf->regs.npc);
- if((pc | npc) & 0x03)
- goto segv;
+ err = get_user(pc, &sf->regs.pc);
+ err |= __get_user(npc, &sf->regs.npc);
+ err |= ((pc | npc) & 0x03);
- regs->pc = pc;
- regs->npc = npc;
+ err |= __get_user(regs->y, &sf->regs.y);
+ err |= __get_user(psr, &sf->regs.psr);
- __get_user(regs->y, &sf->regs.y);
- __get_user(psr, &sf->regs.psr);
-
- __get_user(regs->u_regs[UREG_G1], &sf->regs.u_regs[UREG_G1]);
- __get_user(regs->u_regs[UREG_G2], &sf->regs.u_regs[UREG_G2]);
- __get_user(regs->u_regs[UREG_G3], &sf->regs.u_regs[UREG_G3]);
- __get_user(regs->u_regs[UREG_G4], &sf->regs.u_regs[UREG_G4]);
- __get_user(regs->u_regs[UREG_G5], &sf->regs.u_regs[UREG_G5]);
- __get_user(regs->u_regs[UREG_G6], &sf->regs.u_regs[UREG_G6]);
- __get_user(regs->u_regs[UREG_G7], &sf->regs.u_regs[UREG_G7]);
- __get_user(regs->u_regs[UREG_I0], &sf->regs.u_regs[UREG_I0]);
- __get_user(regs->u_regs[UREG_I1], &sf->regs.u_regs[UREG_I1]);
- __get_user(regs->u_regs[UREG_I2], &sf->regs.u_regs[UREG_I2]);
- __get_user(regs->u_regs[UREG_I3], &sf->regs.u_regs[UREG_I3]);
- __get_user(regs->u_regs[UREG_I4], &sf->regs.u_regs[UREG_I4]);
- __get_user(regs->u_regs[UREG_I5], &sf->regs.u_regs[UREG_I5]);
- __get_user(regs->u_regs[UREG_I6], &sf->regs.u_regs[UREG_I6]);
- __get_user(regs->u_regs[UREG_I7], &sf->regs.u_regs[UREG_I7]);
+ err |= __copy_from_user(&regs->u_regs[UREG_G1], &sf->regs.u_regs[UREG_G1], 15*sizeof(u32));
regs->psr = (regs->psr & ~PSR_ICC) | (psr & PSR_ICC);
- __get_user(fpu_save, &sf->fpu_save);
+ err |= __get_user(fpu_save, &sf->fpu_save);
+
if(fpu_save)
- restore_fpu_state(regs, &sf->fpu_state);
- if(copy_from_user(&set, &sf->mask, sizeof(sigset_t)))
+ err |= restore_fpu_state(regs, &sf->fpu_state);
+ err |= copy_from_user(&set, &sf->mask, sizeof(sigset_t));
+
+ err |= __copy_from_user(&st, &sf->stack, sizeof(stack_t));
+
+ if (err)
goto segv;
+
+ regs->pc = pc;
+ regs->npc = npc;
+
+ /* It is more difficult to avoid calling this function than to
+ call it and ignore errors. */
+ do_sigaltstack(&st, NULL, (unsigned long)sf);
+
sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sigmask_lock);
current->blocked = set;
@@ -381,8 +388,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
spin_unlock_irq(&current->sigmask_lock);
return;
segv:
- lock_kernel();
- do_exit(SIGSEGV);
+ send_sig(SIGSEGV, current, 1);
}
/* Checks if the fp is valid */
@@ -397,6 +403,20 @@ static inline int invalid_frame_pointer (void *fp, int fplen)
return 0;
}
+static inline void *get_sigframe(struct sigaction *sa, struct pt_regs *regs, unsigned long framesize)
+{
+ unsigned long sp;
+
+ sp = regs->u_regs[UREG_FP];
+
+ /* This is the X/Open sanctioned signal stack switching. */
+ if (sa->sa_flags & SA_ONSTACK) {
+ if (!on_sig_stack(sp) && !((current->sas_ss_sp + current->sas_ss_size) & 7))
+ sp = current->sas_ss_sp + current->sas_ss_size;
+ }
+ return (void *)(sp - framesize);
+}
+
static inline void
setup_frame(struct sigaction *sa, unsigned long pc, unsigned long npc,
struct pt_regs *regs, int signr, sigset_t *oldset)
@@ -404,11 +424,9 @@ setup_frame(struct sigaction *sa, unsigned long pc, unsigned long npc,
struct signal_sframe *sframep;
struct sigcontext *sc;
int window = 0;
- int old_status = current->tss.sstk_info.cur_status;
synchronize_user_stack();
- sframep = (struct signal_sframe *) regs->u_regs[UREG_FP];
- sframep = (struct signal_sframe *) (((unsigned long) sframep)-SF_ALIGNEDSZ);
+ sframep = (struct signal_sframe *)get_sigframe(sa, regs, SF_ALIGNEDSZ);
if (invalid_frame_pointer (sframep, sizeof(*sframep))){
#ifdef DEBUG_SIGNALS /* fills up the console logs during crashme runs, yuck... */
printk("%s [%d]: User has trashed signal stack\n",
@@ -425,7 +443,7 @@ setup_frame(struct sigaction *sa, unsigned long pc, unsigned long npc,
sc = &sframep->sig_context;
/* We've already made sure frame pointer isn't in kernel space... */
- __put_user(old_status, &sc->sigc_onstack);
+ __put_user((sas_ss_flags(regs->u_regs[UREG_FP]) == SS_ONSTACK), &sc->sigc_onstack);
__put_user(oldset->sig[0], &sc->sigc_mask);
__copy_to_user(sframep->extramask, &oldset->sig[1],
(_NSIG_WORDS - 1) * sizeof(unsigned int));
@@ -519,14 +537,16 @@ new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
if (!current->used_math)
sigframe_size -= sizeof(__siginfo_fpu_t);
- sf = (struct new_signal_frame *)(regs->u_regs[UREG_FP] - sigframe_size);
+ sf = (struct new_signal_frame *)get_sigframe(&ka->sa, regs, sigframe_size);
if (invalid_frame_pointer (sf, sigframe_size))
goto sigill_and_return;
if (current->tss.w_saved != 0) {
+#ifdef DEBUG_SIGNALS
printk ("%s [%d]: Invalid user stack frame for "
"signal delivery.\n", current->comm, current->pid);
+#endif
goto sigill_and_return;
}
@@ -535,9 +555,9 @@ new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
if (current->used_math) {
save_fpu_state(regs, &sf->fpu_state);
- sf->fpu_save = &sf->fpu_state;
+ __put_user(&sf->fpu_state, &sf->fpu_save);
} else {
- sf->fpu_save = NULL;
+ __put_user(0, &sf->fpu_save);
}
__put_user(oldset->sig[0], &sf->info.si_mask);
@@ -587,7 +607,7 @@ new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
sigframe_size = RT_ALIGNEDSZ;
if(!current->used_math)
sigframe_size -= sizeof(__siginfo_fpu_t);
- sf = (struct rt_signal_frame *)(regs->u_regs[UREG_FP] - sigframe_size);
+ sf = (struct rt_signal_frame *)get_sigframe(&ka->sa, regs, sigframe_size);
if(invalid_frame_pointer(sf, sigframe_size))
goto sigill;
if(current->tss.w_saved != 0)
@@ -609,6 +629,12 @@ new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
__put_user(0, &sf->fpu_save);
}
__copy_to_user(&sf->mask, &oldset->sig[0], sizeof(sigset_t));
+
+ /* Setup sigaltstack */
+ __put_user(current->sas_ss_sp, &sf->stack.ss_sp);
+ __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);
+ __put_user(current->sas_ss_size, &sf->stack.ss_size);
+
copy_to_user(sf, (char *) regs->u_regs [UREG_FP],
sizeof (struct reg_window));
@@ -652,8 +678,7 @@ setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc,
int window = 0;
synchronize_user_stack();
- sfp = (svr4_signal_frame_t *) regs->u_regs[UREG_FP] - REGWIN_SZ;
- sfp = (svr4_signal_frame_t *) (((unsigned long) sfp)-SVR4_SF_ALIGNED);
+ sfp = (svr4_signal_frame_t *) get_sigframe(sa, regs, SVR4_SF_ALIGNED + REGWIN_SZ);
if (invalid_frame_pointer (sfp, sizeof (*sfp))){
#ifdef DEBUG_SIGNALS
@@ -695,10 +720,10 @@ setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc,
copy_to_user(&(*gr)[SVR4_G1], &regs->u_regs [UREG_G1], sizeof (long) * 7);
copy_to_user(&(*gr)[SVR4_O0], &regs->u_regs [UREG_I0], sizeof (long) * 8);
- /* Setup sigaltstack, FIXME */
- __put_user(0xdeadbeef, &uc->stack.sp);
- __put_user(0, &uc->stack.size);
- __put_user(0, &uc->stack.flags); /* Possible: ONSTACK, DISABLE */
+ /* Setup sigaltstack */
+ __put_user(current->sas_ss_sp, &uc->stack.sp);
+ __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags);
+ __put_user(current->sas_ss_size, &uc->stack.size);
/* Save the currently window file: */
@@ -799,10 +824,10 @@ asmlinkage int svr4_getcontext (svr4_ucontext_t *uc, struct pt_regs *regs)
copy_to_user(&(*gr)[SVR4_G1], &regs->u_regs [UREG_G1], sizeof (uint) * 7);
copy_to_user(&(*gr)[SVR4_O0], &regs->u_regs [UREG_I0], sizeof (uint) * 8);
- /* Setup sigaltstack, FIXME */
- __put_user(0xdeadbeef, &uc->stack.sp);
- __put_user(0, &uc->stack.size);
- __put_user(0, &uc->stack.flags); /* Possible: ONSTACK, DISABLE */
+ /* Setup sigaltstack */
+ __put_user(current->sas_ss_sp, &uc->stack.sp);
+ __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags);
+ __put_user(current->sas_ss_size, &uc->stack.size);
/* The register file is not saved
* we have already stuffed all of it with sync_user_stack
@@ -822,6 +847,8 @@ asmlinkage int svr4_setcontext (svr4_ucontext_t *c, struct pt_regs *regs)
unsigned long pc, npc, psr;
sigset_t set;
svr4_sigset_t setv;
+ int err;
+ stack_t st;
/* Fixme: restore windows, or is this already taken care of in
* svr4_setup_frame when sync_user_windows is done?
@@ -839,8 +866,8 @@ asmlinkage int svr4_setcontext (svr4_ucontext_t *c, struct pt_regs *regs)
/* Check for valid PC and nPC */
gr = &c->mcontext.greg;
- __get_user(pc, &((*gr)[SVR4_PC]));
- __get_user(npc, &((*gr)[SVR4_NPC]));
+ err = __get_user(pc, &((*gr)[SVR4_PC]));
+ err |= __get_user(npc, &((*gr)[SVR4_NPC]));
if((pc | npc) & 3)
goto sigsegv_and_return;
@@ -852,8 +879,19 @@ asmlinkage int svr4_setcontext (svr4_ucontext_t *c, struct pt_regs *regs)
/* This is pretty much atomic, no amount locking would prevent
* the races which exist anyways.
*/
- if (__copy_from_user(&setv, &c->sigmask, sizeof(svr4_sigset_t)))
+ err |= __copy_from_user(&setv, &c->sigmask, sizeof(svr4_sigset_t));
+
+ err |= __get_user(st.ss_sp, &c->stack.sp);
+ err |= __get_user(st.ss_flags, &c->stack.flags);
+ err |= __get_user(st.ss_size, &c->stack.size);
+
+ if (err)
goto sigsegv_and_return;
+
+ /* It is more difficult to avoid calling this function than to
+ call it and ignore errors. */
+ do_sigaltstack(&st, NULL, regs->u_regs[UREG_I6]);
+
set.sig[0] = setv.sigbits[0];
set.sig[1] = setv.sigbits[1];
if (_NSIG_WORDS >= 4) {
@@ -1067,24 +1105,36 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
}
asmlinkage int
-sys_sigstack(struct sigstack *ssptr, struct sigstack *ossptr)
+do_sys_sigstack(struct sigstack *ssptr, struct sigstack *ossptr, unsigned long sp)
{
int ret = -EFAULT;
- lock_kernel();
/* First see if old state is wanted. */
- if(ossptr) {
- if(copy_to_user(ossptr, &current->tss.sstk_info, sizeof(struct sigstack)))
+ if (ossptr) {
+ if (put_user(current->sas_ss_sp + current->sas_ss_size, &ossptr->the_stack) ||
+ __put_user(on_sig_stack(sp), &ossptr->cur_status))
goto out;
}
/* Now see if we want to update the new state. */
- if(ssptr) {
- if(copy_from_user(&current->tss.sstk_info, ssptr, sizeof(struct sigstack)))
+ if (ssptr) {
+ void *ss_sp;
+
+ if (get_user((long)ss_sp, &ssptr->the_stack))
goto out;
+ /* If the current stack was set with sigaltstack, don't
+ swap stacks while we are on it. */
+ ret = -EPERM;
+ if (current->sas_ss_sp && on_sig_stack(sp))
+ goto out;
+
+ /* Since we don't know the extent of the stack, and we don't
+ track onstack-ness, but rather calculate it, we must
+ presume a size. Ho hum this interface is lossy. */
+ current->sas_ss_sp = (unsigned long)ss_sp - SIGSTKSZ;
+ current->sas_ss_size = SIGSTKSZ;
}
ret = 0;
out:
- unlock_kernel();
return ret;
}
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index c6d86d36c..0d9c43e9d 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -60,7 +60,9 @@ volatile int __cpu_logical_map[NR_CPUS];
* compared to the Alpha and the Intel no? Most Sparcs have 'swap'
* instruction which is much better...
*/
-struct klock_info klock_info = { KLOCK_CLEAR, 0 };
+
+/* Kernel spinlock */
+spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
volatile unsigned long ipi_count;
@@ -238,7 +240,7 @@ void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr)
/* Reschedule call back. */
void smp_reschedule_irq(void)
{
- need_resched = 1;
+ current->need_resched = 1;
}
/* Stopping processors. */
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 1690a7c69..e6aad243d 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -1,4 +1,4 @@
-/* $Id: sparc_ksyms.c,v 1.64 1998/03/19 15:36:43 jj Exp $
+/* $Id: sparc_ksyms.c,v 1.65 1998/06/04 09:54:50 jj Exp $
* arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -175,6 +175,7 @@ EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(__smp_processor_id));
#endif
EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(enable_irq));
EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(disable_irq));
+EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(__irq_itoa));
EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(mmu_v2p));
EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(mmu_unlockarea));
EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(mmu_lockarea));
diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c
index cef6370ce..cda7564dc 100644
--- a/arch/sparc/kernel/sun4c_irq.c
+++ b/arch/sparc/kernel/sun4c_irq.c
@@ -9,6 +9,7 @@
* Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
*/
+#include <linux/config.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/linkage.h>
@@ -108,9 +109,22 @@ static void sun4c_enable_irq(unsigned int irq_nr)
volatile struct sun4c_timer_info *sun4c_timers;
+#ifdef CONFIG_SUN4
+/* This is an ugly hack to work around the
+ current timer code, and make it work with
+ the sun4/260 intersil
+ */
+volatile struct sun4c_timer_info sun4_timer;
+#endif
+
static void sun4c_clear_clock_irq(void)
{
volatile unsigned int clear_intr;
+#ifdef CONFIG_SUN4
+ if( idprom->id_machtype == SM_SUN4 | SM_4_260 )
+ clear_intr = sun4_timer.timer_limit10;
+ else
+#endif
clear_intr = sun4c_timers->timer_limit10;
}
@@ -131,6 +145,11 @@ __initfunc(static void sun4c_init_timers(void (*counter_fn)(int, void *, struct
/* Map the Timer chip, this is implemented in hardware inside
* the cache chip on the sun4c.
*/
+#ifdef CONFIG_SUN4
+ if (idprom->id_machtype == SM_SUN4 | SM_4_260)
+ sun4c_timers = &sun4_timer;
+ else
+#endif
sun4c_timers = sparc_alloc_io (SUN_TIMER_PHYSADDR, 0,
sizeof(struct sun4c_timer_info),
"timer", 0x0, 0x0);
@@ -152,6 +171,7 @@ __initfunc(static void sun4c_init_timers(void (*counter_fn)(int, void *, struct
prom_halt();
}
+ sun4c_enable_irq(10);
claim_ticker14(NULL, PROFILE_IRQ, 0);
}
@@ -159,6 +179,8 @@ __initfunc(static void sun4c_init_timers(void (*counter_fn)(int, void *, struct
static void sun4c_nop(void) {}
#endif
+extern char *sun4m_irq_itoa(unsigned int irq);
+
__initfunc(void sun4c_init_IRQ(void))
{
struct linux_prom_registers int_regs[2];
@@ -166,7 +188,7 @@ __initfunc(void sun4c_init_IRQ(void))
if (ARCH_SUN4) {
interrupt_enable =
- (char *) sparc_alloc_io(SUN4_IE_PHYSADDR, 0,
+ (char *) sparc_alloc_io(sun4_ie_physaddr, 0,
PAGE_SIZE,
"sun4c_interrupts",
0x0, 0x0);
@@ -193,6 +215,7 @@ __initfunc(void sun4c_init_IRQ(void))
BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(clear_profile_irq, sun4c_clear_profile_irq, BTFIXUPCALL_NOP);
BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP);
+ BTFIXUPSET_CALL(__irq_itoa, sun4m_irq_itoa, BTFIXUPCALL_NORM);
init_timers = sun4c_init_timers;
#ifdef __SMP__
BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP);
diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c
index 302df86f4..3a37df0c9 100644
--- a/arch/sparc/kernel/sun4d_irq.c
+++ b/arch/sparc/kernel/sun4d_irq.c
@@ -1,4 +1,4 @@
-/* $Id: sun4d_irq.c,v 1.12 1998/03/19 15:36:36 jj Exp $
+/* $Id: sun4d_irq.c,v 1.14 1998/06/04 09:54:47 jj Exp $
* arch/sparc/kernel/sun4d_irq.c:
* SS1000/SC2000 interrupt handling.
*
@@ -237,41 +237,32 @@ void sun4d_handler_irq(int irq, struct pt_regs * regs)
irq_exit(cpu, irq);
}
+unsigned int sun4d_build_irq(struct linux_sbus_device *sdev, int irq)
+{
+ int sbusl = pil_to_sbus[irq];
+
+ if (sbusl)
+ return ((sdev->my_bus->board + 1) << 5) + (sbusl << 2) + sdev->slot;
+ else
+ return irq;
+}
+
int sun4d_request_irq(unsigned int irq,
void (*handler)(int, void *, struct pt_regs *),
unsigned long irqflags, const char * devname, void *dev_id)
{
struct irqaction *action, *tmp = NULL, **actionp;
unsigned long flags;
- int sbusl;
- unsigned int *ret = NULL;
- struct linux_sbus_device *sdev = NULL;
- if(irq > 14)
+ if(irq > 14 && irq < (1 << 5))
return -EINVAL;
if (!handler)
return -EINVAL;
-
- if (irqflags & SA_DCOOKIE) {
- struct devid_cookie *d = (struct devid_cookie *)dev_id;
-
- dev_id = d->real_dev_id;
- sdev = (struct linux_sbus_device *)d->bus_cookie;
- ret = &d->ret_ino;
- }
-
- sbusl = pil_to_sbus[irq];
- if (sbusl && !sdev) {
- printk ("Attempt to register SBUS IRQ %d without DCOOKIE\n", irq);
- return -EINVAL;
- }
- if (sbusl) {
- actionp = &(sbus_actions[(sdev->my_bus->board << 5) +
- (sbusl << 2) + sdev->slot].action);
- *ret = ((sdev->my_bus->board + 1) << 5) +
- (sbusl << 2) + sdev->slot;
- } else
+
+ if (irq >= (1 << 5))
+ actionp = &(sbus_actions[irq - (1 << 5)].action);
+ else
actionp = irq + irq_action;
action = *actionp;
@@ -495,7 +486,7 @@ __initfunc(static void sun4d_init_timers(void (*counter_fn)(int, void *, struct
#endif
}
-__initfunc(unsigned long sun4d_init_sbi_irq(unsigned long memory_start))
+__initfunc(void sun4d_init_sbi_irq(void))
{
struct linux_sbus *sbus;
unsigned mask;
@@ -503,9 +494,7 @@ __initfunc(unsigned long sun4d_init_sbi_irq(unsigned long memory_start))
nsbi = 0;
for_each_sbus(sbus)
nsbi++;
- memory_start = ((memory_start + 7) & ~7);
- sbus_actions = (struct sbus_action *)memory_start;
- memory_start += (nsbi * 8 * 4 * sizeof(struct sbus_action));
+ sbus_actions = (struct sbus_action *)kmalloc (nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC);
memset (sbus_actions, 0, (nsbi * 8 * 4 * sizeof(struct sbus_action)));
for_each_sbus(sbus) {
#ifdef __SMP__
@@ -521,7 +510,17 @@ __initfunc(unsigned long sun4d_init_sbi_irq(unsigned long memory_start))
release_sbi(sbus->devid, mask);
}
}
- return memory_start;
+}
+
+static char *sun4d_irq_itoa(unsigned int irq)
+{
+ static char buff[16];
+
+ if (irq < (1 << 5))
+ sprintf(buff, "%d", irq);
+ else
+ sprintf(buff, "%d,%x", sbus_to_pil[(irq >> 2) & 7], irq);
+ return buff;
}
__initfunc(void sun4d_init_IRQ(void))
@@ -533,6 +532,7 @@ __initfunc(void sun4d_init_IRQ(void))
BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(clear_profile_irq, sun4d_clear_profile_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM);
+ BTFIXUPSET_CALL(__irq_itoa, sun4d_irq_itoa, BTFIXUPCALL_NORM);
init_timers = sun4d_init_timers;
#ifdef __SMP__
BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM);
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index 46ce7a83f..5563a0cc6 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -6,7 +6,6 @@
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
*/
-#include <linux/config.h> /* for CONFIG_PROFILE */
#include <asm/head.h>
#include <linux/kernel.h>
@@ -437,8 +436,6 @@ void smp4d_message_pass(int target, int msg, unsigned long data, int wait)
/* Protects counters touched during level14 ticker */
static spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED;
-#ifdef CONFIG_PROFILE
-
/* 32-bit Sparc specific profiling function. */
static inline void sparc_do_profile(unsigned long pc)
{
@@ -457,8 +454,6 @@ static inline void sparc_do_profile(unsigned long pc)
}
}
-#endif
-
extern unsigned int prof_multiplier[NR_CPUS];
extern unsigned int prof_counter[NR_CPUS];
@@ -484,10 +479,9 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
show_leds(cpu);
}
-#ifdef CONFIG_PROFILE
if(!user_mode(regs))
sparc_do_profile(regs->pc);
-#endif
+
if(!--prof_counter[cpu]) {
int user = user_mode(regs);
if(current->pid) {
@@ -495,7 +489,7 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
if(--current->counter < 0) {
current->counter = 0;
- need_resched = 1;
+ current->need_resched = 1;
}
spin_lock(&ticker_lock);
diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c
index e55839a7a..68c04014f 100644
--- a/arch/sparc/kernel/sun4m_irq.c
+++ b/arch/sparc/kernel/sun4m_irq.c
@@ -211,6 +211,13 @@ static void sun4m_load_profile_irq(int cpu, unsigned int limit)
sun4m_timers->cpu_timers[cpu].l14_timer_limit = limit;
}
+char *sun4m_irq_itoa(unsigned int irq)
+{
+ static char buff[16];
+ sprintf(buff, "%d", irq);
+ return buff;
+}
+
__initfunc(static void sun4m_init_timers(void (*counter_fn)(int, void *, struct pt_regs *)))
{
int reg_count, irq, cpu;
@@ -356,6 +363,7 @@ __initfunc(void sun4m_init_IRQ(void))
BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(clear_profile_irq, sun4m_clear_profile_irq, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM);
+ BTFIXUPSET_CALL(__irq_itoa, sun4m_irq_itoa, BTFIXUPCALL_NORM);
init_timers = sun4m_init_timers;
#ifdef __SMP__
BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM);
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index ec1ef424b..597ee7665 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -3,7 +3,6 @@
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
*/
-#include <linux/config.h> /* for CONFIG_PROFILE */
#include <asm/head.h>
#include <linux/kernel.h>
@@ -433,8 +432,6 @@ void smp4m_cross_call_irq(void)
/* Protects counters touched during level14 ticker */
static spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED;
-#ifdef CONFIG_PROFILE
-
/* 32-bit Sparc specific profiling function. */
static inline void sparc_do_profile(unsigned long pc)
{
@@ -453,8 +450,6 @@ static inline void sparc_do_profile(unsigned long pc)
}
}
-#endif
-
extern unsigned int prof_multiplier[NR_CPUS];
extern unsigned int prof_counter[NR_CPUS];
@@ -467,10 +462,10 @@ void smp4m_percpu_timer_interrupt(struct pt_regs *regs)
int cpu = smp_processor_id();
clear_profile_irq(mid_xlate[cpu]);
-#ifdef CONFIG_PROFILE
+
if(!user_mode(regs))
sparc_do_profile(regs->pc);
-#endif
+
if(!--prof_counter[cpu]) {
int user = user_mode(regs);
if(current->pid) {
@@ -478,7 +473,7 @@ void smp4m_percpu_timer_interrupt(struct pt_regs *regs)
if(--current->counter < 0) {
current->counter = 0;
- need_resched = 1;
+ current->need_resched = 1;
}
spin_lock(&ticker_lock);
diff --git a/arch/sparc/kernel/sun4setup.c b/arch/sparc/kernel/sun4setup.c
new file mode 100644
index 000000000..28bd7ce95
--- /dev/null
+++ b/arch/sparc/kernel/sun4setup.c
@@ -0,0 +1,74 @@
+/* sun4setup.c: Setup the hardware address of various items in the sun4
+ * architecture. Called from idprom_init
+ *
+ * Copyright (C) 1998 Chris G. Davis (cdavis@cois.on.ca)
+ */
+
+#include <asm/page.h>
+#include <asm/oplib.h>
+#include <asm/idprom.h>
+#include <asm/sun4paddr.h>
+#include <asm/machines.h>
+
+int sun4_memreg_physaddr;
+int sun4_ie_physaddr;
+int sun4_clock_physaddr;
+int sun4_timer_physaddr;
+int sun4_eth_physaddr;
+int sun4_si_physaddr;
+int sun4_bwtwo_physaddr;
+int sun4_zs0_physaddr;
+int sun4_zs1_physaddr;
+int sun4_dma_physaddr;
+int sun4_esp_physaddr;
+int sun4_ie_physaddr;
+
+__initfunc(void sun4setup())
+{
+ printk("Sun4 Hardware Setup v1.0 18/May/98 Chris Davis (cdavis@cois.on.ca). ");
+ /*
+ setup standard sun4 info
+ */
+ sun4_ie_physaddr=SUN4_IE_PHYSADDR;
+
+ /*
+ setup model specific info
+ */
+ switch(idprom->id_machtype) {
+ case (SM_SUN4 | SM_4_260 ):
+ printk("Setup for a SUN4/260\n");
+ sun4_memreg_physaddr=SUN4_200_MEMREG_PHYSADDR;
+ sun4_clock_physaddr=SUN4_200_CLOCK_PHYSADDR;
+ sun4_timer_physaddr=SUN4_UNUSED_PHYSADDR;
+ sun4_eth_physaddr=SUN4_200_ETH_PHYSADDR;
+ sun4_si_physaddr=SUN4_200_SI_PHYSADDR;
+ sun4_bwtwo_physaddr=SUN4_200_BWTWO_PHYSADDR;
+ sun4_dma_physaddr=SUN4_UNUSED_PHYSADDR;
+ sun4_esp_physaddr=SUN4_UNUSED_PHYSADDR;
+ break;
+ case (SM_SUN4 | SM_4_330 ):
+ printk("Setup for a SUN4/330\n");
+ sun4_memreg_physaddr=SUN4_300_MEMREG_PHYSADDR;
+ sun4_clock_physaddr=SUN4_300_CLOCK_PHYSADDR;
+ sun4_timer_physaddr=SUN4_300_TIMER_PHYSADDR;
+ sun4_eth_physaddr=SUN4_300_ETH_PHYSADDR;
+ sun4_si_physaddr=SUN4_UNUSED_PHYSADDR;
+ sun4_bwtwo_physaddr=SUN4_300_BWTWO_PHYSADDR;
+ sun4_dma_physaddr=SUN4_300_DMA_PHYSADDR;
+ sun4_esp_physaddr=SUN4_300_ESP_PHYSADDR;
+ break;
+ case (SM_SUN4 | SM_4_470 ):
+ printk("Setup for a SUN4/470\n");
+ sun4_memreg_physaddr=SUN4_400_MEMREG_PHYSADDR;
+ sun4_clock_physaddr=SUN4_400_CLOCK_PHYSADDR;
+ sun4_timer_physaddr=SUN4_400_TIMER_PHYSADDR;
+ sun4_eth_physaddr=SUN4_400_ETH_PHYSADDR;
+ sun4_si_physaddr=SUN4_UNUSED_PHYSADDR;
+ sun4_bwtwo_physaddr=SUN4_400_BWTWO_PHYSADDR;
+ sun4_dma_physaddr=SUN4_400_DMA_PHYSADDR;
+ sun4_esp_physaddr=SUN4_400_ESP_PHYSADDR;
+ break;
+ default:
+ }
+}
+
diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
index 2fe56b344..7529c679a 100644
--- a/arch/sparc/kernel/sys_sparc.c
+++ b/arch/sparc/kernel/sys_sparc.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.40 1998/03/28 08:29:26 davem Exp $
+/* $Id: sys_sparc.c,v 1.46 1998/08/03 23:58:01 davem Exp $
* linux/arch/sparc/kernel/sys_sparc.c
*
* This file contains various random system calls that
@@ -37,19 +37,11 @@ extern asmlinkage unsigned long sys_brk(unsigned long brk);
asmlinkage unsigned long sparc_brk(unsigned long brk)
{
- unsigned long ret;
-
- lock_kernel();
if(ARCH_SUN4C_SUN4) {
- if(brk >= 0x20000000 && brk < 0xe0000000) {
- ret = current->mm->brk;
- goto out;
- }
+ if(brk >= 0x20000000 && brk < 0xe0000000)
+ return current->mm->brk;
}
- ret = sys_brk(brk);
-out:
- unlock_kernel();
- return ret;
+ return sys_brk(brk);
}
/*
@@ -181,8 +173,6 @@ out:
return err;
}
-extern unsigned long get_unmapped_area(unsigned long addr, unsigned long len);
-
/* Linux version of mmap */
asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags, unsigned long fd,
@@ -334,15 +324,23 @@ asmlinkage int sys_pause(void)
asmlinkage int sys_getdomainname(char *name, int len)
{
- int nlen = strlen(system_utsname.domainname);
+ int nlen;
+ int err = -EFAULT;
+
+ down(&uts_sem);
+
+ nlen = strlen(system_utsname.domainname) + 1;
if (nlen < len)
len = nlen;
if(len > __NEW_UTS_LEN)
- return -EFAULT;
+ goto done;
if(copy_to_user(name, system_utsname.domainname, len))
- return -EFAULT;
- return 0;
+ goto done;
+ err = 0;
+done:
+ up(&uts_sem);
+ return err;
}
diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
index bd7bf5d77..d54c9352d 100644
--- a/arch/sparc/kernel/sys_sunos.c
+++ b/arch/sparc/kernel/sys_sunos.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.87 1998/03/29 03:48:16 shadow Exp $
+/* $Id: sys_sunos.c,v 1.91 1998/06/16 04:37:04 davem Exp $
* sys_sunos.c: SunOS specific syscall compatibility support.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -60,8 +60,6 @@
/* NR_OPEN is now larger and dynamic in recent kernels. */
#define SUNOS_NR_OPEN 256
-extern unsigned long get_unmapped_area(unsigned long addr, unsigned long len);
-
/* We use the SunOS mmap() semantics. */
asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
@@ -569,25 +567,6 @@ out:
return error;
}
-asmlinkage int sunos_getdomainname(char *name, int len)
-{
- int nlen = strlen(system_utsname.domainname);
- int ret = -EFAULT;
-
- lock_kernel();
- if (nlen < len)
- len = nlen;
-
- if(len > __NEW_UTS_LEN)
- goto out;
- if(copy_to_user(name, system_utsname.domainname, len))
- goto out;
- ret = 0;
-out:
- unlock_kernel();
- return ret;
-}
-
struct sunos_utsname {
char sname[9];
char nname[9];
@@ -601,7 +580,7 @@ asmlinkage int sunos_uname(struct sunos_utsname *name)
{
int ret = -EFAULT;
- lock_kernel();
+ down(&uts_sem);
if(!name)
goto out;
if(copy_to_user(&name->sname[0], &system_utsname.sysname[0], sizeof(name->sname) - 1))
@@ -613,7 +592,7 @@ asmlinkage int sunos_uname(struct sunos_utsname *name)
copy_to_user(&name->mach[0], &system_utsname.machine[0], sizeof(name->mach) - 1);
ret = 0;
out:
- unlock_kernel();
+ up(&uts_sem);
return ret;
}
diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
index 320264255..08aae84c9 100644
--- a/arch/sparc/kernel/systbls.S
+++ b/arch/sparc/kernel/systbls.S
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.71 1998/03/24 06:25:06 ecd Exp $
+/* $Id: systbls.S,v 1.75 1998/07/28 13:07:48 jj Exp $
* systbls.S: System call entry point tables for OS compatibility.
* The native Linux system call table lives here also.
*
@@ -23,17 +23,17 @@ C_LABEL(sys_call_table):
/*5*/ .long C_LABEL(sys_open), C_LABEL(sys_close), C_LABEL(sys_wait4)
.long C_LABEL(sys_creat), C_LABEL(sys_link)
/*10*/ .long C_LABEL(sys_unlink), C_LABEL(sunos_execv), C_LABEL(sys_chdir)
- .long C_LABEL(sys_xstat), C_LABEL(sys_mknod)
+ .long C_LABEL(sys_nis_syscall), C_LABEL(sys_mknod)
/*15*/ .long C_LABEL(sys_chmod), C_LABEL(sys_lchown), C_LABEL(sparc_brk)
- .long C_LABEL(sys_xmknod), C_LABEL(sys_lseek)
-/*20*/ .long C_LABEL(sys_getpid), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
+ .long C_LABEL(sys_nis_syscall), C_LABEL(sys_lseek)
+/*20*/ .long C_LABEL(sys_getpid), C_LABEL(sys_capget), C_LABEL(sys_capset)
.long C_LABEL(sys_setuid), C_LABEL(sys_getuid)
/*25*/ .long C_LABEL(sys_time), C_LABEL(sys_ptrace), C_LABEL(sys_alarm)
- .long C_LABEL(sys_nis_syscall), C_LABEL(sys_pause)
+ .long C_LABEL(sys_sigaltstack), C_LABEL(sys_pause)
/*30*/ .long C_LABEL(sys_utime), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
.long C_LABEL(sys_access), C_LABEL(sys_nice), C_LABEL(sys_nis_syscall)
.long C_LABEL(sys_sync), C_LABEL(sys_kill), C_LABEL(sys_newstat)
- .long C_LABEL(sys_nis_syscall), C_LABEL(sys_newlstat), C_LABEL(sys_dup)
+ .long C_LABEL(sys_sendfile), C_LABEL(sys_newlstat), C_LABEL(sys_dup)
.long C_LABEL(sys_pipe), C_LABEL(sys_times), C_LABEL(sys_nis_syscall)
.long C_LABEL(sys_nis_syscall), C_LABEL(sys_setgid), C_LABEL(sys_getgid)
.long C_LABEL(sys_signal), C_LABEL(sys_geteuid)
@@ -63,14 +63,13 @@ C_LABEL(sys_call_table):
.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
.long C_LABEL(sys_gettimeofday), C_LABEL(sys_getrusage)
- .long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_readv)
+ .long C_LABEL(sys_nis_syscall), C_LABEL(sys_getcwd), C_LABEL(sys_readv)
.long C_LABEL(sys_writev), C_LABEL(sys_settimeofday), C_LABEL(sys_fchown)
.long C_LABEL(sys_fchmod), C_LABEL(sys_nis_syscall), C_LABEL(sys_setreuid)
.long C_LABEL(sys_setregid), C_LABEL(sys_rename), C_LABEL(sys_truncate)
.long C_LABEL(sys_ftruncate), C_LABEL(sys_flock), C_LABEL(sys_nis_syscall)
.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
-
- .long C_LABEL(sys_mkdir), C_LABEL(sys_rmdir), C_LABEL(sys_nis_syscall)
+ .long C_LABEL(sys_mkdir), C_LABEL(sys_rmdir), C_LABEL(sys_utimes)
.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_getrlimit)
.long C_LABEL(sys_setrlimit), C_LABEL(sys_nis_syscall), C_LABEL(sys_prctl)
@@ -187,7 +186,7 @@ C_LABEL(sunos_sys_table):
.long C_LABEL(sys_poll), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
.long C_LABEL(sunos_getdirentries), C_LABEL(sys_statfs), C_LABEL(sys_fstatfs)
.long C_LABEL(sys_umount), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
- .long C_LABEL(sunos_getdomainname), C_LABEL(sys_setdomainname)
+ .long C_LABEL(sys_getdomainname), C_LABEL(sys_setdomainname)
.long C_LABEL(sunos_nosys), C_LABEL(sys_quotactl), C_LABEL(sunos_nosys)
.long C_LABEL(sunos_mount), C_LABEL(sys_ustat), C_LABEL(sunos_semsys)
.long C_LABEL(sunos_msgsys), C_LABEL(sunos_shmsys), C_LABEL(sunos_audit)
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
index 5eb49e22c..dba16891c 100644
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -1,9 +1,12 @@
-/* $Id: time.c,v 1.32 1998/03/23 08:41:13 jj Exp $
+/* $Id: time.c,v 1.33 1998/07/28 16:52:48 jj Exp $
* linux/arch/sparc/kernel/time.c
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
* Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
*
+ * Chris Davis (cdavis@cois.on.ca) 03/27/1998
+ * Added support for the intersil on the sun4/4200
+ *
* This file handles the Sparc specific time handling details.
*/
#include <linux/config.h>
@@ -34,6 +37,27 @@ struct mostek48t02 *mstk48t02_regs = 0;
struct mostek48t08 *mstk48t08_regs = 0;
static int set_rtc_mmss(unsigned long);
+#ifdef CONFIG_SUN4
+struct intersil *intersil_clock;
+#define intersil_cmd(intersil_reg, intsil_cmd) intersil_reg->int_cmd_reg = \
+ (intsil_cmd)
+
+#define intersil_intr(intersil_reg, intsil_cmd) intersil_reg->int_intr_reg = \
+ (intsil_cmd)
+
+#define intersil_start(intersil_reg) intersil_cmd(intersil_reg, \
+ ( INTERSIL_START | INTERSIL_32K | INTERSIL_NORMAL | INTERSIL_24H |\
+ INTERSIL_INTR_ENABLE))
+
+#define intersil_stop(intersil_reg) intersil_cmd(intersil_reg, \
+ ( INTERSIL_STOP | INTERSIL_32K | INTERSIL_NORMAL | INTERSIL_24H |\
+ INTERSIL_INTR_ENABLE))
+
+#define intersil_read_intr(intersil_reg, towhere) towhere = \
+ intersil_reg->int_intr_reg
+
+#endif
+
__volatile__ unsigned int *master_l10_counter;
__volatile__ unsigned int *master_l10_limit;
@@ -46,6 +70,12 @@ void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
/* last time the cmos clock got updated */
static long last_rtc_update=0;
+#ifdef CONFIG_SUN4
+ int temp;
+ intersil_read_intr(intersil_clock, temp);
+ /* re-enable the irq */
+ enable_pil_irq(10);
+#endif
clear_clock_irq();
do_timer(regs);
@@ -154,20 +184,52 @@ static __inline__ int has_low_battery(void)
return (data1 == data2); /* Was the write blocked? */
}
-/* Probe for the real time clock chip on Sun4/300. */
+/* Probe for the real time clock chip on Sun4 */
static __inline__ void sun4_clock_probe(void)
{
- sp_clock_typ = MSTK48T02;
- mstk48t02_regs = (struct mostek48t02 *)
- sparc_alloc_io(SUN4_300_MOSTEK_PHYSADDR, 0,
- sizeof(*mstk48t02_regs),
- "clock", 0x0, 0x0);
- mstk48t08_regs = 0; /* To catch weirdness */
- /* Kick start the clock if it is completely stopped. */
- if (mstk48t02_regs->sec & MSTK_STOP) {
- kick_start_clock();
- }
+#ifdef CONFIG_SUN4
+ int temp;
+
+ if( idprom->id_machtype == (SM_SUN4 | SM_4_330) ) {
+ sp_clock_typ = MSTK48T02;
+ mstk48t02_regs = (struct mostek48t02 *)
+ sparc_alloc_io(sun4_clock_physaddr, 0,
+ sizeof(*mstk48t02_regs),
+ "clock", 0x0, 0x0);
+ mstk48t08_regs = 0; /* To catch weirdness */
+ intersil_clock = 0; /* just in case */
+
+ /* Kick start the clock if it is completely stopped. */
+ if (mstk48t02_regs->sec & MSTK_STOP)
+ kick_start_clock();
+ } else if( idprom->id_machtype == (SM_SUN4 | SM_4_260)) {
+ /* intersil setup code */
+ printk("Clock: INTERSIL at %8x ",sun4_clock_physaddr);
+ sp_clock_typ = INTERSIL;
+ intersil_clock = (struct intersil *)
+ sparc_alloc_io(sun4_clock_physaddr, 0,
+ sizeof(*intersil_clock),
+ "clock", 0x0, 0x0);
+ mstk48t02_regs = 0; /* just be sure */
+ mstk48t08_regs = 0; /* ditto */
+ /* initialise the clock */
+
+ intersil_intr(intersil_clock,INTERSIL_INT_100HZ);
+
+ intersil_start(intersil_clock);
+
+ intersil_read_intr(intersil_clock, temp);
+ while (!(temp & 0x80))
+ intersil_read_intr(intersil_clock, temp);
+
+ intersil_read_intr(intersil_clock, temp);
+ while (!(temp & 0x80))
+ intersil_read_intr(intersil_clock, temp);
+ intersil_stop(intersil_clock);
+
+ }
+#endif
}
/* Probe for the mostek real time clock chip. */
@@ -259,6 +321,11 @@ __initfunc(void time_init(void))
unsigned int year, mon, day, hour, min, sec;
struct mostek48t02 *mregs;
+#ifdef CONFIG_SUN4
+ int temp;
+ struct intersil *iregs;
+#endif
+
do_get_fast_time = do_gettimeofday;
#if CONFIG_AP1000
@@ -273,6 +340,10 @@ __initfunc(void time_init(void))
clock_probe();
init_timers(timer_interrupt);
+
+#ifdef CONFIG_SUN4
+ if(idprom->id_machtype == (SM_SUN4 | SM_4_330)) {
+#endif
mregs = mstk48t02_regs;
if(!mregs) {
@@ -289,6 +360,38 @@ __initfunc(void time_init(void))
xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
xtime.tv_usec = 0;
mregs->creg &= ~MSTK_CREG_READ;
+#ifdef CONFIG_SUN4
+ } else if(idprom->id_machtype == (SM_SUN4 | SM_4_260) ) {
+ /* initialise the intersil on sun4 */
+
+ iregs=intersil_clock;
+ if(!iregs) {
+ prom_printf("Something wrong, clock regs not mapped yet.\n");
+ prom_halt();
+ }
+
+ intersil_intr(intersil_clock,INTERSIL_INT_100HZ);
+ disable_pil_irq(10);
+ intersil_stop(iregs);
+ intersil_read_intr(intersil_clock, temp);
+
+ temp = iregs->clk.int_csec;
+
+ sec = iregs->clk.int_sec;
+ min = iregs->clk.int_min;
+ hour = iregs->clk.int_hour;
+ day = iregs->clk.int_day;
+ mon = iregs->clk.int_month;
+ year = MSTK_CVT_YEAR(iregs->clk.int_year);
+
+ enable_pil_irq(10);
+ intersil_start(iregs);
+
+ xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
+ xtime.tv_usec = 0;
+ printk("%u/%u/%u %u:%u:%u\n",day,mon,year,hour,min,sec);
+ }
+#endif
/* Now that OBP ticker has been silenced, it is safe to enable IRQ. */
__sti();
@@ -375,11 +478,39 @@ static int set_rtc_mmss(unsigned long nowtime)
{
int real_seconds, real_minutes, mostek_minutes;
struct mostek48t02 *regs = mstk48t02_regs;
+#ifdef CONFIG_SUN4
+ struct intersil *iregs = intersil_clock;
+ int temp;
+#endif
/* Not having a register set can lead to trouble. */
- if (!regs)
+ if (!regs) {
+#ifdef CONFIG_SUN4
+ if(!iregs)
return -1;
-
+ else {
+ temp = iregs->clk.int_csec;
+
+ mostek_minutes = iregs->clk.int_min;
+
+ real_seconds = nowtime % 60;
+ real_minutes = nowtime / 60;
+ if (((abs(real_minutes - mostek_minutes) + 15)/30) & 1)
+ real_minutes += 30; /* correct for half hour time zone */
+ real_minutes %= 60;
+
+ if (abs(real_minutes - mostek_minutes) < 30) {
+ intersil_stop(iregs);
+ iregs->clk.int_sec=real_seconds;
+ iregs->clk.int_min=real_minutes;
+ intersil_start(iregs);
+ } else
+ return -1;
+
+ return 0;
+ }
+#endif
+ }
/* Read the current RTC minutes. */
regs->creg |= MSTK_CREG_READ;
mostek_minutes = MSTK_REG_MIN(regs);
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile
index 6ec986c86..9ce3a6630 100644
--- a/arch/sparc/lib/Makefile
+++ b/arch/sparc/lib/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.25 1998/01/30 10:58:43 jj Exp $
+# $Id: Makefile,v 1.26 1998/07/26 03:02:43 davem Exp $
# Makefile for Sparc library files..
#
@@ -45,8 +45,6 @@ blockops.o: blockops.S
memset.o: memset.S
$(CC) -D__ASSEMBLY__ -ansi -c -o memset.o memset.S
-ifdef SMP
-
locks.o: locks.S
$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o locks.o locks.S
@@ -56,20 +54,9 @@ atomic.o: atomic.S
bitops.o: bitops.S
$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o bitops.o bitops.S
+ifdef SMP
irqlock.o: irqlock.S
$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o irqlock.o irqlock.S
-
-else
-
-locks.o: locks.S
- $(CC) -D__ASSEMBLY__ -ansi -c -o locks.o locks.S
-
-atomic.o: atomic.S
- $(CC) -D__ASSEMBLY__ -ansi -c -o atomic.o atomic.S
-
-bitops.o: bitops.S
- $(CC) -D__ASSEMBLY__ -ansi -c -o bitops.o bitops.S
-
endif
strlen.o: strlen.S
diff --git a/arch/sparc/lib/locks.S b/arch/sparc/lib/locks.S
index e91efdc09..8d634704f 100644
--- a/arch/sparc/lib/locks.S
+++ b/arch/sparc/lib/locks.S
@@ -1,4 +1,4 @@
-/* $Id: locks.S,v 1.12 1997/04/22 18:48:07 davem Exp $
+/* $Id: locks.S,v 1.13 1998/07/30 11:29:28 davem Exp $
* locks.S: SMP low-level lock primitives on Sparc.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -20,8 +20,8 @@
* itself in %g1, %g4 must be restored into %o7 when we return,
* and the caller wants us to return to him at three instructions
* previous to the call instruction which got us here. See how
- * this is used in asm/smp_lock.h and asm/spinlock.h if what I
- * just said confuses you to no end.
+ * this is used in asm/spinlock.h if what I just said confuses
+ * you to no end.
*/
.globl ___spinlock_waitfor
___spinlock_waitfor:
@@ -32,74 +32,6 @@ ___spinlock_waitfor:
jmpl %o7 - 12, %g0
mov %g4, %o7
-___lk_busy_spin:
- orcc %g2, 0, %g0
- bne,a ___lk_busy_spin
- ldub [%g1 + 0], %g2
- b 1f
- ldstub [%g1 + 0], %g2
-
- .globl ___lock_kernel
-___lock_kernel:
- addcc %g2, -1, %g2
- bcs,a 9f
- st %g2, [%g6 + AOFF_task_lock_depth]
- rd %psr, %g3
- or %g3, PSR_PIL, %g2
- wr %g2, 0x0, %psr
- nop; nop; nop
- ldstub [%g1 + 0], %g2
-1: orcc %g2, 0, %g0
- bne,a ___lk_busy_spin
- ldub [%g1 + 0], %g2
- stb %g5, [%g1 + 1]
- mov -1, %g2
- st %g2, [%g6 + AOFF_task_lock_depth]
- wr %g3, 0x0, %psr
- nop; nop; nop
-9: jmpl %o7 + 0x8, %g0
- mov %g4, %o7
-
- .globl ___lock_reacquire_kernel
-___lock_reacquire_kernel:
- rd %psr, %g3
- or %g3, PSR_PIL, %g7
- wr %g7, 0x0, %psr
- nop; nop; nop
- st %g2, [%g6 + AOFF_task_lock_depth]
- ldstub [%g1 + 0], %g2
-1: orcc %g2, 0, %g0
- be 3f
- ldub [%g1 + 0], %g2
-2: orcc %g2, 0, %g0
- bne,a 2b
- ldub [%g1 + 0], %g2
- b 1b
- ldstub [%g1 + 0], %g2
-3: stb %g5, [%g1 + 1]
- wr %g3, 0x0, %psr
- nop; nop; nop
- jmpl %o7 + 0x8, %g0
- mov %g4, %o7
-
- .globl ___unlock_kernel
-___unlock_kernel:
- addcc %g2, 1, %g2
- bne,a 1f
- st %g2, [%g6 + AOFF_task_lock_depth]
- rd %psr, %g3
- or %g3, PSR_PIL, %g2
- wr %g2, 0x0, %psr
- nop; nop; nop
- mov NO_PROC_ID, %g2
- stb %g2, [%g1 + 1]
- stb %g0, [%g1 + 0]
- st %g0, [%g6 + AOFF_task_lock_depth]
- wr %g3, 0x0, %psr
- nop; nop; nop;
-1: jmpl %o7 + 0x8, %g0
- mov %g4, %o7
-
/* Read/writer locks, as usual this is overly clever to make it
* as fast as possible.
*/
diff --git a/arch/sparc/math-emu/fnegs.c b/arch/sparc/math-emu/fnegs.c
index 39188eea6..1c662f201 100644
--- a/arch/sparc/math-emu/fnegs.c
+++ b/arch/sparc/math-emu/fnegs.c
@@ -4,4 +4,3 @@ int FNEGS(unsigned long *rd, unsigned long *rs2)
rd[0] = rs2[0] ^ 0x80000000UL;
return 1;
}
-
diff --git a/arch/sparc/mm/Makefile b/arch/sparc/mm/Makefile
index 18eeb1f52..929b2a6f0 100644
--- a/arch/sparc/mm/Makefile
+++ b/arch/sparc/mm/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.30 1998/03/09 14:03:53 jj Exp $
+# $Id: Makefile,v 1.31 1998/07/26 03:02:45 davem Exp $
# Makefile for the linux Sparc-specific parts of the memory manager.
#
# Note! Dependencies are done automagically by 'make dep', which also
@@ -22,8 +22,6 @@ endif
include $(TOPDIR)/Rules.make
-ifdef SMP
-
hypersparc.o: hypersparc.S
$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o hypersparc.o hypersparc.S
@@ -35,19 +33,3 @@ viking.o: viking.S
tsunami.o: tsunami.S
$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o tsunami.o tsunami.S
-
-else
-
-hypersparc.o: hypersparc.S
- $(CC) -D__ASSEMBLY__ -ansi -c -o hypersparc.o hypersparc.S
-
-turbosparc.o: turbosparc.S
- $(CC) -D__ASSEMBLY__ -ansi -c -o turbosparc.o turbosparc.S
-
-viking.o: viking.S
- $(CC) -D__ASSEMBLY__ -ansi -c -o viking.o viking.S
-
-tsunami.o: tsunami.S
- $(CC) -D__ASSEMBLY__ -ansi -c -o tsunami.o tsunami.S
-
-endif
diff --git a/arch/sparc/mm/fault.c b/arch/sparc/mm/fault.c
index 274b9eebf..88d85004c 100644
--- a/arch/sparc/mm/fault.c
+++ b/arch/sparc/mm/fault.c
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.93 1998/03/25 10:43:16 jj Exp $
+/* $Id: fault.c,v 1.94 1998/05/01 16:00:27 jj Exp $
* fault.c: Page fault handlers for the Sparc.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -248,9 +248,11 @@ bad_area:
extern const unsigned __csum_partial_copy_start[];
extern const unsigned __csum_partial_copy_end[];
+#ifdef DEBUG_EXCEPTIONS
printk("Exception: PC<%08lx> faddr<%08lx>\n", regs->pc, address);
printk("EX_TABLE: insn<%08lx> fixup<%08x> g2<%08lx>\n",
regs->pc, fixup, g2);
+#endif
if ((regs->pc >= (unsigned long)__memset_start &&
regs->pc < (unsigned long)__memset_end) ||
(regs->pc >= (unsigned long)__csum_partial_copy_start &&
diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c
index d293fc71c..41bd72671 100644
--- a/arch/sparc/mm/io-unit.c
+++ b/arch/sparc/mm/io-unit.c
@@ -1,4 +1,4 @@
-/* $Id: io-unit.c,v 1.10 1998/03/03 12:31:14 jj Exp $
+/* $Id: io-unit.c,v 1.11 1998/04/13 07:26:37 davem Exp $
* io-unit.c: IO-UNIT specific routines for memory management.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -23,22 +23,17 @@
#define IOD(x) do { } while (0)
#endif
-#define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1))
-
#define IOPERM (IOUPTE_CACHE | IOUPTE_WRITE | IOUPTE_VALID)
#define MKIOPTE(phys) __iopte((((phys)>>4) & IOUPTE_PAGE) | IOPERM)
-__initfunc(unsigned long
-iounit_init(int sbi_node, int io_node, unsigned long memory_start,
- unsigned long memory_end, struct linux_sbus *sbus))
+__initfunc(void
+iounit_init(int sbi_node, int io_node, struct linux_sbus *sbus))
{
iopte_t *xpt, *xptend;
struct iounit_struct *iounit;
struct linux_prom_registers iommu_promregs[PROMREG_MAX];
- memory_start = LONG_ALIGN(memory_start);
- iounit = (struct iounit_struct *)memory_start;
- memory_start = LONG_ALIGN(memory_start + sizeof(struct iounit_struct));
+ iounit = kmalloc(sizeof(struct iounit_struct), GFP_ATOMIC);
memset(iounit, 0, sizeof(*iounit));
iounit->limit[0] = IOUNIT_BMAP1_START;
@@ -62,8 +57,6 @@ iounit_init(int sbi_node, int io_node, unsigned long memory_start,
for (xptend = iounit->page_table + (16 * PAGE_SIZE) / sizeof(iopte_t);
xpt < xptend;)
*xpt++ = 0;
-
- return memory_start;
}
/* One has to hold iounit->lock to call this */
diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c
index e46216233..c7c6bdd5f 100644
--- a/arch/sparc/mm/iommu.c
+++ b/arch/sparc/mm/iommu.c
@@ -1,4 +1,4 @@
-/* $Id: iommu.c,v 1.7 1998/02/22 10:32:26 ecd Exp $
+/* $Id: iommu.c,v 1.9 1998/04/15 14:58:37 jj Exp $
* iommu.c: IOMMU specific routines for memory management.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -10,6 +10,7 @@
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/mm.h>
#include <linux/malloc.h>
#include <asm/pgtable.h>
#include <asm/sbus.h>
@@ -26,14 +27,12 @@ static int viking_flush = 0;
extern void viking_flush_page(unsigned long page);
extern void viking_mxcc_flush_page(unsigned long page);
-#define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1))
-
#define IOPERM (IOPTE_CACHE | IOPTE_WRITE | IOPTE_VALID)
#define MKIOPTE(phys) (((((phys)>>4) & IOPTE_PAGE) | IOPERM) & ~IOPTE_WAZ)
-static inline void iommu_map_dvma_pages_for_iommu(struct iommu_struct *iommu,
- unsigned long kern_end)
+static inline void iommu_map_dvma_pages_for_iommu(struct iommu_struct *iommu)
{
+ unsigned long kern_end = (unsigned long) high_memory;
unsigned long first = page_offset;
unsigned long last = kern_end;
iopte_t *iopte = iommu->page_table;
@@ -45,18 +44,17 @@ static inline void iommu_map_dvma_pages_for_iommu(struct iommu_struct *iommu,
}
}
-__initfunc(unsigned long
-iommu_init(int iommund, unsigned long memory_start,
- unsigned long memory_end, struct linux_sbus *sbus))
+__initfunc(void
+iommu_init(int iommund, struct linux_sbus *sbus))
{
unsigned int impl, vers, ptsize;
unsigned long tmp;
struct iommu_struct *iommu;
struct linux_prom_registers iommu_promregs[PROMREG_MAX];
+ int i, j, k, l, m;
+ struct iommu_alloc { unsigned long addr; int next; } *ia;
- memory_start = LONG_ALIGN(memory_start);
- iommu = (struct iommu_struct *) memory_start;
- memory_start += sizeof(struct iommu_struct);
+ iommu = kmalloc(sizeof(struct iommu_struct), GFP_ATOMIC);
prom_getproperty(iommund, "reg", (void *) iommu_promregs,
sizeof(iommu_promregs));
iommu->regs = (struct iommu_regs *)
@@ -98,16 +96,68 @@ iommu_init(int iommund, unsigned long memory_start,
ptsize = iommu->end - iommu->start + 1;
ptsize = (ptsize >> PAGE_SHIFT) * sizeof(iopte_t);
- /* Stupid alignment constraints give me a headache. */
- memory_start = PAGE_ALIGN(memory_start);
- memory_start = (((memory_start) + (ptsize - 1)) & ~(ptsize - 1));
- iommu->lowest = iommu->page_table = (iopte_t *) memory_start;
- memory_start += ptsize;
+ /* Stupid alignment constraints give me a headache.
+ We want to get very large aligned memory area, larger than
+ maximum what get_free_pages gives us (128K): we need
+ 256K or 512K or 1M or 2M aligned to its size. */
+ ia = (struct iommu_alloc *) kmalloc (sizeof(struct iommu_alloc) * 128, GFP_ATOMIC);
+ for (i = 0; i < 128; i++) {
+ ia[i].addr = 0;
+ ia[i].next = -1;
+ }
+ k = 0;
+ for (i = 0; i < 128; i++) {
+ ia[i].addr = __get_free_pages(GFP_DMA, 5);
+ if (ia[i].addr <= ia[k].addr) {
+ if (i) {
+ ia[i].next = k;
+ k = i;
+ }
+ } else {
+ for (m = k, l = ia[k].next; l != -1; m = l, l = ia[l].next)
+ if (ia[i].addr <= ia[l].addr) {
+ ia[i].next = l;
+ ia[m].next = i;
+ }
+ if (l == -1)
+ ia[m].next = i;
+ }
+ for (m = -1, j = 0, l = k; l != -1; l = ia[l].next) {
+ if (!(ia[l].addr & (ptsize - 1))) {
+ tmp = ia[l].addr;
+ m = l;
+ j = 128 * 1024;
+ } else if (m != -1) {
+ if (ia[l].addr != tmp + j)
+ m = -1;
+ else {
+ j += 128 * 1024;
+ if (j == ptsize) {
+ break;
+ }
+ }
+ }
+ }
+ if (l != -1)
+ break;
+ }
+ if (i == 128) {
+ prom_printf("Could not allocate iopte of size 0x%08x\n", ptsize);
+ prom_halt();
+ }
+ for (l = m, j = 0; j < ptsize; j += 128 * 1024, l = ia[l].next)
+ ia[l].addr = 0;
+ for (l = k; l != -1; l = ia[l].next)
+ if (ia[l].addr)
+ free_pages(ia[l].addr, 5);
+ kfree (ia);
+ iommu->lowest = iommu->page_table = (iopte_t *)tmp;
+
/* Initialize new table. */
flush_cache_all();
memset(iommu->page_table, 0, ptsize);
- iommu_map_dvma_pages_for_iommu(iommu, memory_end);
+ iommu_map_dvma_pages_for_iommu(iommu);
if(viking_mxcc_present) {
unsigned long start = (unsigned long) iommu->page_table;
unsigned long end = (start + ptsize);
@@ -130,7 +180,6 @@ iommu_init(int iommund, unsigned long memory_start,
sbus->iommu = iommu;
printk("IOMMU: impl %d vers %d page table at %p of size %d bytes\n",
impl, vers, iommu->page_table, ptsize);
- return memory_start;
}
static __u32 iommu_get_scsi_one_noflush(char *vaddr, unsigned long len, struct linux_sbus *sbus)
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index f9794125d..97bd5be37 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -1,4 +1,4 @@
-/* $Id: srmmu.c,v 1.170 1998/03/09 14:04:01 jj Exp $
+/* $Id: srmmu.c,v 1.173 1998/08/04 20:48:57 davem Exp $
* srmmu.c: SRMMU specific routines for memory management.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -512,7 +512,7 @@ static inline pgd_t *srmmu_get_pgd_fast(void)
pgd_cache_size--;
}
spin_unlock(&pgd_spinlock);
- return (pte_t *)ret;
+ return (pgd_t *)ret;
}
static inline pgd_t *srmmu_get_pgd_slow(void)
@@ -1034,7 +1034,7 @@ static void cypress_flush_cache_mm(struct mm_struct *mm)
FLUSH_BEGIN(mm)
flush_user_windows();
- save_and_cli(flags);
+ __save_and_cli(flags);
octx = srmmu_get_context();
srmmu_set_context(mm->context);
a = 0x20; b = 0x40; c = 0x60;
@@ -1058,7 +1058,7 @@ static void cypress_flush_cache_mm(struct mm_struct *mm)
"r" (e), "r" (f), "r" (g));
} while(faddr);
srmmu_set_context(octx);
- restore_flags(flags);
+ __restore_flags(flags);
FLUSH_END
}
@@ -1070,7 +1070,7 @@ static void cypress_flush_cache_range(struct mm_struct *mm, unsigned long start,
FLUSH_BEGIN(mm)
flush_user_windows();
- save_and_cli(flags);
+ __save_and_cli(flags);
octx = srmmu_get_context();
srmmu_set_context(mm->context);
a = 0x20; b = 0x40; c = 0x60;
@@ -1099,7 +1099,7 @@ static void cypress_flush_cache_range(struct mm_struct *mm, unsigned long start,
start += SRMMU_PMD_SIZE;
}
srmmu_set_context(octx);
- restore_flags(flags);
+ __restore_flags(flags);
FLUSH_END
}
@@ -1112,7 +1112,7 @@ static void cypress_flush_cache_page(struct vm_area_struct *vma, unsigned long p
FLUSH_BEGIN(mm)
flush_user_windows();
- save_and_cli(flags);
+ __save_and_cli(flags);
octx = srmmu_get_context();
srmmu_set_context(mm->context);
a = 0x20; b = 0x40; c = 0x60;
@@ -1138,7 +1138,7 @@ static void cypress_flush_cache_page(struct vm_area_struct *vma, unsigned long p
"r" (e), "r" (f), "r" (g));
} while(line != page);
srmmu_set_context(octx);
- restore_flags(flags);
+ __restore_flags(flags);
FLUSH_END
}
@@ -2019,7 +2019,7 @@ static void srmmu_vac_update_mmu_cache(struct vm_area_struct * vma,
pmd_t *pmdp;
pte_t *ptep;
- save_and_cli(flags);
+ __save_and_cli(flags);
file = vma->vm_file;
if (!file)
@@ -2065,7 +2065,7 @@ static void srmmu_vac_update_mmu_cache(struct vm_area_struct * vma,
flush_tlb_page(vma, address);
}
done:
- restore_flags(flags);
+ __restore_flags(flags);
}
}
@@ -2722,16 +2722,12 @@ __initfunc(static void get_srmmu_type(void))
srmmu_is_bad();
}
-/* Low and high watermarks for page table cache.
- The system should try to have pgt_water[0] <= cache elements <= pgt_water[1]
- */
-extern int pgt_cache_water[2];
-
-void srmmu_check_pgt_cache(void)
+static int srmmu_check_pgt_cache(int low, int high)
{
struct page *page, *page2;
+ int freed = 0;
- if (pgtable_cache_size > pgt_cache_water[0]) {
+ if (pgtable_cache_size > high) {
spin_lock(&pte_spinlock);
for (page2 = NULL, page = (struct page *)pte_quicklist; page;) {
if ((unsigned int)page->pprev_hash == 0xffff) {
@@ -2743,11 +2739,12 @@ void srmmu_check_pgt_cache(void)
page->pprev_hash = NULL;
pgtable_cache_size -= 16;
free_page(PAGE_OFFSET + (page->map_nr << PAGE_SHIFT));
+ freed++;
if (page2)
page = page2->next_hash;
else
page = (struct page *)pte_quicklist;
- if (pgtable_cache_size <= pgt_cache_water[1])
+ if (pgtable_cache_size <= low)
break;
continue;
}
@@ -2756,7 +2753,7 @@ void srmmu_check_pgt_cache(void)
}
spin_unlock(&pte_spinlock);
}
- if (pgd_cache_size > pgt_cache_water[0] / 4) {
+ if (pgd_cache_size > high / 4) {
spin_lock(&pgd_spinlock);
for (page2 = NULL, page = (struct page *)pgd_quicklist; page;) {
if ((unsigned int)page->pprev_hash == 0xf) {
@@ -2768,11 +2765,12 @@ void srmmu_check_pgt_cache(void)
page->pprev_hash = NULL;
pgd_cache_size -= 4;
free_page(PAGE_OFFSET + (page->map_nr << PAGE_SHIFT));
+ freed++;
if (page2)
page = page2->next_hash;
else
page = (struct page *)pgd_quicklist;
- if (pgd_cache_size <= pgt_cache_water[1] / 4)
+ if (pgd_cache_size <= low / 4)
break;
continue;
}
@@ -2781,6 +2779,7 @@ void srmmu_check_pgt_cache(void)
}
spin_unlock(&pgd_spinlock);
}
+ return freed;
}
extern unsigned long spwin_mmu_patchme, fwin_mmu_patchme,
@@ -2853,6 +2852,7 @@ __initfunc(void ld_mmu_srmmu(void))
BTFIXUPSET_CALL(get_pgd_fast, srmmu_get_pgd_fast, BTFIXUPCALL_RETINT(0));
BTFIXUPSET_CALL(free_pte_slow, srmmu_free_pte_slow, BTFIXUPCALL_NOP);
BTFIXUPSET_CALL(free_pgd_slow, srmmu_free_pgd_slow, BTFIXUPCALL_NOP);
+ BTFIXUPSET_CALL(do_check_pgt_cache, srmmu_check_pgt_cache, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(set_pgdir, srmmu_set_pgdir, BTFIXUPCALL_NORM);
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index d247e1f2d..448881608 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -1,4 +1,4 @@
-/* $Id: sun4c.c,v 1.163 1998/03/11 04:08:21 tdyas Exp $
+/* $Id: sun4c.c,v 1.166 1998/08/04 20:49:05 davem Exp $
* sun4c.c: Doing in software what should be done in hardware.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -611,9 +611,8 @@ __initfunc(static void sun4c_probe_mmu(void))
break;
case (SM_SUN4|SM_4_260):
- prom_printf("No support for 4200 yet\n");
- prom_halt();
- num_segmaps = 512;
+ /* should be 512 segmaps. when it get fixed */
+ num_segmaps = 256;
num_contexts = 16;
break;
@@ -658,7 +657,7 @@ __initfunc(void sun4c_probe_memerr_reg(void))
struct linux_prom_registers regs[1];
if (ARCH_SUN4) {
- sun4c_memerr_reg = sparc_alloc_io(SUN4_MEMREG_PHYSADDR, 0,
+ sun4c_memerr_reg = sparc_alloc_io(sun4_memreg_physaddr, 0,
PAGE_SIZE,
"memory parity error",
0x0, 0);
@@ -756,11 +755,13 @@ static inline void fix_permissions(unsigned long vaddr, unsigned long bits_on,
~bits_off);
}
+/* the 4/260 dies real hard on the prom_putsegment line.
+ not sure why, but it seems to work without it cgd */
static inline void sun4c_init_map_kernelprom(unsigned long kernel_end)
{
unsigned long vaddr;
unsigned char pseg, ctx;
-
+#ifndef CONFIG_SUN4
for(vaddr = KADB_DEBUGGER_BEGVM;
vaddr < LINUX_OPPROM_ENDVM;
vaddr += SUN4C_REAL_PGDIR_SIZE) {
@@ -772,6 +773,7 @@ static inline void sun4c_init_map_kernelprom(unsigned long kernel_end)
fix_permissions(vaddr, _SUN4C_PAGE_PRIV, 0);
}
}
+#endif
for(vaddr = KERNBASE; vaddr < kernel_end; vaddr += SUN4C_REAL_PGDIR_SIZE) {
pseg = sun4c_get_segmap(vaddr);
mmu_entry_pool[pseg].locked = 1;
@@ -2536,6 +2538,22 @@ extern __inline__ pgd_t *sun4c_get_pgd_fast(void)
return (pgd_t *)ret;
}
+static int sun4c_check_pgt_cache(int low, int high)
+{
+ int freed = 0;
+ if(pgtable_cache_size > high) {
+ do {
+ if(pgd_quicklist)
+ free_pgd_slow(get_pgd_fast()), freed++;
+ if(pmd_quicklist)
+ free_pmd_slow(get_pmd_fast()), freed++;
+ if(pte_quicklist)
+ free_pte_slow(get_pte_fast()), freed++;
+ } while(pgtable_cache_size > low);
+ }
+ return freed;
+}
+
static void sun4c_set_pgdir(unsigned long address, pgd_t entry)
{
/* Nothing to do */
@@ -2803,6 +2821,7 @@ __initfunc(void ld_mmu_sun4c(void))
BTFIXUPSET_CALL(get_pgd_fast, sun4c_pgd_alloc, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(free_pte_slow, sun4c_free_pte_slow, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(free_pgd_slow, sun4c_free_pgd_slow, BTFIXUPCALL_NORM);
+ BTFIXUPSET_CALL(do_check_pgt_cache, sun4c_check_pgt_cache, BTFIXUPCALL_NORM);
BTFIXUPSET_CALL(set_pgdir, sun4c_set_pgdir, BTFIXUPCALL_NOP);
diff --git a/arch/sparc/prom/misc.c b/arch/sparc/prom/misc.c
index d2ec600e1..3c2f2434d 100644
--- a/arch/sparc/prom/misc.c
+++ b/arch/sparc/prom/misc.c
@@ -1,4 +1,4 @@
-/* $Id: misc.c,v 1.16 1998/03/09 14:04:25 jj Exp $
+/* $Id: misc.c,v 1.17 1998/07/21 10:36:22 jj Exp $
* misc.c: Miscellaneous prom functions that don't belong
* anywhere else.
*
@@ -45,8 +45,7 @@ prom_feval(char *fstring)
/* We want to do this more nicely some day. */
#ifdef CONFIG_SUN_CONSOLE
-extern void console_restore_palette(void);
-extern void set_palette(void);
+extern void (*prom_palette)(int);
extern int serial_console;
#endif
@@ -63,8 +62,8 @@ prom_cmdline(void)
kernel_enter_debugger();
#ifdef CONFIG_SUN_CONSOLE
- if(!serial_console)
- console_restore_palette ();
+ if(!serial_console && prom_palette)
+ prom_palette (1);
#endif
install_obp_ticker();
save_flags(flags); cli();
@@ -76,8 +75,8 @@ prom_cmdline(void)
TURN_ON_LED;
#endif
#ifdef CONFIG_SUN_CONSOLE
- if(!serial_console)
- set_palette ();
+ if(!serial_console && prom_palette)
+ prom_palette (0);
#endif
}