summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-09-28 22:25:29 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-09-28 22:25:29 +0000
commit0ae8dceaebe3659ee0c3352c08125f403e77ebca (patch)
tree5085c389f09da78182b899d19fe1068b619a69dd /arch/sparc64/kernel
parent273767781288c35c9d679e908672b9996cda4c34 (diff)
Merge with 2.3.10.
Diffstat (limited to 'arch/sparc64/kernel')
-rw-r--r--arch/sparc64/kernel/binfmt_aout32.c5
-rw-r--r--arch/sparc64/kernel/ioctl32.c6
-rw-r--r--arch/sparc64/kernel/psycho.c14
-rw-r--r--arch/sparc64/kernel/ptrace.c596
-rw-r--r--arch/sparc64/kernel/smp.c2
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c13
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c8
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c3
8 files changed, 86 insertions, 561 deletions
diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
index 7d638c5da..bc77266f9 100644
--- a/arch/sparc64/kernel/binfmt_aout32.c
+++ b/arch/sparc64/kernel/binfmt_aout32.c
@@ -311,9 +311,10 @@ static inline int do_load_aout32_binary(struct linux_binprm * bprm,
fd = open_dentry(bprm->dentry, O_RDONLY);
if (fd < 0)
return fd;
- file = fcheck(fd);
+ file = fget(fd);
if (!file->f_op || !file->f_op->mmap) {
+ fput(fd);
sys_close(fd);
do_brk(0, ex.a_text+ex.a_data);
read_exec(bprm->dentry, fd_offset,
@@ -327,6 +328,7 @@ static inline int do_load_aout32_binary(struct linux_binprm * bprm,
fd_offset);
if (error != N_TXTADDR(ex)) {
+ fput(file);
sys_close(fd);
send_sig(SIGKILL, current, 0);
return error;
@@ -336,6 +338,7 @@ static inline int do_load_aout32_binary(struct linux_binprm * bprm,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
fd_offset + ex.a_text);
+ fput(file);
sys_close(fd);
if (error != N_DATADDR(ex)) {
send_sig(SIGKILL, current, 0);
diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
index 6759f74d4..833331202 100644
--- a/arch/sparc64/kernel/ioctl32.c
+++ b/arch/sparc64/kernel/ioctl32.c
@@ -1696,9 +1696,9 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
int error = -EBADF;
lock_kernel();
- filp = fcheck(fd);
+ filp = fget(fd);
if(!filp)
- goto out;
+ goto out2;
if (!filp->f_op || !filp->f_op->ioctl) {
error = sys_ioctl (fd, cmd, arg);
@@ -2381,6 +2381,8 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
break;
}
out:
+ fput(filp);
+out2:
unlock_kernel();
return error;
}
diff --git a/arch/sparc64/kernel/psycho.c b/arch/sparc64/kernel/psycho.c
index 7df9a5882..392ddab55 100644
--- a/arch/sparc64/kernel/psycho.c
+++ b/arch/sparc64/kernel/psycho.c
@@ -1,4 +1,4 @@
-/* $Id: psycho.c,v 1.85 1999/04/02 14:54:28 davem Exp $
+/* $Id: psycho.c,v 1.86 1999/07/01 10:39:43 davem Exp $
* psycho.c: Ultra/AX U2P PCI controller support.
*
* Copyright (C) 1997 David S. Miller (davem@caipfs.rutgers.edu)
@@ -68,7 +68,6 @@ asmlinkage int sys_pciconfig_write(unsigned long bus,
#include <linux/smp_lock.h>
#include <linux/pci.h>
-#include <asm/io.h>
#include <asm/oplib.h>
#include <asm/pbm.h>
#include <asm/apb.h>
@@ -757,13 +756,15 @@ static void __init apb_init(struct linux_psycho *sabre)
unsigned short stmp;
unsigned int itmp;
+#if 0
for(pdev = pci_devices; pdev; pdev = pdev->next) {
if(pdev->vendor == PCI_VENDOR_ID_SUN &&
pdev->device == PCI_DEVICE_ID_SUN_SABRE) {
- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 128);
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
break;
}
}
+#endif
for (pdev = sabre->pci_bus->devices; pdev; pdev = pdev->sibling) {
if (pdev->vendor == PCI_VENDOR_ID_SUN &&
pdev->device == PCI_DEVICE_ID_SUN_SIMBA) {
@@ -795,13 +796,14 @@ static void __init apb_init(struct linux_psycho *sabre)
pci_read_config_dword(pdev, APB_PCI_CONTROL_LOW, &itmp);
itmp = APB_PCI_CTL_LOW_ERRINT_EN | 0x0f;
pci_write_config_dword(pdev, APB_PCI_CONTROL_LOW, itmp);
-
+#if 0
/* Don't mess with the retry limit and PIO/DMA latency
* timer settings. But do set primary and secondary
* latency timers.
*/
- pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 128);
- pci_write_config_byte(pdev, PCI_SEC_LATENCY_TIMER, 128);
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
+ pci_write_config_byte(pdev, PCI_SEC_LATENCY_TIMER, 64);
+#endif
}
}
}
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
index 476d53558..61a6a6bfa 100644
--- a/arch/sparc64/kernel/ptrace.c
+++ b/arch/sparc64/kernel/ptrace.c
@@ -28,242 +28,6 @@
#define MAGIC_CONSTANT 0x80000000
-/*
- * This routine gets a long from any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- */
-static pte_t *ptrace_get_page(struct task_struct * tsk,
- struct vm_area_struct * vma, unsigned long addr, int write)
-{
- pgd_t * pgdir;
- pmd_t * pgmiddle;
- pte_t * pgtable;
-
-repeat:
- pgdir = pgd_offset(vma->vm_mm, addr);
-
- /* Seems non-intuitive but the page copy/clear routines always
- * check current's value.
- */
- current->mm->segments = (void *) (addr & PAGE_SIZE);
-
- if (pgd_none(*pgdir)) {
- handle_mm_fault(tsk, vma, addr, write);
- goto repeat;
- }
- if (pgd_bad(*pgdir)) {
- printk("ptrace: bad page directory %016lx\n", pgd_val(*pgdir));
- pgd_clear(pgdir);
- return 0;
- }
- pgmiddle = pmd_offset(pgdir, addr);
- if (pmd_none(*pgmiddle)) {
- handle_mm_fault(tsk, vma, addr, write);
- goto repeat;
- }
- if (pmd_bad(*pgmiddle)) {
- printk("ptrace: bad page middle %016lx\n", pmd_val(*pgmiddle));
- pmd_clear(pgmiddle);
- return 0;
- }
- pgtable = pte_offset(pgmiddle, addr);
- if (!pte_present(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, write);
- goto repeat;
- }
- if (write && !pte_write(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, write);
- goto repeat;
- }
- return pgtable;
-}
-
-/* We must bypass the L1-cache to avoid alias issues. -DaveM */
-static __inline__ unsigned long read_user_long(unsigned long kvaddr)
-{
- unsigned long ret;
-
- __asm__ __volatile__("ldxa [%1] %2, %0"
- : "=r" (ret)
- : "r" (__pa(kvaddr)), "i" (ASI_PHYS_USE_EC));
- return ret;
-}
-
-static __inline__ unsigned int read_user_int(unsigned long kvaddr)
-{
- unsigned int ret;
-
- __asm__ __volatile__("lduwa [%1] %2, %0"
- : "=r" (ret)
- : "r" (__pa(kvaddr)), "i" (ASI_PHYS_USE_EC));
- return ret;
-}
-
-static __inline__ void write_user_long(unsigned long kvaddr, unsigned long val)
-{
- __asm__ __volatile__("stxa %0, [%1] %2"
- : /* no outputs */
- : "r" (val), "r" (__pa(kvaddr)), "i" (ASI_PHYS_USE_EC));
-}
-
-static __inline__ void write_user_int(unsigned long kvaddr, unsigned int val)
-{
- __asm__ __volatile__("stwa %0, [%1] %2"
- : /* no outputs */
- : "r" (val), "r" (__pa(kvaddr)), "i" (ASI_PHYS_USE_EC));
-}
-
-static inline unsigned long get_long(struct task_struct * tsk,
- struct vm_area_struct * vma, unsigned long addr)
-{
- pte_t * pgtable;
- unsigned long page, retval;
-
- if (!(pgtable = ptrace_get_page (tsk, vma, addr, 0))) return 0;
- page = pte_page(*pgtable);
-/* this is a hack for non-kernel-mapped video buffers and similar */
- if (MAP_NR(page) >= max_mapnr)
- return 0;
- page += addr & ~PAGE_MASK;
- retval = read_user_long(page);
- flush_page_to_ram(page);
- return retval;
-}
-
-static inline void put_long(struct task_struct * tsk, struct vm_area_struct * vma,
- unsigned long addr, unsigned long data)
-{
- pte_t *pgtable;
- unsigned long page;
-
- if (!(pgtable = ptrace_get_page (tsk, vma, addr, 1))) return;
- page = pte_page(*pgtable);
-/* this is a hack for non-kernel-mapped video buffers and similar */
- flush_cache_page(vma, addr);
- if (MAP_NR(page) < max_mapnr) {
- unsigned long pgaddr;
-
- pgaddr = page + (addr & ~PAGE_MASK);
- write_user_long(pgaddr, data);
-
- __asm__ __volatile__("
- membar #StoreStore
- flush %0
-" : : "r" (pgaddr & ~7) : "memory");
- }
-/* we're bypassing pagetables, so we have to set the dirty bit ourselves */
-/* this should also re-instate whatever read-only mode there was before */
- set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
- flush_tlb_page(vma, addr);
-}
-
-static inline unsigned int get_int(struct task_struct * tsk,
- struct vm_area_struct * vma, unsigned long addr)
-{
- pte_t * pgtable;
- unsigned long page;
- unsigned int retval;
-
- if (!(pgtable = ptrace_get_page (tsk, vma, addr, 0))) return 0;
- page = pte_page(*pgtable);
-/* this is a hack for non-kernel-mapped video buffers and similar */
- if (MAP_NR(page) >= max_mapnr)
- return 0;
- page += addr & ~PAGE_MASK;
- retval = read_user_int(page);
- flush_page_to_ram(page);
- return retval;
-}
-
-static inline void put_int(struct task_struct * tsk, struct vm_area_struct * vma,
- unsigned long addr, unsigned int data)
-{
- pte_t *pgtable;
- unsigned long page;
-
- if (!(pgtable = ptrace_get_page (tsk, vma, addr, 1))) return;
- page = pte_page(*pgtable);
-/* this is a hack for non-kernel-mapped video buffers and similar */
- flush_cache_page(vma, addr);
- if (MAP_NR(page) < max_mapnr) {
- unsigned long pgaddr;
-
- pgaddr = page + (addr & ~PAGE_MASK);
- write_user_int(pgaddr, data);
-
- __asm__ __volatile__("
- membar #StoreStore
- flush %0
-" : : "r" (pgaddr & ~7) : "memory");
- }
-/* we're bypassing pagetables, so we have to set the dirty bit ourselves */
-/* this should also re-instate whatever read-only mode there was before */
- set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
- flush_tlb_page(vma, addr);
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls get_long() to read a long.
- */
-static int read_long(struct task_struct * tsk, unsigned long addr,
- unsigned long * result)
-{
- struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
- if (!vma)
- return -EIO;
- *result = get_long(tsk, vma, addr);
- return 0;
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls get_int() to read a int.
- */
-static int read_int(struct task_struct * tsk, unsigned long addr,
- unsigned int * result)
-{
- struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
- if (!vma)
- return -EIO;
- *result = get_int(tsk, vma, addr);
- return 0;
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls put_long() to write a long.
- */
-static int write_long(struct task_struct * tsk, unsigned long addr,
- unsigned long data)
-{
- struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
- if (!vma)
- return -EIO;
- put_long(tsk, vma, addr, data);
- return 0;
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls put_int() to write a int.
- */
-static int write_int(struct task_struct * tsk, unsigned long addr,
- unsigned int data)
-{
- struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
- if (!vma)
- return -EIO;
- put_int(tsk, vma, addr, data);
- return 0;
-}
-
/* Returning from ptrace is a bit tricky because the syscall return
* low level code assumes any value returned which is negative and
* is a valid errno will mean setting the condition codes to indicate
@@ -310,175 +74,6 @@ pt_os_succ_return (struct pt_regs *regs, unsigned long val, long *addr)
pt_succ_return_linux (regs, val, addr);
}
-#if 0
-/* XXX: Implement this some day */
-/* Fuck me gently with a chainsaw... */
-static inline void read_sunos_user(struct pt_regs *regs, unsigned long offset,
- struct task_struct *tsk, long *addr)
-{
- struct pt_regs *cregs = tsk->tss.kregs;
- struct thread_struct *t = &tsk->tss;
- int v;
-
- if(offset >= 1024)
- offset -= 1024; /* whee... */
- if(offset & ((sizeof(unsigned int) - 1))) {
- pt_error_return(regs, EIO);
- return;
- }
- if(offset >= 16 && offset < 784) {
- offset -= 16; offset >>= 2;
- if (t->w_saved)
- pt_os_succ_return(regs, *(((unsigned long *)(&t->reg_window[0]))+offset), addr);
- return;
- }
- if(offset >= 784 && offset < 832) {
- offset -= 784; offset >>= 2;
- if (t->w_saved)
- pt_os_succ_return(regs, *(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset), addr);
- return;
- }
- switch(offset) {
- case 0:
- v = t->ksp;
- break;
-#if 0
- case 4:
- v = t->kpc;
- break;
-#endif
- case 8:
- v = t->kpsr;
- break;
- case 12:
- v = t->uwinmask;
- break;
- case 832:
- v = t->w_saved;
- break;
- case 896:
- v = cregs->u_regs[UREG_I0];
- break;
- case 900:
- v = cregs->u_regs[UREG_I1];
- break;
- case 904:
- v = cregs->u_regs[UREG_I2];
- break;
- case 908:
- v = cregs->u_regs[UREG_I3];
- break;
- case 912:
- v = cregs->u_regs[UREG_I4];
- break;
- case 916:
- v = cregs->u_regs[UREG_I5];
- break;
- case 920:
- v = cregs->u_regs[UREG_I6];
- break;
- case 924:
- if(tsk->tss.flags & MAGIC_CONSTANT)
- v = cregs->u_regs[UREG_G1];
- else
- v = 0;
- break;
- case 940:
- v = cregs->u_regs[UREG_I0];
- break;
- case 944:
- v = cregs->u_regs[UREG_I1];
- break;
-
- case 948:
- /* Isn't binary compatibility _fun_??? */
- if(cregs->psr & PSR_C)
- v = cregs->u_regs[UREG_I0] << 24;
- else
- v = 0;
- break;
-
- /* Rest of them are completely unsupported. */
- default:
- printk("%s [%d]: Wants to read user offset %ld\n",
- current->comm, current->pid, offset);
- pt_error_return(regs, EIO);
- return;
- }
- pt_os_succ_return_linux (regs, v, addr);
- return;
-}
-
-static inline void write_sunos_user(struct pt_regs *regs, unsigned long offset,
- struct task_struct *tsk)
-{
- struct pt_regs *cregs = tsk->tss.kregs;
- struct thread_struct *t = &tsk->tss;
- unsigned int value = regs->u_regs[UREG_I3];
-
- if(offset >= 1024)
- offset -= 1024; /* whee... */
- if(offset & ((sizeof(unsigned long) - 1)))
- goto failure;
- if(offset >= 16 && offset < 784) {
- offset -= 16; offset >>= 2;
- if (t->w_saved)
- *(((unsigned long *)(&t->reg_window[0]))+offset) = value;
- goto success;
- }
- if(offset >= 784 && offset < 832) {
- offset -= 784; offset >>= 2;
- if (t->w_saved)
- *(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset) = value;
- goto success;
- }
- switch(offset) {
- case 896:
- cregs->u_regs[UREG_I0] = value;
- break;
- case 900:
- cregs->u_regs[UREG_I1] = value;
- break;
- case 904:
- cregs->u_regs[UREG_I2] = value;
- break;
- case 908:
- cregs->u_regs[UREG_I3] = value;
- break;
- case 912:
- cregs->u_regs[UREG_I4] = value;
- break;
- case 916:
- cregs->u_regs[UREG_I5] = value;
- break;
- case 920:
- cregs->u_regs[UREG_I6] = value;
- break;
- case 924:
- cregs->u_regs[UREG_I7] = value;
- break;
- case 940:
- cregs->u_regs[UREG_I0] = value;
- break;
- case 944:
- cregs->u_regs[UREG_I1] = value;
- break;
-
- /* Rest of them are completely unsupported or "no-touch". */
- default:
- printk("%s [%d]: Wants to write user offset %ld\n",
- current->comm, current->pid, offset);
- goto failure;
- }
-success:
- pt_succ_return(regs, 0);
- return;
-failure:
- pt_error_return(regs, EIO);
- return;
-}
-#endif
-
/* #define ALLOW_INIT_TRACING */
/* #define DEBUG_PTRACE */
@@ -642,76 +237,54 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
switch(request) {
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: {
- unsigned long tmp;
- int res;
+ unsigned long tmp64;
+ unsigned int tmp32;
+ int res, copied;
- /* Non-word alignment _not_ allowed on Sparc. */
+ res = -EIO;
if (current->tss.flags & SPARC_FLAG_32BIT) {
- unsigned int x;
- if(addr & (sizeof(unsigned int) - 1)) {
- pt_error_return(regs, EINVAL);
- goto out;
- }
- down(&child->mm->mmap_sem);
- res = read_int(child, addr, &x);
- up(&child->mm->mmap_sem);
- tmp = x;
+ copied = access_process_vm(child, addr,
+ &tmp32, sizeof(tmp32), 0);
+ tmp64 = (unsigned long) tmp32;
+ if (copied == sizeof(tmp32))
+ res = 0;
} else {
- if(addr & (sizeof(unsigned long) - 1)) {
- pt_error_return(regs, EINVAL);
- goto out;
- }
- down(&child->mm->mmap_sem);
- res = read_long(child, addr, &tmp);
- up(&child->mm->mmap_sem);
+ copied = access_process_vm(child, addr,
+ &tmp64, sizeof(tmp64), 0);
+ if (copied == sizeof(tmp64))
+ res = 0;
}
- if (res < 0) {
+ if (res < 0)
pt_error_return(regs, -res);
- goto out;
- }
- pt_os_succ_return(regs, tmp, (long *) data);
- goto out;
+ else
+ pt_os_succ_return(regs, tmp64, (long *) data);
+ goto flush_and_out;
}
- case PTRACE_PEEKUSR:
-#if 0
- read_sunos_user(regs, addr, child, (long *) data);
-#endif
- goto out;
-
- case PTRACE_POKEUSR:
-#if 0
- write_sunos_user(regs, addr, child);
-#endif
- goto out;
-
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA: {
- int res;
+ unsigned long tmp64;
+ unsigned int tmp32;
+ int copied, res = -EIO;
- /* Non-word alignment _not_ allowed on Sparc. */
if (current->tss.flags & SPARC_FLAG_32BIT) {
- if(addr & (sizeof(unsigned int) - 1)) {
- pt_error_return(regs, EINVAL);
- goto out;
- }
- down(&child->mm->mmap_sem);
- res = write_int(child, addr, data);
- up(&child->mm->mmap_sem);
+ tmp32 = data;
+ copied = access_process_vm(child, addr,
+ &tmp32, sizeof(tmp32), 1);
+ if (copied == sizeof(tmp32))
+ res = 0;
} else {
- if(addr & (sizeof(unsigned long) - 1)) {
- pt_error_return(regs, EINVAL);
- goto out;
- }
- down(&child->mm->mmap_sem);
- res = write_long(child, addr, data);
- up(&child->mm->mmap_sem);
+ tmp64 = data;
+ copied = access_process_vm(child, addr,
+ &tmp64, sizeof(tmp64), 1);
+ if (copied == sizeof(tmp64))
+ res = 0;
}
if(res < 0)
pt_error_return(regs, -res);
else
pt_succ_return(regs, res);
- goto out;
+ goto flush_and_out;
}
case PTRACE_GETREGS: {
@@ -926,98 +499,31 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
case PTRACE_READTEXT:
case PTRACE_READDATA: {
- unsigned char *dest = (unsigned char *) addr2;
- unsigned long src = addr;
- int len = data, curlen;
- struct vm_area_struct *vma;
- pte_t *pgtable;
- unsigned long page;
-
- while(len) {
- down(&child->mm->mmap_sem);
- vma = find_extend_vma(child, src);
- if (!vma) {
- up(&child->mm->mmap_sem);
- pt_error_return(regs, EIO);
- goto flush_and_out;
- }
- pgtable = ptrace_get_page (child, vma, src, 0);
- up(&child->mm->mmap_sem);
- if (src & ~PAGE_MASK) {
- curlen = PAGE_SIZE - (src & ~PAGE_MASK);
- if (curlen > len) curlen = len;
- } else if (len > PAGE_SIZE)
- curlen = PAGE_SIZE;
- else
- curlen = len;
- if (pgtable && MAP_NR(page = pte_page(*pgtable)) < max_mapnr) {
- if (copy_to_user (dest, ((char *)page) + (src & ~PAGE_MASK), curlen)) {
- flush_page_to_ram(page);
- pt_error_return(regs, EFAULT);
- goto flush_and_out;
- }
- flush_page_to_ram(page);
- } else {
- if (clear_user (dest, curlen)) {
- pt_error_return(regs, EFAULT);
- goto flush_and_out;
- }
- }
- src += curlen;
- dest += curlen;
- len -= curlen;
+ int res = ptrace_readdata(child, addr,
+ (void *)addr2, data);
+ if (res == data) {
+ pt_succ_return(regs, 0);
+ goto flush_and_out;
}
- pt_succ_return(regs, 0);
+ if (res >= 0)
+ res = -EIO;
+ pt_error_return(regs, -res);
goto flush_and_out;
}
case PTRACE_WRITETEXT:
case PTRACE_WRITEDATA: {
- unsigned char *src = (unsigned char *) addr2;
- unsigned long dest = addr;
- int len = data, curlen;
- struct vm_area_struct *vma;
- pte_t *pgtable;
- unsigned long page;
-
- while(len) {
- down(&child->mm->mmap_sem);
- vma = find_extend_vma(child, dest);
- if (!vma) {
- up(&child->mm->mmap_sem);
- pt_error_return(regs, EIO);
- goto flush_and_out;
- }
- pgtable = ptrace_get_page (child, vma, dest, 1);
- up(&child->mm->mmap_sem);
- if (dest & ~PAGE_MASK) {
- curlen = PAGE_SIZE - (dest & ~PAGE_MASK);
- if (curlen > len) curlen = len;
- } else if (len > PAGE_SIZE)
- curlen = PAGE_SIZE;
- else
- curlen = len;
- if (pgtable && MAP_NR(page = pte_page(*pgtable)) < max_mapnr) {
- flush_cache_page(vma, dest);
- if (copy_from_user (((char *)page) + (dest & ~PAGE_MASK), src, curlen)) {
- flush_page_to_ram(page);
- set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
- flush_tlb_page(vma, dest);
- pt_error_return(regs, EFAULT);
- goto flush_and_out;
- }
- flush_page_to_ram(page);
- set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
- flush_tlb_page(vma, dest);
- }
- src += curlen;
- dest += curlen;
- len -= curlen;
+ int res = ptrace_writedata(child, (void *) addr2,
+ addr, data);
+ if (res == data) {
+ pt_succ_return(regs, 0);
+ goto flush_and_out;
}
- pt_succ_return(regs, 0);
+ if (res >= 0)
+ res = -EIO;
+ pt_error_return(regs, -res);
goto flush_and_out;
}
-
case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */
addr = 1;
@@ -1105,6 +611,14 @@ flush_and_out:
unsigned long va;
for(va = 0; va < (PAGE_SIZE << 1); va += 32)
spitfire_put_dcache_tag(va, 0x0);
+ if (request == PTRACE_PEEKTEXT ||
+ request == PTRACE_POKETEXT ||
+ request == PTRACE_READTEXT ||
+ request == PTRACE_WRITETEXT) {
+ for(va = 0; va < (PAGE_SIZE << 1); va += 32)
+ spitfire_put_icache_tag(va, 0x0);
+ __asm__ __volatile__("flush %g6");
+ }
}
out:
unlock_kernel();
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index b0e92d50b..a0e8f7e69 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -615,7 +615,7 @@ do { hardirq_enter(cpu); \
unsigned int *inc, *inc2;
update_one_process(current, 1, user, !user, cpu);
- if(--current->counter < 0) {
+ if(--current->counter <= 0) {
current->counter = 0;
current->need_resched = 1;
}
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 6d6043617..91277fc4a 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.58 1999/05/08 03:00:31 davem Exp $
+/* $Id: sparc64_ksyms.c,v 1.60 1999/07/03 22:11:12 davem Exp $
* arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -45,7 +45,6 @@
#include <asm/ebus.h>
#endif
#include <asm/a.out.h>
-#include <asm/svr4.h>
struct poll {
int fd;
@@ -118,6 +117,12 @@ __attribute__((section("__ksymtab"))) = \
/* used by various drivers */
#ifdef __SMP__
+/* Out of line rw-locking implementation. */
+EXPORT_SYMBOL_PRIVATE(read_lock);
+EXPORT_SYMBOL_PRIVATE(read_unlock);
+EXPORT_SYMBOL_PRIVATE(write_lock);
+EXPORT_SYMBOL_PRIVATE(write_unlock);
+
/* Kernel wide locking */
EXPORT_SYMBOL(kernel_flag);
@@ -158,6 +163,10 @@ EXPORT_SYMBOL(local_irq_count);
EXPORT_SYMBOL(local_bh_count);
#endif
+/* Atomic counter implementation. */
+EXPORT_SYMBOL_PRIVATE(atomic_add);
+EXPORT_SYMBOL_PRIVATE(atomic_sub);
+
EXPORT_SYMBOL(ivector_table);
EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 77d2ddc6c..0e42e2c32 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -17,7 +17,6 @@
#include <linux/utime.h>
#include <linux/resource.h>
#include <linux/times.h>
-#include <linux/utime.h>
#include <linux/utsname.h>
#include <linux/timex.h>
#include <linux/smp.h>
@@ -32,18 +31,15 @@
#include <linux/smb_mount.h>
#include <linux/ncp_fs.h>
#include <linux/quota.h>
-#include <linux/file.h>
#include <linux/module.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/cache.h>
#include <linux/nfsd/xdr.h>
#include <linux/nfsd/syscall.h>
-#include <linux/module.h>
#include <linux/poll.h>
#include <linux/personality.h>
#include <linux/stat.h>
-#include <linux/timex.h>
#include <asm/types.h>
#include <asm/ipc.h>
@@ -2328,8 +2324,8 @@ static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
break;
}
/* Bump the usage count and install the file. */
- atomic_inc(&fp[i]->f_count);
- current->files->fd[new_fd] = fp[i];
+ get_file(fp[i]);
+ fd_install(new_fd, fp[i]);
}
if (i > 0) {
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
index 9ea1ffcc2..156d1d8ee 100644
--- a/arch/sparc64/kernel/sys_sunos32.c
+++ b/arch/sparc64/kernel/sys_sunos32.c
@@ -25,7 +25,6 @@
#include <linux/signal.h>
#include <linux/uio.h>
#include <linux/utsname.h>
-#include <linux/fs.h>
#include <linux/major.h>
#include <linux/stat.h>
#include <linux/malloc.h>
@@ -712,7 +711,7 @@ sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr)
struct inode *inode;
struct file *file;
- file = current->files->fd [fd];
+ file = fcheck(fd);
if(!file)
return 0;