From c7fc24dc4420057f103afe8fc64524ebc25c5d37 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 25 Aug 1998 09:12:35 +0000 Subject: o Merge with Linux 2.1.116. o New Newport console code. o New G364 console code. --- arch/sparc/Makefile | 6 +- arch/sparc/ap1000/aplib.c | 2 +- arch/sparc/ap1000/mpp.c | 2 +- arch/sparc/ap1000/msc.c | 2 +- arch/sparc/ap1000/timer.c | 7 -- arch/sparc/ap1000/tnet.c | 2 +- arch/sparc/ap1000/util.c | 4 +- arch/sparc/config.in | 17 +-- arch/sparc/defconfig | 55 +++++----- arch/sparc/kernel/Makefile | 27 +---- arch/sparc/kernel/entry.S | 20 +++- arch/sparc/kernel/head.S | 12 +-- arch/sparc/kernel/idprom.c | 10 +- arch/sparc/kernel/irq.c | 5 +- arch/sparc/kernel/process.c | 43 +++----- arch/sparc/kernel/rtrap.S | 6 +- arch/sparc/kernel/setup.c | 32 ++++-- arch/sparc/kernel/signal.c | 224 ++++++++++++++++++++++++---------------- arch/sparc/kernel/smp.c | 6 +- arch/sparc/kernel/sparc_ksyms.c | 3 +- arch/sparc/kernel/sun4c_irq.c | 25 ++++- arch/sparc/kernel/sun4d_irq.c | 60 +++++------ arch/sparc/kernel/sun4d_smp.c | 10 +- arch/sparc/kernel/sun4m_irq.c | 8 ++ arch/sparc/kernel/sun4m_smp.c | 11 +- arch/sparc/kernel/sun4setup.c | 74 +++++++++++++ arch/sparc/kernel/sys_sparc.c | 34 +++--- arch/sparc/kernel/sys_sunos.c | 27 +---- arch/sparc/kernel/systbls.S | 19 ++-- arch/sparc/kernel/time.c | 159 +++++++++++++++++++++++++--- arch/sparc/lib/Makefile | 17 +-- arch/sparc/lib/locks.S | 74 +------------ arch/sparc/math-emu/fnegs.c | 1 - arch/sparc/mm/Makefile | 20 +--- arch/sparc/mm/fault.c | 4 +- arch/sparc/mm/io-unit.c | 15 +-- arch/sparc/mm/iommu.c | 85 +++++++++++---- arch/sparc/mm/srmmu.c | 40 +++---- arch/sparc/mm/sun4c.c | 31 ++++-- arch/sparc/prom/misc.c | 13 ++- 40 files changed, 720 insertions(+), 492 deletions(-) create mode 100644 arch/sparc/kernel/sun4setup.c (limited to 'arch/sparc') 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 /* for CONFIG_PROFILE */ #include #include #include @@ -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 @@ -32,20 +53,6 @@ CONFIG_SUN_CONSOLE=y 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 # @@ -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) @@ -1267,6 +1267,22 @@ C_LABEL(sys_pipe): call C_LABEL(sparc_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): 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 #include #include #include @@ -12,6 +13,10 @@ #include #include #include /* Fun with Sun released architectures. */ +#ifdef CONFIG_SUN4 +#include +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 #include #include +#include #include #include @@ -40,8 +41,8 @@ #include 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(¤t->tss.float_regs[0], &fpu->si_float_regs[0], + err = copy_from_user(¤t->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(¤t->tss.fpqueue[0], + err |= copy_from_user(¤t->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(¤t->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(®s->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(¤t->sigmask_lock); current->blocked = set; @@ -381,8 +388,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs) spin_unlock_irq(¤t->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], ®s->u_regs [UREG_G1], sizeof (long) * 7); copy_to_user(&(*gr)[SVR4_O0], ®s->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], ®s->u_regs [UREG_G1], sizeof (uint) * 7); copy_to_user(&(*gr)[SVR4_O0], ®s->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, ¤t->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(¤t->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 #include #include #include @@ -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 /* for CONFIG_PROFILE */ #include #include @@ -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 /* for CONFIG_PROFILE */ #include #include @@ -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 +#include +#include +#include +#include + +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 @@ -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 #include #include +#include #include #include #include @@ -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 } -- cgit v1.2.3