summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/config.in4
-rw-r--r--arch/alpha/kernel/osf_sys.c45
-rw-r--r--arch/alpha/math-emu/fp-emul.c28
-rw-r--r--arch/i386/config.in2
-rw-r--r--arch/i386/defconfig5
-rw-r--r--arch/i386/kernel/head.S4
-rw-r--r--arch/i386/kernel/irq.c19
-rw-r--r--arch/i386/kernel/irq.h14
-rw-r--r--arch/i386/kernel/smp.c14
-rw-r--r--arch/i386/kernel/time.c2
-rw-r--r--arch/i386/kernel/traps.c2
-rw-r--r--arch/m68k/amiga/amifb.c6
-rw-r--r--arch/m68k/amiga/amikeyb.c14
-rw-r--r--arch/m68k/amiga/amisound.c8
-rw-r--r--arch/m68k/amiga/config.c1
-rw-r--r--arch/m68k/atari/ataints.c43
-rw-r--r--arch/m68k/atari/atakeyb.c71
-rw-r--r--arch/m68k/console/fbcon.c4
-rw-r--r--arch/m68k/fpsp040/skeleton.S77
-rw-r--r--arch/m68k/kernel/console.c74
-rw-r--r--arch/m68k/kernel/entry.S160
-rw-r--r--arch/m68k/kernel/setup.c4
-rw-r--r--arch/m68k/kernel/traps.c2
-rw-r--r--arch/m68k/mm/init.c3
-rw-r--r--arch/m68k/mm/memory.c90
-rw-r--r--arch/mips/defconfig3
-rw-r--r--arch/mips/jazz/g364.c11
-rw-r--r--arch/mips/kernel/irixelf.c3
-rw-r--r--arch/sparc/config.in1
-rw-r--r--arch/sparc/defconfig4
-rw-r--r--arch/sparc64/config.in3
-rw-r--r--arch/sparc64/kernel/entry.S497
-rw-r--r--arch/sparc64/kernel/etrap.S30
-rw-r--r--arch/sparc64/kernel/hack.S6
-rw-r--r--arch/sparc64/kernel/head.S4
-rw-r--r--arch/sparc64/kernel/ioctl32.c502
-rw-r--r--arch/sparc64/kernel/process.c46
-rw-r--r--arch/sparc64/kernel/rtrap.S159
-rw-r--r--arch/sparc64/kernel/signal.c10
-rw-r--r--arch/sparc64/kernel/signal32.c67
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c1199
-rw-r--r--arch/sparc64/kernel/systbls.S10
-rw-r--r--arch/sparc64/kernel/traps.c164
-rw-r--r--arch/sparc64/kernel/ttable.S6
-rw-r--r--arch/sparc64/kernel/winfixup.S280
-rw-r--r--arch/sparc64/lib/checksum.S76
-rw-r--r--arch/sparc64/lib/copy_from_user.S16
-rw-r--r--arch/sparc64/lib/copy_to_user.S16
-rw-r--r--arch/sparc64/lib/memset.S8
-rw-r--r--arch/sparc64/lib/strlen_user.S12
-rw-r--r--arch/sparc64/lib/strncpy_from_user.S6
-rw-r--r--arch/sparc64/mm/fault.c39
-rw-r--r--arch/sparc64/vmlinux.lds1
53 files changed, 2473 insertions, 1402 deletions
diff --git a/arch/alpha/config.in b/arch/alpha/config.in
index e62ec31d0..774686ebd 100644
--- a/arch/alpha/config.in
+++ b/arch/alpha/config.in
@@ -94,10 +94,11 @@ bool 'System V IPC' CONFIG_SYSVIPC
bool 'Sysctl support' CONFIG_SYSCTL
tristate 'Kernel support for a.out (ECOFF) binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
-tristate 'Kernel support for Linux/Intel ELF binaries' CONFIG_BINFMT_EM86
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA
fi
+tristate 'Kernel support for Linux/Intel ELF binaries' CONFIG_BINFMT_EM86
tristate 'Parallel port support' CONFIG_PNP_PARPORT
endmenu
@@ -172,4 +173,5 @@ 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/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index ef9576492..3b3d8574b 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -295,7 +295,7 @@ asmlinkage int osf_statfs(char *path, struct osf_statfs *buffer, unsigned long b
retval = verify_area(VERIFY_WRITE, buffer, bufsiz);
if (retval)
goto out;
- retval = namei(path, &inode);
+ retval = namei(NAM_FOLLOW_LINK, path, &inode);
if (retval)
goto out;
retval = -ENOSYS;
@@ -376,7 +376,7 @@ static int getdev(const char *name, int rdonly, struct inode **ino)
struct file_operations *fops;
int retval;
- retval = namei(name, &inode);
+ retval = namei(NAM_FOLLOW_LINK, name, &inode);
if (retval)
return retval;
if (!S_ISBLK(inode->i_mode)) {
@@ -845,14 +845,12 @@ asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer,
unsigned long nbytes,
int *start, void *arg)
{
- extern unsigned long rdfpcr(void);
unsigned long w;
switch (op) {
case GSI_IEEE_FP_CONTROL:
- /* build and return current fp control word: */
- w = current->tss.flags & IEEE_TRAP_ENABLE_MASK;
- w |= ((rdfpcr() >> 52) << 17) & IEEE_STATUS_MASK;
+ /* Return current software fp control & status bits. */
+ w = current->tss.flags & IEEE_SW_MASK;
if (put_user(w, (unsigned long *) buffer))
return -EFAULT;
return 0;
@@ -883,16 +881,32 @@ asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer,
unsigned long nbytes,
int *start, void *arg)
{
- unsigned long v, w, i;
-
switch (op) {
- case SSI_IEEE_FP_CONTROL:
- /* update trap enable bits: */
- if (get_user(w, (unsigned long *) buffer))
+ case SSI_IEEE_FP_CONTROL: {
+ unsigned long swcr, fpcr;
+
+ /*
+ * Alpha Architecture Handbook 4.7.7.3:
+ * To be fully IEEE compiant, we must track the current IEEE
+ * exception state in software, because spurrious bits can be
+ * set in the trap shadow of a software-complete insn.
+ */
+
+ /* Update softare trap enable bits. */
+ if (get_user(swcr, (unsigned long *)buffer))
return -EFAULT;
- current->tss.flags &= ~IEEE_TRAP_ENABLE_MASK;
- current->tss.flags |= (w & IEEE_TRAP_ENABLE_MASK);
+ current->tss.flags &= ~IEEE_SW_MASK;
+ current->tss.flags |= swcr & IEEE_SW_MASK;
+
+ /* Update the real fpcr. For exceptions that are disabled in
+ software but have not been seen, enable the exception in
+ hardware so that we can update our software status mask. */
+ fpcr = rdfpcr() & (~FPCR_MASK | FPCR_DYN_MASK);
+ fpcr = ieee_swcr_to_fpcr(swcr | (~swcr & IEEE_STATUS_MASK)>>16);
+ wrfpcr(fpcr);
+
return 0;
+ }
case SSI_IEEE_STATE_AT_SIGNAL:
case SSI_IEEE_IGNORE_STATE_AT_SIGNAL:
@@ -903,7 +917,9 @@ asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer,
*/
break;
- case SSI_NVPAIRS:
+ case SSI_NVPAIRS: {
+ unsigned long v, w, i;
+
for (i = 0; i < nbytes; ++i) {
if (get_user(v, 2*i + (unsigned int *)buffer))
return -EFAULT;
@@ -922,6 +938,7 @@ asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer,
}
}
return 0;
+ }
default:
break;
diff --git a/arch/alpha/math-emu/fp-emul.c b/arch/alpha/math-emu/fp-emul.c
index 38df501fd..f1ff5a2be 100644
--- a/arch/alpha/math-emu/fp-emul.c
+++ b/arch/alpha/math-emu/fp-emul.c
@@ -13,9 +13,9 @@
#define OPC_INTL 0x11
#define OPC_INTS 0x12
#define OPC_INTM 0x13
-#define OPC_FLTV 0x14
-#define OPC_FLTI 0x15
-#define OPC_FLTL 0x16
+#define OPC_FLTV 0x15
+#define OPC_FLTI 0x16
+#define OPC_FLTL 0x17
#define OPC_MISC 0x18
@@ -298,19 +298,26 @@ alpha_fp_emul (unsigned long pc)
*
* - Set the appropriate bits in the FPCR
* - If the specified exception is enabled in the FPCR,
- * return. The caller (mxr_signal_handler) will dispatch
+ * return. The caller (entArith) will dispatch
* the appropriate signal to the translated program.
+ *
+ * In addition, properly track the exception state in software
+ * as described in the Alpha Architectre Handbook section 4.7.7.3.
*/
if (res) {
- fpcr |= FPCR_SUM | res;
+ /* Record exceptions in software control word. */
+ current->tss.flags = fpcw |= res >> 35;
+
+ /* Update hardware control register */
+ fpcr &= (~FPCR_MASK | FPCR_DYN_MASK);
+ fpcr |= ieee_swcr_to_fpcr(fpcw | (~fpcw&IEEE_STATUS_MASK)>>16);
wrfpcr(fpcr);
- if (((res & FPCR_INV) && (fpcw & IEEE_TRAP_ENABLE_INV)) ||
- ((res & FPCR_DZE) && (fpcw & IEEE_TRAP_ENABLE_DZE)) ||
- ((res & FPCR_OVF) && (fpcw & IEEE_TRAP_ENABLE_OVF)) ||
- ((res & FPCR_UNF) && (fpcw & IEEE_TRAP_ENABLE_UNF)) ||
- ((res & FPCR_INE) && (fpcw & IEEE_TRAP_ENABLE_INE)))
+
+ /* Do we generate a signal? */
+ if (res >> 51 & fpcw & IEEE_TRAP_ENABLE_MASK)
return 0;
}
+
/*
* Whoo-kay... we got this far, and we're not generating a signal
* to the translated program. All that remains is to write the
@@ -326,6 +333,7 @@ alpha_fp_emul_imprecise (struct pt_regs *regs, unsigned long write_mask)
{
unsigned long trigger_pc = regs->pc - 4;
unsigned long insn, opcode, rc;
+
/*
* Turn off the bits corresponding to registers that are the
* target of instructions that set bits in the exception
diff --git a/arch/i386/config.in b/arch/i386/config.in
index f95590407..1612b614f 100644
--- a/arch/i386/config.in
+++ b/arch/i386/config.in
@@ -34,6 +34,7 @@ bool 'System V IPC' CONFIG_SYSVIPC
bool 'Sysctl support' CONFIG_SYSCTL
tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA
fi
@@ -117,4 +118,5 @@ 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/i386/defconfig b/arch/i386/defconfig
index a27b6ebce..ab30a25c8 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -25,6 +25,7 @@ CONFIG_SYSVIPC=y
CONFIG_SYSCTL=y
CONFIG_BINFMT_AOUT=y
CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
# CONFIG_M386 is not set
# CONFIG_M486 is not set
# CONFIG_M586 is not set
@@ -190,6 +191,9 @@ CONFIG_EEXPRESS_PRO100=y
# Filesystems
#
# CONFIG_QUOTA is not set
+# CONFIG_DCACHE_PRELOAD is not set
+# CONFIG_OMIRR is not set
+# CONFIG_TRANS_NAMES is not set
CONFIG_MINIX_FS=y
CONFIG_EXT2_FS=y
CONFIG_FAT_FS=y
@@ -241,3 +245,4 @@ CONFIG_82C710_MOUSE=y
# Kernel hacking
#
# CONFIG_PROFILE is not set
+# CONFIG_MAGIC_SYSRQ is not set
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index a42b87b1b..bd4bf56cf 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -532,8 +532,8 @@ ENTRY(gdt)
.quad 0x0000000000000000 /* not used */
.quad 0x00cf9a000000ffff /* 0x10 kernel 4GB code at 0x00000000 */
.quad 0x00cf92000000ffff /* 0x18 kernel 4GB data at 0x00000000 */
- .quad 0x00cbfa000000ffff /* 0x23 user 3GB code at 0x00000000 */
- .quad 0x00cbf2000000ffff /* 0x2b user 3GB data at 0x00000000 */
+ .quad 0x00cffa000000ffff /* 0x23 user 4GB code at 0x00000000 */
+ .quad 0x00cff2000000ffff /* 0x2b user 4GB data at 0x00000000 */
.quad 0x0000000000000000 /* not used */
.quad 0x0000000000000000 /* not used */
.fill 2*NR_TASKS,8,0 /* space for LDT's and TSS's etc */
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index e5fb5acb1..eedb1d0fe 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -142,21 +142,6 @@ void enable_irq(unsigned int irq_nr)
* the operations that are needed to keep the AT interrupt-controller
* happy. They are also written to be fast - and to disable interrupts
* as little as humanly possible.
- *
- * NOTE! These macros expand to three different handlers for each line: one
- * complete handler that does all the fancy stuff (including signal handling),
- * and one fast handler that is meant for simple IRQ's that want to be
- * atomic. The specific handler is chosen depending on the SA_INTERRUPT
- * flag when installing a handler. Finally, one "bad interrupt" handler, that
- * is used when no handler is present.
- *
- * The timer interrupt is handled specially to insure that the jiffies
- * variable is updated at all times. Specifically, the timer interrupt is
- * just like the complete handlers except that it is invoked with interrupts
- * disabled and should never re-enable them. If other interrupts were
- * allowed to be processed while the timer interrupt is active, then the
- * other interrupts would have to avoid using the jiffies variable for delay
- * and interval timing operations to avoid hanging the system.
*/
#if NR_IRQS != 16
@@ -539,6 +524,9 @@ asmlinkage void do_IRQ(struct pt_regs regs)
status = 0;
action = *(irq + irq_action);
if (action) {
+ if (!(action->flags & SA_INTERRUPT))
+ __sti();
+
do {
status |= action->flags;
action->handler(irq, action->dev_id, &regs);
@@ -546,7 +534,6 @@ asmlinkage void do_IRQ(struct pt_regs regs)
} while (action);
if (status & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
-
__cli();
spin_lock(&irq_controller_lock);
unmask_irq(irq);
diff --git a/arch/i386/kernel/irq.h b/arch/i386/kernel/irq.h
index 1f9e89399..7d70264ba 100644
--- a/arch/i386/kernel/irq.h
+++ b/arch/i386/kernel/irq.h
@@ -9,24 +9,10 @@
#ifdef __SMP__
-#undef INIT_STUCK
-#define INIT_STUCK 200000000
-
-#undef STUCK
-#define STUCK \
-if (!--stuck) {printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n",irq,cpu,global_irq_holder); stuck = INIT_STUCK;}
-
static inline void irq_enter(int cpu, int irq)
{
- int stuck = INIT_STUCK;
-
hardirq_enter(cpu);
while (test_bit(0,&global_irq_lock)) {
- if ((unsigned char) cpu == global_irq_holder) {
- printk("BAD! Local interrupts enabled, global disabled\n");
- break;
- }
- STUCK;
/* nothing */;
}
}
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index 1dc615501..5a020b723 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -870,6 +870,8 @@ __initfunc(static void do_boot_cpu(int i))
*((volatile unsigned long *)phys_to_virt(8192)) = 0;
}
+unsigned int prof_multiplier[NR_CPUS];
+unsigned int prof_counter[NR_CPUS];
/*
* Cycle through the processors sending APIC IPI's to boot each.
@@ -912,8 +914,15 @@ __initfunc(void smp_boot_cpus(void))
* of here now!
*/
- if (!smp_found_config)
+ if (!smp_found_config) {
+ /*
+ * For SMP-simulation on one CPU to work, we must initialize these
+ * values for the single CPU here:
+ */
+ prof_counter[0] = prof_multiplier[0] = 1;
+
return;
+ }
/*
* Map the local APIC into kernel space
@@ -1302,9 +1311,6 @@ void smp_flush_tlb(void)
* value into /proc/profile.
*/
-unsigned int prof_multiplier[NR_CPUS];
-unsigned int prof_counter[NR_CPUS];
-
void smp_local_timer_interrupt(struct pt_regs * regs)
{
int cpu = smp_processor_id();
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index e45cc7279..a08c9c49c 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -515,7 +515,7 @@ unsigned long get_cmos_time(void)
return mktime(year, mon, day, hour, min, sec);
}
-static struct irqaction irq0 = { timer_interrupt, 0, 0, "timer", NULL, NULL};
+static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL};
__initfunc(void time_init(void))
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 696e37004..b397fc76d 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -191,8 +191,6 @@ spinlock_t die_lock;
spin_lock_irq(&die_lock);
printk("%s: %04lx\n", str, err & 0xffff);
show_registers(regs);
-do { int i=2000000000; while (i) i--; } while (0);
-do { int i=2000000000; while (i) i--; } while (0);
spin_unlock_irq(&die_lock);
do_exit(SIGSEGV);
}
diff --git a/arch/m68k/amiga/amifb.c b/arch/m68k/amiga/amifb.c
index eb72970d7..15e424ea7 100644
--- a/arch/m68k/amiga/amifb.c
+++ b/arch/m68k/amiga/amifb.c
@@ -1307,6 +1307,7 @@ static void ami_rebuild_copper(void);
*/
extern unsigned short ami_intena_vals[];
+extern void amiga_init_sound(void);
/*
* Support for Graphics Boards
@@ -1810,6 +1811,11 @@ __initfunc(struct fb_info *amiga_fb_init(long *mem_start))
u_long chipptr;
/*
+ * Our beloved beeper
+ */
+ amiga_init_sound();
+
+ /*
* Check for a Graphics Board
*/
diff --git a/arch/m68k/amiga/amikeyb.c b/arch/m68k/amiga/amikeyb.c
index 1058270dd..06fe55d29 100644
--- a/arch/m68k/amiga/amikeyb.c
+++ b/arch/m68k/amiga/amikeyb.c
@@ -23,18 +23,17 @@
#include <linux/random.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/kbd_ll.h>
#include <asm/amigaints.h>
#include <asm/amigahw.h>
#include <asm/irq.h>
-extern void handle_scancode(unsigned char);
-
#define AMIKEY_CAPS (0x62)
#define BREAK_MASK (0x80)
#define RESET_WARNING (0xf0) /* before rotation */
-static u_short amiplain_map[NR_KEYS] = {
+static u_short amiplain_map[NR_KEYS] __initdata = {
0xf060, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf05c, 0xf200, 0xf300,
0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
@@ -178,15 +177,13 @@ static unsigned char rep_scancode;
static void amikeyb_rep(unsigned long ignore);
static struct timer_list amikeyb_rep_timer = {NULL, NULL, 0, 0, amikeyb_rep};
-extern struct pt_regs *pt_regs;
-
static void amikeyb_rep(unsigned long ignore)
{
unsigned long flags;
save_flags(flags);
cli();
- pt_regs = NULL;
+ kbd_pt_regs = NULL;
amikeyb_rep_timer.expires = jiffies + key_repeat_rate;
amikeyb_rep_timer.prev = amikeyb_rep_timer.next = NULL;
@@ -202,7 +199,7 @@ static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp)
static int reset_warning = 0;
/* save frame for register dump */
- pt_regs = (struct pt_regs *)fp;
+ kbd_pt_regs = fp;
/* get and invert scancode (keyboard is active low) */
scancode = ~ciaa.sdr;
@@ -302,14 +299,13 @@ __initfunc(int amiga_keyb_init(void))
return -EIO;
/* setup key map */
- key_maps[0] = amiplain_map;
+ memcpy(plain_map, amiplain_map, sizeof(plain_map));
key_maps[1] = amishift_map;
key_maps[2] = amialtgr_map;
key_maps[4] = amictrl_map;
key_maps[5] = amishift_ctrl_map;
key_maps[8] = amialt_map;
key_maps[12] = amictrl_alt_map;
- memcpy(plain_map, amiplain_map, sizeof(plain_map));
/*
* Initialize serial data direction.
diff --git a/arch/m68k/amiga/amisound.c b/arch/m68k/amiga/amisound.c
index d5656d170..72d2091f5 100644
--- a/arch/m68k/amiga/amisound.c
+++ b/arch/m68k/amiga/amisound.c
@@ -40,7 +40,7 @@ u_short amiga_audio_period = MAX_PERIOD;
static u_long clock_constant;
-__initfunc(static void init_sound(void))
+__initfunc(void amiga_init_sound(void))
{
snd_data = amiga_chip_alloc(sizeof(sine_data));
if (!snd_data) {
@@ -58,14 +58,8 @@ static struct timer_list sound_timer = { NULL, NULL, 0, 0, nosound };
void amiga_mksound( unsigned int hz, unsigned int ticks )
{
- static int inited = 0;
unsigned long flags;
- if (!inited) {
- init_sound();
- inited = 1;
- }
-
if (!snd_data)
return;
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 7b6bd208f..e36016306 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -78,6 +78,7 @@ static void amiga_wait_key(void);
extern struct consw fb_con;
extern struct fb_info *amiga_fb_init(long *);
extern void zorro_init(void);
+extern void amiga_init_sound(void);
static void amiga_savekmsg_init(void);
static void amiga_mem_console_write(const char *b, unsigned int count);
static void amiga_serial_console_write(const char *s, unsigned int count);
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c
index b2887f7da..189095cfc 100644
--- a/arch/m68k/atari/ataints.c
+++ b/arch/m68k/atari/ataints.c
@@ -48,6 +48,7 @@
#include <asm/atariints.h>
#include <asm/atari_stdma.h>
#include <asm/irq.h>
+#include <asm/entry.h>
/*
@@ -161,22 +162,6 @@ static int free_vme_vec_bitmap = 0;
#define IRQ_NAME(nr) atari_slow_irq_##nr##_handler(void)
-#define MFP_MK_BASE "0xfa13"
-
-/* This must agree with entry.S. */
-#define ORIG_DO "0x24"
-#define FORMATVEC "0x32"
-#define SR "0x2C"
-#define SAVE_ALL \
- "clrl %%sp@-;" /* stk_adj */ \
- "pea -1:w;" /* orig d0 = -1 */ \
- "movel %%d0,%%sp@-;" /* d0 */ \
- "moveml %%d1-%%d5/%%a0-%%a2,%%sp@-"
-#define GET_CURRENT(tmp) \
- "movel %%sp,"#tmp";" \
- "andw #-8192,"#tmp";" \
- "movel "#tmp",%%a2"
-
#define BUILD_SLOW_IRQ(n) \
asmlinkage void IRQ_NAME(n); \
/* Dummy function to allow asm with operands. */ \
@@ -184,29 +169,31 @@ void atari_slow_irq_##n##_dummy (void) { \
__asm__ (ALIGN_STR "\n" \
SYMBOL_NAME_STR(atari_slow_irq_) #n "_handler:\t" \
" addql #1,"SYMBOL_NAME_STR(local_irq_count)"\n" \
- SAVE_ALL "\n" \
+ SAVE_ALL_INT "\n" \
GET_CURRENT(%%d0) "\n" \
-" andb #~(1<<(" #n "&7))," /* mask this interrupt */ \
- "("MFP_MK_BASE"+(((" #n "&8)^8)>>2)+((" #n "&16)<<3)):w\n" \
-" bfextu %%sp@("SR"){#5,#3},%%d0\n" /* get old IPL from stack frame */ \
+" andb #~(1<<(%c3&7)),%a4:w\n" /* mask this interrupt */ \
+ /* get old IPL from stack frame */ \
+" bfextu %%sp@(%c2){#5,#3},%%d0\n" \
" movew %%sr,%%d1\n" \
" bfins %%d0,%%d1{#21,#3}\n" \
" movew %%d1,%%sr\n" /* set IPL = previous value */ \
" addql #1,%a0\n" \
-" lea "SYMBOL_NAME_STR(irq_handler)"+("#n"+8)*8,%%a0\n" \
+" lea %a1,%%a0\n" \
" pea %%sp@\n" /* push addr of frame */ \
" movel %%a0@(4),%%sp@-\n" /* push handler data */ \
-" pea (" #n "+8)\n" /* push int number */ \
+" pea (%c3+8)\n" /* push int number */ \
" movel %%a0@,%%a0\n" \
" jbsr %%a0@\n" /* call the handler */ \
" addql #8,%%sp\n" \
" addql #4,%%sp\n" \
" orw #0x0600,%%sr\n" \
" andw #0xfeff,%%sr\n" /* set IPL = 6 again */ \
-" orb #(1<<(" #n "&7))," /* now unmask the int again */ \
- "("MFP_MK_BASE"+(((" #n "&8)^8)>>2)+((" #n "&16)<<3)):w\n" \
+" orb #(1<<(%c3&7)),%a4:w\n" /* now unmask the int again */ \
" jbra "SYMBOL_NAME_STR(ret_from_interrupt)"\n" \
- : : "i" (&kstat.interrupts[n+8]) \
+ : : "i" (&kstat.interrupts[n+8]), "i" (&irq_handler[n+8]), \
+ "n" (PT_OFF_SR), "n" (n), \
+ "i" (n & 8 ? (n & 16 ? &tt_mfp.int_mk_a : &mfp.int_mk_a) \
+ : (n & 16 ? &tt_mfp.int_mk_b : &mfp.int_mk_b)) \
); \
}
@@ -288,10 +275,10 @@ SYMBOL_NAME_STR(atari_fast_irq_handler) ":
orw #0x700,%%sr /* disable all interrupts */
"SYMBOL_NAME_STR(atari_prio_irq_handler) ":\t
addql #1,"SYMBOL_NAME_STR(local_irq_count)"\n"
- SAVE_ALL "\n"
+ SAVE_ALL_INT "\n"
GET_CURRENT(%%d0) "
/* get vector number from stack frame and convert to source */
- bfextu %%sp@(" FORMATVEC "){#4,#10},%%d0
+ bfextu %%sp@(%c1){#4,#10},%%d0
subw #(0x40-8),%%d0
jpl 1f
addw #(0x40-8-0x18),%%d0
@@ -307,7 +294,7 @@ SYMBOL_NAME_STR(atari_fast_irq_handler) ":
addql #8,%%sp
addql #4,%%sp
jbra "SYMBOL_NAME_STR(ret_from_interrupt)
- : : "i" (&kstat.interrupts)
+ : : "i" (&kstat.interrupts), "n" (PT_OFF_FORMATVEC)
);
}
diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c
index beccf9a84..d5d45be01 100644
--- a/arch/m68k/atari/atakeyb.c
+++ b/arch/m68k/atari/atakeyb.c
@@ -23,6 +23,7 @@
#include <linux/kd.h>
#include <linux/random.h>
#include <linux/init.h>
+#include <linux/kbd_ll.h>
#include <asm/atariints.h>
#include <asm/atarihw.h>
@@ -31,7 +32,6 @@
#include <asm/atari_joystick.h>
#include <asm/irq.h>
-extern void handle_scancode(unsigned char);
extern int ovsc_switchmode;
extern unsigned char mach_keyboard_type;
static void atakeyb_rep( unsigned long ignore );
@@ -99,7 +99,7 @@ static unsigned long broken_keys[128/(sizeof(unsigned long)*8)] = { 0, };
* - Keypad Left/Right Parenthesis mapped to new K_PPAREN[LR]
*/
-static u_short ataplain_map[NR_KEYS] = {
+static u_short ataplain_map[NR_KEYS] __initdata = {
0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036,
0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf008, 0xf009,
0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
@@ -139,7 +139,7 @@ static u_short atashift_map[NR_KEYS] = {
static u_short atactrl_map[NR_KEYS] = {
0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e,
- 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf07f, 0xf200, 0xf008, 0xf200,
+ 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200,
0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013,
0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
@@ -158,18 +158,18 @@ static u_short atactrl_map[NR_KEYS] = {
static u_short atashift_ctrl_map[NR_KEYS] = {
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf008, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf201, 0xf702, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf700, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf700, 0xf200,
- 0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf117,
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200,
+ 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
+ 0xf00f, 0xf010, 0xf200, 0xf200, 0xf201, 0xf702, 0xf001, 0xf013,
+ 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
+ 0xf200, 0xf200, 0xf700, 0xf200, 0xf01a, 0xf018, 0xf003, 0xf016,
+ 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf07f, 0xf700, 0xf200,
+ 0xf703, 0xf200, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
+ 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf117,
0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
- 0xf600, 0xf200, 0xf115, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307,
+ 0xf200, 0xf1ff, 0xf11b, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307,
0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303,
0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
@@ -207,7 +207,7 @@ static u_short atashift_alt_map[NR_KEYS] = {
0xf118, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
0xf119, 0xf200, 0xf115, 0xf87f, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307,
+ 0xf200, 0xf1ff, 0xf11b, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307,
0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303,
0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
@@ -215,7 +215,7 @@ static u_short atashift_alt_map[NR_KEYS] = {
static u_short atactrl_alt_map[NR_KEYS] = {
0xf200, 0xf200, 0xf200, 0xf800, 0xf81b, 0xf81c, 0xf81d, 0xf81e,
- 0xf81f, 0xf87f, 0xf200, 0xf200, 0xf87f, 0xf200, 0xf808, 0xf200,
+ 0xf81f, 0xf87f, 0xf200, 0xf200, 0xf81f, 0xf200, 0xf808, 0xf200,
0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809,
0xf80f, 0xf810, 0xf81b, 0xf81d, 0xf201, 0xf702, 0xf801, 0xf813,
0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200,
@@ -224,7 +224,7 @@ static u_short atactrl_alt_map[NR_KEYS] = {
0xf703, 0xf800, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf114,
0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
- 0xf600, 0xf200, 0xf115, 0xf07f, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf600, 0xf200, 0xf115, 0xf87f, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf1ff, 0xf202, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307,
0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303,
@@ -234,18 +234,18 @@ static u_short atactrl_alt_map[NR_KEYS] = {
static u_short atashift_ctrl_alt_map[NR_KEYS] = {
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf808, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf201, 0xf702, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf700, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf700, 0xf200,
- 0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf117,
+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf81f, 0xf200, 0xf808, 0xf200,
+ 0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809,
+ 0xf80f, 0xf810, 0xf200, 0xf200, 0xf201, 0xf702, 0xf801, 0xf813,
+ 0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200,
+ 0xf200, 0xf200, 0xf700, 0xf200, 0xf81a, 0xf818, 0xf803, 0xf816,
+ 0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf87f, 0xf700, 0xf200,
+ 0xf703, 0xf200, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
+ 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf200, 0xf200, 0xf117,
0xf603, 0xf200, 0xf30b, 0xf601, 0xf200, 0xf602, 0xf30a, 0xf200,
- 0xf600, 0xf200, 0xf115, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
+ 0xf600, 0xf200, 0xf115, 0xf87f, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
- 0xf200, 0xf200, 0xf200, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307,
+ 0xf200, 0xf1ff, 0xf11b, 0xf312, 0xf313, 0xf30d, 0xf30c, 0xf307,
0xf308, 0xf309, 0xf304, 0xf305, 0xf306, 0xf301, 0xf302, 0xf303,
0xf300, 0xf310, 0xf30e, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200
@@ -277,12 +277,10 @@ static unsigned int key_repeat_rate = DEFAULT_KEYB_REP_RATE;
static unsigned char rep_scancode;
static struct timer_list atakeyb_rep_timer = { NULL, NULL, 0, 0, atakeyb_rep };
-extern struct pt_regs *pt_regs;
-
static void atakeyb_rep( unsigned long ignore )
{
- pt_regs = NULL;
+ kbd_pt_regs = NULL;
/* Disable keyboard for the time we call handle_scancode(), else a race
* in the keyboard tty queue may happen */
@@ -327,7 +325,7 @@ static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp)
int break_flag;
/* save frame for register dump */
- pt_regs = (struct pt_regs *)fp;
+ kbd_pt_regs = fp;
repeat:
if (acia.mid_ctrl & ACIA_IRQ)
@@ -420,14 +418,14 @@ static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp)
* make codes instead. Therefore, simply ignore
* break_flag...
* */
- int keyval = ataplain_map[scancode], keytyp;
-
+ int keyval = plain_map[scancode], keytyp;
+
set_bit( scancode, broken_keys );
self_test_last_rcv = jiffies;
- keyval = ataplain_map[scancode];
+ keyval = plain_map[scancode];
keytyp = KTYP(keyval) - 0xf0;
keyval = KVAL(keyval);
-
+
printk( KERN_WARNING "Key with scancode %d ", scancode );
if (keytyp == KT_LATIN || keytyp == KT_LETTER) {
if (keyval < ' ')
@@ -440,7 +438,7 @@ static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp)
}
else if (test_bit( scancode, broken_keys ))
break;
-
+
if (break_flag) {
del_timer( &atakeyb_rep_timer );
rep_scancode = 0;
@@ -808,7 +806,7 @@ void atari_kbd_leds (unsigned int leds)
__initfunc(int atari_keyb_init(void))
{
/* setup key map */
- key_maps[0] = ataplain_map;
+ memcpy (plain_map, ataplain_map, sizeof(plain_map));
key_maps[1] = atashift_map;
key_maps[2] = 0; /* ataaltgr_map */
key_maps[4] = atactrl_map;
@@ -817,7 +815,6 @@ __initfunc(int atari_keyb_init(void))
key_maps[9] = atashift_alt_map;
key_maps[12] = atactrl_alt_map;
key_maps[13] = atashift_ctrl_alt_map;
- memcpy (plain_map, ataplain_map, sizeof(plain_map));
keymap_count = 8;
/* say that we don't have an AltGr key */
diff --git a/arch/m68k/console/fbcon.c b/arch/m68k/console/fbcon.c
index 376249c90..62457c0cb 100644
--- a/arch/m68k/console/fbcon.c
+++ b/arch/m68k/console/fbcon.c
@@ -69,8 +69,8 @@
#include <asm/system.h>
#include <asm/uaccess.h>
-#include "../../../drivers/char/vt_kern.h" /* vt_cons and vc_resize_con() */
-#include "../../../drivers/char/console_struct.h"
+#include <linux/vt_kern.h>
+#include <linux/console_struct.h>
/* Import console_blanked from console.c */
diff --git a/arch/m68k/fpsp040/skeleton.S b/arch/m68k/fpsp040/skeleton.S
index 466cf3fbc..719bcc9ce 100644
--- a/arch/m68k/fpsp040/skeleton.S
+++ b/arch/m68k/fpsp040/skeleton.S
@@ -39,6 +39,7 @@
|
#include <linux/linkage.h>
+#include <asm/entry.h>
|SKELETON idnt 2,1 | Motorola 040 Floating Point Software Package
@@ -51,24 +52,6 @@
.include "fpsp.h"
-/*
- * This has to match entry.S
- */
-LOFF_ORIG_D0 = 0x24
-
-#define curptr a2
-
-#define SAVE_ALL \
- clrl %sp@-; /* stk_adj */ \
- movel %d0,%sp@-; /* orig d0 */ \
- movel %d0,%sp@-; /* d0 */ \
- moveml %d1-%d5/%a0-%a1/%curptr,%sp@-;
-
-#define GET_CURRENT(tmp) \
- movel %sp,tmp; \
- andw &-8192,tmp; \
- movel tmp,%curptr;
-
|xref b1238_fix
|
@@ -86,11 +69,7 @@ real_dz:
frestore (%sp)+
unlk %a6
- SAVE_ALL
- moveq #-1,%d0
- movel %d0,%sp@(LOFF_ORIG_D0) | a -1 in the ORIG_D0 field
- | signifies that the stack frame
- | is NOT for syscall
+ SAVE_ALL_INT
GET_CURRENT(%d0)
movel %sp,%sp@- | stack frame pointer argument
bsrl SYMBOL_NAME(trap_c)
@@ -181,11 +160,7 @@ inex_done:
frestore (%sp)+
unlk %a6
- SAVE_ALL
- moveq #-1,%d0
- movel %d0,%sp@(LOFF_ORIG_D0) | a -1 in the ORIG_D0 field
- | signifies that the stack frame
- | is NOT for syscall
+ SAVE_ALL_INT
GET_CURRENT(%d0)
movel %sp,%sp@- | stack frame pointer argument
bsrl SYMBOL_NAME(trap_c)
@@ -211,11 +186,7 @@ ovfl_done:
frestore (%sp)+
unlk %a6
- SAVE_ALL
- moveq #-1,%d0
- movel %d0,%sp@(LOFF_ORIG_D0) | a -1 in the ORIG_D0 field
- | signifies that the stack frame
- | is NOT for syscall
+ SAVE_ALL_INT
GET_CURRENT(%d0)
movel %sp,%sp@- | stack frame pointer argument
bsrl SYMBOL_NAME(trap_c)
@@ -241,11 +212,7 @@ unfl_done:
frestore (%sp)+
unlk %a6
- SAVE_ALL
- moveq #-1,%d0
- movel %d0,%sp@(LOFF_ORIG_D0) | a -1 in the ORIG_D0 field
- | signifies that the stack frame
- | is NOT for syscall
+ SAVE_ALL_INT
GET_CURRENT(%d0)
movel %sp,%sp@- | stack frame pointer argument
bsrl SYMBOL_NAME(trap_c)
@@ -267,11 +234,7 @@ real_snan:
frestore (%sp)+
unlk %a6
- SAVE_ALL
- moveq #-1,%d0
- movel %d0,%sp@(LOFF_ORIG_D0) | a -1 in the ORIG_D0 field
- | signifies that the stack frame
- | is NOT for syscall
+ SAVE_ALL_INT
GET_CURRENT(%d0)
movel %sp,%sp@- | stack frame pointer argument
bsrl SYMBOL_NAME(trap_c)
@@ -293,11 +256,7 @@ real_operr:
frestore (%sp)+
unlk %a6
- SAVE_ALL
- moveq #-1,%d0
- movel %d0,%sp@(LOFF_ORIG_D0) | a -1 in the ORIG_D0 field
- | signifies that the stack frame
- | is NOT for syscall
+ SAVE_ALL_INT
GET_CURRENT(%d0)
movel %sp,%sp@- | stack frame pointer argument
bsrl SYMBOL_NAME(trap_c)
@@ -325,11 +284,7 @@ real_bsun:
frestore (%sp)+
unlk %a6
- SAVE_ALL
- moveq #-1,%d0
- movel %d0,%sp@(LOFF_ORIG_D0) | a -1 in the ORIG_D0 field
- | signifies that the stack frame
- | is NOT for syscall
+ SAVE_ALL_INT
GET_CURRENT(%d0)
movel %sp,%sp@- | stack frame pointer argument
bsrl SYMBOL_NAME(trap_c)
@@ -350,11 +305,7 @@ fline:
jmp fpsp_fline
real_fline:
- SAVE_ALL
- moveq #-1,%d0
- movel %d0,%sp@(LOFF_ORIG_D0) | a -1 in the ORIG_D0 field
- | signifies that the stack frame
- | is NOT for syscall
+ SAVE_ALL_INT
GET_CURRENT(%d0)
movel %sp,%sp@- | stack frame pointer argument
bsrl SYMBOL_NAME(trap_c)
@@ -376,11 +327,7 @@ real_unsupp:
frestore (%sp)+
unlk %a6
- SAVE_ALL
- moveq #-1,%d0
- movel %d0,%sp@(LOFF_ORIG_D0) | a -1 in the ORIG_D0 field
- | signifies that the stack frame
- | is NOT for syscall
+ SAVE_ALL_INT
GET_CURRENT(%d0)
movel %sp,%sp@- | stack frame pointer argument
bsrl SYMBOL_NAME(trap_c)
@@ -435,9 +382,7 @@ Lnotkern:
bne Lmustsched
rte
Lmustsched:
- SAVE_ALL
- moveq #-1,%d0
- movel %d0,%sp@(LOFF_ORIG_D0) | indicate stack frame not for syscall
+ SAVE_ALL_INT
GET_CURRENT(%d0)
bral SYMBOL_NAME(ret_from_exception) | deliver signals, reschedule etc..
diff --git a/arch/m68k/kernel/console.c b/arch/m68k/kernel/console.c
index 468ae0b59..31608e904 100644
--- a/arch/m68k/kernel/console.c
+++ b/arch/m68k/kernel/console.c
@@ -109,7 +109,6 @@
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
-#include <linux/console.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
@@ -119,17 +118,18 @@
#include <linux/major.h>
#include <linux/mm.h>
#include <linux/ioport.h>
+#include <linux/init.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/bitops.h>
-#include "../../../drivers/char/kbd_kern.h"
-#include "../../../drivers/char/vt_kern.h"
-#include "../../../drivers/char/consolemap.h"
-#include "../../../drivers/char/selection.h"
-#include "../../../drivers/char/console_struct.h"
+#include <linux/kbd_kern.h>
+#include <linux/vt_kern.h>
+#include <linux/consolemap.h>
+#include <linux/selection.h>
+#include <linux/console_struct.h>
#ifndef MIN
@@ -159,6 +159,8 @@ static void set_vesa_blanking(unsigned long arg);
extern void vesa_blank(void);
extern void vesa_unblank(void);
extern void compute_shiftstate(void);
+extern void reset_palette(int currcons);
+extern void set_palette(void);
void poke_blanked_console(void);
void do_blank_screen(int);
@@ -257,6 +259,7 @@ struct consw *conswitchp;
#define ulcolor (vc_cons[currcons].d->vc_ulcolor)
#define halfcolor (vc_cons[currcons].d->vc_halfcolor)
#define tab_stop (vc_cons[currcons].d->vc_tab_stop)
+#define palette (vc_cons[currcons].d->vc_palette)
#define bell_pitch (vc_cons[currcons].d->vc_bell_pitch)
#define bell_duration (vc_cons[currcons].d->vc_bell_duration)
#define sw (vc_cons[currcons].d->vc_sw)
@@ -539,6 +542,14 @@ void vc_disallocate(unsigned int currcons)
static unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
8,12,10,14, 9,13,11,15 };
+/* the default colour table, for VGA+ colour systems */
+int default_red[] = {0x00,0xaa,0x00,0xaa,0x00,0xaa,0x00,0xaa,
+ 0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff};
+int default_grn[] = {0x00,0x00,0xaa,0x55,0x00,0x00,0xaa,0xaa,
+ 0x55,0x55,0xff,0xff,0x55,0x55,0xff,0xff};
+int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa,
+ 0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff};
+
/*
* gotoxy() must verify all boundaries, because the arguments
* might also be negative. If the given position is out of
@@ -1655,7 +1666,7 @@ static int do_con_write(struct tty_struct * tty, int from_user,
if (nextx == cols) {
sw->con_putc(vc_cons[currcons].d,
*putcs_buf, y, x);
- ((unsigned short *)pos)--;
+ pos--;
need_wrap = decawm;
continue;
}
@@ -1837,9 +1848,7 @@ static int do_con_write(struct tty_struct * tty, int from_user,
vc_state = ESpalette;
continue;
} else if (c=='R') { /* reset palette */
-#if 0
reset_palette (currcons);
-#endif
vc_state = ESnormal;
} else
vc_state = ESnormal;
@@ -1848,7 +1857,6 @@ static int do_con_write(struct tty_struct * tty, int from_user,
if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) {
par[npar++] = (c>'9' ? (c&0xDF)-'A'+10 : c-'0') ;
if (npar==7) {
-#if 0
int i = par[0]*3, j = 1;
palette[i] = 16*par[j++];
palette[i++] += par[j++];
@@ -1857,7 +1865,6 @@ static int do_con_write(struct tty_struct * tty, int from_user,
palette[i] = 16*par[j++];
palette[i] += par[j];
set_palette() ;
-#endif
vc_state = ESnormal;
}
} else
@@ -2283,7 +2290,7 @@ static void console_bh(void)
* Reads the information preserved by setup.s to determine the current display
* type and sets everything accordingly.
*/
-unsigned long con_init(unsigned long kmem_start)
+__initfunc(unsigned long con_init(unsigned long kmem_start))
{
const char *display_desc = "????";
unsigned int currcons = 0;
@@ -2617,22 +2624,61 @@ static int set_get_font(char * arg, int set, int ch512)
* map, 3 bytes per colour, 16 colours, range from 0 to 255.
*/
+static int set_get_cmap(unsigned char *arg, int set)
+{
+ int i, j, k;
+
+ for (i = 0; i < 16; i++)
+ if (set) {
+ get_user(default_red[i], arg++);
+ get_user(default_grn[i], arg++);
+ get_user(default_blu[i], arg++);
+ } else {
+ put_user(default_red[i], arg++);
+ put_user(default_grn[i], arg++);
+ put_user(default_blu[i], arg++);
+ }
+ if (set) {
+ for (i = 0; i < MAX_NR_CONSOLES; i++)
+ if (vc_cons_allocated(i))
+ for (j = k = 0; j < 16; j++) {
+ vc_cons[i].d->vc_palette[k++] =
+ default_red[j];
+ vc_cons[i].d->vc_palette[k++] =
+ default_grn[j];
+ vc_cons[i].d->vc_palette[k++] =
+ default_blu[j];
+ }
+ set_palette();
+ }
+ return 0;
+}
+
int con_set_cmap (unsigned char *arg)
{
- return -EINVAL;
+ return set_get_cmap (arg, 1);
}
int con_get_cmap (unsigned char *arg)
{
- return -EINVAL;
+ return set_get_cmap (arg, 0);
}
void reset_palette(int currcons)
{
+ int j, k;
+ for (j = k = 0; j < 16; j++) {
+ palette[k++] = default_red[j];
+ palette[k++] = default_grn[j];
+ palette[k++] = default_blu[j];
+ }
+ set_palette() ;
}
void set_palette(void)
{
+ if (vt_cons[fg_console]->vc_mode != KD_GRAPHICS)
+ conswitchp->con_set_palette(vc_cons[fg_console].d, color_table);
}
/*
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index ef5ef46d6..33542ca96 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -22,24 +22,6 @@
* NOTE: This code handles signal-recognition, which happens every time
* after a timer-interrupt and after each system call.
*
- * Stack layout in 'ret_from_exception':
- *
- * This allows access to the syscall arguments in registers d1-d5
- *
- * 0(sp) - d1
- * 4(sp) - d2
- * 8(sp) - d3
- * C(sp) - d4
- * 10(sp) - d5
- * 14(sp) - a0
- * 18(sp) - a1
- * 1C(sp) - a2
- * 20(sp) - d0
- * 24(sp) - orig_d0
- * 28(sp) - stack adjustment
- * 2C(sp) - sr
- * 2E(sp) - pc
- * 32(sp) - format & vector
*/
/*
@@ -48,94 +30,12 @@
* number 0 in the 'current_set' list.
*/
-/*
- * 97/05/14 Andreas: Register %a2 is now set to the current task throughout
- * the whole kernel.
- */
-
#include <linux/sys.h>
#include <linux/config.h>
#include <linux/linkage.h>
+#include <asm/entry.h>
#include <asm/setup.h>
#include <asm/segment.h>
-#ifdef CONFIG_KGDB
-#include <asm/kgdb.h>
-.globl SYMBOL_NAME(kgdb_registers)
-#endif
-
-#define curptr a2
-
-LENOSYS = 38
-
-/*
- * these are offsets into the task-struct
- */
-LTASK_STATE = 0
-LTASK_COUNTER = 4
-LTASK_PRIORITY = 8
-LTASK_SIGNAL = 12
-LTASK_BLOCKED = 16
-LTASK_FLAGS = 20
-
-/* the following macro is used when enabling interrupts */
-#if defined(MACH_ATARI_ONLY)
- /* block out HSYNC on the atari */
-#define ALLOWINT 0xfbff
-#define MAX_NOINT_IPL 3
-#else
- /* portable version */
-#define ALLOWINT 0xf8ff
-#define MAX_NOINT_IPL 0
-#endif /* machine compilation types */
-
-LD0 = 0x20
-LORIG_D0 = 0x24
-LSR = 0x2C
-LFORMATVEC = 0x32
-
-/*
- * This defines the normal kernel pt-regs layout.
- *
- * regs a3-a6 and d6-d7 are preserved by C code
- * the kernel doesn't mess with usp unless it needs to
- */
-#ifndef CONFIG_KGDB
-#define SAVE_ALL \
- clrl %sp@-; /* stk_adj */ \
- movel %d0,%sp@-; /* orig d0 */ \
- movel %d0,%sp@-; /* d0 */ \
- moveml %d1-%d5/%a0-%a1/%curptr,%sp@-;
-#else
-/* Need to save the "missing" registers for kgdb...
- */
-#define SAVE_ALL \
- clrl %sp@-; /* stk_adj */ \
- movel %d0,%sp@-; /* orig d0 */ \
- movel %d0,%sp@-; /* d0 */ \
- moveml %d1-%d5/%a0-%a1/%curptr,%sp@-; \
- moveml %d6-%d7,SYMBOL_NAME(kgdb_registers)+GDBOFFA_D6; \
- moveml %a3-%a6,SYMBOL_NAME(kgdb_registers)+GDBOFFA_A3;
-#endif
-
-#define RESTORE_ALL \
- moveml %sp@+,%a0-%a1/%curptr/%d1-%d5; \
- movel %sp@+,%d0; \
- addql #4,%sp; /* orig d0 */ \
- addl %sp@+,%sp; /* stk adj */ \
- rte
-
-#define SWITCH_STACK_SIZE (6*4+4) /* includes return address */
-
-#define SAVE_SWITCH_STACK \
- moveml %a3-%a6/%d6-%d7,%sp@-
-
-#define RESTORE_SWITCH_STACK \
- moveml %sp@+,%a3-%a6/%d6-%d7
-
-#define GET_CURRENT(tmp) \
- movel %sp,tmp; \
- andw &-8192,tmp; \
- movel tmp,%curptr;
.globl SYMBOL_NAME(system_call), SYMBOL_NAME(buserr), SYMBOL_NAME(trap)
.globl SYMBOL_NAME(resume), SYMBOL_NAME(ret_from_exception)
@@ -146,12 +46,7 @@ LFORMATVEC = 0x32
.text
ENTRY(buserr)
- SAVE_ALL
- moveq #-1,%d0
- movel %d0,%sp@(LORIG_D0) | a -1 in the ORIG_D0 field
- | signifies that the stack frame
- | is NOT for syscall
-
+ SAVE_ALL_INT
GET_CURRENT(%d0)
movel %sp,%sp@- | stack frame pointer argument
bsrl SYMBOL_NAME(buserr_c)
@@ -159,11 +54,7 @@ ENTRY(buserr)
jra SYMBOL_NAME(ret_from_exception)
ENTRY(trap)
- SAVE_ALL
- moveq #-1,%d0
- movel %d0,%sp@(LORIG_D0) | a -1 in the ORIG_D0 field
- | signifies that the stack frame
- | is NOT for syscall
+ SAVE_ALL_INT
GET_CURRENT(%d0)
movel %sp,%sp@- | stack frame pointer argument
bsrl SYMBOL_NAME(trap_c)
@@ -180,18 +71,18 @@ ENTRY(reschedule)
jmp SYMBOL_NAME(schedule)
badsys:
- movel #-LENOSYS,LD0(%sp)
+ movel #-LENOSYS,LPT_OFF_D0(%sp)
jra SYMBOL_NAME(ret_from_exception)
do_trace:
- movel #-LENOSYS,LD0(%sp) | needed for strace
+ movel #-LENOSYS,LPT_OFF_D0(%sp) | needed for strace
subql #4,%sp
SAVE_SWITCH_STACK
jbsr SYMBOL_NAME(syscall_trace)
RESTORE_SWITCH_STACK
addql #4,%sp
jbsr @(SYMBOL_NAME(sys_call_table),%d2:l:4)@(0)
- movel %d0,%sp@(LD0) | save the return value
+ movel %d0,%sp@(LPT_OFF_D0) | save the return value
subql #4,%sp | dummy return address
SAVE_SWITCH_STACK
jbsr SYMBOL_NAME(syscall_trace)
@@ -202,7 +93,7 @@ SYMBOL_NAME_LABEL(ret_from_signal)
jra SYMBOL_NAME(ret_from_exception)
ENTRY(system_call)
- SAVE_ALL
+ SAVE_ALL_SYS
movel %d0,%d2
GET_CURRENT(%d0)
@@ -213,19 +104,20 @@ ENTRY(system_call)
cmpl #NR_syscalls,%d2
jcc badsys
- btst #5,%curptr@(LTASK_FLAGS+3) | PF_TRACESYS
+ btst #LPF_TRACESYS_BIT,%curptr@(LTASK_FLAGS+LPF_TRACESYS_OFF)
jne do_trace
jbsr @(SYMBOL_NAME(sys_call_table),%d2:l:4)@(0)
- movel %d0,%sp@(LD0) | save the return value
+ movel %d0,%sp@(LPT_OFF_D0) | save the return value
SYMBOL_NAME_LABEL(ret_from_exception)
- btst #5,%sp@(LSR) | check if returning to kernel
+ btst #5,%sp@(LPT_OFF_SR) | check if returning to kernel
bnes 2f | if so, skip resched, signals
tstl SYMBOL_NAME(need_resched)
jne SYMBOL_NAME(reschedule)
cmpl #SYMBOL_NAME(task),%curptr | task[0] cannot have signals
jeq 2f
- bclr #5,%curptr@(LTASK_FLAGS+1) | check for delayed trace
+ | check for delayed trace
+ bclr #LPF_DTRACE_BIT,%curptr@(LTASK_FLAGS+LPF_DTRACE_OFF)
jne do_delayed_trace
5:
tstl %curptr@(LTASK_STATE) | state
@@ -236,7 +128,7 @@ SYMBOL_NAME_LABEL(ret_from_exception)
movel %curptr@(LTASK_BLOCKED),%d0
movel %d0,%d1 | save blocked in d1 for sig handling
notl %d0
- btst #4,%curptr@(LTASK_FLAGS+3) | PF_PTRACED
+ btst #LPF_PTRACED_BIT,%curptr@(LTASK_FLAGS+LPF_PTRACED_OFF)
jeq 1f
moveq #-1,%d0 | let the debugger see all signals
1: andl %curptr@(LTASK_SIGNAL),%d0
@@ -255,10 +147,10 @@ Lsignal_return:
RESTORE_ALL
do_delayed_trace:
- bclr #7,%sp@(LSR) | clear trace bit in SR
+ bclr #7,%sp@(LPT_OFF_SR) | clear trace bit in SR
pea 1 | send SIGTRAP
- movel %a0,%sp@-
- pea 5
+ movel %curptr,%sp@-
+ pea LSIGTRAP
jbsr SYMBOL_NAME(send_sig)
addql #8,%sp
addql #4,%sp
@@ -268,15 +160,11 @@ do_delayed_trace:
** This is the main interrupt handler, responsible for calling process_int()
*/
SYMBOL_NAME_LABEL(inthandler)
- SAVE_ALL
- moveq #-1,%d0
- movel %d0,%sp@(LORIG_D0) | a -1 in the ORIG_D0 field
- | signifies that the stack frame
- | is NOT for syscall
+ SAVE_ALL_INT
GET_CURRENT(%d0)
addql #1,SYMBOL_NAME(local_irq_count)
| put exception # in d0
- bfextu %sp@(LFORMATVEC){#4,#10},%d0
+ bfextu %sp@(LPT_OFF_FORMATVEC){#4,#10},%d0
movel %sp,%sp@-
movel %d0,%sp@- | put vector # on stack
@@ -290,7 +178,7 @@ SYMBOL_NAME_LABEL(ret_from_interrupt)
RESTORE_ALL
1:
#if 1
- bfextu %sp@(LSR){#5,#3},%d0 | Check for nested interrupt.
+ bfextu %sp@(LPT_OFF_SR){#5,#3},%d0 | Check for nested interrupt.
#if MAX_NOINT_IPL > 0
cmpiw #MAX_NOINT_IPL,%d0
#endif
@@ -347,14 +235,6 @@ ENTRY(sys_sigreturn)
RESTORE_SWITCH_STACK
rts
-LFLUSH_I_AND_D = 0x00000808
-LTSS_KSP = 0
-LTSS_USP = 4
-LTSS_SR = 8
-LTSS_FS = 10
-LTSS_CRP = 12
-LTSS_FPCTXT = 24
-
SYMBOL_NAME_LABEL(resume)
/*
* Beware - when entering resume, offset of tss is in d1,
@@ -460,8 +340,10 @@ SYMBOL_NAME_LABEL(resume)
#if defined (CONFIG_M68060)
/* is it a '060 ? */
+#if !defined(CPU_M68060_ONLY)
btst #3,SYMBOL_NAME(m68k_cputype)+3
beqs 2f
+#endif
/* clear user entries in the branch cache */
movec %cacr,%d0
orl #0x00200000,%d0
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index def50a747..c27f7f320 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -142,8 +142,8 @@ __initfunc(static void m68k_parse_bootinfo(const struct bi_record *record))
}
}
- __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p,
- unsigned long * memory_end_p))
+__initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p,
+ unsigned long * memory_end_p))
{
unsigned long memory_start, memory_end;
extern int _etext, _edata, _end;
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index 25be40007..44e45b9a0 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -201,7 +201,7 @@ static inline void access_error060 (struct frame *fp)
if ((!(fslw & MMU060_ERR_BITS)) && !(fslw & MMU060_SEE))
return;
}
-
+
if (fslw & (MMU060_DESC_ERR | MMU060_WP)) {
unsigned long errorcode;
unsigned long addr = fp->un.fmt4.effaddr;
diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c
index b46037f80..02dff0eea 100644
--- a/arch/m68k/mm/init.c
+++ b/arch/m68k/mm/init.c
@@ -296,7 +296,8 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
* The parameters are pointers to where to stick the starting and ending
* addresses of available kernel virtual memory.
*/
-__initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_mem))
+__initfunc(unsigned long paging_init(unsigned long start_mem,
+ unsigned long end_mem))
{
int chunk;
unsigned long mem_avail = 0;
diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c
index 77eb2dbfe..dea7695e8 100644
--- a/arch/m68k/mm/memory.c
+++ b/arch/m68k/mm/memory.c
@@ -552,39 +552,26 @@ unsigned long mm_ptov (unsigned long paddr)
void cache_clear (unsigned long paddr, int len)
{
if (CPU_IS_040_OR_060) {
+ int tmp;
+
/*
* cwe need special treatment for the first page, in case it
* is not page-aligned.
*/
- if (paddr & (PAGE_SIZE - 1)){
+ if ((tmp = -paddr & (PAGE_SIZE - 1))) {
pushcl040(paddr);
- if (len <= PAGE_SIZE){
- if (((paddr + len - 1) ^ paddr) & PAGE_MASK) {
- pushcl040(paddr + len - 1);
- }
+ if ((len -= tmp) <= 0)
return;
- }else{
- len -=PAGE_SIZE;
- paddr += PAGE_SIZE;
- }
+ paddr += tmp;
}
-
- while (len > PAGE_SIZE) {
-#if 0
- pushcl040(paddr);
-#else
+ tmp = PAGE_SIZE;
+ while ((len -= tmp) >= 0) {
clear040(paddr);
-#endif
- len -= PAGE_SIZE;
- paddr += PAGE_SIZE;
+ paddr += tmp;
}
- if (len > 0) {
+ if ((len += tmp))
+ /* a page boundary gets crossed at the end */
pushcl040(paddr);
- if (((paddr + len - 1) ^ paddr) & PAGE_MASK) {
- /* a page boundary gets crossed at the end */
- pushcl040(paddr + len - 1);
- }
- }
}
else /* 68030 or 68020 */
asm volatile ("movec %/cacr,%/d0\n\t"
@@ -605,26 +592,19 @@ void cache_clear (unsigned long paddr, int len)
void cache_push (unsigned long paddr, int len)
{
if (CPU_IS_040_OR_060) {
+ int tmp = PAGE_SIZE;
+
/*
* on 68040 or 68060, push cache lines for pages in the range;
* on the '040 this also invalidates the pushed lines, but not on
* the '060!
*/
- while (len > PAGE_SIZE) {
- pushcli040(paddr);
- len -= PAGE_SIZE;
- paddr += PAGE_SIZE;
- }
- if (len > 0) {
+ len += paddr & (PAGE_SIZE - 1);
+ do {
pushcli040(paddr);
- if (((paddr + len - 1) ^ paddr) & PAGE_MASK) {
- /* a page boundary gets crossed at the end */
- pushcli040(paddr + len - 1);
- }
- }
- }
-
-
+ paddr += tmp;
+ } while ((len -= tmp) > 0);
+ }
/*
* 68030/68020 have no writeback cache. On the other hand,
* cache_push is actually a superset of cache_clear (the lines
@@ -654,34 +634,24 @@ void cache_push (unsigned long paddr, int len)
void cache_push_v (unsigned long vaddr, int len)
{
if (CPU_IS_040) {
+ int tmp = PAGE_SIZE;
+
/* on 68040, push cache lines for pages in the range */
- while (len > PAGE_SIZE) {
- pushv040(vaddr);
- len -= PAGE_SIZE;
- vaddr += PAGE_SIZE;
- }
- if (len > 0) {
+ len += vaddr & (PAGE_SIZE - 1);
+ do {
pushv040(vaddr);
- if (((vaddr + len - 1) ^ vaddr) & PAGE_MASK) {
- /* a page boundary gets crossed at the end */
- pushv040(vaddr + len - 1);
- }
- }
- }
+ vaddr += tmp;
+ } while ((len -= tmp) > 0);
+ }
else if (CPU_IS_060) {
+ int tmp = PAGE_SIZE;
+
/* on 68040, push cache lines for pages in the range */
- while (len > PAGE_SIZE) {
- pushv060(vaddr);
- len -= PAGE_SIZE;
- vaddr += PAGE_SIZE;
- }
- if (len > 0) {
+ len += vaddr & (PAGE_SIZE - 1);
+ do {
pushv060(vaddr);
- if (((vaddr + len - 1) ^ vaddr) & PAGE_MASK) {
- /* a page boundary gets crossed at the end */
- pushv060(vaddr + len - 1);
- }
- }
+ vaddr += tmp;
+ } while ((len -= tmp) > 0);
}
/* 68030/68020 have no writeback cache; still need to clear icache. */
else /* 68030 or 68020 */
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
index 33f54a301..9c6fb9073 100644
--- a/arch/mips/defconfig
+++ b/arch/mips/defconfig
@@ -153,6 +153,9 @@ CONFIG_PCNET32=y
# Filesystems
#
# CONFIG_QUOTA is not set
+# CONFIG_DCACHE_PRELOAD is not set
+# CONFIG_OMIRR is not set
+# CONFIG_TRANS_NAMES is not set
# CONFIG_MINIX_FS is not set
CONFIG_EXT2_FS=y
# CONFIG_FAT_FS is not set
diff --git a/arch/mips/jazz/g364.c b/arch/mips/jazz/g364.c
index 92e130522..1503cc559 100644
--- a/arch/mips/jazz/g364.c
+++ b/arch/mips/jazz/g364.c
@@ -25,6 +25,11 @@
#include <linux/major.h>
#include <linux/mm.h>
#include <linux/ioport.h>
+#include <linux/kbd_kern.h>
+#include <linux/vt_kern.h>
+#include <linux/consolemap.h>
+#include <linux/selection.h>
+#include <linux/console_struct.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -33,12 +38,6 @@
#include <asm/bootinfo.h>
#include <asm/types.h>
-#include "../../../drivers/char/kbd_kern.h"
-#include "../../../drivers/char/vt_kern.h"
-#include "../../../drivers/char/consolemap.h"
-#include "../../../drivers/char/selection.h"
-#include "../../../drivers/char/console_struct.h"
-
extern void register_console(void (*proc)(const char *));
extern void console_print(const char *);
unsigned video_res_x;
diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c
index d994155d0..fc0d542fc 100644
--- a/arch/mips/kernel/irixelf.c
+++ b/arch/mips/kernel/irixelf.c
@@ -465,7 +465,7 @@ static inline int look_for_irix_interpreter(char **name,
goto losing;
old_fs = get_fs(); set_fs(get_ds());
- retval = namei(*name, interpreter_inode);
+ retval = namei(NAM_FOLLOW_LINK, *name, interpreter_inode);
set_fs(old_fs);
if(retval < 0)
goto losing;
@@ -973,6 +973,7 @@ unsigned long irix_mapelf(int fd, struct elf_phdr *user_phdrp, int cnt)
*/
static int dump_write(struct file *file, const void *addr, int nr)
{
+ file->f_inode->i_status |= ST_MODIFIED;
return file->f_op->write(file->f_inode, file, addr, nr) == nr;
}
diff --git a/arch/sparc/config.in b/arch/sparc/config.in
index 0005004be..85566667f 100644
--- a/arch/sparc/config.in
+++ b/arch/sparc/config.in
@@ -54,6 +54,7 @@ bool 'Sysctl support' CONFIG_SYSCTL
tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA
fi
endmenu
diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig
index ff91819b0..a6df2dcc0 100644
--- a/arch/sparc/defconfig
+++ b/arch/sparc/defconfig
@@ -42,6 +42,7 @@ SUN_FB_CGFOURTEEN=y
SUN_FB_BWTWO=y
SUN_FB_LEO=y
TADPOLE_FB_WEITEK=y
+SUN_FB_CREATOR=y
#
# Misc Linux/SPARC drivers
@@ -177,6 +178,9 @@ CONFIG_MYRI_SBUS=m
# Filesystems
#
CONFIG_QUOTA=y
+# CONFIG_DCACHE_PRELOAD is not set
+# CONFIG_OMIRR is not set
+# CONFIG_TRANS_NAMES is not set
CONFIG_MINIX_FS=m
CONFIG_EXT2_FS=y
CONFIG_FAT_FS=m
diff --git a/arch/sparc64/config.in b/arch/sparc64/config.in
index c8cdc0134..6354edded 100644
--- a/arch/sparc64/config.in
+++ b/arch/sparc64/config.in
@@ -59,6 +59,9 @@ fi
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA
fi
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+fi
endmenu
mainmenu_option next_comment
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index 579fbb4c2..0d95e1b75 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.27 1997/05/27 19:30:11 jj Exp $
+/* $Id: entry.S,v 1.31 1997/06/02 06:33:25 davem Exp $
* arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -18,7 +18,7 @@
#include <asm/signal.h>
#include <asm/pgtable.h>
-/* define SYSCALL_TRACING */
+/* #define SYSCALL_TRACING */
#define curptr g6
@@ -39,82 +39,84 @@
* it will not get updated properly.
*/
sparc64_dtlb_prot_catch:
- wr %g0, ASI_DMMU, %asi
- rdpr %pstate, %g1
- wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate
- rdpr %tl, %g2
- ldxa [%g0 + TLB_TAG_ACCESS] %asi, %g5
- ldxa [%g0 + TLB_SFSR] %asi, %g4
- cmp %g2, 1
- stxa %g0, [%g0 + TLB_SFSR] %asi
- bgu,a %icc, winfix_trampoline
- rdpr %tpc, %g5
- ba,pt %xcc, etrap
- rd %pc, %g7
- b,a,pt %xcc, 1f
+ wr %g0, ASI_DMMU, %asi
+ rdpr %pstate, %g1
+ wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate
+ rdpr %tl, %g3
+ ldxa [%g0 + TLB_TAG_ACCESS] %asi, %g5
+ ldxa [%g0 + TLB_SFSR] %asi, %g4
+ cmp %g3, 1
+ stxa %g0, [%g0 + TLB_SFSR] %asi
+ bgu,a,pn %icc, winfix_trampoline
+ rdpr %tpc, %g3
+ ba,pt %xcc, etrap
+ rd %pc, %g7
+ b,a,pt %xcc, 1f
sparc64_dtlb_refbit_catch:
- srlx %g5, 9, %g4
- and %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4
- cmp %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9)
- be,a,pt %xcc, 2f
- mov 1, %g4
- wr %g0, ASI_DMMU, %asi
- rdpr %pstate, %g1
- wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate
- rdpr %tl, %g2
- ldxa [%g0 + TLB_TAG_ACCESS] %asi, %g5
- cmp %g2, 1
- clr %g4 ! sfsr not updated for tlb misses
- bgu,a %icc, winfix_trampoline
- rdpr %tpc, %g5
- ba,pt %xcc, etrap
- rd %pc, %g7
+ srlx %g5, 9, %g4
+ and %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4
+ cmp %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9)
+ be,a,pt %xcc, 2f
+ mov 1, %g4
+ wr %g0, ASI_DMMU, %asi
+ rdpr %pstate, %g1
+ wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate
+ rdpr %tl, %g3
+ ldxa [%g0 + TLB_TAG_ACCESS] %asi, %g5
+ cmp %g3, 1
+ clr %g4 ! sfsr not updated for tlb misses
+ bgu,a,pn %icc, winfix_trampoline
+ rdpr %tpc, %g3
+ ba,pt %xcc, etrap
+ rd %pc, %g7
1:
- mov %l5, %o4 ! raw tag access
- mov %l4, %o5 ! raw sfsr
- srlx %l5, PAGE_SHIFT, %o3
- clr %o1 ! text_fault == 0
- sllx %o3, PAGE_SHIFT, %o3 ! address
- and %l4, 0x4, %o2 ! write == sfsr.W
- call do_sparc64_fault
- add %sp, STACK_BIAS + REGWIN_SZ, %o0 ! pt_regs ptr
- ba,a,pt %xcc, rtrap
+ mov %l5, %o4 ! raw tag access
+ mov %l4, %o5 ! raw sfsr
+ srlx %l5, PAGE_SHIFT, %o3
+ clr %o1 ! text_fault == 0
+ sllx %o3, PAGE_SHIFT, %o3 ! address
+ and %l4, 0x4, %o2 ! write == sfsr.W
+ call do_sparc64_fault
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0 ! pt_regs ptr
+ ba,pt %xcc, rtrap
+ clr %l6
sparc64_itlb_refbit_catch:
- srlx %g5, 9, %g4
- and %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4
- cmp %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9)
- be,a,pt %xcc, 3f
- mov 1, %g4
- rdpr %pstate, %g1
- wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate
- ba,pt %xcc, etrap
- rd %pc, %g7
-
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC], %o3
- mov 1, %o1 ! text_fault == 1
- clr %o2 ! write == 0
- clr %o4 ! tag access (N/A)
- clr %o5 ! raw sfsr (N/A)
- call do_sparc64_fault
- add %sp, STACK_BIAS + REGWIN_SZ, %o0 ! pt_regs ptr
- ba,a,pt %xcc, rtrap
+ srlx %g5, 9, %g4
+ and %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4
+ cmp %g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9)
+ be,a,pt %xcc, 3f
+ mov 1, %g4
+ rdpr %pstate, %g1
+ wrpr %g1, PSTATE_AG|PSTATE_MG, %pstate
+ ba,pt %xcc, etrap
+ rd %pc, %g7
+
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC], %o3
+ mov 1, %o1 ! text_fault == 1
+ clr %o2 ! write == 0
+ clr %o4 ! tag access (N/A)
+ clr %o5 ! raw sfsr (N/A)
+ call do_sparc64_fault
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0 ! pt_regs ptr
+ ba,pt %xcc, rtrap
+ clr %l6
2:
- sllx %g4, 63, %g4 ! _PAGE_VALID
- or %g5, _PAGE_ACCESSED, %g5
- or %g5, %g4, %g5
- stxa %g5, [%g3 + %g1] ASI_PHYS_USE_EC ! store new PTE
- stxa %g5, [%g0] ASI_DTLB_DATA_IN ! TLB load
+ sllx %g4, 63, %g4 ! _PAGE_VALID
+ or %g5, _PAGE_ACCESSED, %g5
+ or %g5, %g4, %g5
+ stxa %g5, [%g3 + %g1] ASI_PHYS_USE_EC ! store new PTE
+ stxa %g5, [%g0] ASI_DTLB_DATA_IN ! TLB load
retry
3:
- sllx %g4, 63, %g4 ! _PAGE_VALID
- or %g5, _PAGE_ACCESSED, %g5
- or %g5, %g4, %g5
- stxa %g5, [%g3 + %g1] ASI_PHYS_USE_EC ! store new PTE
- stxa %g5, [%g0] ASI_ITLB_DATA_IN ! TLB load
+ sllx %g4, 63, %g4 ! _PAGE_VALID
+ or %g5, _PAGE_ACCESSED, %g5
+ or %g5, %g4, %g5
+ stxa %g5, [%g3 + %g1] ASI_PHYS_USE_EC ! store new PTE
+ stxa %g5, [%g0] ASI_ITLB_DATA_IN ! TLB load
retry
/* Note check out head.h, this code isn't even used for UP,
@@ -131,268 +133,285 @@ sparc64_itlb_refbit_catch:
.align 4
.globl do_ivec
do_ivec:
- ldxa [%g0] ASI_INTR_RECEIVE, %g1
- andcc %g1, 0x20, %g0
- be,pn %xcc, do_ivec_return
- mov 0x40, %g2
+ ldxa [%g0] ASI_INTR_RECEIVE, %g1
+ andcc %g1, 0x20, %g0
+ be,pn %xcc, do_ivec_return
+ mov 0x40, %g2
/* Load up Interrupt Vector Data 0 register. */
- sethi %uhi(ivector_to_mask), %g4
- ldxa [%g2] ASI_UDB_INTR_R, %g3
- or %g4, %ulo(ivector_to_mask), %g4
- and %g3, 0x7ff, %g3
- sllx %g4, 32, %g4
- sethi %hi(ivector_to_mask), %g5
- sllx %g3, 3, %g3
- or %g5, %lo(ivector_to_mask), %g5
- add %g5, %g4, %g4
- ldx [%g4 + %g3], %g2
- brz,pn %g2, do_ivec_spurious
+ sethi %uhi(ivector_to_mask), %g4
+ ldxa [%g2] ASI_UDB_INTR_R, %g3
+ or %g4, %ulo(ivector_to_mask), %g4
+ and %g3, 0x7ff, %g3
+ sllx %g4, 32, %g4
+ sethi %hi(ivector_to_mask), %g5
+ sllx %g3, 3, %g3
+ or %g5, %lo(ivector_to_mask), %g5
+ add %g5, %g4, %g4
+ ldx [%g4 + %g3], %g2
+ brz,pn %g2, do_ivec_spurious
nop
/* No branches, worse case we don't know about this interrupt
* yet, so we would just write a zero into the softint register
* which is completely harmless.
*/
- wr %g2, 0x0, %set_softint
+ wr %g2, 0x0, %set_softint
do_ivec_return:
/* Acknowledge the UPA */
- stxa %g0, [%g0] ASI_INTR_RECEIVE
- membar #Sync
+ stxa %g0, [%g0] ASI_INTR_RECEIVE
+ membar #Sync
retry
do_ivec_spurious:
- stxa %g0, [%g0] ASI_INTR_RECEIVE
- rdpr %pstate, %g1
- wrpr %g1, PSTATE_IG | PSTATE_AG, %pstate
- ba,pt %xcc, etrap
- rd %pc, %g7
- call report_spurious_ivec
- add %sp, STACK_BIAS + REGWIN_SZ, %o0
- ba,pt %xcc, rtrap
- nop
+ stxa %g0, [%g0] ASI_INTR_RECEIVE
+ rdpr %pstate, %g1
+ wrpr %g1, PSTATE_IG | PSTATE_AG, %pstate
+ ba,pt %xcc, etrap
+ rd %pc, %g7
+ call report_spurious_ivec
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
+ ba,pt %xcc, rtrap
+ clr %l6
+
+ .globl do_mna
+do_mna:
+ rdpr %tl, %g3
+ cmp %g3, 1
+ bgu,a,pn %icc, winfix_mna
+ rdpr %tpc, %g3
+ ba,pt %xcc, etrap
+ rd %pc, %g7
+ call mem_address_unaligned
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
+ ba,pt %xcc, rtrap
+ clr %l6
-breakpoint_t:
- .asciz "Breakpoint Trap %lx\n"
- .align 4
.globl breakpoint_trap
breakpoint_trap:
- mov %o0, %o1
- sethi %hi(breakpoint_t), %o0
- or %o0, %lo(breakpoint_t), %o0
- call prom_printf
- add %o0, %g4, %o0
- call prom_cmdline
+ call sparc_breakpoint
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
+ ba,pt %xcc, rtrap
nop
- ba,a,pt %xcc, rtrap
.globl sys_pipe, sys_execve, sys_sigpause, sys_nis_syscall
.globl sys_sigsuspend, sys_sigreturn
.globl sys32_execve, sys_ptrace
sys_pipe:
- sethi %hi(sparc_pipe), %g1
- add %g1, %g4, %g1
- jmpl %g1 + %lo(sparc_pipe), %g0
- add %sp, STACK_BIAS + REGWIN_SZ, %o0
+ sethi %hi(sparc_pipe), %g1
+ add %g1, %g4, %g1
+ jmpl %g1 + %lo(sparc_pipe), %g0
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
sys_nis_syscall:
- sethi %hi(c_sys_nis_syscall), %g1
- add %g1, %g4, %g1
- jmpl %g1 + %lo(c_sys_nis_syscall), %g0
- add %sp, STACK_BIAS + REGWIN_SZ, %o0
+ sethi %hi(c_sys_nis_syscall), %g1
+ add %g1, %g4, %g1
+ jmpl %g1 + %lo(c_sys_nis_syscall), %g0
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
sys_execve:
- sethi %hi(sparc_execve), %g1
- add %g1, %g4, %g1
- jmpl %g1 + %lo(sparc_execve), %g0
- add %sp, STACK_BIAS + REGWIN_SZ, %o0
+ sethi %hi(sparc_execve), %g1
+ add %g1, %g4, %g1
+ jmpl %g1 + %lo(sparc_execve), %g0
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
sys32_execve:
- sethi %hi(sparc32_execve), %g1
- add %g1, %g4, %g1
- jmpl %g1 + %lo(sparc32_execve), %g0
- add %sp, STACK_BIAS + REGWIN_SZ, %o0
+ sethi %hi(sparc32_execve), %g1
+ add %g1, %g4, %g1
+ jmpl %g1 + %lo(sparc32_execve), %g0
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
sys_sigpause:
/* NOTE: %o0 has a correct value already */
- call do_sigpause
- add %sp, STACK_BIAS + REGWIN_SZ, %o1
+ call do_sigpause
+ add %sp, STACK_BIAS + REGWIN_SZ, %o1
- ld [%curptr + AOFF_task_flags], %l5
- andcc %l5, 0x20, %g0
- be,pt %icc, rtrap
+ ld [%curptr + AOFF_task_flags], %l5
+ andcc %l5, 0x20, %g0
+ be,pt %icc, rtrap
+ clr %l6
+ call syscall_trace
nop
- call syscall_trace
- nop
- ba,a,pt %xcc, rtrap
+ ba,pt %xcc, rtrap
+ clr %l6
sys_sigsuspend:
- call do_sigsuspend
- add %sp, STACK_BIAS + REGWIN_SZ, %o0
+ call do_sigsuspend
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
- ld [%curptr + AOFF_task_flags], %l5
- andcc %l5, 0x20, %g0
- be,pt %icc, rtrap
- nop
- call syscall_trace
+ ld [%curptr + AOFF_task_flags], %l5
+ andcc %l5, 0x20, %g0
+ be,pt %icc, rtrap
+ clr %l6
+ call syscall_trace
nop
- ba,a,pt %xcc, rtrap
+ ba,pt %xcc, rtrap
+ clr %l6
sys_sigreturn:
- call do_sigreturn
- add %sp, STACK_BIAS + REGWIN_SZ, %o0
+ call do_sigreturn
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
- ld [%curptr + AOFF_task_flags], %l5
- andcc %l5, 0x20, %g0
- be,pt %icc, rtrap
+ ld [%curptr + AOFF_task_flags], %l5
+ andcc %l5, 0x20, %g0
+ be,pt %icc, rtrap
+ clr %l6
+ call syscall_trace
nop
- call syscall_trace
- nop
- ba,a,pt %xcc, rtrap
+ ba,pt %xcc, rtrap
+ clr %l6
sys_ptrace:
- call do_ptrace
- add %sp, STACK_BIAS + REGWIN_SZ, %o0
+ call do_ptrace
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
- ld [%curptr + AOFF_task_flags], %l5
- andcc %l5, 0x20, %g0
- be,pt %icc, rtrap
- nop
- call syscall_trace
+ ld [%curptr + AOFF_task_flags], %l5
+ andcc %l5, 0x20, %g0
+ be,pt %icc, rtrap
+ clr %l6
+ call syscall_trace
nop
- ba,a,pt %xcc, rtrap
+ ba,pt %xcc, rtrap
+ clr %l6
- /* This is how fork() was meant to be done, 10 instruction entry. -DaveM */
+ /* This is how fork() was meant to be done, 12 instruction entry. -DaveM */
.globl sys_fork, sys_vfork, sys_clone
sys_fork:
sys_vfork:
- mov SIGCHLD, %o0
- clr %o1
+ mov SIGCHLD, %o0
+ clr %o1
sys_clone:
- mov %o7, %l5
+ mov %o7, %l5
+ save %sp, -REGWIN_SZ, %sp
flushw
- rdpr %cwp, %o4
- add %sp, STACK_BIAS + REGWIN_SZ, %o2
- movrz %o1, %fp, %o1
+ restore %g0, %g0, %g0
+ rdpr %cwp, %o4
+ add %sp, STACK_BIAS + REGWIN_SZ, %o2
+ movrz %o1, %fp, %o1
/* Don't try this at home. */
- stx %o4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G0]
- call do_fork
- mov %l5, %o7
+ stx %o4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G0]
+ call do_fork
+ mov %l5, %o7
linux_sparc_ni_syscall:
- sethi %hi(sys_ni_syscall), %l7
- or %l7, %lo(sys_ni_syscall), %l7
- ba,pt %xcc,syscall_is_too_hard
- add %l7, %g4, %l7
+ sethi %hi(sys_ni_syscall), %l7
+ or %l7, %lo(sys_ni_syscall), %l7
+ ba,pt %xcc,syscall_is_too_hard
+ add %l7, %g4, %l7
linux_fast_syscall:
- andn %l7, 3, %l7
- mov %i0, %o0
- mov %i1, %o1
- mov %i2, %o2
- jmpl %l7 + %g0, %g0
- mov %i3, %o3
+ andn %l7, 3, %l7
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ jmpl %l7 + %g0, %g0
+ mov %i3, %o3
linux_syscall_trace:
- call syscall_trace
+ call syscall_trace
nop
- mov %i0, %o0
- mov %i1, %o1
- mov %i2, %o2
- mov %i3, %o3
- ba,pt %xcc, 2f
- mov %i4, %o4
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ mov %i3, %o3
+ ba,pt %xcc, 2f
+ mov %i4, %o4
.globl ret_from_syscall
ret_from_syscall:
- ba,pt %xcc, ret_sys_call
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0], %o0
+ ba,pt %xcc, ret_sys_call
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0], %o0
/* Linux native and SunOS system calls enter here... */
.align 4
.globl linux_sparc_syscall
linux_sparc_syscall:
/* Direct access to user regs, must faster. */
- cmp %g1, NR_SYSCALLS
- add %l7, %g4, %l7
- bgeu,pn %xcc, linux_sparc_ni_syscall
- sll %g1, 3, %l4
- ldx [%l7 + %l4], %l7
- andcc %l7, 1, %g0
- bne,pn %icc, linux_fast_syscall
+ cmp %g1, NR_SYSCALLS
+ add %l7, %g4, %l7
+ bgeu,pn %xcc, linux_sparc_ni_syscall
+ sll %g1, 3, %l4
+ ldx [%l7 + %l4], %l7
+ andcc %l7, 1, %g0
+ bne,pn %icc, linux_fast_syscall
/* Just do the next insn in the delay slot */
.globl syscall_is_too_hard
syscall_is_too_hard:
#ifdef SYSCALL_TRACING /* Debugging... */
- mov %g1, %o0 ! o0=scall, o1=ptregs
- call syscall_trace_entry
- add %sp, STACK_BIAS + REGWIN_SZ, %o1
+ mov %g1, %o0 ! o0=scall, o1=ptregs
+ call syscall_trace_entry
+ add %sp, STACK_BIAS + REGWIN_SZ, %o1
#endif
- mov %i0, %o0
- mov %i1, %o1
- mov %i2, %o2
-
- ldx [%curptr + AOFF_task_flags], %l5
- mov %i3, %o3
- mov %i4, %o4
- andcc %l5, 0x20, %g0
- bne,pn %icc, linux_syscall_trace
- mov %i0, %l5
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+
+ ldx [%curptr + AOFF_task_flags], %l5
+ mov %i3, %o3
+ mov %i4, %o4
+ andcc %l5, 0x20, %g0
+ bne,pn %icc, linux_syscall_trace
+ mov %i0, %l5
2:
- call %l7
- mov %i5, %o5
+ call %l7
+ mov %i5, %o5
#ifdef SYSCALL_TRACING /* Debugging... */
- call syscall_trace_exit ! o0=sysret, o1=ptregs
- add %sp, STACK_BIAS + REGWIN_SZ, %o1
+ call syscall_trace_exit ! o0=sysret, o1=ptregs
+ add %sp, STACK_BIAS + REGWIN_SZ, %o1
#endif
- stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
+ stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
.globl ret_sys_call
ret_sys_call:
- ldx [%curptr + AOFF_task_flags], %l6
- mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %g3
- cmp %o0, -ENOIOCTLCMD
- sllx %g2, 32, %g2
- bgeu,pn %xcc, 1f
- andcc %l6, 0x20, %l6
+ ldx [%curptr + AOFF_task_flags], %l6
+ ldx [%curptr + AOFF_task_tss + AOFF_thread_flags], %l2
+ mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
+ and %l2, SPARC_FLAG_32BIT, %l2
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %g3
+ brnz,a,pn %l2, 1f
+ sra %o0, 0, %o0
+1:
+ cmp %o0, -ENOIOCTLCMD
+ sllx %g2, 32, %g2
+ bgeu,pn %xcc, 1f
+ andcc %l6, 0x20, %l6
/* System call success, clear Carry condition code. */
- andn %g3, %g2, %g3
- clr %l6
- stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE]
- bne,pn %icc, linux_syscall_trace2
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 /* pc = npc */
- add %l1, 0x4, %l2 /* npc = npc+4 */
- stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]
- ba,pt %xcc, rtrap
- stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]
+ andn %g3, %g2, %g3
+ clr %l6
+ stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE]
+ bne,pn %icc, linux_syscall_trace2
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 ! pc = npc
+ add %l1, 0x4, %l2 !npc = npc+4
+ stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]
+ ba,pt %xcc, rtrap
+ stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]
1:
/* System call failure, set Carry condition code.
* Also, get abs(errno) to return to the process.
*/
- sub %g0, %o0, %o0
- or %g3, %g2, %g3
- stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
- mov 1, %l6
- stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE]
- bne,pn %icc, linux_syscall_trace2
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 /* pc = npc */
- add %l1, 0x4, %l2 /* npc = npc+4 */
- stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]
- ba,pt %xcc, rtrap
- stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]
+ sub %g0, %o0, %o0
+ or %g3, %g2, %g3
+ stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
+ mov 1, %l6
+ stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE]
+ bne,pn %icc, linux_syscall_trace2
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 ! pc = npc
+ add %l1, 0x4, %l2 !npc = npc+4
+ stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]
+ ba,pt %xcc, rtrap
+ stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]
linux_syscall_trace2:
- call syscall_trace
- add %l1, 0x4, %l2 /* npc = npc+4 */
- stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]
- ba,pt %xcc, rtrap
- stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]
+ call syscall_trace
+ add %l1, 0x4, %l2 /* npc = npc+4 */
+ stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]
+ ba,pt %xcc, rtrap
+ stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]
/* End of entry.S */
diff --git a/arch/sparc64/kernel/etrap.S b/arch/sparc64/kernel/etrap.S
index 0c166ec25..efb1b48fc 100644
--- a/arch/sparc64/kernel/etrap.S
+++ b/arch/sparc64/kernel/etrap.S
@@ -1,4 +1,4 @@
-/* $Id: etrap.S,v 1.18 1997/05/19 05:58:51 davem Exp $
+/* $Id: etrap.S,v 1.21 1997/06/02 06:33:28 davem Exp $
* etrap.S: Preparing for entry into the kernel on Sparc V9.
*
* Copyright (C) 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -22,7 +22,7 @@
.text
.align 32
- .globl etrap, etrap_irq
+ .globl etrap, etrap_irq, etraptl1
etrap:
rdpr %pil, %g2
etrap_irq:
@@ -45,13 +45,14 @@ etrap_irq:
stx %g3, [%g2 + REGWIN_SZ + PT_V9_TNPC]
stx %g1, [%g2 + REGWIN_SZ + PT_V9_Y]
- rdpr %pstate, %g1
- save %g2, -STACK_BIAS, %sp
- bne,pn %xcc, 1f
+ save %g2, -STACK_BIAS, %sp ! The ordering of these two instructions
+ rdpr %pstate, %g1 ! is critical, see winfixup.S for details
+ bne,pn %xcc, 2f
rdpr %canrestore, %g3
rdpr %wstate, %g6
- wrpr %g0, 0, %canrestore
+ wrpr %g0, 7, %cleanwin
+ wrpr %g0, 0, %canrestore
sll %g6, 3, %g6
wrpr %g3, 0, %otherwin
wrpr %g6, %wstate
@@ -59,17 +60,17 @@ etrap_irq:
sllx %g3, 32, %g3
mov PRIMARY_CONTEXT, %g2
stxa %g0, [%g2] ASI_DMMU
+
flush %g3
-1:
- wrpr %g0, 0x0, %tl
+2: wrpr %g0, 0x0, %tl
mov %g1, %l1
mov %g4, %l4
mov %g5, %l5
mov %g7, %l2
wrpr %l1, PSTATE_AG, %pstate
stx %g1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G1]
- stx %g2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G2]
+ stx %g2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G2]
stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G3]
stx %g4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G4]
stx %g5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G5]
@@ -77,8 +78,8 @@ etrap_irq:
stx %g7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G7]
stx %i0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
stx %i1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
- stx %i2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2]
+ stx %i2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2]
stx %i3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I3]
stx %i4, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I4]
stx %i5, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I5]
@@ -86,16 +87,13 @@ etrap_irq:
stx %i7, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I7]
wrpr %l1, (PSTATE_IE | PSTATE_AG), %pstate
sethi %uhi(KERNBASE), %g4
- rd %pic, %g6
+ rd %pic, %g6
jmpl %l2 + 0x4, %g0
sllx %g4, 32, %g4
-
- .globl etraptl1
etraptl1:
rdpr %tstate, %g1
+ sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2
ba,pt %xcc, 1b
- sub %sp, REGWIN_SZ + TRACEREG_SZ - STACK_BIAS, %g2
- nop
- nop
+ andcc %g1, TSTATE_PRIV, %g0
nop
diff --git a/arch/sparc64/kernel/hack.S b/arch/sparc64/kernel/hack.S
index 6303bd9e9..843221395 100644
--- a/arch/sparc64/kernel/hack.S
+++ b/arch/sparc64/kernel/hack.S
@@ -24,16 +24,12 @@ do_fpother_tl1: retl;nop
do_iae_tl1: retl;nop
.globl do_ill_tl1
do_ill_tl1: retl;nop
- .globl do_irq
-do_irq: retl;nop
.globl do_irq_tl1
do_irq_tl1: retl;nop
.globl do_lddfmna
do_lddfmna: retl;nop
.globl do_lddfmna_tl1
do_lddfmna_tl1: retl;nop
- .globl do_mna_tl1
-do_mna_tl1: retl;nop
.globl do_paw
do_paw: retl;nop
.globl do_paw_tl1
@@ -51,7 +47,7 @@ do_vaw_tl1: retl;nop
.globl floppy_hardint
floppy_hardint: retl;nop
.globl get_cpuid
-get_cpuid: retl;nop
+get_cpuid: retl;mov 0, %o0
.globl getcc
getcc: retl;nop
.globl halt
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S
index 4babe3eb4..3844c24c3 100644
--- a/arch/sparc64/kernel/head.S
+++ b/arch/sparc64/kernel/head.S
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.30 1997/05/18 22:52:12 davem Exp $
+/* $Id: head.S,v 1.31 1997/05/30 22:35:28 davem Exp $
* head.S: Initial boot code for the Sparc64 port of Linux.
*
* Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -55,7 +55,7 @@ ramdisk_image:
.word 0
ramdisk_size:
.word 0
- .word reboot_command
+ .xword reboot_command
/* We must be careful, 32-bit OpenBOOT will get confused if it
* tries to save away a register window to a 64-bit kernel
diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
index 3db6fa945..d3792dec6 100644
--- a/arch/sparc64/kernel/ioctl32.c
+++ b/arch/sparc64/kernel/ioctl32.c
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.3 1997/05/27 19:30:13 jj Exp $
+/* $Id: ioctl32.c,v 1.8 1997/06/04 13:05:15 jj Exp $
* ioctl32.c: Conversion between 32bit and 64bit native ioctls.
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -7,22 +7,369 @@
* ioctls.
*/
+#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/ioctl.h>
+#include <linux/if.h>
+#include <linux/malloc.h>
+#include <linux/hdreg.h>
+#include <linux/md.h>
+#include <linux/kd.h>
+#include <linux/route.h>
+#include <linux/netlink.h>
#include <asm/types.h>
#include <asm/uaccess.h>
-/* As gcc will warn about casting u32 to some ptr, we have to cast it to unsigned long first, and that's what is A() for.
- * You just do (void *)A(x), instead of having to type (void *)((unsigned long)x) or instead of just (void *)x, which will
- * produce warnings */
+/* As gcc will warn about casting u32 to some ptr, we have to cast it to
+ * unsigned long first, and that's what is A() for.
+ * You just do (void *)A(x), instead of having to type (void *)((unsigned long)x)
+ * or instead of just (void *)x, which will produce warnings.
+ */
#define A(x) ((unsigned long)x)
extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
+
+static int w_long(unsigned int fd, unsigned int cmd, u32 arg)
+{
+ unsigned long old_fs = get_fs();
+ int err;
+ unsigned long val;
+
+ set_fs (KERNEL_DS);
+ err = sys_ioctl(fd, cmd, (unsigned long)&val);
+ set_fs (old_fs);
+ if (!err && put_user(val, (u32 *)A(arg)))
+ return -EFAULT;
+ return err;
+}
+struct ifmap32 {
+ u32 mem_start;
+ u32 mem_end;
+ unsigned short base_addr;
+ unsigned char irq;
+ unsigned char dma;
+ unsigned char port;
+};
+
+struct ifreq32 {
+#define IFHWADDRLEN 6
+#define IFNAMSIZ 16
+ union {
+ char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */
+ } ifr_ifrn;
+ union {
+ struct sockaddr ifru_addr;
+ struct sockaddr ifru_dstaddr;
+ struct sockaddr ifru_broadaddr;
+ struct sockaddr ifru_netmask;
+ struct sockaddr ifru_hwaddr;
+ short ifru_flags;
+ int ifru_ivalue;
+ int ifru_mtu;
+ struct ifmap32 ifru_map;
+ char ifru_slave[IFNAMSIZ]; /* Just fits the size */
+ __kernel_caddr_t32 ifru_data;
+ } ifr_ifru;
+};
+
+struct ifconf32 {
+ int ifc_len; /* size of buffer */
+ __kernel_caddr_t32 ifcbuf;
+};
+
+static inline int dev_ifconf(unsigned int fd, u32 arg)
+{
+ struct ifconf32 ifc32;
+ struct ifconf ifc;
+ struct ifreq32 *ifr32;
+ struct ifreq *ifr;
+ unsigned long old_fs;
+ unsigned int i, j;
+ int err;
+
+ if (copy_from_user(&ifc32, (struct ifconf32 *)A(arg), sizeof(struct ifconf32)))
+ return -EFAULT;
+ ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32)) + 1) * sizeof (struct ifreq);
+ ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL);
+ if (!ifc.ifc_buf) return -ENOMEM;
+ ifr = ifc.ifc_req;
+ ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf);
+ for (i = 0; i < ifc32.ifc_len; i += sizeof (struct ifreq32)) {
+ if (copy_from_user(ifr++, ifr32++, sizeof (struct ifreq32))) {
+ kfree (ifc.ifc_buf);
+ return -EFAULT;
+ }
+ }
+ old_fs = get_fs(); set_fs (KERNEL_DS);
+ err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc);
+ set_fs (old_fs);
+ if (!err) {
+ ifr = ifc.ifc_req;
+ ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf);
+ for (i = 0, j = 0; i < ifc32.ifc_len && j < ifc.ifc_len;
+ i += sizeof (struct ifreq32), j += sizeof (struct ifreq)) {
+ if (copy_to_user(ifr32++, ifr++, sizeof (struct ifreq32))) {
+ err = -EFAULT;
+ break;
+ }
+ }
+ if (!err) {
+ if (i <= ifc32.ifc_len)
+ ifc32.ifc_len = i;
+ else
+ ifc32.ifc_len = i - sizeof (struct ifreq32);
+ if (copy_to_user((struct ifconf32 *)A(arg), &ifc32, sizeof(struct ifconf32)))
+ err = -EFAULT;
+ }
+ }
+ kfree (ifc.ifc_buf);
+ return err;
+}
+
+static inline int dev_ifsioc(unsigned int fd, unsigned int cmd, u32 arg)
+{
+ struct ifreq ifr;
+ unsigned long old_fs;
+ int err;
+
+ if (cmd == SIOCSIFMAP) {
+ if (copy_from_user(&ifr, (struct ifreq32 *)A(arg), sizeof(ifr.ifr_name)) ||
+ __get_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.mem_start)) ||
+ __get_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.mem_end)) ||
+ __get_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.base_addr)) ||
+ __get_user(ifr.ifr_map.irq, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.irq)) ||
+ __get_user(ifr.ifr_map.dma, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.dma)) ||
+ __get_user(ifr.ifr_map.port, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.port)))
+ return -EFAULT;
+ } else {
+ if (copy_from_user(&ifr, (struct ifreq32 *)A(arg), sizeof(struct ifreq32)))
+ return -EFAULT;
+ }
+ old_fs = get_fs();
+ set_fs (KERNEL_DS);
+ err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
+ set_fs (old_fs);
+ if (!err) {
+ switch (cmd) {
+ case SIOCGIFFLAGS:
+ case SIOCGIFMETRIC:
+ case SIOCGIFMTU:
+ case SIOCGIFMEM:
+ case SIOCGIFHWADDR:
+ case SIOGIFINDEX:
+ case SIOCGIFADDR:
+ case SIOCGIFBRDADDR:
+ case SIOCGIFDSTADDR:
+ case SIOCGIFNETMASK:
+ if (copy_to_user((struct ifreq32 *)A(arg), &ifr, sizeof(struct ifreq32)))
+ return -EFAULT;
+ break;
+ case SIOCGIFMAP:
+ if (copy_to_user((struct ifreq32 *)A(arg), &ifr, sizeof(ifr.ifr_name)) ||
+ __put_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.mem_start)) ||
+ __put_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.mem_end)) ||
+ __put_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.base_addr)) ||
+ __put_user(ifr.ifr_map.irq, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.irq)) ||
+ __put_user(ifr.ifr_map.dma, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.dma)) ||
+ __put_user(ifr.ifr_map.port, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.port)))
+ return -EFAULT;
+ break;
+ }
+ }
+ return err;
+}
+
+struct rtentry32 {
+ u32 rt_pad1;
+ struct sockaddr rt_dst; /* target address */
+ struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */
+ struct sockaddr rt_genmask; /* target network mask (IP) */
+ unsigned short rt_flags;
+ short rt_pad2;
+ u32 rt_pad3;
+ unsigned char rt_tos;
+ unsigned char rt_class;
+ short rt_pad4;
+ short rt_metric; /* +1 for binary compatibility! */
+ /* char * */ u32 rt_dev; /* forcing the device at add */
+ u32 rt_mtu; /* per route MTU/Window */
+ u32 rt_window; /* Window clamping */
+ unsigned short rt_irtt; /* Initial RTT */
+
+};
+
+static inline int routing_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
+{
+ struct rtentry r;
+ char devname[16];
+ u32 rtdev;
+ int ret;
+ unsigned long old_fs = get_fs();
+
+ if (get_user (r.rt_pad1, &(((struct rtentry32 *)A(arg))->rt_pad1)) ||
+ copy_from_user (&r.rt_dst, &(((struct rtentry32 *)A(arg))->rt_dst), 3 * sizeof(struct sockaddr)) ||
+ __get_user (r.rt_flags, &(((struct rtentry32 *)A(arg))->rt_flags)) ||
+ __get_user (r.rt_pad2, &(((struct rtentry32 *)A(arg))->rt_pad2)) ||
+ __get_user (r.rt_pad3, &(((struct rtentry32 *)A(arg))->rt_pad3)) ||
+ __get_user (r.rt_tos, &(((struct rtentry32 *)A(arg))->rt_tos)) ||
+ __get_user (r.rt_class, &(((struct rtentry32 *)A(arg))->rt_class)) ||
+ __get_user (r.rt_pad4, &(((struct rtentry32 *)A(arg))->rt_pad4)) ||
+ __get_user (r.rt_metric, &(((struct rtentry32 *)A(arg))->rt_metric)) ||
+ __get_user (r.rt_mtu, &(((struct rtentry32 *)A(arg))->rt_mtu)) ||
+ __get_user (r.rt_window, &(((struct rtentry32 *)A(arg))->rt_window)) ||
+ __get_user (r.rt_irtt, &(((struct rtentry32 *)A(arg))->rt_irtt)) ||
+ __get_user (rtdev, &(((struct rtentry32 *)A(arg))->rt_dev)) ||
+ (rtdev && copy_from_user (devname, (char *)A(rtdev), 15)))
+ return -EFAULT;
+ if (rtdev) {
+ r.rt_dev = devname; devname[15] = 0;
+ } else
+ r.rt_dev = 0;
+ set_fs (KERNEL_DS);
+ ret = sys_ioctl (fd, cmd, (long)&r);
+ set_fs (old_fs);
+ return ret;
+}
+
+struct nlmsghdr32 {
+ u32 nlmsg_len; /* Length of message including header */
+ u32 nlmsg_type; /* Message type */
+ u32 nlmsg_seq; /* Sequence number */
+ u32 nlmsg_pid; /* Sending process PID */
+ unsigned char nlmsg_data[0];
+};
+
+struct in_rtmsg32 {
+ struct in_addr rtmsg_prefix;
+ struct in_addr rtmsg_gateway;
+ unsigned rtmsg_flags;
+ u32 rtmsg_mtu;
+ u32 rtmsg_window;
+ unsigned short rtmsg_rtt;
+ short rtmsg_metric;
+ unsigned char rtmsg_tos;
+ unsigned char rtmsg_class;
+ unsigned char rtmsg_prefixlen;
+ unsigned char rtmsg_reserved;
+ int rtmsg_ifindex;
+};
+
+struct in_ifmsg32 {
+ struct sockaddr ifmsg_lladdr;
+ struct in_addr ifmsg_prefix;
+ struct in_addr ifmsg_brd;
+ unsigned ifmsg_flags;
+ u32 ifmsg_mtu;
+ short ifmsg_metric;
+ unsigned char ifmsg_prefixlen;
+ unsigned char ifmsg_reserved;
+ int ifmsg_index;
+ char ifmsg_name[16];
+};
+
+static inline int rtmsg_ioctl(unsigned int fd, u32 arg)
+{
+ struct {
+ struct nlmsghdr n;
+ union {
+ struct in_rtmsg rt;
+ struct in_ifmsg iff;
+ struct in_rtctlmsg ctl;
+ struct in_rtrulemsg rule;
+ } u;
+ } nn;
+ char *p;
+ int ret;
+ unsigned long old_fs = get_fs();
+
+ if (get_user (nn.n.nlmsg_len, &(((struct nlmsghdr32 *)A(arg))->nlmsg_len)) ||
+ __get_user (nn.n.nlmsg_type, &(((struct nlmsghdr32 *)A(arg))->nlmsg_type)) ||
+ __get_user (nn.n.nlmsg_seq, &(((struct nlmsghdr32 *)A(arg))->nlmsg_seq)) ||
+ __get_user (nn.n.nlmsg_pid, &(((struct nlmsghdr32 *)A(arg))->nlmsg_pid)) ||
+ __get_user (nn.n.nlmsg_data[0], &(((struct nlmsghdr32 *)A(arg))->nlmsg_data[0])))
+ return -EFAULT;
+ p = ((char *)(&nn.n)) + sizeof(struct nlmsghdr);
+ arg += sizeof(struct nlmsghdr32);
+ switch (nn.n.nlmsg_type) {
+ case RTMSG_NEWRULE:
+ case RTMSG_DELRULE:
+ if (nn.n.nlmsg_len < sizeof(struct nlmsghdr32) + sizeof(struct in_rtrulemsg)
+ - sizeof(struct in_rtmsg) + sizeof(struct in_rtmsg32))
+ return -EINVAL;
+ if (copy_from_user (p, (struct in_rtrulemsg *)A(arg), sizeof(struct in_rtrulemsg) - sizeof(struct in_rtmsg)))
+ return -EFAULT;
+ nn.n.nlmsg_len = sizeof(struct nlmsghdr) + sizeof(struct in_rtrulemsg);
+ p += sizeof (struct in_rtrulemsg) - sizeof(struct in_rtmsg);
+ arg += sizeof (struct in_rtrulemsg) - sizeof(struct in_rtmsg);
+ goto newroute;
+ case RTMSG_NEWROUTE:
+ case RTMSG_DELROUTE:
+ if (nn.n.nlmsg_len < sizeof(struct nlmsghdr32) + sizeof(struct in_rtmsg))
+ return -EINVAL;
+ nn.n.nlmsg_len = sizeof(struct nlmsghdr) + sizeof(struct in_rtmsg);
+newroute:
+ if (copy_from_user (p, (struct in_rtmsg32 *)A(arg), 2*sizeof(struct in_addr) + sizeof(unsigned)) ||
+ __get_user (((struct in_rtmsg *)p)->rtmsg_mtu, &((struct in_rtmsg32 *)A(arg))->rtmsg_mtu) ||
+ __get_user (((struct in_rtmsg *)p)->rtmsg_window, &((struct in_rtmsg32 *)A(arg))->rtmsg_window) ||
+ copy_from_user (&(((struct in_rtmsg *)p)->rtmsg_rtt), &((struct in_rtmsg32 *)A(arg))->rtmsg_rtt,
+ 2 * sizeof(short) + 4 + sizeof(int)))
+ return -EFAULT;
+ break;
+ case RTMSG_NEWDEVICE:
+ case RTMSG_DELDEVICE:
+ if (nn.n.nlmsg_len < sizeof(struct nlmsghdr32) + sizeof(struct in_ifmsg))
+ return -EINVAL;
+ nn.n.nlmsg_len = sizeof(struct nlmsghdr) + sizeof(struct in_ifmsg);
+ if (copy_from_user (p, (struct in_ifmsg32 *)A(arg),
+ sizeof(struct sockaddr) + 2*sizeof(struct in_addr) + sizeof(unsigned)) ||
+ __get_user (((struct in_ifmsg *)p)->ifmsg_mtu, &((struct in_ifmsg32 *)A(arg))->ifmsg_mtu) ||
+ copy_from_user (&(((struct in_ifmsg *)p)->ifmsg_metric), &((struct in_ifmsg32 *)A(arg))->ifmsg_metric,
+ sizeof(short) + 2 + sizeof(int) + 16))
+ return -EFAULT;
+ break;
+ case RTMSG_CONTROL:
+ if (nn.n.nlmsg_len < sizeof(struct nlmsghdr32) + sizeof(struct in_rtctlmsg))
+ return -EINVAL;
+ nn.n.nlmsg_len = sizeof(struct nlmsghdr) + sizeof(struct in_rtctlmsg);
+ if (copy_from_user (p, (struct in_rtctlmsg *)A(arg), sizeof(struct in_rtctlmsg)))
+ return -EFAULT;
+ break;
+ }
+ set_fs (KERNEL_DS);
+ ret = sys_ioctl (fd, SIOCRTMSG, (long)&(nn.n));
+ set_fs (old_fs);
+ return ret;
+}
+
+struct hd_geometry32 {
+ unsigned char heads;
+ unsigned char sectors;
+ unsigned short cylinders;
+ u32 start;
+};
+
+static inline int hdio_getgeo(unsigned int fd, u32 arg)
+{
+ unsigned long old_fs = get_fs();
+ struct hd_geometry geo;
+ int err;
+
+ set_fs (KERNEL_DS);
+ err = sys_ioctl(fd, HDIO_GETGEO, (unsigned long)&geo);
+ set_fs (old_fs);
+ if (!err) {
+ if (copy_to_user ((struct hd_geometry32 *)A(arg), &geo, 4) ||
+ __put_user (geo.start, &(((struct hd_geometry32 *)A(arg))->start)))
+ return -EFAULT;
+ }
+ return err;
+}
+
asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
{
struct file * filp;
@@ -35,16 +382,149 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
error = sys_ioctl (fd, cmd, (unsigned long)arg);
goto out;
}
- error = 0;
+ error = -EFAULT;
switch (cmd) {
- default:
- error = sys_ioctl (fd, cmd, (unsigned long)arg);
- goto out;
+ case SIOCGIFCONF:
+ error = dev_ifconf(fd, arg);
+ goto out;
+
+ case SIOCGIFFLAGS:
+ case SIOCSIFFLAGS:
+ case SIOCGIFMETRIC:
+ case SIOCSIFMETRIC:
+ case SIOCGIFMTU:
+ case SIOCSIFMTU:
+ case SIOCGIFMEM:
+ case SIOCSIFMEM:
+ case SIOCGIFHWADDR:
+ case SIOCSIFHWADDR:
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ case SIOGIFINDEX:
+ case SIOCGIFMAP:
+ case SIOCSIFMAP:
+ case SIOCGIFADDR:
+ case SIOCSIFADDR:
+ case SIOCGIFBRDADDR:
+ case SIOCSIFBRDADDR:
+ case SIOCGIFDSTADDR:
+ case SIOCSIFDSTADDR:
+ case SIOCGIFNETMASK:
+ case SIOCSIFNETMASK:
+ error = dev_ifsioc(fd, cmd, arg);
+ goto out;
+
+ case SIOCADDRT:
+ case SIOCDELRT:
+ error = routing_ioctl(fd, cmd, arg);
+ goto out;
+
+ case SIOCRTMSG:
+ error = rtmsg_ioctl(fd, arg);
+ goto out;
+
+ case HDIO_GETGEO:
+ error = hdio_getgeo(fd, arg);
+ goto out;
+
+ case BLKRAGET:
+ case BLKGETSIZE:
+ error = w_long(fd, cmd, arg);
+ goto out;
+
+ /* List here exlicitly which ioctl's are known to have
+ * compatable types passed or none at all...
+ */
+
+ /* Bit T */
+ case TCGETA:
+ case TCSETA:
+ case TCSETAW:
+ case TCSETAF:
+ case TCSBRK:
+ case TCXONC:
+ case TCFLSH:
+ case TCGETS:
+ case TCSETS:
+ case TCSETSW:
+ case TCSETSF:
+ case TIOCLINUX:
+
+ /* Little t */
+ case TIOCGETD:
+ case TIOCSETD:
+ case TIOCEXCL:
+ case TIOCNXCL:
+ case TIOCCONS:
+ case TIOCGSOFTCAR:
+ case TIOCSSOFTCAR:
+ case TIOCSWINSZ:
+ case TIOCGWINSZ:
+ case TIOCMGET:
+ case TIOCMBIC:
+ case TIOCMBIS:
+ case TIOCMSET:
+ case TIOCPKT:
+ case TIOCNOTTY:
+ case TIOCSTI:
+ case TIOCOUTQ:
+ case TIOCSPGRP:
+ case TIOCGPGRP:
+ case TIOCSCTTY:
+
+ /* Little f */
+ case FIOCLEX:
+ case FIONCLEX:
+ case FIOASYNC:
+ case FIONBIO:
+ case FIONREAD: /* This is also TIOCINQ */
+
+ /* 0x12 */
+ case BLKRRPART:
+ case BLKFLSBUF:
+ case BLKRASET:
+
+ /* 0x09 */
+ case REGISTER_DEV:
+ case START_MD:
+ case STOP_MD:
+
+ /* Big K */
+ case PIO_FONT:
+ case GIO_FONT:
+ case KDSIGACCEPT:
+ case KDGETKEYCODE:
+ case KDSETKEYCODE:
+
+ /* Socket level stuff */
+ case FIOSETOWN:
+ case SIOCSPGRP:
+ case FIOGETOWN:
+ case SIOCGPGRP:
+ case SIOCATMARK:
+ case SIOCGSTAMP:
+ case SIOCSIFLINK:
+ case SIOCSIFENCAP:
+ case SIOCGIFENCAP:
+ case SIOCSIFBR:
+ case SIOCGIFBR:
+ case SIOCSARP:
+ case SIOCGARP:
+ case SIOCDARP:
+ case SIOCADDDLCI:
+ case SIOCDELDLCI:
+ error = sys_ioctl (fd, cmd, (unsigned long)arg);
+ goto out;
+ break;
+
+ default:
+ printk("sys32_ioctl: Unknown cmd fd(%d) cmd(%08x) arg(%08x)\n",
+ (int)fd, (unsigned int)cmd, (unsigned int)arg);
+ error = -EINVAL;
+ goto out;
+ break;
}
out:
- if (error == -EINVAL) {
- printk ("sys32_ioctl on %016lx's %08x returns EINVAL\n", filp->f_op ? (long)filp->f_op->ioctl : 0UL, cmd);
- }
unlock_kernel();
return error;
}
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 593c1efc6..cc8183618 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.12 1997/05/23 09:35:43 jj Exp $
+/* $Id: process.c,v 1.17 1997/06/02 06:33:32 davem Exp $
* arch/sparc64/kernel/process.c
*
* Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -317,6 +317,13 @@ void exit_thread(void)
#else
if(current->flags & PF_USEDFPU) {
#endif
+ fprs_write(FPRS_FEF);
+ if(current->tss.flags & SPARC_FLAG_32BIT)
+ fpsave32((unsigned long *)&current->tss.float_regs[0],
+ &current->tss.fsr);
+ else
+ fpsave((unsigned long *)&current->tss.float_regs[0],
+ &current->tss.fsr);
#ifndef __SMP__
last_task_used_math = NULL;
#else
@@ -338,6 +345,13 @@ void flush_thread(void)
#else
if(current->flags & PF_USEDFPU) {
#endif
+ fprs_write(FPRS_FEF);
+ if(current->tss.flags & SPARC_FLAG_32BIT)
+ fpsave32((unsigned long *)&current->tss.float_regs[0],
+ &current->tss.fsr);
+ else
+ fpsave((unsigned long *)&current->tss.float_regs[0],
+ &current->tss.fsr);
#ifndef __SMP__
last_task_used_math = NULL;
#else
@@ -424,6 +438,8 @@ clone_stackframe(struct sparc_stackf *dst, struct sparc_stackf *src)
return sp;
}
+/* #define DEBUG_WINFIXUPS */
+
/* Standard stuff. */
static inline void shift_window_buffer(int first_win, int last_win,
struct thread_struct *tp)
@@ -440,12 +456,15 @@ static inline void shift_window_buffer(int first_win, int last_win,
void synchronize_user_stack(void)
{
struct thread_struct *tp = &current->tss;
- unsigned long window = tp->w_saved;
+ unsigned long window;
flush_user_windows();
- if(window) {
+ if((window = tp->w_saved) != 0) {
int winsize = REGWIN_SZ;
+#ifdef DEBUG_WINFIXUPS
+ printk("sus(%d", (int)window);
+#endif
if(tp->flags & SPARC_FLAG_32BIT)
winsize = REGWIN32_SZ;
@@ -459,18 +478,26 @@ void synchronize_user_stack(void)
tp->w_saved--;
}
} while(window--);
+#ifdef DEBUG_WINFIXUPS
+ printk(")");
+#endif
}
}
void fault_in_user_windows(struct pt_regs *regs)
{
struct thread_struct *tp = &current->tss;
- unsigned long window = tp->w_saved;
+ unsigned long window;
int winsize = REGWIN_SZ;
if(tp->flags & SPARC_FLAG_32BIT)
winsize = REGWIN32_SZ;
- if(window) {
+ flush_user_windows();
+ window = tp->w_saved;
+#ifdef DEBUG_WINFIXUPS
+ printk("fiuw(%d", (int)window);
+#endif
+ if(window != 0) {
window -= 1;
do {
unsigned long sp = tp->rwbuf_stkptrs[window];
@@ -481,6 +508,9 @@ void fault_in_user_windows(struct pt_regs *regs)
} while(window--);
}
current->tss.w_saved = 0;
+#ifdef DEBUG_WINFIXUPS
+ printk(")");
+#endif
}
/* Copy a Sparc thread. The fork() return value conventions
@@ -504,19 +534,17 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
struct reg_window *new_stack, *old_stack;
unsigned long stack_offset;
-#if 0
#ifndef __SMP__
if(last_task_used_math == current) {
#else
if(current->flags & PF_USEDFPU) {
#endif
- put_psr(get_psr() | PSR_EF);
- fpsave(&p->tss.float_regs[0], &p->tss.fsr);
+ fprs_write(FPRS_FEF);
+ fpsave((unsigned long *)&p->tss.float_regs[0], &p->tss.fsr);
#ifdef __SMP__
current->flags &= ~PF_USEDFPU;
#endif
}
-#endif
/* Calculate offset to stack_frame & pt_regs */
stack_offset = ((PAGE_SIZE<<1) - TRACEREG_SZ);
diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S
index 0f1dceb33..165b17ef0 100644
--- a/arch/sparc64/kernel/rtrap.S
+++ b/arch/sparc64/kernel/rtrap.S
@@ -1,4 +1,4 @@
-/* $Id: rtrap.S,v 1.18 1997/05/27 06:28:05 davem Exp $
+/* $Id: rtrap.S,v 1.21 1997/06/02 07:26:54 davem Exp $
* rtrap.S: Preparing for return from trap on Sparc V9.
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -17,109 +17,114 @@
.text
.align 32
- .globl rtrap
-rtrap:
- sethi %hi(bh_active), %l2
- or %l2, %lo(bh_active), %l2
- sethi %hi(bh_mask), %l1
- or %l1, %lo(bh_mask), %l1
- ldx [%l2 + %g4], %l3
- ldx [%l1 + %g4], %l4
- andcc %l3, %l4, %g0
- nop
+ .globl rtrap_clr_l6, rtrap
+rtrap_clr_l6:
+ ba,pt %xcc, rtrap
+ clr %l6
+rtrap: sethi %hi(bh_active), %l2
+ or %l2, %lo(bh_active), %l2
+ sethi %hi(bh_mask), %l1
+ or %l1, %lo(bh_mask), %l1
+ ldx [%l2 + %g4], %l3
+ ldx [%l1 + %g4], %l4
- be,pt %xcc, 2f
+ andcc %l3, %l4, %g0
+ be,pt %xcc, 2f
nop
- call do_bottom_half
+ call do_bottom_half
nop
-2: ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %l1
- sethi %hi(0xf << 20), %l4
- andcc %l1, TSTATE_PRIV, %l3
- and %l1, %l4, %l4
+2: ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %l1
+ sethi %hi(0xf << 20), %l4
+ andcc %l1, TSTATE_PRIV, %l3
+
+ and %l1, %l4, %l4
+ rdpr %pstate, %l7
+ andn %l1, %l4, %l1
+ be,pt %icc, to_user
+ andn %l7, PSTATE_IE, %l7
+3: ldx [%g6 + AOFF_task_tss + AOFF_thread_ctx], %l0
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G1], %g1
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G2], %g2
- rdpr %pstate, %l7
- andn %l1, %l4, %l1
- be,pt %icc, to_user
- andn %l7, PSTATE_IE, %l7
-3: ldx [%g6 + AOFF_task_tss + AOFF_thread_ctx], %l6
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G1], %g1
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G2], %g2
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G3], %g3
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G3], %g3
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G4], %g4
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G5], %g5
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G6], %g6
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G7], %g7
+ wrpr %l7, PSTATE_AG, %pstate
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0], %i0
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1], %i1
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G4], %g4
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G5], %g5
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G6], %g6
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_G7], %g7
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0], %i0
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1], %i1
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2], %i2
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I3], %i3
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I2], %i2
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I3], %i3
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I4], %i4
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I5], %i5
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I6], %i6
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I7], %i7
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_Y], %o3
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC], %l2
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I4], %i4
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I5], %i5
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I6], %i6
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I7], %i7
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_Y], %o3
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC], %l2
- ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %o2
- wr %o3, %g0, %y
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %o2
+ wr %o3, %g0, %y
+ srl %l4, 20, %l4
+ wrpr %l4, 0x0, %pil
+ wrpr %g0, 0x1, %tl
+ wrpr %l1, %g0, %tstate
+ wrpr %l2, %g0, %tpc
+ mov PRIMARY_CONTEXT, %l7
- srl %l4, 20, %l4
- wrpr %l7, %g0, %pstate
- wrpr %l4, 0x0, %pil
- wrpr %g0, 0x1, %tl
- wrpr %l1, %g0, %tstate
- wrpr %l2, %g0, %tpc
- brnz,pn %l3, 1f
- wrpr %o2, %g0, %tnpc
+ wrpr %o2, %g0, %tnpc
+ brnz,a,pn %l3, 1f
+ restore
+ sethi %uhi(KERNBASE), %l5
+ sllx %l5, 32, %l5
+ stxa %l0, [%l7] ASI_DMMU
+ flush %l5
+ rdpr %wstate, %l1
- mov PRIMARY_CONTEXT, %l7
- sethi %uhi(KERNBASE), %l5
- sllx %l5, 32, %l5
- stxa %l6, [%l7] ASI_DMMU
- flush %l5
- rdpr %wstate, %l1
- rdpr %otherwin, %l2
- srl %l1, 3, %l1
+ rdpr %otherwin, %l2
+ srl %l1, 3, %l1
+ wrpr %l2, %g0, %canrestore
+ wrpr %l1, %g0, %wstate
+ wrpr %g0, %g0, %otherwin
+ restore
+ rdpr %canrestore, %g1
+ wrpr %g1, 0x0, %cleanwin
- wrpr %l2, %g0, %canrestore
- wrpr %l1, %g0, %wstate
- wrpr %g0, %g0, %otherwin
-1: restore
- retry
+1: retry
to_user:
sethi %hi(need_resched), %l0
or %l0, %lo(need_resched), %l0
ld [%l0 + %g4], %l0
-
wrpr %l7, PSTATE_IE, %pstate
brz,pt %l0, check_signal
ldx [%g6 + AOFF_task_signal], %l0
+ nop
+
call schedule
nop
- ldx [%g6 + AOFF_task_signal], %l0
- nop
+ ba,pt %xcc, check_signal
+ ldx [%g6 + AOFF_task_signal], %l0
check_signal:
ldx [%g6 + AOFF_task_blocked], %o0
-
- or %l7, PSTATE_AG, %l7 ! Will need this for setting back wstate
andncc %l0, %o0, %g0
- be,pt %xcc, check_user_wins
- mov %l5, %o2
+ be,a,pt %xcc, check_user_wins
+ ldx [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2
+
+ mov %l5, %o2
mov %l6, %o3
call do_signal
add %sp, STACK_BIAS + REGWIN_SZ, %o1
-check_user_wins:
-#if 0
- call user_rtrap_report
- add %sp, STACK_BIAS + REGWIN_SZ, %o0
-#endif
ldx [%g6 + AOFF_task_tss + AOFF_thread_w_saved], %o2
-
+ clr %l6
+check_user_wins:
brz,pt %o2, 3b
- add %sp, STACK_BIAS + REGWIN_SZ, %o1
+ nop
+
call fault_in_user_windows
- add %o7, 3b-.-4, %o7
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
+ ba,a,pt %xcc, 3b
+ nop
nop
nop
nop
diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
index f81e30093..fe4615a6b 100644
--- a/arch/sparc64/kernel/signal.c
+++ b/arch/sparc64/kernel/signal.c
@@ -1,4 +1,4 @@
-/* $Id: signal.c,v 1.4 1997/05/27 06:28:05 davem Exp $
+/* $Id: signal.c,v 1.6 1997/05/29 12:44:48 jj Exp $
* arch/sparc64/kernel/signal.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
@@ -193,13 +193,17 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu)
{
#ifdef __SMP__
if (current->flags & PF_USEDFPU) {
- fpsave(&current->tss.float_regs[0], &current->tss.fsr);
+ fprs_write(FPRS_FEF);
+ fpsave((unsigned long *)&current->tss.float_regs[0],
+ &current->tss.fsr);
regs->tstate &= ~(TSTATE_PEF);
current->flags &= ~(PF_USEDFPU);
}
#else
if (current == last_task_used_math) {
- fpsave((unsigned long *)&current->tss.float_regs[0], &current->tss.fsr);
+ fprs_write(FPRS_FEF);
+ fpsave((unsigned long *)&current->tss.float_regs[0],
+ &current->tss.fsr);
last_task_used_math = 0;
regs->tstate &= ~(TSTATE_PEF);
}
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
index 33892065f..c0454658b 100644
--- a/arch/sparc64/kernel/signal32.c
+++ b/arch/sparc64/kernel/signal32.c
@@ -1,4 +1,4 @@
-/* $Id: signal32.c,v 1.10 1997/05/27 06:28:07 davem Exp $
+/* $Id: signal32.c,v 1.13 1997/06/01 05:46:09 davem Exp $
* arch/sparc64/kernel/signal32.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
@@ -139,35 +139,51 @@ restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu32_t *fpu)
void do_new_sigreturn32(struct pt_regs *regs)
{
struct new_signal_frame32 *sf;
- unsigned int psr, i;
+ unsigned int psr;
unsigned pc, npc, fpu_save, mask;
sf = (struct new_signal_frame32 *) regs->u_regs [UREG_FP];
+
/* 1. Make sure we are not getting garbage from the user */
- if (verify_area (VERIFY_READ, sf, sizeof (*sf))){
- goto segv;
- }
- if (((unsigned long) sf) & 3){
+ if (verify_area (VERIFY_READ, sf, sizeof (*sf)) ||
+ (((unsigned long) sf) & 3))
goto segv;
- }
+
get_user(pc, &sf->info.si_regs.pc);
__get_user(npc, &sf->info.si_regs.npc);
- if ((pc | npc) & 3){
+
+ if ((pc | npc) & 3)
goto segv;
- }
+
regs->tpc = pc;
regs->tnpc = npc;
/* 2. Restore the state */
__get_user(regs->y, &sf->info.si_regs.y);
__get_user(psr, &sf->info.si_regs.psr);
- for (i = 0; i < 16; i++)
- __get_user(regs->u_regs[i], &sf->info.si_regs.u_regs[i]);
+
+ __get_user(regs->u_regs[UREG_G1], &sf->info.si_regs.u_regs[UREG_G1]);
+ __get_user(regs->u_regs[UREG_G2], &sf->info.si_regs.u_regs[UREG_G2]);
+ __get_user(regs->u_regs[UREG_G3], &sf->info.si_regs.u_regs[UREG_G3]);
+ __get_user(regs->u_regs[UREG_G4], &sf->info.si_regs.u_regs[UREG_G4]);
+ __get_user(regs->u_regs[UREG_G5], &sf->info.si_regs.u_regs[UREG_G5]);
+ __get_user(regs->u_regs[UREG_G6], &sf->info.si_regs.u_regs[UREG_G6]);
+ __get_user(regs->u_regs[UREG_G7], &sf->info.si_regs.u_regs[UREG_G7]);
+ __get_user(regs->u_regs[UREG_I0], &sf->info.si_regs.u_regs[UREG_I0]);
+ __get_user(regs->u_regs[UREG_I1], &sf->info.si_regs.u_regs[UREG_I1]);
+ __get_user(regs->u_regs[UREG_I2], &sf->info.si_regs.u_regs[UREG_I2]);
+ __get_user(regs->u_regs[UREG_I3], &sf->info.si_regs.u_regs[UREG_I3]);
+ __get_user(regs->u_regs[UREG_I4], &sf->info.si_regs.u_regs[UREG_I4]);
+ __get_user(regs->u_regs[UREG_I5], &sf->info.si_regs.u_regs[UREG_I5]);
+ __get_user(regs->u_regs[UREG_I6], &sf->info.si_regs.u_regs[UREG_I6]);
+ __get_user(regs->u_regs[UREG_I7], &sf->info.si_regs.u_regs[UREG_I7]);
/* User can only change condition codes and FPU enabling in %tstate. */
regs->tstate &= ~(TSTATE_ICC | TSTATE_PEF);
regs->tstate |= psr_to_tstate_icc(psr);
- if (psr & PSR_EF) regs->tstate |= TSTATE_PEF;
+
+ if (psr & PSR_EF)
+ regs->tstate |= TSTATE_PEF;
__get_user(fpu_save, &sf->fpu_save);
if (fpu_save)
@@ -193,11 +209,12 @@ asmlinkage void do_sigreturn32(struct pt_regs *regs)
scptr = (struct sigcontext32 *) regs->u_regs[UREG_I0];
/* Check sanity of the user arg. */
if(verify_area(VERIFY_READ, scptr, sizeof(struct sigcontext32)) ||
- (((unsigned long) scptr) & 3)) {
+ (((unsigned long) scptr) & 3))
goto segv;
- }
+
__get_user(pc, &scptr->sigc_pc);
__get_user(npc, &scptr->sigc_npc);
+
if((pc | npc) & 3)
goto segv; /* Nice try. */
@@ -241,7 +258,6 @@ setup_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc,
int old_status = current->tss.sstk_info.cur_status;
unsigned psr;
int i;
- u32 temp;
synchronize_user_stack();
sframep = (struct signal_sframe32 *) regs->u_regs[UREG_FP];
@@ -285,7 +301,10 @@ setup_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc,
}
else
#endif
+ /* XXX Perhaps we need a copy_in_user()? -DaveM */
for (i = 0; i < 16; i++) {
+ u32 temp;
+
get_user (temp, (((u32 *)(regs->u_regs[UREG_FP]))+i));
put_user (temp, (((u32 *)sframep)+i));
}
@@ -315,13 +334,17 @@ save_fpu_state32(struct pt_regs *regs, __siginfo_fpu32_t *fpu)
{
#ifdef __SMP__
if (current->flags & PF_USEDFPU) {
- fpsave32(&current->tss.float_regs[0], &current->tss.fsr);
+ fprs_write(FPRS_FEF);
+ fpsave32((unsigned long *)&current->tss.float_regs[0],
+ &current->tss.fsr);
regs->tstate &= ~(TSTATE_PEF);
current->flags &= ~(PF_USEDFPU);
}
#else
if (current == last_task_used_math) {
- fpsave32((unsigned long *)&current->tss.float_regs[0], &current->tss.fsr);
+ fprs_write(FPRS_FEF);
+ fpsave32((unsigned long *)&current->tss.float_regs[0],
+ &current->tss.fsr);
last_task_used_math = 0;
regs->tstate &= ~(TSTATE_PEF);
}
@@ -338,7 +361,7 @@ new_setup_frame32(struct sigaction *sa, struct pt_regs *regs,
{
struct new_signal_frame32 *sf;
int sigframe_size;
- u32 psr, tmp;
+ u32 psr;
int i;
/* 1. Make sure everything is clean */
@@ -349,12 +372,12 @@ new_setup_frame32(struct sigaction *sa, struct pt_regs *regs,
sf = (struct new_signal_frame32 *)(regs->u_regs[UREG_FP] - sigframe_size);
- if (invalid_frame_pointer (sf, sigframe_size)){
+ if (invalid_frame_pointer (sf, sigframe_size)) {
lock_kernel ();
do_exit(SIGILL);
}
- if (current->tss.w_saved != 0){
+ if (current->tss.w_saved != 0) {
printk ("%s[%d]: Invalid user stack frame for "
"signal delivery.\n", current->comm, current->pid);
lock_kernel ();
@@ -378,7 +401,11 @@ new_setup_frame32(struct sigaction *sa, struct pt_regs *regs,
}
__put_user(oldmask, &sf->info.si_mask);
+
+ /* XXX Perhaps we need a copy_in_user()? -DaveM */
for (i = 0; i < sizeof(struct reg_window32)/4; i++) {
+ u32 tmp;
+
__get_user(tmp, (((u32 *)regs->u_regs[UREG_FP])+i));
__put_user(tmp, (((u32 *)sf)+i));
}
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index c54036de6..59815b7a8 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -1,7 +1,8 @@
-/* $Id: sys_sparc32.c,v 1.18 1997/05/27 06:28:08 davem Exp $
+/* $Id: sys_sparc32.c,v 1.26 1997/06/04 13:05:21 jj Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
*
* These routines maintain argument size conversion between 32bit and 64bit
* environment.
@@ -28,6 +29,7 @@
#include <linux/smb_fs.h>
#include <linux/ncp_fs.h>
#include <linux/quota.h>
+#include <linux/file.h>
#include <asm/types.h>
#include <asm/poll.h>
@@ -42,112 +44,7 @@
*/
#define A(x) ((unsigned long)x)
-extern asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
-extern asmlinkage unsigned long sys_brk(unsigned long brk);
-extern asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off);
-extern asmlinkage int sys_bdflush(int func, long data);
-extern asmlinkage int sys_uselib(const char * library);
-extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
-extern asmlinkage int sys_mknod(const char * filename, int mode, dev_t dev);
-extern asmlinkage int sys_mkdir(const char * pathname, int mode);
-extern asmlinkage int sys_rmdir(const char * pathname);
-extern asmlinkage int sys_unlink(const char * pathname);
-extern asmlinkage int sys_symlink(const char * oldname, const char * newname);
-extern asmlinkage int sys_link(const char * oldname, const char * newname);
-extern asmlinkage int sys_rename(const char * oldname, const char * newname);
-extern asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr);
-extern asmlinkage int sys_statfs(const char * path, struct statfs * buf);
-extern asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf);
-extern asmlinkage int sys_truncate(const char * path, unsigned long length);
-extern asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length);
-extern asmlinkage int sys_utime(char * filename, struct utimbuf * times);
-extern asmlinkage int sys_utimes(char * filename, struct timeval * utimes);
-extern asmlinkage int sys_access(const char * filename, int mode);
-extern asmlinkage int sys_chdir(const char * filename);
-extern asmlinkage int sys_chroot(const char * filename);
-extern asmlinkage int sys_chmod(const char * filename, mode_t mode);
-extern asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group);
-extern asmlinkage int sys_open(const char * filename,int flags,int mode);
-extern asmlinkage int sys_creat(const char * pathname, int mode);
-extern asmlinkage long sys_lseek(unsigned int fd, off_t offset, unsigned int origin);
-extern asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high, unsigned long offset_low, loff_t *result, unsigned int origin);
-extern asmlinkage long sys_read(unsigned int fd, char * buf, unsigned long count);
-extern asmlinkage long sys_write(unsigned int fd, const char * buf, unsigned long count);
-extern asmlinkage long sys_readv(unsigned long fd, const struct iovec * vector, unsigned long count);
-extern asmlinkage long sys_writev(unsigned long fd, const struct iovec * vector, unsigned long count);
-extern asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp);
-extern asmlinkage int sys_poll(struct pollfd * ufds, unsigned int nfds, int timeout);
-extern asmlinkage int sys_newstat(char * filename, struct stat * statbuf);
-extern asmlinkage int sys_newlstat(char * filename, struct stat * statbuf);
-extern asmlinkage int sys_newfstat(unsigned int fd, struct stat * statbuf);
-extern asmlinkage int sys_readlink(const char * path, char * buf, int bufsiz);
-extern asmlinkage int sys_sysfs(int option, ...);
-extern asmlinkage int sys_ustat(dev_t dev, struct ustat * ubuf);
-extern asmlinkage int sys_umount(char * name);
-extern asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type, unsigned long new_flags, void *data);
-extern asmlinkage int sys_syslog(int type, char * bug, int count);
-extern asmlinkage int sys_personality(unsigned long personality);
-extern asmlinkage int sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru);
-extern asmlinkage int sys_waitpid(pid_t pid,unsigned int * stat_addr, int options);
-extern asmlinkage int sys_sysinfo(struct sysinfo *info);
-extern asmlinkage int sys_getitimer(int which, struct itimerval *value);
-extern asmlinkage int sys_setitimer(int which, struct itimerval *value, struct itimerval *ovalue);
-extern asmlinkage int sys_sched_setscheduler(pid_t pid, int policy, struct sched_param *param);
-extern asmlinkage int sys_sched_setparam(pid_t pid, struct sched_param *param);
-extern asmlinkage int sys_sched_getparam(pid_t pid, struct sched_param *param);
-extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval);
-extern asmlinkage int sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp);
-extern asmlinkage int sys_sigprocmask(int how, sigset_t *set, sigset_t *oset);
-extern asmlinkage int sys_sigpending(sigset_t *set);
-extern asmlinkage unsigned long sys_signal(int signum, __sighandler_t handler);
-extern asmlinkage int sys_reboot(int magic1, int magic2, int cmd, void * arg);
-extern asmlinkage int sys_acct(const char *name);
-extern asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
-extern asmlinkage long sys_times(struct tms * tbuf);
-extern asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist);
-extern asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist);
-extern asmlinkage int sys_newuname(struct new_utsname * name);
-extern asmlinkage int sys_olduname(struct oldold_utsname * name);
-extern asmlinkage int sys_sethostname(char *name, int len);
-extern asmlinkage int sys_gethostname(char *name, int len);
-extern asmlinkage int sys_setdomainname(char *name, int len);
-extern asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim);
-extern asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim);
-extern asmlinkage int sys_getrusage(int who, struct rusage *ru);
-extern asmlinkage int sys_time(int * tloc);
-extern asmlinkage int sys_gettimeofday(struct timeval *tv, struct timezone *tz);
-extern asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz);
-extern asmlinkage int sys_adjtimex(struct timex *txc_p);
-extern asmlinkage int sys_msync(unsigned long start, size_t len, int flags);
-extern asmlinkage int sys_mlock(unsigned long start, size_t len);
-extern asmlinkage int sys_munlock(unsigned long start, size_t len);
-extern asmlinkage int sys_munmap(unsigned long addr, size_t len);
-extern asmlinkage int sys_mprotect(unsigned long start, size_t len, unsigned long prot);
-extern asmlinkage unsigned long sys_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags);
-extern asmlinkage int sys_swapoff(const char * specialfile);
-extern asmlinkage int sys_swapon(const char * specialfile, int swap_flags);
-extern asmlinkage int sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
-extern asmlinkage int sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen);
-extern asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen);
-extern asmlinkage int sys_getsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len);
-extern asmlinkage int sys_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len);
-extern asmlinkage int sys_send(int fd, void * buff, size_t len, unsigned flags);
-extern asmlinkage int sys_sendto(int fd, void * buff, size_t len, unsigned flags, struct sockaddr *addr, int addr_len);
-extern asmlinkage int sys_recv(int fd, void * ubuf, size_t size, unsigned flags);
-extern asmlinkage int sys_recvfrom(int fd, void * ubuf, size_t size, unsigned flags, struct sockaddr *addr, int *addr_len);
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname, char *optval, int optlen);
-extern asmlinkage int sys_getsockopt(int fd, int level, int optname, char *optval, int *optlen);
-extern asmlinkage int sys_sendmsg(int fd, struct msghdr *msg, unsigned flags);
-extern asmlinkage int sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags);
-extern asmlinkage int sys_socketcall(int call, unsigned long *args);
-extern asmlinkage int sys_nfsservctl(int cmd, void *argp, void *resp);
-extern asmlinkage int sys_listen(int fd, int backlog);
-extern asmlinkage int sys_socket(int family, int type, int protocol);
-extern asmlinkage int sys_socketpair(int family, int type, int protocol, int usockvec[2]);
-extern asmlinkage int sys_shutdown(int fd, int how);
-
-/*
- * In order to reduce some races, while at the same time doing additional
+/* In order to reduce some races, while at the same time doing additional
* checking and hopefully speeding things up, we copy filenames to the
* kernel data space before using them..
*
@@ -168,8 +65,7 @@ static inline int do_getname32(u32 filename, char *page)
return retval;
}
-/*
- * This is a single page for faster getname.
+/* This is a single page for faster getname.
* If the page is available when entering getname, use it.
* If the page is not available, call __get_free_page instead.
* This works even though do_getname can block (think about it).
@@ -209,6 +105,8 @@ int getname32(u32 filename, char **result)
return retval;
}
+extern asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
+
asmlinkage int sys32_ioperm(u32 from, u32 num, int on)
{
return sys_ioperm((unsigned long)from, (unsigned long)num, on);
@@ -571,22 +469,56 @@ out:
return err;
}
-asmlinkage unsigned long sys32_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 off)
+extern asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long off);
+
+asmlinkage unsigned long sys32_mmap(u32 addr, u32 len, u32 prot,
+ u32 flags, u32 fd, u32 off)
{
- return sys_mmap((unsigned long)addr, (unsigned long)len, (unsigned long)prot, (unsigned long)flags,
+ return sys_mmap((unsigned long)addr, (unsigned long)len,
+ (unsigned long)prot, (unsigned long)flags,
(unsigned long)fd, (unsigned long)off);
}
+extern asmlinkage int sys_bdflush(int func, long data);
+
asmlinkage int sys32_bdflush(int func, s32 data)
{
return sys_bdflush(func, (long)data);
}
+extern asmlinkage int sys_uselib(const char * library);
+
asmlinkage int sys32_uselib(u32 library)
{
return sys_uselib((const char *)A(library));
}
+static inline int get_flock(struct flock *kfl, struct flock32 *ufl)
+{
+ if(get_user(kfl->l_type, &ufl->l_type) ||
+ __get_user(kfl->l_whence, &ufl->l_whence) ||
+ __get_user(kfl->l_start, &ufl->l_start) ||
+ __get_user(kfl->l_len, &ufl->l_len) ||
+ __get_user(kfl->l_pid, &ufl->l_pid))
+ return -EFAULT;
+ return 0;
+}
+
+static inline int put_flock(struct flock *kfl, struct flock32 *ufl)
+{
+ if(__put_user(kfl->l_type, &ufl->l_type) ||
+ __put_user(kfl->l_whence, &ufl->l_whence) ||
+ __put_user(kfl->l_start, &ufl->l_start) ||
+ __put_user(kfl->l_len, &ufl->l_len) ||
+ __put_user(kfl->l_pid, &ufl->l_pid))
+ return -EFAULT;
+ return 0;
+}
+
+extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
+
asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, u32 arg)
{
switch (cmd) {
@@ -598,20 +530,12 @@ asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, u32 arg)
unsigned long old_fs;
long ret;
- if (get_user (f.l_type, &(((struct flock32 *)A(arg))->l_type)) ||
- __get_user (f.l_whence, &(((struct flock32 *)A(arg))->l_whence)) ||
- __get_user (f.l_start, &(((struct flock32 *)A(arg))->l_start)) ||
- __get_user (f.l_len, &(((struct flock32 *)A(arg))->l_len)) ||
- __get_user (f.l_pid, &(((struct flock32 *)A(arg))->l_pid)))
+ if(get_flock(&f, (struct flock32 *)A(arg)))
return -EFAULT;
old_fs = get_fs(); set_fs (KERNEL_DS);
ret = sys_fcntl(fd, cmd, (unsigned long)&f);
set_fs (old_fs);
- if (__put_user (f.l_type, &(((struct flock32 *)A(arg))->l_type)) ||
- __put_user (f.l_whence, &(((struct flock32 *)A(arg))->l_whence)) ||
- __put_user (f.l_start, &(((struct flock32 *)A(arg))->l_start)) ||
- __put_user (f.l_len, &(((struct flock32 *)A(arg))->l_len)) ||
- __put_user (f.l_pid, &(((struct flock32 *)A(arg))->l_pid)))
+ if(put_flock(&f, (struct flock32 *)A(arg)))
return -EFAULT;
return ret;
}
@@ -620,36 +544,50 @@ asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, u32 arg)
}
}
+extern asmlinkage int sys_mknod(const char * filename, int mode, dev_t dev);
+
asmlinkage int sys32_mknod(u32 filename, int mode, __kernel_dev_t32 dev)
{
return sys_mknod((const char *)A(filename), mode, dev);
}
+extern asmlinkage int sys_mkdir(const char * pathname, int mode);
+
asmlinkage int sys32_mkdir(u32 pathname, int mode)
{
return sys_mkdir((const char *)A(pathname), mode);
}
+extern asmlinkage int sys_rmdir(const char * pathname);
+
asmlinkage int sys32_rmdir(u32 pathname)
{
return sys_rmdir((const char *)A(pathname));
}
+extern asmlinkage int sys_unlink(const char * pathname);
+
asmlinkage int sys32_unlink(u32 pathname)
{
return sys_unlink((const char *)A(pathname));
}
+extern asmlinkage int sys_symlink(const char * oldname, const char * newname);
+
asmlinkage int sys32_symlink(u32 oldname, u32 newname)
{
return sys_symlink((const char *)A(oldname), (const char *)A(newname));
}
+extern asmlinkage int sys_link(const char * oldname, const char * newname);
+
asmlinkage int sys32_link(u32 oldname, u32 newname)
{
return sys_link((const char *)A(oldname), (const char *)A(newname));
}
+extern asmlinkage int sys_rename(const char * oldname, const char * newname);
+
asmlinkage int sys32_rename(u32 oldname, u32 newname)
{
return sys_rename((const char *)A(oldname), (const char *)A(newname));
@@ -666,12 +604,15 @@ struct dqblk32 {
__kernel_time_t32 dqb_itime;
};
+extern asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr);
+
asmlinkage int sys32_quotactl(int cmd, u32 special, int id, u32 addr)
{
int cmds = cmd >> SUBCMDSHIFT;
int err;
struct dqblk d;
unsigned long old_fs;
+ char *spec;
switch (cmds) {
case Q_GETQUOTA:
@@ -679,57 +620,73 @@ asmlinkage int sys32_quotactl(int cmd, u32 special, int id, u32 addr)
case Q_SETQUOTA:
case Q_SETUSE:
case Q_SETQLIM:
- if (copy_from_user (&d, (struct dqblk32 *)A(addr), sizeof (struct dqblk32)))
+ if (copy_from_user (&d, (struct dqblk32 *)A(addr),
+ sizeof (struct dqblk32)))
return -EFAULT;
d.dqb_itime = ((struct dqblk32 *)&d)->dqb_itime;
d.dqb_btime = ((struct dqblk32 *)&d)->dqb_btime;
break;
default:
- return sys_quotactl(cmd, (const char *)A(special), id, (caddr_t)A(addr));
+ return sys_quotactl(cmd, (const char *)A(special),
+ id, (caddr_t)A(addr));
}
+ err = getname32 (special, &spec);
+ if (err) return err;
old_fs = get_fs ();
set_fs (KERNEL_DS);
- err = sys_quotactl(cmd, (const char *)A(special), id, (caddr_t)A(addr));
+ err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)A(addr));
set_fs (old_fs);
+ putname32 (spec);
if (cmds == Q_GETQUOTA) {
__kernel_time_t b = d.dqb_btime, i = d.dqb_itime;
((struct dqblk32 *)&d)->dqb_itime = i;
((struct dqblk32 *)&d)->dqb_btime = b;
- if (copy_to_user ((struct dqblk32 *)A(addr), &d, sizeof (struct dqblk32)))
+ if (copy_to_user ((struct dqblk32 *)A(addr), &d,
+ sizeof (struct dqblk32)))
return -EFAULT;
}
return err;
}
-static int put_statfs (u32 buf, struct statfs *s)
+static inline int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf)
{
- if (put_user (s->f_type, &(((struct statfs32 *)A(buf))->f_type)) ||
- __put_user (s->f_bsize, &(((struct statfs32 *)A(buf))->f_bsize)) ||
- __put_user (s->f_blocks, &(((struct statfs32 *)A(buf))->f_blocks)) ||
- __put_user (s->f_bfree, &(((struct statfs32 *)A(buf))->f_bfree)) ||
- __put_user (s->f_bavail, &(((struct statfs32 *)A(buf))->f_bavail)) ||
- __put_user (s->f_files, &(((struct statfs32 *)A(buf))->f_files)) ||
- __put_user (s->f_ffree, &(((struct statfs32 *)A(buf))->f_ffree)) ||
- __put_user (s->f_namelen, &(((struct statfs32 *)A(buf))->f_namelen)) ||
- __put_user (s->f_fsid.val[0], &(((struct statfs32 *)A(buf))->f_fsid.val[0])) ||
- __put_user (s->f_fsid.val[1], &(((struct statfs32 *)A(buf))->f_fsid.val[1])))
+ if (put_user (kbuf->f_type, &ubuf->f_type) ||
+ __put_user (kbuf->f_bsize, &ubuf->f_bsize) ||
+ __put_user (kbuf->f_blocks, &ubuf->f_blocks) ||
+ __put_user (kbuf->f_bfree, &ubuf->f_bfree) ||
+ __put_user (kbuf->f_bavail, &ubuf->f_bavail) ||
+ __put_user (kbuf->f_files, &ubuf->f_files) ||
+ __put_user (kbuf->f_ffree, &ubuf->f_ffree) ||
+ __put_user (kbuf->f_namelen, &ubuf->f_namelen) ||
+ __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) ||
+ __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]))
return -EFAULT;
return 0;
}
+extern asmlinkage int sys_statfs(const char * path, struct statfs * buf);
+
asmlinkage int sys32_statfs(u32 path, u32 buf)
{
int ret;
struct statfs s;
unsigned long old_fs = get_fs();
+ char *pth;
- set_fs (KERNEL_DS);
- ret = sys_statfs((const char *)A(path), &s);
- set_fs (old_fs);
- if (put_statfs(buf, &s)) return -EFAULT;
+ ret = getname32 (path, &pth);
+ if (!ret) {
+ set_fs (KERNEL_DS);
+ ret = sys_statfs((const char *)pth, &s);
+ set_fs (old_fs);
+ putname32 (pth);
+ if (put_statfs((struct statfs32 *)A(buf), &s))
+ return -EFAULT;
+ }
return ret;
}
+extern asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf);
+
asmlinkage int sys32_fstatfs(unsigned int fd, u32 buf)
{
int ret;
@@ -739,20 +696,27 @@ asmlinkage int sys32_fstatfs(unsigned int fd, u32 buf)
set_fs (KERNEL_DS);
ret = sys_fstatfs(fd, &s);
set_fs (old_fs);
- if (put_statfs(buf, &s)) return -EFAULT;
+ if (put_statfs((struct statfs32 *)A(buf), &s))
+ return -EFAULT;
return ret;
}
+extern asmlinkage int sys_truncate(const char * path, unsigned long length);
+
asmlinkage int sys32_truncate(u32 path, u32 length)
{
return sys_truncate((const char *)A(path), (unsigned long)length);
}
+extern asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length);
+
asmlinkage int sys32_ftruncate(unsigned int fd, u32 length)
{
return sys_ftruncate(fd, (unsigned long)length);
}
+extern asmlinkage int sys_utime(char * filename, struct utimbuf * times);
+
asmlinkage int sys32_utime(u32 filename, u32 times)
{
struct utimbuf32 { __kernel_time_t32 actime, modtime; };
@@ -777,63 +741,91 @@ asmlinkage int sys32_utime(u32 filename, u32 times)
return ret;
}
+extern asmlinkage int sys_utimes(char * filename, struct timeval * utimes);
+
asmlinkage int sys32_utimes(u32 filename, u32 utimes)
{
/* struct timeval is the same :)) */
return sys_utimes((char *)A(filename), (struct timeval *)A(utimes));
}
+extern asmlinkage int sys_access(const char * filename, int mode);
+
asmlinkage int sys32_access(u32 filename, int mode)
{
return sys_access((const char *)A(filename), mode);
}
+extern asmlinkage int sys_chdir(const char * filename);
+
asmlinkage int sys32_chdir(u32 filename)
{
return sys_chdir((const char *)A(filename));
}
+extern asmlinkage int sys_chroot(const char * filename);
+
asmlinkage int sys32_chroot(u32 filename)
{
return sys_chroot((const char *)A(filename));
}
+extern asmlinkage int sys_chmod(const char * filename, mode_t mode);
+
asmlinkage int sys32_chmod(u32 filename, __kernel_mode_t32 mode)
{
return sys_chmod((const char *)A(filename), mode);
}
+extern asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group);
+
asmlinkage int sys32_chown(u32 filename, __kernel_uid_t32 user, __kernel_gid_t32 group)
{
return sys_chown((const char *)A(filename), user, group);
}
+extern asmlinkage int sys_open(const char * filename,int flags,int mode);
+
asmlinkage int sys32_open(u32 filename, int flags, int mode)
{
return sys_open((const char *)A(filename), flags, mode);
}
+extern asmlinkage int sys_creat(const char * pathname, int mode);
+
asmlinkage int sys32_creat(u32 pathname, int mode)
{
return sys_creat((const char *)A(pathname), mode);
}
+extern asmlinkage long sys_lseek(unsigned int fd, off_t offset, unsigned int origin);
+
asmlinkage long sys32_lseek(unsigned int fd, s32 offset, unsigned int origin)
{
return sys_lseek(fd, (off_t)offset, origin);
}
-asmlinkage int sys32_llseek(unsigned int fd, u32 offset_high, u32 offset_low, u32 result, unsigned int origin)
+extern asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high,
+ unsigned long offset_low,
+ loff_t *result, unsigned int origin);
+
+asmlinkage int sys32_llseek(unsigned int fd, u32 offset_high,
+ u32 offset_low, u32 result, unsigned int origin)
{
/* loff_t is the same :)) */
- return sys_llseek(fd, (unsigned long)offset_high, (unsigned long)offset_low, (loff_t *)A(result), origin);
+ return sys_llseek(fd, (unsigned long)offset_high, (unsigned long)offset_low,
+ (loff_t *)A(result), origin);
}
+extern asmlinkage long sys_read(unsigned int fd, char * buf, unsigned long count);
+
asmlinkage long sys32_read(unsigned int fd, u32 buf, u32 count)
{
return sys_read(fd, (char *)A(buf), (unsigned long)count);
}
+extern asmlinkage long sys_write(unsigned int fd, const char * buf, unsigned long count);
+
asmlinkage long sys32_write(unsigned int fd, u32 buf, u32 count)
{
return sys_write(fd, (const char *)A(buf), (unsigned long)count);
@@ -841,86 +833,146 @@ asmlinkage long sys32_write(unsigned int fd, u32 buf, u32 count)
struct iovec32 { u32 iov_base; __kernel_size_t32 iov_len; };
-asmlinkage long sys32_readv(u32 fd, u32 vector, u32 count)
+typedef long (*IO_fn_t)(struct inode *, struct file *, char *, unsigned long);
+
+static long do_readv_writev32(int type, struct inode *inode, struct file *file,
+ const struct iovec32 *vector, u32 count)
{
- struct iovec *v;
- struct iovec vf[UIO_FASTIOV];
- u32 i;
- long ret;
- unsigned long old_fs;
-
- if (!count) return 0; if (count > UIO_MAXIOV) return -EINVAL;
- if (count <= UIO_FASTIOV)
- v = vf;
- else {
- lock_kernel ();
- v = kmalloc (count * sizeof (struct iovec), GFP_KERNEL);
- if (!v) {
- ret = -ENOMEM;
- goto out;
- }
+ unsigned long tot_len;
+ struct iovec iovstack[UIO_FASTIOV];
+ struct iovec *iov=iovstack, *ivp;
+ long retval, i;
+ IO_fn_t fn;
+
+ /* First get the "struct iovec" from user memory and
+ * verify all the pointers
+ */
+ if (!count)
+ return 0;
+ if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
+ return -EFAULT;
+ if (count > UIO_MAXIOV)
+ return -EINVAL;
+ if (count > UIO_FASTIOV) {
+ iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
+ if (!iov)
+ return -ENOMEM;
}
- for (i = 0; i < count; i++) {
- if (__get_user ((unsigned long)(v[i].iov_base), &((((struct iovec32 *)A(vector))+i)->iov_base)) ||
- __get_user (v[i].iov_len, &((((struct iovec32 *)A(vector))+i)->iov_len))) {
- ret = -EFAULT;
- goto out;
- }
+
+ tot_len = 0;
+ i = count;
+ ivp = iov;
+ while(i > 0) {
+ u32 len;
+ u32 buf;
+
+ __get_user(len, &vector->iov_len);
+ __get_user(buf, &vector->iov_base);
+ tot_len += len;
+ ivp->iov_base = (void *)A(buf);
+ ivp->iov_len = (__kernel_size_t) len;
+ vector++;
+ ivp++;
+ i--;
}
- old_fs = get_fs();
- set_fs (KERNEL_DS);
- ret = sys_readv((unsigned long)fd, v, (unsigned long)count);
- set_fs (old_fs);
-out:
- if (count > UIO_FASTIOV) {
- kfree (v);
- unlock_kernel ();
+
+ retval = locks_verify_area((type == VERIFY_READ) ?
+ FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
+ inode, file, file->f_pos, tot_len);
+ if (retval) {
+ if (iov != iovstack)
+ kfree(iov);
+ return retval;
}
- return ret;
-}
-asmlinkage long sys32_writev(u32 fd, u32 vector, u32 count)
-{
- struct iovec *v;
- struct iovec vf[UIO_FASTIOV];
- u32 i;
- long ret;
- unsigned long old_fs;
-
- if (!count) return 0; if (count > UIO_MAXIOV) return -EINVAL;
- if (count <= UIO_FASTIOV)
- v = vf;
- else {
- lock_kernel ();
- v = kmalloc (count * sizeof (struct iovec), GFP_KERNEL);
- if (!v) {
- ret = -ENOMEM;
- goto out;
- }
+ /* Then do the actual IO. Note that sockets need to be handled
+ * specially as they have atomicity guarantees and can handle
+ * iovec's natively
+ */
+ if (inode->i_sock) {
+ int err;
+ err = sock_readv_writev(type, inode, file, iov, count, tot_len);
+ if (iov != iovstack)
+ kfree(iov);
+ return err;
}
- for (i = 0; i < count; i++) {
- if (__get_user ((unsigned long)(v[i].iov_base), &((((struct iovec32 *)A(vector))+i)->iov_base)) ||
- __get_user (v[i].iov_len, &((((struct iovec32 *)A(vector))+i)->iov_len))) {
- ret = -EFAULT;
- goto out;
- }
+
+ if (!file->f_op) {
+ if (iov != iovstack)
+ kfree(iov);
+ return -EINVAL;
}
- old_fs = get_fs();
- set_fs (KERNEL_DS);
- ret = sys_writev((unsigned long)fd, v, (unsigned long)count);
- set_fs (old_fs);
-out:
- if (count > UIO_FASTIOV) {
- kfree (v);
- unlock_kernel ();
+ /* VERIFY_WRITE actually means a read, as we write to user space */
+ fn = file->f_op->read;
+ if (type == VERIFY_READ)
+ fn = (IO_fn_t) file->f_op->write;
+ ivp = iov;
+ while (count > 0) {
+ void * base;
+ int len, nr;
+
+ base = ivp->iov_base;
+ len = ivp->iov_len;
+ ivp++;
+ count--;
+ nr = fn(inode, file, base, len);
+ if (nr < 0) {
+ if (retval)
+ break;
+ retval = nr;
+ break;
+ }
+ retval += nr;
+ if (nr != len)
+ break;
}
- return ret;
+ if (iov != iovstack)
+ kfree(iov);
+ return retval;
+}
+
+asmlinkage long sys32_readv(int fd, u32 vector, u32 count)
+{
+ struct file *file;
+ struct inode *inode;
+ long err = -EBADF;
+
+ lock_kernel();
+ if (fd >= NR_OPEN || !(file = current->files->fd[fd]) || !(inode=file->f_inode))
+ goto out;
+ if (!(file->f_mode & 1))
+ goto out;
+ err = do_readv_writev32(VERIFY_WRITE, inode, file,
+ (struct iovec32 *)A(vector), count);
+out:
+ unlock_kernel();
+ return err;
+}
+
+asmlinkage long sys32_writev(int fd, u32 vector, u32 count)
+{
+ int error = -EBADF;
+ struct file *file;
+ struct inode *inode;
+
+ lock_kernel();
+ if (fd >= NR_OPEN || !(file = current->files->fd[fd]) || !(inode=file->f_inode))
+ goto out;
+ if (!(file->f_mode & 2))
+ goto out;
+ down(&inode->i_sem);
+ error = do_readv_writev32(VERIFY_READ, inode, file,
+ (struct iovec32 *)A(vector), count);
+ up(&inode->i_sem);
+out:
+ unlock_kernel();
+ return error;
}
/* readdir & getdents */
#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
-#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
+#define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1))
struct old_linux_dirent32 {
u32 d_ino;
@@ -934,7 +986,8 @@ struct readdir_callback32 {
int count;
};
-static int fillonedir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino)
+static int fillonedir(void * __buf, const char * name, int namlen,
+ off_t offset, ino_t ino)
{
struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf;
struct old_linux_dirent32 * dirent;
@@ -963,7 +1016,8 @@ asmlinkage int old32_readdir(unsigned int fd, u32 dirent, unsigned int count)
error = -ENOTDIR;
if (!file->f_op || !file->f_op->readdir)
goto out;
- error = verify_area(VERIFY_WRITE, (void *)A(dirent), sizeof(struct old_linux_dirent32));
+ error = verify_area(VERIFY_WRITE, (void *)A(dirent),
+ sizeof(struct old_linux_dirent32));
if (error)
goto out;
buf.count = 0;
@@ -1052,84 +1106,124 @@ out:
/* end of readdir & getdents */
+extern asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp,
+ fd_set *exp, struct timeval *tvp);
+
asmlinkage int sys32_select(int n, u32 inp, u32 outp, u32 exp, u32 tvp)
{
struct timeval kern_tv, *ktvp;
unsigned long old_fs;
char *p;
- u32 *q;
+ u32 *q, *Inp, *Outp, *Exp;
int i, ret = -EINVAL, nn;
- u32 *Inp, *Outp, *Exp;
- if (n < 0 || n > PAGE_SIZE*2) return -EINVAL;
+ if (n < 0 || n > PAGE_SIZE*2)
+ return -EINVAL;
+
lock_kernel ();
p = (char *)__get_free_page (GFP_KERNEL);
- if (!p) goto out;
+ if (!p)
+ goto out;
+
q = (u32 *)p;
- nn = (n + 8 * sizeof(unsigned long) - 1) / (8 * sizeof (unsigned long));
- Inp = (u32 *)A(inp); Outp = (u32 *)A(outp); Exp = (u32 *)A(exp);
+ Inp = (u32 *)A(inp);
+ Outp = (u32 *)A(outp);
+ Exp = (u32 *)A(exp);
+
ret = -EFAULT;
- for (i = 0; i < ret; i++, Inp += 2, Outp += 2, Exp += 2, q += 2) {
- if (__get_user (q[1], Inp) ||
- __get_user (q[0], Inp+1) ||
- __get_user (q[1+PAGE_SIZE/4], Outp) ||
- __get_user (q[PAGE_SIZE/4], Outp+1) ||
- __get_user (q[1+PAGE_SIZE/2], Exp) ||
- __get_user (q[PAGE_SIZE/2], Exp+1))
+
+ nn = (n + (8 * sizeof(unsigned long)) - 1) / (8 * sizeof (unsigned long));
+ for (i = 0; i < nn; i++, Inp += 2, Outp += 2, Exp += 2, q += 2) {
+ if(inp && (__get_user (q[1], Inp) || __get_user (q[0], Inp+1)))
+ goto out;
+ if(outp && (__get_user (q[1+(PAGE_SIZE/4/sizeof(u32))], Outp) ||
+ __get_user (q[(PAGE_SIZE/4/sizeof(u32))], Outp+1)))
+ goto out;
+ if(exp && (__get_user (q[1+(PAGE_SIZE/2/sizeof(u32))], Exp) ||
+ __get_user (q[(PAGE_SIZE/2/sizeof(u32))], Exp+1)))
goto out;
}
+
ktvp = NULL;
if(tvp) {
if(copy_from_user(&kern_tv, (struct timeval *)A(tvp), sizeof(*ktvp)))
goto out;
ktvp = &kern_tv;
}
+
old_fs = get_fs ();
set_fs (KERNEL_DS);
- ret = sys_select(n, (fd_set *)p, (fd_set *)(p + PAGE_SIZE/4), (fd_set *)(p + PAGE_SIZE/2), ktvp);
+ q = (u32 *) p;
+ ret = sys_select(n,
+ inp ? (fd_set *)&q[0] : (fd_set *)0,
+ outp ? (fd_set *)&q[PAGE_SIZE/4/sizeof(u32)] : (fd_set *)0,
+ exp ? (fd_set *)&q[PAGE_SIZE/2/sizeof(u32)] : (fd_set *)0,
+ ktvp);
set_fs (old_fs);
+
+ if(tvp && !(current->personality & STICKY_TIMEOUTS))
+ copy_to_user((struct timeval *)A(tvp), &kern_tv, sizeof(*ktvp));
+
q = (u32 *)p;
- Inp = (u32 *)A(inp); Outp = (u32 *)A(outp); Exp = (u32 *)A(exp);
- for (i = 0; i < ret; i++, Inp += 2, Outp += 2, Exp += 2, q += 2) {
- if (__put_user (q[1], Inp) ||
- __put_user (q[0], Inp+1) ||
- __put_user (q[1+PAGE_SIZE/4], Outp) ||
- __put_user (q[PAGE_SIZE/4], Outp+1) ||
- __put_user (q[1+PAGE_SIZE/2], Exp) ||
- __put_user (q[PAGE_SIZE/2], Exp+1)) {
+ Inp = (u32 *)A(inp);
+ Outp = (u32 *)A(outp);
+ Exp = (u32 *)A(exp);
+
+ if(ret < 0)
+ goto out;
+
+ for (i = 0;
+ i < nn;
+ i++, Inp += 2, Outp += 2, Exp += 2, q += 2) {
+ if(inp && (__put_user (q[1], Inp) || __put_user (q[0], Inp+1))) {
+ ret = -EFAULT;
+ goto out;
+ }
+ if(outp && (__put_user (q[1+(PAGE_SIZE/4/sizeof(u32))], Outp) ||
+ __put_user (q[(PAGE_SIZE/4/sizeof(u32))], Outp+1))) {
+ ret = -EFAULT;
+ goto out;
+ }
+ if(exp && (__put_user (q[1+(PAGE_SIZE/2/sizeof(u32))], Exp) ||
+ __put_user (q[(PAGE_SIZE/2/sizeof(u32))], Exp+1))) {
ret = -EFAULT;
goto out;
}
}
out:
free_page ((unsigned long)p);
+ unlock_kernel();
return ret;
}
+extern asmlinkage int sys_poll(struct pollfd * ufds, unsigned int nfds, int timeout);
+
asmlinkage int sys32_poll(u32 ufds, unsigned int nfds, int timeout)
{
return sys_poll((struct pollfd *)A(ufds), nfds, timeout);
}
-static inline int putstat(u32 statbuf, struct stat *s)
-{
- if (put_user (s->st_dev, &(((struct stat32 *)A(statbuf))->st_dev)) ||
- __put_user (s->st_ino, &(((struct stat32 *)A(statbuf))->st_ino)) ||
- __put_user (s->st_mode, &(((struct stat32 *)A(statbuf))->st_mode)) ||
- __put_user (s->st_nlink, &(((struct stat32 *)A(statbuf))->st_nlink)) ||
- __put_user (s->st_uid, &(((struct stat32 *)A(statbuf))->st_uid)) ||
- __put_user (s->st_gid, &(((struct stat32 *)A(statbuf))->st_gid)) ||
- __put_user (s->st_rdev, &(((struct stat32 *)A(statbuf))->st_rdev)) ||
- __put_user (s->st_size, &(((struct stat32 *)A(statbuf))->st_size)) ||
- __put_user (s->st_atime, &(((struct stat32 *)A(statbuf))->st_atime)) ||
- __put_user (s->st_mtime, &(((struct stat32 *)A(statbuf))->st_mtime)) ||
- __put_user (s->st_ctime, &(((struct stat32 *)A(statbuf))->st_ctime)) ||
- __put_user (s->st_blksize, &(((struct stat32 *)A(statbuf))->st_blksize)) ||
- __put_user (s->st_blocks, &(((struct stat32 *)A(statbuf))->st_blocks)))
+static inline int putstat(struct stat32 *ubuf, struct stat *kbuf)
+{
+ if (put_user (kbuf->st_dev, &ubuf->st_dev) ||
+ __put_user (kbuf->st_ino, &ubuf->st_ino) ||
+ __put_user (kbuf->st_mode, &ubuf->st_mode) ||
+ __put_user (kbuf->st_nlink, &ubuf->st_nlink) ||
+ __put_user (kbuf->st_uid, &ubuf->st_uid) ||
+ __put_user (kbuf->st_gid, &ubuf->st_gid) ||
+ __put_user (kbuf->st_rdev, &ubuf->st_rdev) ||
+ __put_user (kbuf->st_size, &ubuf->st_size) ||
+ __put_user (kbuf->st_atime, &ubuf->st_atime) ||
+ __put_user (kbuf->st_mtime, &ubuf->st_mtime) ||
+ __put_user (kbuf->st_ctime, &ubuf->st_ctime) ||
+ __put_user (kbuf->st_blksize, &ubuf->st_blksize) ||
+ __put_user (kbuf->st_blocks, &ubuf->st_blocks))
return -EFAULT;
return 0;
}
+extern asmlinkage int sys_newstat(char * filename, struct stat * statbuf);
+
asmlinkage int sys32_newstat(u32 filename, u32 statbuf)
{
int ret;
@@ -1143,11 +1237,14 @@ asmlinkage int sys32_newstat(u32 filename, u32 statbuf)
ret = sys_newstat(filenam, &s);
set_fs (old_fs);
putname32 (filenam);
- if (putstat (statbuf, &s)) return -EFAULT;
+ if (putstat ((struct stat32 *)A(statbuf), &s))
+ return -EFAULT;
}
return ret;
}
+extern asmlinkage int sys_newlstat(char * filename, struct stat * statbuf);
+
asmlinkage int sys32_newlstat(u32 filename, u32 statbuf)
{
int ret;
@@ -1161,11 +1258,14 @@ asmlinkage int sys32_newlstat(u32 filename, u32 statbuf)
ret = sys_newlstat(filenam, &s);
set_fs (old_fs);
putname32 (filenam);
- if (putstat (statbuf, &s)) return -EFAULT;
+ if (putstat ((struct stat32 *)A(statbuf), &s))
+ return -EFAULT;
}
return ret;
}
+extern asmlinkage int sys_newfstat(unsigned int fd, struct stat * statbuf);
+
asmlinkage int sys32_newfstat(unsigned int fd, u32 statbuf)
{
int ret;
@@ -1175,15 +1275,20 @@ asmlinkage int sys32_newfstat(unsigned int fd, u32 statbuf)
set_fs (KERNEL_DS);
ret = sys_newfstat(fd, &s);
set_fs (old_fs);
- if (putstat (statbuf, &s)) return -EFAULT;
+ if (putstat ((struct stat32 *)A(statbuf), &s))
+ return -EFAULT;
return ret;
}
+extern asmlinkage int sys_readlink(const char * path, char * buf, int bufsiz);
+
asmlinkage int sys32_readlink(u32 path, u32 buf, int bufsiz)
{
return sys_readlink((const char *)A(path), (char *)A(buf), bufsiz);
}
+extern asmlinkage int sys_sysfs(int option, ...);
+
asmlinkage int sys32_sysfs(int option, ...)
{
va_list args;
@@ -1207,28 +1312,39 @@ asmlinkage int sys32_sysfs(int option, ...)
return ret;
}
+extern asmlinkage int sys_ustat(dev_t dev, struct ustat * ubuf);
+
asmlinkage int sys32_ustat(dev_t dev, u32 ubuf)
{
/* ustat is the same :)) */
return sys_ustat(dev, (struct ustat *)A(ubuf));
}
+extern asmlinkage int sys_umount(char * name);
+
asmlinkage int sys32_umount(u32 name)
{
return sys_umount((char *)A(name));
}
+extern asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
+ unsigned long new_flags, void *data);
+
asmlinkage int sys32_mount(u32 dev_name, u32 dir_name, u32 type, u32 new_flags, u32 data)
{
return sys_mount((char *)A(dev_name), (char *)A(dir_name), (char *)A(type),
(unsigned long)new_flags, (void *)A(data));
}
+extern asmlinkage int sys_syslog(int type, char * bug, int count);
+
asmlinkage int sys32_syslog(int type, u32 bug, int count)
{
return sys_syslog(type, (char *)A(bug), count);
}
+extern asmlinkage int sys_personality(unsigned long personality);
+
asmlinkage int sys32_personality(u32 personality)
{
return sys_personality((unsigned long)personality);
@@ -1277,6 +1393,9 @@ static int put_rusage (u32 ru, struct rusage *r)
return 0;
}
+extern asmlinkage int sys_wait4(pid_t pid,unsigned int * stat_addr,
+ int options, struct rusage * ru);
+
asmlinkage int sys32_wait4(__kernel_pid_t32 pid, u32 stat_addr, int options, u32 ru)
{
if (!ru)
@@ -1284,16 +1403,21 @@ asmlinkage int sys32_wait4(__kernel_pid_t32 pid, u32 stat_addr, int options, u32
else {
struct rusage r;
int ret;
+ unsigned int status;
unsigned long old_fs = get_fs();
set_fs (KERNEL_DS);
- ret = sys_wait4(pid, (unsigned int *)A(stat_addr), options, &r);
+ ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r);
set_fs (old_fs);
if (put_rusage (ru, &r)) return -EFAULT;
+ if (stat_addr && put_user (status, (unsigned int *)A(stat_addr)))
+ return -EFAULT;
return ret;
}
}
+extern asmlinkage int sys_waitpid(pid_t pid,unsigned int * stat_addr, int options);
+
asmlinkage int sys32_waitpid(__kernel_pid_t32 pid, u32 stat_addr, int options)
{
return sys_waitpid(pid, (unsigned int *)A(stat_addr), options);
@@ -1312,6 +1436,8 @@ struct sysinfo32 {
char _f[22];
};
+extern asmlinkage int sys_sysinfo(struct sysinfo *info);
+
asmlinkage int sys32_sysinfo(u32 info)
{
struct sysinfo s;
@@ -1336,28 +1462,41 @@ asmlinkage int sys32_sysinfo(u32 info)
return ret;
}
+extern asmlinkage int sys_getitimer(int which, struct itimerval *value);
+
asmlinkage int sys32_getitimer(int which, u32 value)
{
/* itimerval is the same :)) */
return sys_getitimer(which, (struct itimerval *)A(value));
}
+extern asmlinkage int sys_setitimer(int which, struct itimerval *value,
+ struct itimerval *ovalue);
+
asmlinkage int sys32_setitimer(int which, u32 value, u32 ovalue)
{
- return sys_setitimer(which, (struct itimerval *)A(value), (struct itimerval *)A(ovalue));
+ return sys_setitimer(which, (struct itimerval *)A(value),
+ (struct itimerval *)A(ovalue));
}
+extern asmlinkage int sys_sched_setscheduler(pid_t pid, int policy,
+ struct sched_param *param);
+
asmlinkage int sys32_sched_setscheduler(__kernel_pid_t32 pid, int policy, u32 param)
{
/* sched_param is the same :)) */
return sys_sched_setscheduler(pid, policy, (struct sched_param *)A(param));
}
+extern asmlinkage int sys_sched_setparam(pid_t pid, struct sched_param *param);
+
asmlinkage int sys32_sched_setparam(__kernel_pid_t32 pid, u32 param)
{
return sys_sched_setparam(pid, (struct sched_param *)A(param));
}
+extern asmlinkage int sys_sched_getparam(pid_t pid, struct sched_param *param);
+
asmlinkage int sys32_sched_getparam(__kernel_pid_t32 pid, u32 param)
{
return sys_sched_getparam(pid, (struct sched_param *)A(param));
@@ -1368,6 +1507,8 @@ struct timespec32 {
s32 tv_nsec;
};
+extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval);
+
asmlinkage int sys32_sched_rr_get_interval(__kernel_pid_t32 pid, u32 interval)
{
struct timespec t;
@@ -1383,6 +1524,8 @@ asmlinkage int sys32_sched_rr_get_interval(__kernel_pid_t32 pid, u32 interval)
return ret;
}
+extern asmlinkage int sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp);
+
asmlinkage int sys32_nanosleep(u32 rqtp, u32 rmtp)
{
struct timespec t;
@@ -1403,6 +1546,8 @@ asmlinkage int sys32_nanosleep(u32 rqtp, u32 rmtp)
return ret;
}
+extern asmlinkage int sys_sigprocmask(int how, sigset_t *set, sigset_t *oset);
+
asmlinkage int sys32_sigprocmask(int how, u32 set, u32 oset)
{
sigset_t s;
@@ -1417,6 +1562,8 @@ asmlinkage int sys32_sigprocmask(int how, u32 set, u32 oset)
return ret;
}
+extern asmlinkage int sys_sigpending(sigset_t *set);
+
asmlinkage int sys32_sigpending(u32 set)
{
sigset_t s;
@@ -1430,21 +1577,29 @@ asmlinkage int sys32_sigpending(u32 set)
return ret;
}
+extern asmlinkage unsigned long sys_signal(int signum, __sighandler_t handler);
+
asmlinkage unsigned long sys32_signal(int signum, u32 handler)
{
return sys_signal(signum, (__sighandler_t)A(handler));
}
+extern asmlinkage int sys_reboot(int magic1, int magic2, int cmd, void * arg);
+
asmlinkage int sys32_reboot(int magic1, int magic2, int cmd, u32 arg)
{
return sys_reboot(magic1, magic2, cmd, (void *)A(arg));
}
+extern asmlinkage int sys_acct(const char *name);
+
asmlinkage int sys32_acct(u32 name)
{
return sys_acct((const char *)A(name));
}
+extern asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
+
asmlinkage int sys32_getresuid(u32 ruid, u32 euid, u32 suid)
{
uid_t a, b, c;
@@ -1468,6 +1623,8 @@ struct tms32 {
__kernel_clock_t32 tms_cstime;
};
+extern asmlinkage long sys_times(struct tms * tbuf);
+
asmlinkage long sys32_times(u32 tbuf)
{
struct tms t;
@@ -1486,6 +1643,8 @@ asmlinkage long sys32_times(u32 tbuf)
return ret;
}
+extern asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist);
+
asmlinkage int sys32_getgroups(int gidsetsize, u32 grouplist)
{
gid_t gl[NGROUPS];
@@ -1502,6 +1661,8 @@ asmlinkage int sys32_getgroups(int gidsetsize, u32 grouplist)
return ret;
}
+extern asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist);
+
asmlinkage int sys32_setgroups(int gidsetsize, u32 grouplist)
{
gid_t gl[NGROUPS];
@@ -1519,27 +1680,37 @@ asmlinkage int sys32_setgroups(int gidsetsize, u32 grouplist)
return ret;
}
+extern asmlinkage int sys_newuname(struct new_utsname * name);
+
asmlinkage int sys32_newuname(u32 name)
{
/* utsname is the same :)) */
return sys_newuname((struct new_utsname *)A(name));
}
+extern asmlinkage int sys_olduname(struct oldold_utsname * name);
+
asmlinkage int sys32_olduname(u32 name)
{
return sys_olduname((struct oldold_utsname *)A(name));
}
+extern asmlinkage int sys_sethostname(char *name, int len);
+
asmlinkage int sys32_sethostname(u32 name, int len)
{
return sys_sethostname((char *)A(name), len);
}
+extern asmlinkage int sys_gethostname(char *name, int len);
+
asmlinkage int sys32_gethostname(u32 name, int len)
{
return sys_gethostname((char *)A(name), len);
}
+extern asmlinkage int sys_setdomainname(char *name, int len);
+
asmlinkage int sys32_setdomainname(u32 name, int len)
{
return sys_setdomainname((char *)A(name), len);
@@ -1550,6 +1721,8 @@ struct rlimit32 {
s32 rlim_max;
};
+extern asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim);
+
asmlinkage int sys32_getrlimit(unsigned int resource, u32 rlim)
{
struct rlimit r;
@@ -1566,6 +1739,8 @@ asmlinkage int sys32_getrlimit(unsigned int resource, u32 rlim)
return ret;
}
+extern asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim);
+
asmlinkage int sys32_setrlimit(unsigned int resource, u32 rlim)
{
struct rlimit r;
@@ -1582,6 +1757,8 @@ asmlinkage int sys32_setrlimit(unsigned int resource, u32 rlim)
return ret;
}
+extern asmlinkage int sys_getrusage(int who, struct rusage *ru);
+
asmlinkage int sys32_getrusage(int who, u32 ru)
{
struct rusage r;
@@ -1595,17 +1772,23 @@ asmlinkage int sys32_getrusage(int who, u32 ru)
return ret;
}
+extern asmlinkage int sys_time(int * tloc);
+
asmlinkage int sys32_time(u32 tloc)
{
return sys_time((int *)A(tloc));
}
+extern asmlinkage int sys_gettimeofday(struct timeval *tv, struct timezone *tz);
+
asmlinkage int sys32_gettimeofday(u32 tv, u32 tz)
{
/* both timeval and timezone are ok :)) */
return sys_gettimeofday((struct timeval *)A(tv), (struct timezone *)A(tz));
}
+extern asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz);
+
asmlinkage int sys32_settimeofday(u32 tv, u32 tz)
{
return sys_settimeofday((struct timeval *)A(tv), (struct timezone *)A(tz));
@@ -1636,6 +1819,8 @@ struct timex32 {
int :32; int :32; int :32; int :32;
};
+extern asmlinkage int sys_adjtimex(struct timex *txc_p);
+
asmlinkage int sys32_adjtimex(u32 txc_p)
{
struct timex t;
@@ -1680,98 +1865,154 @@ asmlinkage int sys32_adjtimex(u32 txc_p)
return ret;
}
+extern asmlinkage int sys_msync(unsigned long start, size_t len, int flags);
+
asmlinkage int sys32_msync(u32 start, __kernel_size_t32 len, int flags)
{
return sys_msync((unsigned long)start, (size_t)len, flags);
}
+extern asmlinkage int sys_mlock(unsigned long start, size_t len);
+
asmlinkage int sys32_mlock(u32 start, __kernel_size_t32 len)
{
return sys_mlock((unsigned long)start, (size_t)len);
}
+extern asmlinkage int sys_munlock(unsigned long start, size_t len);
+
asmlinkage int sys32_munlock(u32 start, __kernel_size_t32 len)
{
return sys_munlock((unsigned long)start, (size_t)len);
}
+extern asmlinkage unsigned long sys_brk(unsigned long brk);
+
asmlinkage unsigned long sparc32_brk(u32 brk)
{
return sys_brk((unsigned long)brk);
}
+extern asmlinkage int sys_munmap(unsigned long addr, size_t len);
+
asmlinkage int sys32_munmap(u32 addr, __kernel_size_t32 len)
{
return sys_munmap((unsigned long)addr, (size_t)len);
}
+extern asmlinkage int sys_mprotect(unsigned long start, size_t len, unsigned long prot);
+
asmlinkage int sys32_mprotect(u32 start, __kernel_size_t32 len, u32 prot)
{
return sys_mprotect((unsigned long)start, (size_t)len, (unsigned long)prot);
}
+extern asmlinkage unsigned long sys_mremap(unsigned long addr, unsigned long old_len,
+ unsigned long new_len, unsigned long flags);
+
asmlinkage unsigned long sys32_mremap(u32 addr, u32 old_len, u32 new_len, u32 flags)
{
- return sys_mremap((unsigned long)addr, (unsigned long)old_len, (unsigned long)new_len, (unsigned long)flags);
+ return sys_mremap((unsigned long)addr, (unsigned long)old_len,
+ (unsigned long)new_len, (unsigned long)flags);
}
+extern asmlinkage int sys_swapoff(const char * specialfile);
+
asmlinkage int sys32_swapoff(u32 specialfile)
{
return sys_swapoff((const char *)A(specialfile));
}
+extern asmlinkage int sys_swapon(const char * specialfile, int swap_flags);
+
asmlinkage int sys32_swapon(u32 specialfile, int swap_flags)
{
return sys_swapon((const char *)A(specialfile), swap_flags);
}
-asmlinkage int sys32_bind(int fd, u32 umyaddr, int addrlen)
+extern asmlinkage int sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
+
+asmlinkage inline int sys32_bind(int fd, u32 umyaddr, int addrlen)
{
/* sockaddr is the same :)) */
return sys_bind(fd, (struct sockaddr *)A(umyaddr), addrlen);
}
-asmlinkage int sys32_accept(int fd, u32 upeer_sockaddr, u32 upeer_addrlen)
+extern asmlinkage int sys_accept(int fd, struct sockaddr *upeer_sockaddr,
+ int *upeer_addrlen);
+
+asmlinkage inline int sys32_accept(int fd, u32 upeer_sockaddr, u32 upeer_addrlen)
{
- return sys_accept(fd, (struct sockaddr *)A(upeer_sockaddr), (int *)A(upeer_addrlen));
+ return sys_accept(fd, (struct sockaddr *)A(upeer_sockaddr),
+ (int *)A(upeer_addrlen));
}
-asmlinkage int sys32_connect(int fd, u32 uservaddr, int addrlen)
+extern asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen);
+
+asmlinkage inline int sys32_connect(int fd, u32 uservaddr, int addrlen)
{
return sys_connect(fd, (struct sockaddr *)A(uservaddr), addrlen);
}
+extern asmlinkage int sys_getsockname(int fd, struct sockaddr *usockaddr,
+ int *usockaddr_len);
+
asmlinkage int sys32_getsockname(int fd, u32 usockaddr, u32 usockaddr_len)
{
- return sys_getsockname(fd, (struct sockaddr *)A(usockaddr), (int *)A(usockaddr_len));
+ return sys_getsockname(fd, (struct sockaddr *)A(usockaddr),
+ (int *)A(usockaddr_len));
}
+extern asmlinkage int sys_getpeername(int fd, struct sockaddr *usockaddr,
+ int *usockaddr_len);
+
asmlinkage int sys32_getpeername(int fd, u32 usockaddr, u32 usockaddr_len)
{
- return sys_getpeername(fd, (struct sockaddr *)A(usockaddr), (int *)A(usockaddr_len));
+ return sys_getpeername(fd, (struct sockaddr *)A(usockaddr),
+ (int *)A(usockaddr_len));
}
-asmlinkage int sys32_send(int fd, u32 buff, __kernel_size_t32 len, unsigned flags)
+extern asmlinkage int sys_send(int fd, void * buff, size_t len, unsigned flags);
+
+asmlinkage inline int sys32_send(int fd, u32 buff,
+ __kernel_size_t32 len, unsigned flags)
{
return sys_send(fd, (void *)A(buff), (size_t)len, flags);
}
-asmlinkage int sys32_sendto(int fd, u32 buff, __kernel_size_t32 len, unsigned flags, u32 addr, int addr_len)
+extern asmlinkage int sys_sendto(int fd, void * buff, size_t len, unsigned flags,
+ struct sockaddr *addr, int addr_len);
+
+asmlinkage inline int sys32_sendto(int fd, u32 buff, __kernel_size_t32 len,
+ unsigned flags, u32 addr, int addr_len)
{
- return sys_sendto(fd, (void *)A(buff), (size_t)len, flags, (struct sockaddr *)A(addr), addr_len);
+ return sys_sendto(fd, (void *)A(buff), (size_t)len, flags,
+ (struct sockaddr *)A(addr), addr_len);
}
-asmlinkage int sys32_recv(int fd, u32 ubuf, __kernel_size_t32 size, unsigned flags)
+extern asmlinkage int sys_recv(int fd, void * ubuf, size_t size, unsigned flags);
+
+asmlinkage inline int sys32_recv(int fd, u32 ubuf,
+ __kernel_size_t32 size, unsigned flags)
{
return sys_recv(fd, (void *)A(ubuf), (size_t)size, flags);
}
-asmlinkage int sys32_recvfrom(int fd, u32 ubuf, __kernel_size_t32 size, unsigned flags, u32 addr, u32 addr_len)
+extern asmlinkage int sys_recvfrom(int fd, void * ubuf, size_t size, unsigned flags,
+ struct sockaddr *addr, int *addr_len);
+
+asmlinkage inline int sys32_recvfrom(int fd, u32 ubuf, __kernel_size_t32 size,
+ unsigned flags, u32 addr, u32 addr_len)
{
- return sys_recvfrom(fd, (void *)A(ubuf), (size_t)size, flags, (struct sockaddr *)A(addr), (int *)A(addr_len));
+ return sys_recvfrom(fd, (void *)A(ubuf), (size_t)size, flags,
+ (struct sockaddr *)A(addr), (int *)A(addr_len));
}
-asmlinkage int sys32_setsockopt(int fd, int level, int optname, u32 optval, int optlen)
+extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
+ char *optval, int optlen);
+
+asmlinkage inline int sys32_setsockopt(int fd, int level, int optname,
+ u32 optval, int optlen)
{
/* XXX handle ip_fw32->ip_fw conversion for IP firewalling and accounting.
Do it using some macro in ip_sockglue.c
@@ -1779,11 +2020,54 @@ asmlinkage int sys32_setsockopt(int fd, int level, int optname, u32 optval, int
return sys_setsockopt(fd, level, optname, (char *)A(optval), optlen);
}
-asmlinkage int sys32_getsockopt(int fd, int level, int optname, u32 optval, u32 optlen)
+extern asmlinkage int sys_getsockopt(int fd, int level, int optname,
+ char *optval, int *optlen);
+
+asmlinkage inline int sys32_getsockopt(int fd, int level, int optname,
+ u32 optval, u32 optlen)
{
return sys_getsockopt(fd, level, optname, (char *)A(optval), (int *)A(optlen));
}
+/* XXX This really belongs in some header file... -DaveM */
+#define MAX_SOCK_ADDR 128 /* 108 for Unix domain -
+ 16 for IP, 16 for IPX,
+ 24 for IPv6,
+ about 80 for AX.25 */
+
+/* XXX These as well... */
+extern __inline__ struct socket *socki_lookup(struct inode *inode)
+{
+ return &inode->u.socket_i;
+}
+
+extern __inline__ struct socket *sockfd_lookup(int fd, int *err)
+{
+ struct file *file;
+ struct inode *inode;
+
+ if (!(file = fget(fd)))
+ {
+ *err = -EBADF;
+ return NULL;
+ }
+
+ inode = file->f_inode;
+ if (!inode || !inode->i_sock || !socki_lookup(inode))
+ {
+ *err = -ENOTSOCK;
+ fput(file,inode);
+ return NULL;
+ }
+
+ return socki_lookup(inode);
+}
+
+extern __inline__ void sockfd_put(struct socket *sock)
+{
+ fput(sock->file,sock->inode);
+}
+
struct msghdr32 {
u32 msg_name;
int msg_namelen;
@@ -1801,207 +2085,270 @@ struct cmsghdr32 {
unsigned char cmsg_data[0];
};
-asmlinkage int sys32_sendmsg(int fd, u32 msg, unsigned flags)
+static inline int iov_from_user32_to_kern(struct iovec *kiov,
+ struct iovec32 *uiov32,
+ int niov)
{
- struct msghdr m;
- int count;
- struct iovec *v;
- struct iovec vf[UIO_FASTIOV];
- u32 i, vector;
- long ret;
- unsigned long old_fs;
-
- if (get_user ((long)m.msg_name, &(((struct msghdr32 *)A(msg))->msg_name)) ||
- __get_user (m.msg_namelen, &(((struct msghdr32 *)A(msg))->msg_namelen)) ||
- __get_user (vector, &(((struct msghdr32 *)A(msg))->msg_iov)) ||
- __get_user (m.msg_iovlen, &(((struct msghdr32 *)A(msg))->msg_iovlen)) ||
- __get_user ((long)m.msg_control, &(((struct msghdr32 *)A(msg))->msg_control)) ||
- __get_user (m.msg_controllen, &(((struct msghdr32 *)A(msg))->msg_controllen)) ||
- __get_user (m.msg_flags, &(((struct msghdr32 *)A(msg))->msg_flags)))
- return -EFAULT;
-
- count = m.msg_iovlen;
- if (!count) return 0; if (count > UIO_MAXIOV) return -EINVAL;
- if (count <= UIO_FASTIOV)
- v = vf;
- else {
- lock_kernel ();
- v = kmalloc (count * sizeof (struct iovec), GFP_KERNEL);
- if (!v) {
- ret = -ENOMEM;
- goto out;
+ int tot_len = 0;
+
+ while(niov > 0) {
+ u32 len, buf;
+
+ if(get_user(len, &uiov32->iov_len) ||
+ get_user(buf, &uiov32->iov_base)) {
+ tot_len = -EFAULT;
+ break;
}
+ tot_len += len;
+ kiov->iov_base = (void *)A(buf);
+ kiov->iov_len = (__kernel_size_t) len;
+ uiov32++;
+ kiov++;
+ niov--;
}
+ return tot_len;
+}
- for (i = 0; i < count; i++) {
- if (__get_user ((unsigned long)(v[i].iov_base), &((((struct iovec32 *)A(vector))+i)->iov_base)) ||
- __get_user (v[i].iov_len, &((((struct iovec32 *)A(vector))+i)->iov_len))) {
- ret = -EFAULT;
- goto out;
+static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg,
+ struct msghdr32 *umsg)
+{
+ u32 tmp1, tmp2, tmp3;
+
+ if(get_user(tmp1, &umsg->msg_name) ||
+ get_user(tmp2, &umsg->msg_iov) ||
+ get_user(tmp3, &umsg->msg_control))
+ return -EFAULT;
+
+ kmsg->msg_name = (void *)A(tmp1);
+ kmsg->msg_iov = (struct iovec *)A(tmp2);
+ kmsg->msg_control = (void *)A(tmp3);
+
+ if(get_user(kmsg->msg_namelen, &umsg->msg_namelen) ||
+ get_user(kmsg->msg_controllen, &umsg->msg_controllen) ||
+ get_user(kmsg->msg_flags, &umsg->msg_flags))
+ return -EFAULT;
+
+ return 0;
+}
+
+/* I've named the args so it is easy to tell whose space the pointers are in. */
+static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
+ char *kern_address, int mode)
+{
+ int tot_len;
+
+ if(kern_msg->msg_namelen) {
+ if(mode==VERIFY_READ) {
+ int err = move_addr_to_kernel(kern_msg->msg_name,
+ kern_msg->msg_namelen,
+ kern_address);
+ if(err < 0)
+ return err;
}
+ kern_msg->msg_name = kern_address;
+ } else
+ kern_msg->msg_name = NULL;
+
+ if(kern_msg->msg_iovlen > UIO_FASTIOV) {
+ kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
+ GFP_KERNEL);
+ if(!kern_iov)
+ return -ENOMEM;
}
-
- m.msg_iov = v;
- if (m.msg_controllen) {
- /* XXX Handle msg_control stuff... Or should that go into ip_sockglue.c etc.? */
- }
- old_fs = get_fs();
- set_fs (KERNEL_DS);
- ret = sys_sendmsg(fd, &m, flags);
- set_fs (old_fs);
-out:
- if (count > UIO_FASTIOV) {
- kfree (v);
- unlock_kernel ();
- }
- return ret;
+ tot_len = iov_from_user32_to_kern(kern_iov,
+ (struct iovec32 *)kern_msg->msg_iov,
+ kern_msg->msg_iovlen);
+ if(tot_len >= 0)
+ kern_msg->msg_iov = kern_iov;
+ else if(kern_msg->msg_iovlen > UIO_FASTIOV)
+ kfree(kern_iov);
+
+ return tot_len;
}
-asmlinkage int sys32_recvmsg(int fd, u32 msg, unsigned int flags)
+asmlinkage int sys32_sendmsg(int fd, u32 user_msg, unsigned user_flags)
{
- struct msghdr m;
- int count;
- struct iovec *v;
- struct iovec vf[UIO_FASTIOV];
- u32 i, vector;
- long ret;
- unsigned long old_fs;
-
- if (get_user ((long)m.msg_name, &(((struct msghdr32 *)A(msg))->msg_name)) ||
- __get_user (m.msg_namelen, &(((struct msghdr32 *)A(msg))->msg_namelen)) ||
- __get_user (vector, &(((struct msghdr32 *)A(msg))->msg_iov)) ||
- __get_user (m.msg_iovlen, &(((struct msghdr32 *)A(msg))->msg_iovlen)) ||
- __get_user ((long)m.msg_control, &(((struct msghdr32 *)A(msg))->msg_control)) ||
- __get_user (m.msg_controllen, &(((struct msghdr32 *)A(msg))->msg_controllen)) ||
- __get_user (m.msg_flags, &(((struct msghdr32 *)A(msg))->msg_flags)))
+ struct socket *sock;
+ char address[MAX_SOCK_ADDR];
+ struct iovec iov[UIO_FASTIOV];
+ unsigned char ctl[sizeof(struct cmsghdr) + 20];
+ struct msghdr kern_msg;
+ int err;
+ int total_len;
+ unsigned char *ctl_buf = ctl;
+
+ if(msghdr_from_user32_to_kern(&kern_msg, (struct msghdr32 *)A(user_msg)))
return -EFAULT;
-
- count = m.msg_iovlen;
- if (!count) return 0; if (count > UIO_MAXIOV) return -EINVAL;
- if (count <= UIO_FASTIOV)
- v = vf;
- else {
- lock_kernel ();
- v = kmalloc (count * sizeof (struct iovec), GFP_KERNEL);
- if (!v) {
- ret = -ENOMEM;
- goto out;
+ if(kern_msg.msg_iovlen > UIO_MAXIOV)
+ return -EINVAL;
+ total_len = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
+ if(total_len < 0)
+ return total_len;
+ if(kern_msg.msg_controllen) {
+ struct cmsghdr32 *ucmsg = (struct cmsghdr32 *)kern_msg.msg_control;
+ unsigned long *kcmsg;
+ __kernel_size_t32 cmlen;
+
+ if(kern_msg.msg_controllen > sizeof(ctl) &&
+ kern_msg.msg_controllen <= 256) {
+ ctl_buf = kmalloc(kern_msg.msg_controllen, GFP_KERNEL);
+ if(!ctl_buf) {
+ if(kern_msg.msg_iov != iov)
+ kfree(kern_msg.msg_iov);
+ return -ENOBUFS;
+ }
}
- }
-
- for (i = 0; i < count; i++) {
- if (__get_user ((unsigned long)(v[i].iov_base), &((((struct iovec32 *)A(vector))+i)->iov_base)) ||
- __get_user (v[i].iov_len, &((((struct iovec32 *)A(vector))+i)->iov_len))) {
- ret = -EFAULT;
- goto out;
+ __get_user(cmlen, &ucmsg->cmsg_len);
+ kcmsg = (unsigned long *) ctl_buf;
+ *kcmsg++ = (unsigned long)cmlen;
+ if(copy_from_user(kcmsg, &ucmsg->cmsg_level,
+ kern_msg.msg_controllen - sizeof(__kernel_size_t32))) {
+ if(ctl_buf != ctl)
+ kfree_s(ctl_buf, kern_msg.msg_controllen);
+ if(kern_msg.msg_iov != iov)
+ kfree(kern_msg.msg_iov);
+ return -EFAULT;
}
+ kern_msg.msg_control = ctl_buf;
}
-
- m.msg_iov = v;
+ kern_msg.msg_flags = user_flags;
- if (m.msg_controllen) {
- /* XXX Handle msg_control stuff... Or should that go into ip_sockglue.c etc.? */
+ lock_kernel();
+ if(current->files->fd[fd]->f_flags & O_NONBLOCK)
+ kern_msg.msg_flags |= MSG_DONTWAIT;
+ if((sock = sockfd_lookup(fd, &err)) != NULL) {
+ err = sock_sendmsg(sock, &kern_msg, total_len);
+ sockfd_put(sock);
}
- old_fs = get_fs();
- set_fs (KERNEL_DS);
- ret = sys_recvmsg(fd, &m, flags);
- set_fs (old_fs);
- if (ret >= 0) {
- /* XXX Handle msg_control stuff... */
- if (put_user (m.msg_flags, &(((struct msghdr32 *)A(msg))->msg_flags)) ||
- __put_user (m.msg_controllen, &(((struct msghdr32 *)A(msg))->msg_controllen)))
- return -EFAULT;
+ unlock_kernel();
+
+ if(ctl_buf != ctl)
+ kfree_s(ctl_buf, kern_msg.msg_controllen);
+ if(kern_msg.msg_iov != iov)
+ kfree(kern_msg.msg_iov);
+ return err;
+}
+
+asmlinkage int sys32_recvmsg(int fd, u32 user_msg, unsigned int user_flags)
+{
+ struct iovec iovstack[UIO_FASTIOV];
+ struct msghdr kern_msg;
+ char addr[MAX_SOCK_ADDR];
+ struct socket *sock;
+ struct iovec *iov = iovstack;
+ struct sockaddr *uaddr;
+ int *uaddr_len;
+ unsigned long cmsg_ptr;
+ int err, total_len, len = 0;
+
+ if(msghdr_from_user32_to_kern(&kern_msg, (struct msghdr32 *)A(user_msg)))
+ return -EFAULT;
+ if(kern_msg.msg_iovlen > UIO_MAXIOV)
+ return -EINVAL;
+
+ uaddr = kern_msg.msg_name;
+ uaddr_len = &((struct msghdr32 *)A(user_msg))->msg_namelen;
+ err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
+ if(err < 0)
+ return err;
+ total_len = err;
+
+ cmsg_ptr = (unsigned long) kern_msg.msg_control;
+ kern_msg.msg_flags = 0;
+
+ lock_kernel();
+ if(current->files->fd[fd]->f_flags & O_NONBLOCK)
+ user_flags |= MSG_DONTWAIT;
+ if((sock = sockfd_lookup(fd, &err)) != NULL) {
+ err = sock_recvmsg(sock, &kern_msg, total_len, user_flags);
+ if(err >= 0)
+ len = err;
+ sockfd_put(sock);
}
-out:
- if (count > UIO_FASTIOV) {
- kfree (v);
- unlock_kernel ();
+ unlock_kernel();
+
+ if(kern_msg.msg_iov != iov)
+ kfree(kern_msg.msg_iov);
+ if(uaddr != NULL && err >= 0)
+ err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
+ if(err >= 0) {
+ err = __put_user(kern_msg.msg_flags,
+ &((struct msghdr32 *)A(user_msg))->msg_flags);
+ if(!err) {
+ /* XXX Convert cmsg back into userspace 32-bit format... */
+ err = __put_user((unsigned long)kern_msg.msg_control - cmsg_ptr,
+ &((struct msghdr32 *)A(user_msg))->msg_controllen);
+ }
}
- return ret;
+ if(err < 0)
+ return err;
+ return len;
}
+/* Argument list sizes for sys_socketcall */
+#define AL(x) ((x) * sizeof(u32))
+static unsigned char nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
+ AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
+ AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
+#undef AL
+
+extern asmlinkage int sys_socket(int family, int type, int protocol);
+extern asmlinkage int sys_socketpair(int family, int type, int protocol,
+ int usockvec[2]);
+extern asmlinkage int sys_shutdown(int fd, int how);
+extern asmlinkage int sys_listen(int fd, int backlog);
+
asmlinkage int sys32_socketcall(int call, u32 args)
{
- static unsigned char nargs[18]={0,3,3,3,2,3,3,3,
- 4,4,4,6,6,2,5,5,3,3};
u32 a[6];
u32 a0,a1;
- int err = -EINVAL;
- int i;
- lock_kernel();
- if(call<1||call>SYS_RECVMSG)
- goto out;
- err = -EFAULT;
-
- for (i = 0; i < nargs[call]; i++, args += sizeof (u32))
- if (get_user(a[i], (u32 *)A(args)))
- goto out;
-
+ if (call<SYS_SOCKET||call>SYS_RECVMSG)
+ return -EINVAL;
+ if (copy_from_user(a, (u32 *)A(args), nargs[call]))
+ return -EFAULT;
a0=a[0];
a1=a[1];
switch(call)
{
case SYS_SOCKET:
- err = sys_socket(a0, a1, a[2]);
- break;
+ return sys_socket(a0, a1, a[2]);
case SYS_BIND:
- err = sys32_bind(a0, a1, a[2]);
- break;
+ return sys32_bind(a0, a1, a[2]);
case SYS_CONNECT:
- err = sys32_connect(a0, a1, a[2]);
- break;
+ return sys32_connect(a0, a1, a[2]);
case SYS_LISTEN:
- err = sys_listen(a0, a1);
- break;
+ return sys_listen(a0, a1);
case SYS_ACCEPT:
- err = sys32_accept(a0, a1, a[2]);
- break;
+ return sys32_accept(a0, a1, a[2]);
case SYS_GETSOCKNAME:
- err = sys32_getsockname(a0, a1, a[2]);
- break;
+ return sys32_getsockname(a0, a1, a[2]);
case SYS_GETPEERNAME:
- err = sys32_getpeername(a0, a1, a[2]);
- break;
+ return sys32_getpeername(a0, a1, a[2]);
case SYS_SOCKETPAIR:
- err = sys_socketpair(a0, a1, a[2], (int *)A(a[3]));
- break;
+ return sys_socketpair(a0, a1, a[2], (int *)A(a[3]));
case SYS_SEND:
- err = sys32_send(a0, a1, a[2], a[3]);
- break;
+ return sys32_send(a0, a1, a[2], a[3]);
case SYS_SENDTO:
- err = sys32_sendto(a0, a1, a[2], a[3], a[4], a[5]);
- break;
+ return sys32_sendto(a0, a1, a[2], a[3], a[4], a[5]);
case SYS_RECV:
- err = sys32_recv(a0, a1, a[2], a[3]);
- break;
+ return sys32_recv(a0, a1, a[2], a[3]);
case SYS_RECVFROM:
- err = sys32_recvfrom(a0, a1, a[2], a[3], a[4], a[5]);
- break;
+ return sys32_recvfrom(a0, a1, a[2], a[3], a[4], a[5]);
case SYS_SHUTDOWN:
- err = sys_shutdown(a0,a1);
- break;
+ return sys_shutdown(a0,a1);
case SYS_SETSOCKOPT:
- err = sys32_setsockopt(a0, a1, a[2], a[3], a[4]);
- break;
+ return sys32_setsockopt(a0, a1, a[2], a[3], a[4]);
case SYS_GETSOCKOPT:
- err = sys32_getsockopt(a0, a1, a[2], a[3], a[4]);
- break;
+ return sys32_getsockopt(a0, a1, a[2], a[3], a[4]);
case SYS_SENDMSG:
- err = sys32_sendmsg(a0, a1, a[2]);
- break;
+ return sys32_sendmsg(a0, a1, a[2]);
case SYS_RECVMSG:
- err = sys32_recvmsg(a0, a1, a[2]);
- break;
- default:
- err = -EINVAL;
- break;
+ return sys32_recvmsg(a0, a1, a[2]);
}
-out:
- unlock_kernel();
- return err;
+ return -EINVAL;
}
extern void check_pending(int signum);
@@ -2060,6 +2407,8 @@ out:
return err;
}
+extern asmlinkage int sys_nfsservctl(int cmd, void *argp, void *resp);
+
asmlinkage int sys32_nfsservctl(int cmd, u32 argp, u32 resp)
{
/* XXX handle argp and resp args */
@@ -2204,6 +2553,12 @@ asmlinkage int sparc32_execve(struct pt_regs *regs)
return error;
}
+/* Modules will be supported with 64bit modutils only */
+asmlinkage int sys32_no_modules(void)
+{
+ return -ENOSYS;
+}
+
struct ncp_mount_data32 {
int version;
unsigned int ncp_fd;
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 02707186a..a74d0ffbd 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.11 1997/05/27 19:30:20 jj Exp $
+/* $Id: systbls.S,v 1.13 1997/06/04 13:05:29 jj Exp $
* systbls.S: System call entry point tables for OS compatibility.
* The native Linux system call table lives here also.
*
@@ -53,20 +53,20 @@ sys_call_table32:
.xword sys32_quotactl, sys_nis_syscall, sys32_mount, sys32_ustat, sys_nis_syscall
/*170*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents
.xword sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-/*180*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys_nis_syscall
+/*180*/ .xword sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys32_no_modules
.xword sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_newuname
-/*190*/ .xword sys_nis_syscall, sys32_personality, sys_prof, sys_break, sys_lock
+/*190*/ .xword sys32_no_modules, sys32_personality, sys_prof, sys_break, sys_lock
.xword sys_mpx, sys_ulimit, sys_getppid, sparc32_sigaction, sys_sgetmask
/*200*/ .xword sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys32_uselib, old32_readdir
.xword sys_nis_syscall, sys32_socketcall, sys32_syslog, sys32_olduname, sys_nis_syscall
/*210*/ .xword sys_idle, sys_nis_syscall, sys32_waitpid, sys32_swapoff, sys32_sysinfo
.xword sys32_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex
-/*220*/ .xword sys32_sigprocmask, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getpgid
+/*220*/ .xword sys32_sigprocmask, sys32_no_modules, sys32_no_modules, sys32_no_modules, sys_getpgid
.xword sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid
/*230*/ .xword sys32_llseek, sys32_time, sys_nis_syscall, sys_stime, sys_nis_syscall
.xword sys_nis_syscall, sys32_llseek, sys32_mlock, sys32_munlock, sys_mlockall
/*240*/ .xword sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys_nis_syscall, sys_nis_syscall
- .xword sys_nis_syscall, sys_sched_get_priority_max, sys_sched_get_priority_min, sys32_sched_rr_get_interval, sys_nanosleep
+ .xword sys_nis_syscall, sys_sched_get_priority_max, sys_sched_get_priority_min, sys32_sched_rr_get_interval, sys32_nanosleep
/*250*/ .xword sys32_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys32_nfsservctl
.xword sys_aplib, sys_nis_syscall
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 6f96408ad..824a3ddb4 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -1,7 +1,7 @@
-/* $Id: traps.c,v 1.13 1997/05/27 19:30:08 jj Exp $
+/* $Id: traps.c,v 1.19 1997/06/05 06:22:49 davem Exp $
* arch/sparc/kernel/traps.c
*
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*/
@@ -23,6 +23,7 @@
#include <asm/pgtable.h>
#include <asm/unistd.h>
#include <asm/uaccess.h>
+#include <asm/fpumacro.h>
/* #define SYSCALL_TRACING */
/* #define VERBOSE_SYSCALL_TRACING */
@@ -122,7 +123,8 @@ void syscall_trace_entry(unsigned long g1, struct pt_regs *regs)
int i;
#endif
- printk("SYS[%s:%d]: <%d> ", current->comm, current->pid, (int)g1);
+ printk("SYS[%s:%d]: PC(%016lx) <%3d> ",
+ current->comm, current->pid, regs->tpc, (int)g1);
#ifdef VERBOSE_SYSCALL_TRACING
sdp = NULL;
for(i = 0; i < NUM_SDESC_ENTRIES; i++)
@@ -151,7 +153,7 @@ void syscall_trace_entry(unsigned long g1, struct pt_regs *regs)
unsigned long syscall_trace_exit(unsigned long retval, struct pt_regs *regs)
{
- printk("ret[%08x]\n", (unsigned int) retval);
+ printk("ret[%016lx]\n", retval);
return retval;
}
#endif /* SYSCALL_TRACING */
@@ -254,25 +256,143 @@ void do_iae(struct pt_regs *regs)
barrier();
}
+static unsigned long init_fsr = 0x0UL;
+static unsigned int init_fregs[64] __attribute__ ((aligned (64))) =
+ { ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
+ ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
+ ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
+ ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
+ ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
+ ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
+ ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
+ ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U };
+
void do_fpdis(struct pt_regs *regs)
{
- printk("FPDIS: at %016lx\n", regs->tpc);
- while(1)
- barrier();
+ lock_kernel();
+
+ regs->tstate |= TSTATE_PEF;
+ fprs_write(FPRS_FEF);
+
+ /* This is allowed now because the V9 ABI varargs passes floating
+ * point args in floating point registers, so vsprintf() and sprintf()
+ * cause problems. Luckily we never actually pass floating point values
+ * to those routines in the kernel and the code generated just does
+ * stores of them to the stack. Therefore, for the moment this fix
+ * is sufficient. -DaveM
+ */
+ if(regs->tstate & TSTATE_PRIV)
+ goto out;
+
+#ifndef __SMP__
+ if(last_task_used_math == current)
+ goto out;
+ if(last_task_used_math) {
+ struct task_struct *fptask = last_task_used_math;
+
+ if(fptask->tss.flags & SPARC_FLAG_32BIT)
+ fpsave32((unsigned long *)&fptask->tss.float_regs[0],
+ &fptask->tss.fsr);
+ else
+ fpsave((unsigned long *)&fptask->tss.float_regs[0],
+ &fptask->tss.fsr);
+ }
+ last_task_used_math = current;
+ if(current->used_math) {
+ if(current->tss.flags & SPARC_FLAG_32BIT)
+ fpload32(&current->tss.float_regs[0],
+ &current->tss.fsr);
+ else
+ fpload(&current->tss.float_regs[0],
+ &current->tss.fsr);
+ } else {
+ /* Set inital sane state. */
+ fpload(&init_fregs[0], &init_fsr);
+ current->used_math = 1;
+ }
+#else
+ if(!current->used_math) {
+ fpload(&init_fregs[0], &init_fsr);
+ current->used_math = 1;
+ } else {
+ if(current->tss.flags & SPARC_FLAG_32BIT)
+ fpload32(&current->tss.float_regs[0],
+ &current->tss.fsr);
+ else
+ fpload(&current->tss.float_regs[0],
+ &current->tss.fsr);
+ }
+ current->flags |= PF_USEDFPU;
+#endif
+#ifndef __SMP__
+out:
+#endif
+ unlock_kernel();
+}
+
+static unsigned long fake_regs[32] __attribute__ ((aligned (8)));
+static unsigned long fake_fsr;
+
+void do_fpe_common(struct pt_regs *regs)
+{
+ static int calls = 0;
+#ifndef __SMP__
+ struct task_struct *fpt = last_task_used_math;
+#else
+ struct task_struct *fpt = current;
+#endif
+
+ lock_kernel();
+ fprs_write(FPRS_FEF);
+
+#ifndef __SMP__
+ if(!fpt) {
+#else
+ if(!(fpt->flags & PF_USEDFPU)) {
+#endif
+ fpsave(&fake_regs[0], &fake_fsr);
+ regs->tstate &= ~(TSTATE_PEF);
+ goto out;
+ }
+ if(fpt->tss.flags & SPARC_FLAG_32BIT)
+ fpsave32((unsigned long *)&fpt->tss.float_regs[0], &fpt->tss.fsr);
+ else
+ fpsave((unsigned long *)&fpt->tss.float_regs[0], &fpt->tss.fsr);
+ fpt->tss.sig_address = regs->tpc;
+ fpt->tss.sig_desc = SUBSIG_FPERROR;
+#ifdef __SMP__
+ fpt->flags &= ~PF_USEDFPU;
+#endif
+ if(regs->tstate & TSTATE_PRIV) {
+ printk("WARNING: FPU exception from kernel mode. at pc=%016lx\n",
+ regs->tpc);
+ regs->tpc = regs->tnpc;
+ regs->tnpc += 4;
+ calls++;
+ if(calls > 2)
+ die_if_kernel("Too many Penguin-FPU traps from kernel mode",
+ regs);
+ goto out;
+ }
+ send_sig(SIGFPE, fpt, 1);
+#ifndef __SMP__
+ last_task_used_math = NULL;
+#endif
+ regs->tstate &= ~TSTATE_PEF;
+ if(calls > 0)
+ calls = 0;
+out:
+ unlock_kernel();
}
void do_fpieee(struct pt_regs *regs)
{
- printk("FPIEEE: at %016lx\n", regs->tpc);
- while(1)
- barrier();
+ do_fpe_common(regs);
}
void do_fpother(struct pt_regs *regs)
{
- printk("FPOTHER: at %016lx\n", regs->tpc);
- while(1)
- barrier();
+ do_fpe_common(regs);
}
void do_tof(struct pt_regs *regs)
@@ -352,23 +472,29 @@ void do_illegal_instruction(struct pt_regs *regs)
printk("Ill instr. at pc=%016lx ", pc);
get_user(insn, ((unsigned int *)pc));
printk("insn=[%08x]\n", insn);
+ show_regs(regs);
}
#endif
current->tss.sig_address = pc;
current->tss.sig_desc = SUBSIG_ILLINST;
send_sig(SIGILL, current, 1);
unlock_kernel();
-
- while(1)
- barrier();
}
-void do_mna(struct pt_regs *regs)
+void mem_address_unaligned(struct pt_regs *regs)
{
printk("AIEEE: do_mna at %016lx\n", regs->tpc);
show_regs(regs);
- while(1)
- barrier();
+ if(regs->tstate & TSTATE_PRIV) {
+ printk("MNA from kernel, spinning\n");
+ sti();
+ while(1)
+ barrier();
+ } else {
+ current->tss.sig_address = regs->tpc;
+ current->tss.sig_desc = SUBSIG_PRIVINST;
+ send_sig(SIGBUS, current, 1);
+ }
}
void do_privop(struct pt_regs *regs)
diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S
index 326382c3f..8db708f07 100644
--- a/arch/sparc64/kernel/ttable.S
+++ b/arch/sparc64/kernel/ttable.S
@@ -1,4 +1,4 @@
-/* $Id: ttable.S,v 1.12 1997/05/17 08:22:30 davem Exp $
+/* $Id: ttable.S,v 1.13 1997/06/02 06:33:34 davem Exp $
* ttable.S: Sparc V9 Trap Table(s) with SpitFire extensions.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -30,7 +30,7 @@ tl0_dax: ACCESS_EXCEPTION_TRAP(data_access_exception)
tl0_resv031: BTRAP(0x31)
tl0_dae: TRAP(do_dae)
tl0_resv033: BTRAP(0x33)
-tl0_mna: TRAP(do_mna)
+tl0_mna: TRAP_NOSAVE(do_mna)
tl0_lddfmna: TRAP(do_lddfmna)
tl0_stdfmna: TRAP(do_stdfmna)
tl0_privact: TRAP(do_privact)
@@ -163,7 +163,7 @@ tl1_dax: ACCESS_EXCEPTION_TRAPTL1(data_access_exception)
tl1_resv031: BTRAPTL1(0x31)
tl1_dae: TRAPTL1(do_dae_tl1)
tl1_resv033: BTRAPTL1(0x33)
-tl1_mna: TRAPTL1(do_mna_tl1)
+tl1_mna: TRAP_NOSAVE(do_mna)
tl1_lddfmna: TRAPTL1(do_lddfmna_tl1)
tl1_stdfmna: TRAPTL1(do_stdfmna_tl1)
tl1_privact: BTRAPTL1(0x37)
diff --git a/arch/sparc64/kernel/winfixup.S b/arch/sparc64/kernel/winfixup.S
index a8293c453..2ac19a440 100644
--- a/arch/sparc64/kernel/winfixup.S
+++ b/arch/sparc64/kernel/winfixup.S
@@ -1,4 +1,4 @@
-/* $Id: winfixup.S,v 1.3 1997/05/18 22:52:26 davem Exp $
+/* $Id: winfixup.S,v 1.8 1997/06/02 06:33:35 davem Exp $
*
* winfixup.S: Handle cases where user stack pointer is found to be bogus.
*
@@ -10,6 +10,7 @@
#include <asm/page.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
+#include <asm/spitfire.h>
#include <asm/asm_offsets.h>
.text
@@ -28,74 +29,223 @@
*/
.globl winfix_trampoline, fill_fixup, spill_fixup
fill_fixup:
- ba,pt %xcc, etrap
- rd %pc, %g7
- mov %l5, %o4
- mov %l4, %o5
- srlx %l5, PAGE_SHIFT, %o3
- clr %o1
- sllx %o3, PAGE_SHIFT, %o3
- and %l4, 0x4, %o2
-
- call do_sparc64_fault
- add %sp, STACK_BIAS + REGWIN_SZ, %o0
- ba,a,pt %xcc, rtrap
+ rdpr %tstate, %g1
+ andcc %g1, TSTATE_PRIV, %g0
+ be,pt %xcc, window_scheisse_from_user_common
+ and %g1, TSTATE_CWP, %g1
+
+ /* This is the extremely complex case, but it does happen from
+ * time to time if things are just right. Essentially the restore
+ * done in rtrap right before going back to user mode, with tl=1
+ * and that levels trap stack registers all setup, took a fill trap,
+ * the user stack was not mapped in the tlb, and tlb miss occurred,
+ * the pte found was not valid, and a simple ref bit watch update
+ * could not satisfy the miss, so we got here.
+ *
+ * We must carefully unwind the state so we get back to tl=0, preserve
+ * all the register values we were going to give to the user. Luckily
+ * most things are where they need to be, we also have the address
+ * which triggered the fault handy as well.
+ *
+ * First, get into the window where the original restore was executed.
+ */
+
+ rdpr %wstate, %g2 ! Grab user mode wstate.
+ wrpr %g1, %cwp ! Get into the right window.
+ sll %g2, 3, %g2 ! NORMAL-->OTHER
+ wrpr %g0, 0x0, %canrestore ! Standard etrap stuff.
+
+ wrpr %g2, 0x0, %wstate ! This must be consistant.
+ wrpr %g0, 0x0, %otherwin ! We know this.
+ sethi %uhi(KERNBASE), %g2 ! Set this up
+ sllx %g2, 32, %g2 ! for the iflush
+ mov PRIMARY_CONTEXT, %g1 ! Change contexts...
+ stxa %g0, [%g1] ASI_DMMU ! Back into the nucleus.
+ flush %g2 ! Flush instruction buffers
+ rdpr %pstate, %l1 ! Prepare to change globals.
+ mov %g4, %o5 ! Setup args for
+ mov %g5, %o4 ! final call to do_sparc64_fault.
+
+ wrpr %g0, 0x0, %tl ! Out of trap levels.
+ wrpr %l1, (PSTATE_IE | PSTATE_AG), %pstate
+ sethi %uhi(KERNBASE), %g4 ! Restore med-any global reg.
+ rd %pic, %g6 ! Get current as well.
+ b,pt %xcc, window_scheisse_merge ! And merge.
+ sllx %g4, 32, %g4 ! Finish med-any reg setup.
+
+ /* Be very careful about usage of the alternate globals here.
+ * You cannot touch %g4/%g5 as that has the fault information
+ * should this be from usermode. Also be careful for the case
+ * where we get here from the save instruction in etrap.S when
+ * coming from either user or kernel (does not matter which, it
+ * is the same problem in both cases). Essentially this means
+ * do not touch %g7 or %g2 so we handle the two cases fine.
+ */
+spill_fixup:
+ rd %pic, %g1
+ ldx [%g1 + AOFF_task_tss + AOFF_thread_flags], %g6
+ andcc %g6, SPARC_FLAG_32BIT, %g0
+ ldx [%g1 + AOFF_task_tss + AOFF_thread_w_saved], %g6
+ sll %g6, 3, %g3
+ add %g1, %g3, %g3
+ stx %sp, [%g3 + AOFF_task_tss + AOFF_thread_rwbuf_stkptrs]
+ sll %g6, 7, %g3
+
+ bne,pt %xcc, 1f
+ add %g1, %g3, %g3
+ stx %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
+ stx %l1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
+ stx %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
+ stx %l3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18]
+ stx %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20]
+ stx %l5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
+
+ stx %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30]
+ stx %l7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38]
+ stx %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x40]
+ stx %i1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x48]
+ stx %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x50]
+ stx %i3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x58]
+ stx %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x60]
+ stx %i5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x68]
+
+ stx %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x70]
+ stx %i7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x78]
+ b,pt %xcc, 2f
+ add %g6, 1, %g6
+1: std %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
+ std %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
+ std %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
+ std %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18]
+
+ std %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20]
+ std %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
+ std %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30]
+ std %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38]
+ add %g6, 1, %g6
+2: stx %g6, [%g1 + AOFF_task_tss + AOFF_thread_w_saved]
+ rdpr %tstate, %g1
+ nop
+
+ andcc %g1, TSTATE_PRIV, %g0
+ saved
+ and %g1, TSTATE_CWP, %g1
+ be,a,pn %xcc, window_scheisse_from_user_common
+ or %g4, 0x4, %g4 ! we know it was a write
+ retry
+window_scheisse_from_user_common:
nop
+ wrpr %g1, %cwp
+
+ ba,pt %xcc, etrap
+ rd %pc, %g7
+ mov %l5, %o4
+ mov %l4, %o5
+window_scheisse_merge:
+ srlx %o4, PAGE_SHIFT, %o3
+ clr %o1
+ sllx %o3, PAGE_SHIFT, %o3
+ and %o5, 0x4, %o2
+
+ call do_sparc64_fault
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
+ ba,pt %xcc, rtrap
+ clr %l6
winfix_trampoline:
- andn %g5, 0x7f, %g5
- add %g5, 0x7c, %g5
- wrpr %g5, %tnpc
+ andn %g3, 0x7f, %g3
+ add %g3, 0x7c, %g3
+ wrpr %g3, %tnpc
done
-spill_fixup:
- rd %pic, %g1
- ldx [%g1 + AOFF_task_tss + AOFF_thread_w_saved], %g2
- sll %g2, 3, %g5
- ldx [%g1 + AOFF_task_tss + AOFF_thread_flags], %g7
- add %g1, %g5, %g5
- andcc %g7, SPARC_FLAG_32BIT, %g0
- stx %sp, [%g5 + AOFF_task_tss + AOFF_thread_rwbuf_stkptrs]
- sll %g2, 5, %g5
-
- bne,pt %xcc, 1f
- add %g1, %g5, %g5
- stx %l0, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
- stx %l1, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
- stx %l2, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
- stx %l3, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x18]
- stx %l4, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x20]
- stx %l5, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
-
- stx %l6, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x30]
- stx %l7, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x38]
- stx %i0, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x40]
- stx %i1, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x48]
- stx %i2, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x50]
- stx %i3, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x58]
- stx %i4, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x60]
- stx %i5, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x68]
-
- stx %i6, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x70]
- stx %i7, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x78]
- b,a,pt %xcc, 2f
- add %g2, 1, %g2
-1:
- std %l0, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
- std %l2, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
- std %l4, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
- std %l6, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x18]
-
- std %i0, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x20]
- std %i2, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
- std %i4, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x30]
- std %i6, [%g5 + AOFF_task_tss + AOFF_thread_reg_window + 0x38]
- add %g2, 1, %g2
-2:
- stx %g2, [%g1 + AOFF_task_tss + AOFF_thread_w_saved]
- rdpr %tstate, %g1
+ .globl winfix_mna, fill_fixup_mna, spill_fixup_mna
+winfix_mna:
+ andn %g3, 0x7f, %g3
+ add %g3, 0x78, %g3
+ wrpr %g3, %tnpc
+ done
+fill_fixup_mna:
+ rdpr %tstate, %g1
+ andcc %g1, TSTATE_PRIV, %g0
+ be,pt %xcc, window_mna_from_user_common
+ and %g1, TSTATE_CWP, %g1
+ rdpr %wstate, %g2 ! Grab user mode wstate.
+ wrpr %g1, %cwp ! Get into the right window.
+ sll %g2, 3, %g2 ! NORMAL-->OTHER
+ wrpr %g0, 0x0, %canrestore ! Standard etrap stuff.
+ wrpr %g2, 0x0, %wstate ! This must be consistant.
+ wrpr %g0, 0x0, %otherwin ! We know this.
+ sethi %uhi(KERNBASE), %g2 ! Set this up
+ sllx %g2, 32, %g2 ! for the iflush
+ mov PRIMARY_CONTEXT, %g1 ! Change contexts...
+ stxa %g0, [%g1] ASI_DMMU ! Back into the nucleus.
+ flush %g2 ! Flush instruction buffers
+ rdpr %pstate, %l1 ! Prepare to change globals.
+ mov %g4, %o5 ! Setup args for
+ mov %g5, %o4 ! final call to do_sparc64_fault.
+ wrpr %g0, 0x0, %tl ! Out of trap levels.
+ wrpr %l1, (PSTATE_IE | PSTATE_AG), %pstate
+ sethi %uhi(KERNBASE), %g4 ! Restore med-any global reg.
+ rd %pic, %g6 ! Get current as well.
+ b,pt %xcc, window_mna_merge ! And merge.
+ sllx %g4, 32, %g4 ! Finish med-any reg setup.
+spill_fixup_mna:
+ rd %pic, %g1
+ ldx [%g1 + AOFF_task_tss + AOFF_thread_flags], %g6
+ andcc %g6, SPARC_FLAG_32BIT, %g0
+ ldx [%g1 + AOFF_task_tss + AOFF_thread_w_saved], %g6
+ sll %g6, 3, %g3
+ add %g1, %g3, %g3
+ stx %sp, [%g3 + AOFF_task_tss + AOFF_thread_rwbuf_stkptrs]
+ sll %g6, 7, %g3
+
+ bne,pt %xcc, 1f
+ add %g1, %g3, %g3
+ stx %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
+ stx %l1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
+ stx %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
+ stx %l3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18]
+ stx %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20]
+ stx %l5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
+
+ stx %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30]
+ stx %l7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38]
+ stx %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x40]
+ stx %i1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x48]
+ stx %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x50]
+ stx %i3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x58]
+ stx %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x60]
+ stx %i5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x68]
+
+ stx %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x70]
+ stx %i7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x78]
+ b,pt %xcc, 2f
+ add %g6, 1, %g6
+1: std %l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
+ std %l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
+ std %l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
+ std %l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18]
+
+ std %i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20]
+ std %i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
+ std %i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30]
+ std %i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38]
+ add %g6, 1, %g6
+2: stx %g6, [%g1 + AOFF_task_tss + AOFF_thread_w_saved]
+ rdpr %tstate, %g1
nop
- andcc %g1, TSTATE_PRIV, %g0
- be,pn %xcc, fill_fixup
- saved
+ andcc %g1, TSTATE_PRIV, %g0
+ saved
+ be,pn %xcc, window_mna_from_user_common
+ and %g1, TSTATE_CWP, %g1
retry
+window_mna_from_user_common:
+ wrpr %g1, %cwp
+ ba,pt %xcc, etrap
+ rd %pc, %g7
+window_mna_merge:
+ call mem_address_unaligned
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
+ ba,pt %xcc, rtrap
+ clr %l6
+
diff --git a/arch/sparc64/lib/checksum.S b/arch/sparc64/lib/checksum.S
index b63f0d6e8..10eebb8df 100644
--- a/arch/sparc64/lib/checksum.S
+++ b/arch/sparc64/lib/checksum.S
@@ -71,8 +71,9 @@ csum_partial_end_cruft:
or %o5, %o4, %o4 ! coalese with hword (if any)
6: addcc %o4, %o2, %o2 ! add to sum
1: sllx %g4, 32, %g4 ! give gfp back
+ addc %g0, %o2, %o0 ! add final carry into retval
retl ! get outta here
- addc %g0, %o2, %o0 ! add final carry into retval
+ srl %o0, 0, %o0
/* Also do alignment out of band to get better cache patterns. */
csum_partial_fix_alignment:
@@ -82,7 +83,9 @@ csum_partial_fix_alignment:
*/
.globl csum_partial
csum_partial: /* %o0=buf, %o1=len, %o2=sum */
+ srl %o1, 0, %o1 ! doof scheiss
andcc %o0, 0x7, %g0 ! alignment problems?
+ srl %o2, 0, %o2
be,pt %icc, csum_partial_fix_aligned ! yep, handle it
andn %o1, 0x7f, %o3 ! num loop iterations
cmp %o1, 6
@@ -154,31 +157,31 @@ __csum_partial_copy_start:
99: ba,pt %xcc, 30f; \
a, b, %o3; \
.section __ex_table,z##alloc; \
- .align 4; \
- .word 98b, 99b; \
+ .align 8; \
+ .xword 98b, 99b; \
.text; \
.align 4
#define EX2(x,y,z) \
98: x,y; \
.section __ex_table,z##alloc; \
- .align 4; \
- .word 98b, 30f; \
+ .align 8; \
+ .xword 98b, 30f; \
.text; \
.align 4
#define EX3(x,y,z) \
98: x,y; \
.section __ex_table,z##alloc; \
- .align 4; \
- .word 98b, 96f; \
+ .align 8; \
+ .xword 98b, 96f; \
.text; \
.align 4
#define EXT(start,end,handler,z) \
.section __ex_table,z##alloc; \
- .align 4; \
- .word start, 0, end, handler; \
+ .align 8; \
+ .xword start, 0, end, handler; \
.text; \
.align 4
@@ -189,12 +192,12 @@ __csum_partial_copy_start:
* please check the fixup code below as well.
*/
#define CSUMCOPY_BIGCHUNK_ALIGNED(src, dst, sum, off, t0, t1, t2, t3, t4, t5, t6, t7) \
- ldd [src + off + 0x00], t0; \
- ldd [src + off + 0x08], t2; \
+ ldda [src + off + 0x00] %asi, t0; \
+ ldda [src + off + 0x08] %asi, t2; \
addccc t0, sum, sum; \
- ldd [src + off + 0x10], t4; \
+ ldda [src + off + 0x10] %asi, t4; \
addccc t1, sum, sum; \
- ldd [src + off + 0x18], t6; \
+ ldda [src + off + 0x18] %asi, t6; \
addccc t2, sum, sum; \
std t0, [dst + off + 0x00]; \
addccc t3, sum, sum; \
@@ -211,10 +214,10 @@ __csum_partial_copy_start:
* Viking MXCC into streaming mode. Ho hum...
*/
#define CSUMCOPY_BIGCHUNK(src, dst, sum, off, t0, t1, t2, t3, t4, t5, t6, t7) \
- ldd [src + off + 0x00], t0; \
- ldd [src + off + 0x08], t2; \
- ldd [src + off + 0x10], t4; \
- ldd [src + off + 0x18], t6; \
+ ldda [src + off + 0x00] %asi, t0; \
+ ldda [src + off + 0x08] %asi, t2; \
+ ldda [src + off + 0x10] %asi, t4; \
+ ldda [src + off + 0x18] %asi, t6; \
st t0, [dst + off + 0x00]; \
addccc t0, sum, sum; \
st t1, [dst + off + 0x04]; \
@@ -234,8 +237,8 @@ __csum_partial_copy_start:
/* Yuck, 6 superscalar cycles... */
#define CSUMCOPY_LASTCHUNK(src, dst, sum, off, t0, t1, t2, t3) \
- ldd [src - off - 0x08], t0; \
- ldd [src - off - 0x00], t2; \
+ ldda [src - off - 0x08] %asi, t0; \
+ ldda [src - off - 0x00] %asi, t2; \
addccc t0, sum, sum; \
st t0, [dst - off - 0x08]; \
addccc t1, sum, sum; \
@@ -250,7 +253,7 @@ cc_end_cruft:
andcc %o3, 8, %g0 ! begin checks for that code
be,pn %icc, 1f
and %o3, 4, %g5
- EX(ldd [%o0 + 0x00], %g2, and %o3, 0xf,#)
+ EX(ldda [%o0 + 0x00] %asi, %g2, and %o3, 0xf,#)
add %o1, 8, %o1
addcc %g2, %g7, %g7
add %o0, 8, %o0
@@ -260,7 +263,7 @@ cc_end_cruft:
EX2(st %g3, [%o1 - 0x04],#)
1: brz,pt %g5, 1f
andcc %o3, 3, %o3
- EX(ld [%o0 + 0x00], %g2, add %o3, 4,#)
+ EX(lda [%o0 + 0x00] %asi, %g2, add %o3, 4,#)
add %o1, 4, %o1
addcc %g2, %g7, %g7
EX2(st %g2, [%o1 - 0x04],#)
@@ -272,20 +275,21 @@ cc_end_cruft:
subcc %o3, 2, %o3
ba,pt %xcc, 4f
clr %o4
-2: EX(lduh [%o0 + 0x00], %o4, add %o3, 2,#)
+2: EX(lduha [%o0 + 0x00] %asi, %o4, add %o3, 2,#)
add %o0, 2, %o0
EX2(sth %o4, [%o1 + 0x00],#)
be,pn %icc, 6f
add %o1, 2, %o1
sll %o4, 16, %o4
-4: EX(ldub [%o0 + 0x00], %o5, add %g0, 1,#)
+4: EX(lduba [%o0 + 0x00] %asi, %o5, add %g0, 1,#)
EX2(stb %o5, [%o1 + 0x00],#)
sll %o5, 8, %o5
or %o5, %o4, %o4
6: addcc %o4, %g7, %g7
1: sllx %g4, 32, %g4
+ addc %g0, %g7, %o0
retl
- addc %g0, %g7, %o0
+ srl %o0, 0, %o0
/* Sun, you just can't beat me, you just can't. Stop trying,
* give up. I'm serious, I am going to kick the living shit
@@ -295,7 +299,9 @@ cc_end_cruft:
.globl __csum_partial_copy_sparc_generic
__csum_partial_copy_sparc_generic:
/* %o0=src, %o1=dest, %g1=len, %g7=sum */
+ srl %g7, 0, %g7 ! you neve know...
xor %o0, %o1, %o4 ! get changing bits
+ srl %g1, 0, %g1 ! doof scheiss
andcc %o4, 3, %g0 ! check for mismatched alignment
bne,pn %icc, ccslow ! better this than unaligned/fixups
andcc %o0, 7, %g0 ! need to align things?
@@ -309,7 +315,7 @@ __csum_partial_copy_sparc_generic:
andcc %o0, 0x2, %g0
be,pn %icc, 1f
andcc %o0, 0x4, %g0
- EX(lduh [%o0 + 0x00], %g4, add %g1, 0,#)
+ EX(lduha [%o0 + 0x00] %asi, %g4, add %g1, 0,#)
sub %g1, 2, %g1
EX2(sth %g4, [%o1 + 0x00],#)
add %o0, 2, %o0
@@ -325,7 +331,7 @@ __csum_partial_copy_sparc_generic:
or %g3, %g7, %g7
1: be,pt %icc, 3f
andn %g1, 0x7f, %g2
- EX(ld [%o0 + 0x00], %g4, add %g1, 0,#)
+ EX(lda [%o0 + 0x00] %asi, %g4, add %g1, 0,#)
sub %g1, 4, %g1
EX2(st %g4, [%o1 + 0x00],#)
add %o0, 4, %o0
@@ -372,8 +378,9 @@ cctbl: CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x68,%g2,%g3,%g4,%g5)
ccte: bne,pn %icc, cc_end_cruft ! something left, handle it out of band
sethi %uhi(KERNBASE), %g4 ! restore gfp
mov %g7, %o0 ! give em the computed checksum
+ sllx %g4, 32, %g4 ! finish gfp restoration
retl ! return
- sllx %g4, 32, %g4 ! finish gfp restoration
+ srl %o0, 0, %o0
ccdbl: CSUMCOPY_BIGCHUNK_ALIGNED(%o0,%o1,%g7,0x00,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
CSUMCOPY_BIGCHUNK_ALIGNED(%o0,%o1,%g7,0x20,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
CSUMCOPY_BIGCHUNK_ALIGNED(%o0,%o1,%g7,0x40,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3)
@@ -394,7 +401,7 @@ ccslow: mov 0, %g5
be,a,pt %icc, 1f
srl %g1, 1, %o3
sub %g1, 1, %g1
- EX(ldub [%o0], %g5, add %g1, 1,#)
+ EX(lduba [%o0] %asi, %g5, add %g1, 1,#)
add %o0, 1, %o0
EX2(stb %g5, [%o1],#)
srl %g1, 1, %o3
@@ -404,7 +411,7 @@ ccslow: mov 0, %g5
andcc %o0, 2, %g0
be,a,pt %icc, 1f
srl %o3, 1, %o3
- EX(lduh [%o0], %o4, add %g1, 0,#)
+ EX(lduha [%o0] %asi, %o4, add %g1, 0,#)
sub %g1, 2, %g1
srl %o4, 8, %g2
sub %o3, 1, %o3
@@ -416,7 +423,7 @@ ccslow: mov 0, %g5
add %o1, 2, %o1
1: brz,a,pn %o3, 2f
andcc %g1, 2, %g0
- EX3(ld [%o0], %o4,#)
+ EX3(lda [%o0] %asi, %o4,#)
5: srl %o4, 24, %g2
srl %o4, 16, %g3
EX2(stb %g2, [%o1],#)
@@ -430,7 +437,7 @@ ccslow: mov 0, %g5
add %o1, 4, %o1 ! is worthy). Maybe some day - with the sll/srl
subcc %o3, 1, %o3 ! tricks
bne,a,pt %icc, 5b
- EX3(ld [%o0], %o4,#)
+ EX3(lda [%o0] %asi, %o4,#)
sll %g5, 16, %g2
srl %g5, 16, %g5
srl %g2, 16, %g2
@@ -438,7 +445,7 @@ ccslow: mov 0, %g5
add %g2, %g5, %g5
2: be,a,pt %icc, 3f
andcc %g1, 1, %g0
- EX(lduh [%o0], %o4, and %g1, 3,#)
+ EX(lduha [%o0] %asi, %o4, and %g1, 3,#)
andcc %g1, 1, %g0
srl %o4, 8, %g2
add %o0, 2, %o0
@@ -448,7 +455,7 @@ ccslow: mov 0, %g5
add %o1, 2, %o1
3: be,a,pt %icc, 1f
sll %g5, 16, %o4
- EX(ldub [%o0], %g2, add %g0, 1,#)
+ EX(lduba [%o0] %asi, %g2, add %g0, 1,#)
sll %g2, 8, %o4
EX2(stb %g2, [%o1],#)
add %g5, %o4, %g5
@@ -463,8 +470,9 @@ ccslow: mov 0, %g5
sll %g2, 8, %g2
or %g2, %o4, %g5
4: addcc %g7, %g5, %g7
+ addc %g0, %g7, %o0
retl
- addc %g0, %g7, %o0
+ srl %o0, 0, %o0
__csum_partial_copy_end:
.section .fixup,#alloc,#execinstr
diff --git a/arch/sparc64/lib/copy_from_user.S b/arch/sparc64/lib/copy_from_user.S
index 50ec7bb3d..196435aed 100644
--- a/arch/sparc64/lib/copy_from_user.S
+++ b/arch/sparc64/lib/copy_from_user.S
@@ -27,8 +27,8 @@
retl; \
a, b, %o0; \
.section __ex_table,z##alloc; \
- .align 4; \
- .word 98b, 99b; \
+ .align 8; \
+ .xword 98b, 99b; \
.text; \
.align 4
@@ -41,23 +41,23 @@
retl; \
a, b, %o0; \
.section __ex_table,z##alloc; \
- .align 4; \
- .word 98b, 99b; \
+ .align 8; \
+ .xword 98b, 99b; \
.text; \
.align 4
#define EXO2(x,y,z) \
98: x,##y; \
.section __ex_table,z##alloc; \
- .align 4; \
- .word 98b, 97f; \
+ .align 8; \
+ .xword 98b, 97f; \
.text; \
.align 4
#define EXT(start,end,handler,z) \
.section __ex_table,z##alloc; \
- .align 4; \
- .word start, 0, end, handler; \
+ .align 8; \
+ .xword start, 0, end, handler; \
.text; \
.align 4
diff --git a/arch/sparc64/lib/copy_to_user.S b/arch/sparc64/lib/copy_to_user.S
index 733953743..cc6db141f 100644
--- a/arch/sparc64/lib/copy_to_user.S
+++ b/arch/sparc64/lib/copy_to_user.S
@@ -27,8 +27,8 @@
retl; \
a, b, %o0; \
.section __ex_table,z##alloc; \
- .align 4; \
- .word 98b, 99b; \
+ .align 8; \
+ .xword 98b, 99b; \
.text; \
.align 4
@@ -41,23 +41,23 @@
retl; \
a, b, %o0; \
.section __ex_table,z##alloc; \
- .align 4; \
- .word 98b, 99b; \
+ .align 8; \
+ .xword 98b, 99b; \
.text; \
.align 4
#define EXO2(x,y,z) \
98: x,##y; \
.section __ex_table,z##alloc; \
- .align 4; \
- .word 98b, 97f; \
+ .align 8; \
+ .xword 98b, 97f; \
.text; \
.align 4
#define EXT(start,end,handler,z) \
.section __ex_table,z##alloc; \
- .align 4; \
- .word start, 0, end, handler; \
+ .align 8; \
+ .xword start, 0, end, handler; \
.text; \
.align 4
diff --git a/arch/sparc64/lib/memset.S b/arch/sparc64/lib/memset.S
index 55de4ea9d..713c78ca8 100644
--- a/arch/sparc64/lib/memset.S
+++ b/arch/sparc64/lib/memset.S
@@ -17,15 +17,15 @@
99: ba,pt %xcc, 30f; \
a, b, %o0; \
.section __ex_table,z##alloc; \
- .align 4; \
- .word 98b, 99b; \
+ .align 8; \
+ .xword 98b, 99b; \
.text; \
.align 4
#define EXT(start,end,handler,z) \
.section __ex_table,z##alloc; \
- .align 4; \
- .word start, 0, end, handler; \
+ .align 8; \
+ .xword start, 0, end, handler; \
.text; \
.align 4
diff --git a/arch/sparc64/lib/strlen_user.S b/arch/sparc64/lib/strlen_user.S
index 30beee3ff..4d57aed64 100644
--- a/arch/sparc64/lib/strlen_user.S
+++ b/arch/sparc64/lib/strlen_user.S
@@ -92,10 +92,10 @@ __strlen_user:
clr %o0
.section __ex_table,#alloc
- .align 4
+ .align 8
- .word 10b, 30b
- .word 11b, 30b
- .word 12b, 30b
- .word 13b, 30b
- .word 14b, 30b
+ .xword 10b, 30b
+ .xword 11b, 30b
+ .xword 12b, 30b
+ .xword 13b, 30b
+ .xword 14b, 30b
diff --git a/arch/sparc64/lib/strncpy_from_user.S b/arch/sparc64/lib/strncpy_from_user.S
index e0fb0f09b..7a5dc768f 100644
--- a/arch/sparc64/lib/strncpy_from_user.S
+++ b/arch/sparc64/lib/strncpy_from_user.S
@@ -49,6 +49,6 @@ __strncpy_from_user:
mov -EFAULT, %o0
.section __ex_table,#alloc
- .align 4
- .word 10b, 4b
- .word 11b, 4b
+ .align 8
+ .xword 10b, 4b
+ .xword 11b, 4b
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index e23e736a9..6df923a4b 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.9 1997/05/19 05:58:54 davem Exp $
+/* $Id: fault.c,v 1.11 1997/06/01 05:46:15 davem Exp $
* arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -135,6 +135,7 @@ asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc,
}
/* #define FAULT_TRACER */
+/* #define FAULT_TRACER_VERBOSE */
asmlinkage void do_sparc64_fault(struct pt_regs *regs, int text_fault, int write,
unsigned long address, unsigned long tag,
@@ -150,12 +151,23 @@ asmlinkage void do_sparc64_fault(struct pt_regs *regs, int text_fault, int write
static unsigned long last_addr = 0;
static int rcnt = 0;
- printk("FAULT(PC[%016lx],t[%d],w[%d],addr[%016lx])\n",
+#ifdef FAULT_TRACER_VERBOSE
+ printk("FAULT(PC[%016lx],t[%d],w[%d],addr[%016lx])...",
regs->tpc, text_fault, write, address);
- if(address == last_addr && rcnt++ > 5) {
- printk("Wheee lotsa bogus faults, something wrong, spinning\n");
- while(1)
- barrier();
+#else
+ printk("F[%016lx:%016lx:w(%d)", regs->tpc, address, write);
+#endif
+ if(address == last_addr) {
+ if(rcnt++ > 15) {
+ printk("Wheee lotsa bogus faults, something wrong, spinning\n");
+ __asm__ __volatile__("flushw");
+ printk("o7[%016lx] i7[%016lx]\n",
+ regs->u_regs[UREG_I7],
+ ((struct reg_window *)(regs->u_regs[UREG_FP]+STACK_BIAS))->ins[7]);
+ sti();
+ while(1)
+ barrier();
+ }
} else rcnt = 0;
last_addr = address;
#endif
@@ -205,6 +217,13 @@ bad_area:
goto out;
}
if(from_user) {
+#if 1
+ unsigned long cpc;
+ __asm__ __volatile__("mov %%i7, %0" : "=r" (cpc));
+ printk("[%s:%d] SIGSEGV pc[%016lx] addr[%016lx] w[%d] sfsr[%016lx] "
+ "caller[%016lx]\n", current->comm, current->pid, regs->tpc,
+ address, write, sfsr, cpc);
+#endif
tsk->tss.sig_address = address;
tsk->tss.sig_desc = SUBSIG_NOMAPPING;
send_sig(SIGSEGV, tsk, 1);
@@ -213,4 +232,12 @@ bad_area:
unhandled_fault (address, tsk, regs);
out:
unlock_kernel();
+#ifdef FAULT_TRACER
+#ifdef FAULT_TRACER_VERBOSE
+ printk(" done\n");
+#else
+ printk("]");
+#endif
+#endif
}
+
diff --git a/arch/sparc64/vmlinux.lds b/arch/sparc64/vmlinux.lds
index f8ba23528..d2d0cac34 100644
--- a/arch/sparc64/vmlinux.lds
+++ b/arch/sparc64/vmlinux.lds
@@ -26,6 +26,7 @@ SECTIONS
_edata = .;
PROVIDE (edata = .);
.fixup : { *(.fixup) }
+ . = ALIGN(16);
__start___ex_table = .;
__ex_table : { *(__ex_table) }
__stop___ex_table = .;