summaryrefslogtreecommitdiffstats
path: root/arch/sparc64
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-18 00:24:27 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-18 00:24:27 +0000
commitb9558d5f86c471a125abf1fb3a3882fb053b1f8c (patch)
tree707b53ec64e740a7da87d5f36485e3cd9b1c794e /arch/sparc64
parentb3ac367c7a3e6047abe74817db27e34e759f279f (diff)
Merge with Linux 2.3.41.
Diffstat (limited to 'arch/sparc64')
-rw-r--r--arch/sparc64/config.in2
-rw-r--r--arch/sparc64/kernel/binfmt_aout32.c28
-rw-r--r--arch/sparc64/kernel/ioctl32.c29
-rw-r--r--arch/sparc64/kernel/iommu_common.c11
-rw-r--r--arch/sparc64/kernel/irq.c4
-rw-r--r--arch/sparc64/kernel/pci_iommu.c156
-rw-r--r--arch/sparc64/kernel/pci_psycho.c4
-rw-r--r--arch/sparc64/kernel/pci_sabre.c4
-rw-r--r--arch/sparc64/kernel/process.c5
-rw-r--r--arch/sparc64/kernel/sbus.c44
-rw-r--r--arch/sparc64/kernel/signal32.c173
-rw-r--r--arch/sparc64/kernel/smp.c10
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c14
-rw-r--r--arch/sparc64/kernel/sys_sparc.c15
-rw-r--r--arch/sparc64/kernel/sys_sparc32.c42
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c27
-rw-r--r--arch/sparc64/kernel/systbls.S8
-rw-r--r--arch/sparc64/kernel/traps.c172
-rw-r--r--arch/sparc64/lib/Makefile6
-rw-r--r--arch/sparc64/lib/VIScsumcopy.S4
-rw-r--r--arch/sparc64/lib/VIScsumcopyusr.S914
-rw-r--r--arch/sparc64/lib/checksum.S238
-rw-r--r--arch/sparc64/mm/asyncd.c13
-rw-r--r--arch/sparc64/mm/fault.c53
-rw-r--r--arch/sparc64/mm/init.c13
-rw-r--r--arch/sparc64/solaris/misc.c8
26 files changed, 1658 insertions, 339 deletions
diff --git a/arch/sparc64/config.in b/arch/sparc64/config.in
index 448dad773..ace1366ba 100644
--- a/arch/sparc64/config.in
+++ b/arch/sparc64/config.in
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.86 1999/12/23 01:46:09 davem Exp $
+# $Id: config.in,v 1.87 2000/01/16 06:18:53 davem Exp $
# For a description of the syntax of this configuration file,
# see the Configure script.
#
diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c
index cbbb3557b..009c506a0 100644
--- a/arch/sparc64/kernel/binfmt_aout32.c
+++ b/arch/sparc64/kernel/binfmt_aout32.c
@@ -30,16 +30,16 @@
#include <asm/system.h>
#include <asm/uaccess.h>
-#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
static int load_aout32_binary(struct linux_binprm *, struct pt_regs * regs);
static int load_aout32_library(int fd);
-static int aout32_core_dump(long signr, struct pt_regs * regs);
+static int aout32_core_dump(long signr, struct pt_regs * regs, struct file *file);
extern void dump_thread(struct pt_regs *, struct user *);
static struct linux_binfmt aout32_format = {
- NULL, NULL, load_aout32_binary, load_aout32_library, aout32_core_dump,
+ NULL, THIS_MODULE, load_aout32_binary, load_aout32_library, aout32_core_dump,
PAGE_SIZE
};
@@ -214,7 +214,6 @@ static inline int do_load_aout32_binary(struct linux_binprm * bprm,
struct file * file;
int fd;
unsigned long error;
- unsigned long p = bprm->p;
unsigned long fd_offset;
unsigned long rlim;
int retval;
@@ -275,9 +274,13 @@ static inline int do_load_aout32_binary(struct linux_binprm * bprm,
read_exec(bprm->dentry, fd_offset, (char *) N_TXTADDR(ex),
ex.a_text+ex.a_data, 0);
} else {
+ static unsigned long error_time;
if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
- (N_MAGIC(ex) != NMAGIC))
+ (N_MAGIC(ex) != NMAGIC) && (jiffies-error_time) > 5*HZ)
+ {
printk(KERN_NOTICE "executable not page aligned\n");
+ error_time = jiffies;
+ }
fd = open_dentry(bprm->dentry, O_RDONLY);
if (fd < 0)
@@ -285,7 +288,7 @@ static inline int do_load_aout32_binary(struct linux_binprm * bprm,
file = fget(fd);
if (!file->f_op || !file->f_op->mmap) {
- fput(fd);
+ fput(file);
sys_close(fd);
do_brk(0, ex.a_text+ex.a_data);
read_exec(bprm->dentry, fd_offset,
@@ -452,8 +455,17 @@ load_aout32_library(int fd)
return retval;
}
-
-int __init init_aout32_binfmt(void)
+static int __init init_aout32_binfmt(void)
{
return register_binfmt(&aout32_format);
}
+
+static void __exit exit_aout32_binfmt(void)
+{
+ unregister_binfmt(&aout32_format);
+}
+
+EXPORT_NO_SYMBOLS;
+
+module_init(init_aout32_binfmt);
+module_exit(exit_aout32_binfmt);
diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
index cba5cfac3..7a7315003 100644
--- a/arch/sparc64/kernel/ioctl32.c
+++ b/arch/sparc64/kernel/ioctl32.c
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.73 2000/01/11 01:06:47 davem Exp $
+/* $Id: ioctl32.c,v 1.74 2000/01/15 04:47:48 davem Exp $
* ioctl32.c: Conversion between 32bit and 64bit native ioctls.
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -39,6 +39,7 @@
#include <linux/videodev.h>
#include <linux/netdevice.h>
#include <linux/raw.h>
+#include <linux/smb_fs.h>
#include <scsi/scsi.h>
/* Ugly hack. */
@@ -1734,6 +1735,24 @@ static int do_unimap_ioctl(struct file *file, int cmd, struct unimapdesc32 *user
return 0;
}
+static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ mm_segment_t old_fs = get_fs();
+ __kernel_uid_t kuid;
+ int err;
+
+ cmd = SMB_IOC_GETMOUNTUID;
+
+ set_fs(KERNEL_DS);
+ err = sys_ioctl(fd, cmd, (unsigned long)&kuid);
+ set_fs(old_fs);
+
+ if (err >= 0)
+ err = put_user(kuid, (__kernel_uid_t32 *)arg);
+
+ return err;
+}
+
asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
struct file * filp;
@@ -1921,6 +1940,11 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
error = do_video_ioctl(fd, cmd, arg);
goto out;
+ /* One SMB ioctl needs translations. */
+ case _IOR('u', 1, __kernel_uid_t32): /* SMB_IOC_GETMOUNTUID */
+ error = do_smb_getmountuid(fd, cmd, arg);
+ goto out;
+
/* List here exlicitly which ioctl's are known to have
* compatable types passed or none at all...
*/
@@ -2427,6 +2451,9 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
case RAW_SETBIND:
case RAW_GETBIND:
+ /* SMB ioctls which do not need any translations */
+ case SMB_IOC_NEWCONN:
+
error = sys_ioctl (fd, cmd, arg);
goto out;
diff --git a/arch/sparc64/kernel/iommu_common.c b/arch/sparc64/kernel/iommu_common.c
index c537353e0..d1041b85f 100644
--- a/arch/sparc64/kernel/iommu_common.c
+++ b/arch/sparc64/kernel/iommu_common.c
@@ -59,7 +59,6 @@ int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, int ne
{
struct scatterlist *sg = *__sg;
iopte_t *iopte = *__iopte;
- int retval = 0;
u32 dlen = dma_sg->dvma_length;
u32 daddr = dma_sg->dvma_address;
unsigned int sglen;
@@ -75,7 +74,7 @@ int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, int ne
printk("verify_one_map: Wrong start offset "
"sg[%08lx] dma[%08x]\n",
sgaddr, daddr);
- retval = -nents;
+ nents = -1;
goto out;
}
@@ -85,7 +84,7 @@ int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, int ne
printk("verify_one_map: IOPTE[%08lx] maps the "
"wrong page, should be [%08lx]\n",
iopte_val(*iopte), (sgaddr & PAGE_MASK) - PAGE_OFFSET);
- retval = -nents;
+ nents = -1;
goto out;
}
@@ -114,6 +113,8 @@ int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, int ne
iopte++;
sg++;
+ if (--nents <= 0)
+ break;
sgaddr = (unsigned long) sg->address;
sglen = sg->length;
}
@@ -121,7 +122,7 @@ int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, int ne
/* Transfer overrun, big problems. */
printk("verify_one_map: Transfer overrun by %d bytes.\n",
-dlen);
- retval = -nents;
+ nents = -1;
} else {
/* Advance to next dma_sg implies that the next iopte will
* begin it.
@@ -132,7 +133,7 @@ int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, int ne
out:
*__sg = sg;
*__iopte = iopte;
- return retval;
+ return nents;
}
int verify_maps(struct scatterlist *sg, int nents, iopte_t *iopte)
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index b70d936c3..820b93bb4 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.80 1999/12/06 03:14:48 davem Exp $
+/* $Id: irq.c,v 1.81 2000/01/21 06:33:59 davem Exp $
* irq.c: UltraSparc IRQ handling/init/registry.
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -756,7 +756,7 @@ void handler_irq(int irq, struct pt_regs *regs)
* of our buddy.
*/
if(should_forward != 0) {
- buddy = cpu_number_map[cpu] + 1;
+ buddy = cpu_number_map(cpu) + 1;
if (buddy >= NR_CPUS ||
(buddy = cpu_logical_map(buddy)) == -1)
buddy = cpu_logical_map(0);
diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c
index 12f7211d1..e72671428 100644
--- a/arch/sparc64/kernel/pci_iommu.c
+++ b/arch/sparc64/kernel/pci_iommu.c
@@ -2,7 +2,7 @@
* pci_iommu.c: UltraSparc PCI controller IOM/STC support.
*
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
- * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
+ * Copyright (C) 1999, 2000 Jakub Jelinek (jakub@redhat.com)
*/
#include <linux/kernel.h>
@@ -63,7 +63,7 @@ static iopte_t *alloc_streaming_cluster(struct pci_iommu *iommu, unsigned long n
return iopte;
}
-static inline void free_streaming_cluster(struct pci_iommu *iommu, u32 base, unsigned long npages)
+static inline void free_streaming_cluster(struct pci_iommu *iommu, dma_addr_t base, unsigned long npages)
{
unsigned long cnum, ent;
@@ -76,8 +76,8 @@ static inline void free_streaming_cluster(struct pci_iommu *iommu, u32 base, uns
iommu->lowest_free[cnum] = ent;
}
-/* We allocate consistant mappings from the end of cluster zero. */
-static iopte_t *alloc_consistant_cluster(struct pci_iommu *iommu, unsigned long npages)
+/* We allocate consistent mappings from the end of cluster zero. */
+static iopte_t *alloc_consistent_cluster(struct pci_iommu *iommu, unsigned long npages)
{
iopte_t *iopte;
@@ -109,11 +109,11 @@ static iopte_t *alloc_consistant_cluster(struct pci_iommu *iommu, unsigned long
#define IOPTE_INVALID 0UL
-/* Allocate and map kernel buffer of size SIZE using consistant mode
+/* Allocate and map kernel buffer of size SIZE using consistent mode
* DMA for PCI device PDEV. Return non-NULL cpu-side address if
* successful and set *DMA_ADDRP to the PCI side dma address.
*/
-void *pci_alloc_consistant(struct pci_dev *pdev, long size, u32 *dma_addrp)
+void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
@@ -122,10 +122,6 @@ void *pci_alloc_consistant(struct pci_dev *pdev, long size, u32 *dma_addrp)
void *ret;
int npages;
- if (size <= 0 || pdev == NULL ||
- pdev->sysdata == NULL || dma_addrp == NULL)
- return NULL;
-
size = PAGE_ALIGN(size);
for (order = 0; order < 10; order++) {
if ((PAGE_SIZE << order) >= size)
@@ -134,6 +130,11 @@ void *pci_alloc_consistant(struct pci_dev *pdev, long size, u32 *dma_addrp)
if (order == 10)
return NULL;
+ /* We still don't support devices which don't recognize at least 30 bits
+ of bus address. Bug me to code it (is pretty easy actually). -jj */
+ if ((pdev->dma_mask & 0x3fffffff) != 0x3fffffff)
+ BUG();
+
first_page = __get_free_pages(GFP_ATOMIC, order);
if (first_page == 0UL)
return NULL;
@@ -143,7 +144,7 @@ void *pci_alloc_consistant(struct pci_dev *pdev, long size, u32 *dma_addrp)
iommu = &pcp->pbm->parent->iommu;
spin_lock_irqsave(&iommu->lock, flags);
- iopte = alloc_consistant_cluster(iommu, size >> PAGE_SHIFT);
+ iopte = alloc_consistent_cluster(iommu, size >> PAGE_SHIFT);
if (iopte == NULL) {
spin_unlock_irqrestore(&iommu->lock, flags);
free_pages(first_page, order);
@@ -182,18 +183,14 @@ void *pci_alloc_consistant(struct pci_dev *pdev, long size, u32 *dma_addrp)
return ret;
}
-/* Free and unmap a consistant DMA translation. */
-void pci_free_consistant(struct pci_dev *pdev, long size, void *cpu, u32 dvma)
+/* Free and unmap a consistent DMA translation. */
+void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_t dvma)
{
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
iopte_t *iopte;
unsigned long flags, order, npages, i;
- if (size <= 0 || pdev == NULL ||
- pdev->sysdata == NULL || cpu == NULL)
- return;
-
npages = PAGE_ALIGN(size) >> PAGE_SHIFT;
pcp = pdev->sysdata;
iommu = &pcp->pbm->parent->iommu;
@@ -202,7 +199,7 @@ void pci_free_consistant(struct pci_dev *pdev, long size, void *cpu, u32 dvma)
spin_lock_irqsave(&iommu->lock, flags);
- /* Data for consistant mappings cannot enter the streaming
+ /* Data for consistent mappings cannot enter the streaming
* buffers, so we only need to update the TSB. Flush of the
* IOTLB is done later when these ioptes are used for a new
* allocation.
@@ -224,16 +221,25 @@ void pci_free_consistant(struct pci_dev *pdev, long size, void *cpu, u32 dvma)
/* Map a single buffer at PTR of SZ bytes for PCI DMA
* in streaming mode.
*/
-u32 pci_map_single(struct pci_dev *pdev, void *ptr, long sz)
+dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz)
{
- struct pcidev_cookie *pcp = pdev->sysdata;
- struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
- struct pci_strbuf *strbuf = &pcp->pbm->stc;
+ struct pcidev_cookie *pcp;
+ struct pci_iommu *iommu;
+ struct pci_strbuf *strbuf;
iopte_t *base;
unsigned long flags, npages, oaddr;
unsigned long i, base_paddr, ctx;
u32 bus_addr, ret;
+ pcp = pdev->sysdata;
+ iommu = &pcp->pbm->parent->iommu;
+ strbuf = &pcp->pbm->stc;
+
+ /* We still don't support devices which don't recognize at least 30 bits
+ of bus address. Bug me to code it (is pretty easy actually). -jj */
+ if ((pdev->dma_mask & 0x3fffffff) != 0x3fffffff)
+ BUG();
+
oaddr = (unsigned long)ptr;
npages = PAGE_ALIGN(oaddr + sz) - (oaddr & PAGE_MASK);
npages >>= PAGE_SHIFT;
@@ -270,18 +276,26 @@ u32 pci_map_single(struct pci_dev *pdev, void *ptr, long sz)
}
/* Unmap a single streaming mode DMA translation. */
-void pci_unmap_single(struct pci_dev *pdev, u32 bus_addr, long sz)
+void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz)
{
- struct pcidev_cookie *pcp = pdev->sysdata;
- struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
- struct pci_strbuf *strbuf = &pcp->pbm->stc;
+ struct pcidev_cookie *pcp;
+ struct pci_iommu *iommu;
+ struct pci_strbuf *strbuf;
iopte_t *base;
unsigned long flags, npages, i, ctx;
+ pcp = pdev->sysdata;
+ iommu = &pcp->pbm->parent->iommu;
+ strbuf = &pcp->pbm->stc;
+
npages = PAGE_ALIGN(bus_addr + sz) - (bus_addr & PAGE_MASK);
npages >>= PAGE_SHIFT;
base = iommu->page_table +
((bus_addr - iommu->page_table_map_base) >> PAGE_SHIFT);
+#ifdef DEBUG_PCI_IOMMU
+ if (iopte_val(*base) == IOPTE_INVALID)
+ printk("pci_unmap_single called on non-mapped region %08x,%08x from %016lx\n", bus_addr, sz, __builtin_return_address(0));
+#endif
bus_addr &= PAGE_MASK;
spin_lock_irqsave(&iommu->lock, flags);
@@ -327,11 +341,12 @@ void pci_unmap_single(struct pci_dev *pdev, u32 bus_addr, long sz)
spin_unlock_irqrestore(&iommu->lock, flags);
}
-static inline struct scatterlist *fill_sg(iopte_t *iopte, struct scatterlist *sg, int nents, unsigned long ctx, int streaming)
+static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nused, unsigned long ctx, int streaming)
{
struct scatterlist *dma_sg = sg;
+ int i;
- do {
+ for (i = 0; i < nused; i++) {
unsigned long pteval = ~0UL;
u32 dma_npages;
@@ -396,8 +411,7 @@ static inline struct scatterlist *fill_sg(iopte_t *iopte, struct scatterlist *sg
pteval = ~0UL;
} while (dma_npages != 0);
dma_sg++;
- } while (dma_sg->dvma_length != 0);
- return dma_sg;
+ }
}
/* Map a set of buffers described by SGLIST with NELEMS array
@@ -414,7 +428,7 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
iopte_t *base;
u32 dma_base;
struct scatterlist *sgtmp;
- int tmp;
+ int used;
/* Fast path single entry scatterlists. */
if (nelems == 1) {
@@ -422,11 +436,16 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
sglist->dvma_length = sglist->length;
return 1;
}
-
+
pcp = pdev->sysdata;
iommu = &pcp->pbm->parent->iommu;
strbuf = &pcp->pbm->stc;
+ /* We still don't support devices which don't recognize at least 30 bits
+ of bus address. Bug me to code it (is pretty easy actually). -jj */
+ if ((pdev->dma_mask & 0x3fffffff) != 0x3fffffff)
+ BUG();
+
/* Step 1: Prepare scatter list. */
npages = prepare_sg(sglist, nelems);
@@ -439,13 +458,15 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
dma_base = iommu->page_table_map_base + ((base - iommu->page_table) << PAGE_SHIFT);
/* Step 3: Normalize DMA addresses. */
- tmp = nelems;
+ used = nelems;
sgtmp = sglist;
- while (tmp-- && sgtmp->dvma_length) {
+ while (used && sgtmp->dvma_length) {
sgtmp->dvma_address += dma_base;
sgtmp++;
+ used--;
}
+ used = nelems - used;
/* Step 4: Choose a context if necessary. */
ctx = 0;
@@ -453,7 +474,7 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
ctx = iommu->iommu_cur_ctx++;
/* Step 5: Create the mappings. */
- sgtmp = fill_sg (base, sglist, nelems, ctx, strbuf->strbuf_enabled);
+ fill_sg (base, sglist, used, ctx, strbuf->strbuf_enabled);
#ifdef VERIFY_SG
verify_sglist(sglist, nelems, base, npages);
#endif
@@ -468,33 +489,39 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
spin_unlock_irqrestore(&iommu->lock, flags);
- return sgtmp - sglist;
+ return used;
}
/* Unmap a set of streaming mode DMA translations. */
void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
{
- struct pcidev_cookie *pcp = pdev->sysdata;
- struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
- struct pci_strbuf *strbuf = &pcp->pbm->stc;
+ struct pcidev_cookie *pcp;
+ struct pci_iommu *iommu;
+ struct pci_strbuf *strbuf;
iopte_t *base;
unsigned long flags, ctx, i, npages;
u32 bus_addr;
+
+ pcp = pdev->sysdata;
+ iommu = &pcp->pbm->parent->iommu;
+ strbuf = &pcp->pbm->stc;
bus_addr = sglist->dvma_address & PAGE_MASK;
- i = 0;
- if (nelems > 1) {
- for (; i < nelems; i++)
- if (sglist[i].dvma_length == 0)
- break;
- i--;
- }
+ for (i = 1; i < nelems; i++)
+ if (sglist[i].dvma_length == 0)
+ break;
+ i--;
npages = (PAGE_ALIGN(sglist[i].dvma_address + sglist[i].dvma_length) - bus_addr) >> PAGE_SHIFT;
base = iommu->page_table +
((bus_addr - iommu->page_table_map_base) >> PAGE_SHIFT);
+#ifdef DEBUG_PCI_IOMMU
+ if (iopte_val(*base) == IOPTE_INVALID)
+ printk("pci_unmap_sg called on non-mapped region %08x,%d from %016lx\n", sglist->dvma_address, nelems, __builtin_return_address(0));
+#endif
+
spin_lock_irqsave(&iommu->lock, flags);
/* Step 1: Kick data out of streaming buffers if necessary. */
@@ -538,16 +565,20 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
spin_unlock_irqrestore(&iommu->lock, flags);
}
-/* Make physical memory consistant for a single
+/* Make physical memory consistent for a single
* streaming mode DMA translation after a transfer.
*/
-void pci_dma_sync_single(struct pci_dev *pdev, u32 bus_addr, long sz)
+void pci_dma_sync_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz)
{
- struct pcidev_cookie *pcp = pdev->sysdata;
- struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
- struct pci_strbuf *strbuf = &pcp->pbm->stc;
+ struct pcidev_cookie *pcp;
+ struct pci_iommu *iommu;
+ struct pci_strbuf *strbuf;
unsigned long flags, ctx, npages;
+ pcp = pdev->sysdata;
+ iommu = &pcp->pbm->parent->iommu;
+ strbuf = &pcp->pbm->stc;
+
if (!strbuf->strbuf_enabled)
return;
@@ -595,16 +626,20 @@ void pci_dma_sync_single(struct pci_dev *pdev, u32 bus_addr, long sz)
spin_unlock_irqrestore(&iommu->lock, flags);
}
-/* Make physical memory consistant for a set of streaming
+/* Make physical memory consistent for a set of streaming
* mode DMA translations after a transfer.
*/
void pci_dma_sync_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
{
- struct pcidev_cookie *pcp = pdev->sysdata;
- struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
- struct pci_strbuf *strbuf = &pcp->pbm->stc;
+ struct pcidev_cookie *pcp;
+ struct pci_iommu *iommu;
+ struct pci_strbuf *strbuf;
unsigned long flags, ctx;
+ pcp = pdev->sysdata;
+ iommu = &pcp->pbm->parent->iommu;
+ strbuf = &pcp->pbm->stc;
+
if (!strbuf->strbuf_enabled)
return;
@@ -636,15 +671,12 @@ void pci_dma_sync_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelem
unsigned long i, npages;
u32 bus_addr;
- i = 0;
bus_addr = sglist[0].dvma_address & PAGE_MASK;
- if (nelems > 1) {
- for(; i < nelems; i++)
- if (!sglist[i].dvma_length)
- break;
- i--;
- }
+ for(i = 1; i < nelems; i++)
+ if (!sglist[i].dvma_length)
+ break;
+ i--;
npages = (PAGE_ALIGN(sglist[i].dvma_address + sglist[i].dvma_length) - bus_addr) >> PAGE_SHIFT;
for (i = 0; i < npages; i++, bus_addr += PAGE_SIZE)
pci_iommu_write(strbuf->strbuf_pflush, bus_addr);
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index c12b5182d..559769b87 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -1284,6 +1284,10 @@ static void __init psycho_iommu_init(struct pci_controller_info *p)
memset((char *)tsbbase, 0, PAGE_SIZE << 7);
#endif
+ /* Make sure DMA address 0 is never returned just to allow catching
+ of buggy drivers. */
+ p->iommu.lowest_free[0] = 1;
+
#ifndef NEW_PCI_DMA_MAP
iopte = (iopte_t *)tsbbase;
/* Initialize to "none" settings. */
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index 7409b3164..2f82de9ce 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -1150,6 +1150,10 @@ static void __init sabre_iommu_init(struct pci_controller_info *p,
p->iommu.page_table_map_base = dvma_offset;
memset((char *)tsbbase, 0, PAGE_SIZE << order);
+ /* Make sure DMA address 0 is never returned just to allow catching
+ of buggy drivers. */
+ p->iommu.lowest_free[0] = 1;
+
#ifndef NEW_PCI_DMA_MAP
iopte = (iopte_t *)tsbbase;
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 922e74d2e..503f5b875 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.102 1999/12/15 22:24:49 davem Exp $
+/* $Id: process.c,v 1.103 2000/01/21 11:38:53 jj Exp $
* arch/sparc64/kernel/process.c
*
* Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -364,8 +364,6 @@ void show_thread(struct thread_struct *thread)
printk("kregs: 0x%016lx\n", (unsigned long)thread->kregs);
show_regs(thread->kregs);
#endif
- printk("sig_address: 0x%016lx\n", thread->sig_address);
- printk("sig_desc: 0x%016lx\n", thread->sig_desc);
printk("ksp: 0x%016lx\n", thread->ksp);
if (thread->w_saved) {
@@ -701,7 +699,6 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
memcpy(&dump->fpu.fpstatus.fregs.regs[0], &current->thread.float_regs[0], (sizeof(unsigned long) * 32));
dump->fpu.fpstatus.fsr = current->thread.fsr;
dump->fpu.fpstatus.flags = dump->fpu.fpstatus.extra = 0;
- dump->sigcode = current->thread.sig_desc;
#endif
}
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
index 9e24c7bb3..a73387754 100644
--- a/arch/sparc64/kernel/sbus.c
+++ b/arch/sparc64/kernel/sbus.c
@@ -212,8 +212,8 @@ static void free_streaming_cluster(struct sbus_iommu *iommu, u32 base, unsigned
iommu->lowest_free[cnum] = ent;
}
-/* We allocate consistant mappings from the end of cluster zero. */
-static iopte_t *alloc_consistant_cluster(struct sbus_iommu *iommu, unsigned long npages)
+/* We allocate consistent mappings from the end of cluster zero. */
+static iopte_t *alloc_consistent_cluster(struct sbus_iommu *iommu, unsigned long npages)
{
iopte_t *iopte;
@@ -235,7 +235,7 @@ static iopte_t *alloc_consistant_cluster(struct sbus_iommu *iommu, unsigned long
return NULL;
}
-static void free_consistant_cluster(struct sbus_iommu *iommu, u32 base, unsigned long npages)
+static void free_consistent_cluster(struct sbus_iommu *iommu, u32 base, unsigned long npages)
{
iopte_t *iopte = iommu->page_table + ((base - MAP_BASE) >> PAGE_SHIFT);
@@ -243,7 +243,7 @@ static void free_consistant_cluster(struct sbus_iommu *iommu, u32 base, unsigned
*iopte++ = __iopte(0UL);
}
-void *sbus_alloc_consistant(struct sbus_dev *sdev, long size, u32 *dvma_addr)
+void *sbus_alloc_consistent(struct sbus_dev *sdev, size_t size, dma_addr_t *dvma_addr)
{
unsigned long order, first_page, flags;
struct sbus_iommu *iommu;
@@ -269,7 +269,7 @@ void *sbus_alloc_consistant(struct sbus_dev *sdev, long size, u32 *dvma_addr)
iommu = sdev->bus->iommu;
spin_lock_irqsave(&iommu->lock, flags);
- iopte = alloc_consistant_cluster(iommu, size >> PAGE_SHIFT);
+ iopte = alloc_consistent_cluster(iommu, size >> PAGE_SHIFT);
if (iopte == NULL) {
spin_unlock_irqrestore(&iommu->lock, flags);
free_pages(first_page, order);
@@ -291,7 +291,7 @@ void *sbus_alloc_consistant(struct sbus_dev *sdev, long size, u32 *dvma_addr)
return ret;
}
-void sbus_free_consistant(struct sbus_dev *sdev, long size, void *cpu, u32 dvma)
+void sbus_free_consistent(struct sbus_dev *sdev, size_t size, void *cpu, dma_addr_t dvma)
{
unsigned long order, npages;
struct sbus_iommu *iommu;
@@ -303,7 +303,7 @@ void sbus_free_consistant(struct sbus_dev *sdev, long size, void *cpu, u32 dvma)
iommu = sdev->bus->iommu;
spin_lock_irq(&iommu->lock);
- free_consistant_cluster(iommu, dvma, npages);
+ free_consistent_cluster(iommu, dvma, npages);
spin_unlock_irq(&iommu->lock);
for (order = 0; order < 10; order++) {
@@ -314,7 +314,7 @@ void sbus_free_consistant(struct sbus_dev *sdev, long size, void *cpu, u32 dvma)
free_pages((unsigned long)cpu, order);
}
-u32 sbus_map_single(struct sbus_dev *sdev, void *ptr, long size)
+dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t size)
{
struct sbus_iommu *iommu = sdev->bus->iommu;
unsigned long npages, phys_base, flags;
@@ -344,7 +344,7 @@ u32 sbus_map_single(struct sbus_dev *sdev, void *ptr, long size)
return (dma_base | offset);
}
-void sbus_unmap_single(struct sbus_dev *sdev, u32 dma_addr, long size)
+void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size)
{
struct sbus_iommu *iommu = sdev->bus->iommu;
u32 dma_base = dma_addr & PAGE_MASK;
@@ -358,11 +358,12 @@ void sbus_unmap_single(struct sbus_dev *sdev, u32 dma_addr, long size)
spin_unlock_irqrestore(&iommu->lock, flags);
}
-static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nents)
+static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nused)
{
struct scatterlist *dma_sg = sg;
+ int i;
- do {
+ for (i = 0; i < nused; i++) {
unsigned long pteval = ~0UL;
u32 dma_npages;
@@ -426,7 +427,7 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nents)
pteval = ~0UL;
} while (dma_npages != 0);
dma_sg++;
- } while (dma_sg->dvma_length != 0);
+ }
}
int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents)
@@ -436,7 +437,7 @@ int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents)
iopte_t *iopte;
u32 dma_base;
struct scatterlist *sgtmp;
- int unused;
+ int used;
/* Fast path single entry scatterlists. */
if (nents == 1) {
@@ -453,22 +454,23 @@ int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents)
/* Normalize DVMA addresses. */
sgtmp = sg;
- unused = nents;
+ used = nents;
- while (unused && sgtmp->dvma_length) {
+ while (used && sgtmp->dvma_length) {
sgtmp->dvma_address += dma_base;
sgtmp++;
- unused--;
+ used--;
}
+ used = nents - used;
- fill_sg(iopte, sg, nents);
+ fill_sg(iopte, sg, used);
#ifdef VERIFY_SG
verify_sglist(sg, nents, iopte, npages);
#endif
iommu_flush(iommu, dma_base, npages);
spin_unlock_irqrestore(&iommu->lock, flags);
- return nents - unused;
+ return used;
}
void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents)
@@ -499,7 +501,7 @@ void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents)
spin_unlock_irqrestore(&iommu->lock, flags);
}
-void sbus_dma_sync_single(struct sbus_dev *sdev, u32 base, long size)
+void sbus_dma_sync_single(struct sbus_dev *sdev, dma_addr_t base, size_t size)
{
struct sbus_iommu *iommu = sdev->bus->iommu;
unsigned long flags;
@@ -1054,6 +1056,10 @@ void __init sbus_iommu_init(int prom_node, struct sbus_bus *sbus)
memset(iommu, 0, sizeof(*iommu));
+ /* Make sure DMA address 0 is never returned just to allow catching
+ of buggy drivers. */
+ iommu->lowest_free[0] = 1;
+
/* Setup spinlock. */
spin_lock_init(&iommu->lock);
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
index f0e512666..f226a8ae5 100644
--- a/arch/sparc64/kernel/signal32.c
+++ b/arch/sparc64/kernel/signal32.c
@@ -1,4 +1,4 @@
-/* $Id: signal32.c,v 1.58 2000/01/14 09:40:08 jj Exp $
+/* $Id: signal32.c,v 1.59 2000/01/21 11:38:52 jj Exp $
* arch/sparc64/kernel/signal32.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
@@ -101,6 +101,44 @@ struct rt_signal_frame32 {
#define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame32) + 7) & (~7)))
#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame32) + 7) & (~7)))
+int copy_siginfo_to_user32(siginfo_t32 *to, siginfo_t *from)
+{
+ int err;
+
+ if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32)))
+ return -EFAULT;
+
+ err = __put_user(from->si_signo, &to->si_signo);
+ err |= __put_user(from->si_errno, &to->si_errno);
+ err |= __put_user(from->si_code, &to->si_code);
+ if (from->si_code < 0)
+ err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
+ else {
+ int signo = from->si_signo;
+ if (from->si_code == SI_USER || from->si_code == SI_KERNEL)
+ signo = SIGRTMIN;
+ switch (signo) {
+ case SIGCHLD:
+ err |= __put_user(from->si_utime, &to->si_utime);
+ err |= __put_user(from->si_stime, &to->si_stime);
+ err |= __put_user(from->si_status, &to->si_status);
+ default:
+ err |= __put_user(from->si_pid, &to->si_pid);
+ err |= __put_user(from->si_uid, &to->si_uid);
+ break;
+ case SIGSEGV:
+ case SIGILL:
+ case SIGFPE:
+ case SIGBUS:
+ case SIGEMT:
+ err |= __put_user(from->si_trapno, &to->si_trapno);
+ err |= __put_user((long)from->si_addr, &to->si_addr);
+ break;
+ }
+ }
+ return err;
+}
+
/*
* atomically swap in the new signal mask, and wait for a signal.
* This is really tricky on the Sparc, watch out...
@@ -436,13 +474,16 @@ static inline void *get_sigframe(struct sigaction *sa, struct pt_regs *regs, uns
}
static void
-setup_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc,
- struct pt_regs *regs, int signr, sigset_t *oldset)
+setup_frame32(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *oldset, siginfo_t *info)
{
struct signal_sframe32 *sframep;
struct sigcontext32 *sc;
unsigned seta[_NSIG_WORDS32];
int err = 0;
+ void *sig_address;
+ int sig_code;
+ unsigned long pc = regs->tpc;
+ unsigned long npc = regs->tnpc;
#if 0
int window = 0;
@@ -513,17 +554,61 @@ setup_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc,
current->thread.w_saved = 0; /* So process is allowed to execute. */
err |= __put_user(signr, &sframep->sig_num);
- if(signr == SIGSEGV ||
- signr == SIGILL ||
- signr == SIGFPE ||
- signr == SIGBUS ||
- signr == SIGEMT) {
- err |= __put_user(current->thread.sig_desc, &sframep->sig_code);
- err |= __put_user(current->thread.sig_address, &sframep->sig_address);
- } else {
- err |= __put_user(0, &sframep->sig_code);
- err |= __put_user(0, &sframep->sig_address);
+ sig_address = NULL;
+ sig_code = 0;
+ if (SI_FROMKERNEL (info) && (info->si_code & __SI_MASK) == __SI_FAULT) {
+ sig_address = info->si_addr;
+ switch (signr) {
+ case SIGSEGV:
+ switch (info->si_code) {
+ case SEGV_MAPERR: sig_code = SUBSIG_NOMAPPING; break;
+ default: sig_code = SUBSIG_PROTECTION; break;
+ }
+ break;
+ case SIGILL:
+ switch (info->si_code) {
+ case ILL_ILLOPC: sig_code = SUBSIG_ILLINST; break;
+ case ILL_PRVOPC: sig_code = SUBSIG_PRIVINST; break;
+ case ILL_ILLTRP: sig_code = SUBSIG_BADTRAP (info->si_trapno); break;
+ default: sig_code = SUBSIG_STACK; break;
+ }
+ break;
+ case SIGFPE:
+ switch (info->si_code) {
+ case FPE_INTDIV: sig_code = SUBSIG_IDIVZERO; break;
+ case FPE_INTOVF: sig_code = SUBSIG_FPINTOVFL; break;
+ case FPE_FLTDIV: sig_code = SUBSIG_FPDIVZERO; break;
+ case FPE_FLTOVF: sig_code = SUBSIG_FPOVFLOW; break;
+ case FPE_FLTUND: sig_code = SUBSIG_FPUNFLOW; break;
+ case FPE_FLTRES: sig_code = SUBSIG_FPINEXACT; break;
+ case FPE_FLTINV: sig_code = SUBSIG_FPOPERROR; break;
+ default: sig_code = SUBSIG_FPERROR; break;
+ }
+ break;
+ case SIGBUS:
+ switch (info->si_code) {
+ case BUS_ADRALN: sig_code = SUBSIG_ALIGNMENT; break;
+ case BUS_ADRERR: sig_code = SUBSIG_MISCERROR; break;
+ default: sig_code = SUBSIG_BUSTIMEOUT; break;
+ }
+ break;
+ case SIGEMT:
+ switch (info->si_code) {
+ case EMT_TAGOVF: sig_code = SUBSIG_TAG; break;
+ }
+ break;
+ case SIGSYS:
+ if (info->si_code == (__SI_FAULT|0x100)) {
+ /* See sys_sunos32.c */
+ sig_code = info->si_trapno;
+ break;
+ }
+ default:
+ sig_address = NULL;
+ }
}
+ err |= __put_user((long)sig_address, &sframep->sig_address);
+ err |= __put_user(sig_code, &sframep->sig_code);
err |= __put_user((u64)sc, &sframep->sig_scptr);
if (err)
goto sigsegv;
@@ -790,8 +875,7 @@ setup_svr4_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc,
/* Setup the signal information. Solaris expects a bunch of
* information to be passed to the signal handler, we don't provide
- * that much currently, should use those that David already
- * is providing with thread.sig_desc
+ * that much currently, should use siginfo.
*/
err |= __put_user(signr, &si->siginfo.signo);
err |= __put_user(SVR4_SINOINFO, &si->siginfo.code);
@@ -1034,61 +1118,8 @@ static inline void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs
err |= __put_user(0, &sf->fpu_save);
}
- /* Update the siginfo structure. Is this good? */
- if (info->si_code == 0) {
- info->si_signo = signr;
- info->si_errno = 0;
-
- switch (signr) {
- case SIGSEGV:
- case SIGILL:
- case SIGFPE:
- case SIGBUS:
- case SIGEMT:
- info->si_code = current->thread.sig_desc;
- info->si_addr = (void *)current->thread.sig_address;
- info->si_trapno = 0;
- break;
- default:
- break;
- }
- }
-
- err = __put_user (info->si_signo, &sf->info.si_signo);
- err |= __put_user (info->si_errno, &sf->info.si_errno);
- err |= __put_user (info->si_code, &sf->info.si_code);
- if (info->si_code < 0)
- err |= __copy_to_user (sf->info._sifields._pad, info->_sifields._pad, SI_PAD_SIZE);
- else {
- i = info->si_signo;
- if (info->si_code == SI_USER)
- i = SIGRTMIN;
- switch (i) {
- case SIGPOLL:
- err |= __put_user (info->si_band, &sf->info.si_band);
- err |= __put_user (info->si_fd, &sf->info.si_fd);
- break;
- case SIGCHLD:
- err |= __put_user (info->si_pid, &sf->info.si_pid);
- err |= __put_user (info->si_uid, &sf->info.si_uid);
- err |= __put_user (info->si_status, &sf->info.si_status);
- err |= __put_user (info->si_utime, &sf->info.si_utime);
- err |= __put_user (info->si_stime, &sf->info.si_stime);
- break;
- case SIGSEGV:
- case SIGILL:
- case SIGFPE:
- case SIGBUS:
- case SIGEMT:
- err |= __put_user ((long)info->si_addr, &sf->info.si_addr);
- err |= __put_user (info->si_trapno, &sf->info.si_trapno);
- break;
- default:
- err |= __put_user (info->si_pid, &sf->info.si_pid);
- err |= __put_user (info->si_uid, &sf->info.si_uid);
- break;
- }
- }
+ /* Update the siginfo structure. */
+ err |= copy_siginfo_to_user32(&sf->info, info);
/* Setup sigaltstack */
err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp);
@@ -1174,7 +1205,7 @@ static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
else if (current->thread.flags & SPARC_FLAG_NEWSIGNALS)
new_setup_frame32(ka, regs, signr, oldset);
else
- setup_frame32(&ka->sa, regs->tpc, regs->tnpc, regs, signr, oldset);
+ setup_frame32(&ka->sa, regs, signr, oldset, info);
}
if(ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 2fa4945d8..6e8899435 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -38,7 +38,7 @@ extern unsigned prom_cpu_nodes[];
struct cpuinfo_sparc cpu_data[NR_CPUS] __attribute__ ((aligned (64)));
-volatile int cpu_number_map[NR_CPUS] __attribute__ ((aligned (64)));
+volatile int __cpu_number_map[NR_CPUS] __attribute__ ((aligned (64)));
volatile int __cpu_logical_map[NR_CPUS] __attribute__ ((aligned (64)));
/* Please don't make this stuff initdata!!! --DaveM */
@@ -243,7 +243,7 @@ void __init smp_boot_cpus(void)
udelay(100);
}
if(callin_flag) {
- cpu_number_map[i] = cpucount;
+ __cpu_number_map[i] = cpucount;
__cpu_logical_map[cpucount] = i;
prom_cpu_nodes[i] = linux_cpus[no].prom_node;
prom_printf("OK\n");
@@ -255,7 +255,7 @@ void __init smp_boot_cpus(void)
}
if(!callin_flag) {
cpu_present_map &= ~(1UL << i);
- cpu_number_map[i] = -1;
+ __cpu_number_map[i] = -1;
}
}
cpu_new_task = NULL;
@@ -697,10 +697,10 @@ void __init smp_tick_init(void)
for(i = 0; i < linux_num_cpus; i++)
cpu_present_map |= (1UL << linux_cpus[i].mid);
for(i = 0; i < NR_CPUS; i++) {
- cpu_number_map[i] = -1;
+ __cpu_number_map[i] = -1;
__cpu_logical_map[i] = -1;
}
- cpu_number_map[boot_cpu_id] = 0;
+ __cpu_number_map[boot_cpu_id] = 0;
prom_cpu_nodes[boot_cpu_id] = linux_cpus[0].prom_node;
__cpu_logical_map[0] = boot_cpu_id;
current->processor = boot_cpu_id;
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index aa28151c8..418b2f7b2 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -185,8 +185,8 @@ EXPORT_SYMBOL(request_fast_irq);
EXPORT_SYMBOL(sbus_root);
EXPORT_SYMBOL(dma_chain);
EXPORT_SYMBOL(sbus_set_sbus64);
-EXPORT_SYMBOL(sbus_alloc_consistant);
-EXPORT_SYMBOL(sbus_free_consistant);
+EXPORT_SYMBOL(sbus_alloc_consistent);
+EXPORT_SYMBOL(sbus_free_consistent);
EXPORT_SYMBOL(sbus_map_single);
EXPORT_SYMBOL(sbus_unmap_single);
EXPORT_SYMBOL(sbus_map_sg);
@@ -209,6 +209,16 @@ EXPORT_SYMBOL(insb);
EXPORT_SYMBOL(insw);
EXPORT_SYMBOL(insl);
#endif
+#ifdef NEW_PCI_DMA_MAP
+EXPORT_SYMBOL(pci_alloc_consistent);
+EXPORT_SYMBOL(pci_free_consistent);
+EXPORT_SYMBOL(pci_map_single);
+EXPORT_SYMBOL(pci_unmap_single);
+EXPORT_SYMBOL(pci_map_sg);
+EXPORT_SYMBOL(pci_unmap_sg);
+EXPORT_SYMBOL(pci_dma_sync_single);
+EXPORT_SYMBOL(pci_dma_sync_sg);
+#endif
/* Solaris/SunOS binary compatibility */
EXPORT_SYMBOL(_sigpause_common);
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
index af4743ec1..3c3a5c1c6 100644
--- a/arch/sparc64/kernel/sys_sparc.c
+++ b/arch/sparc64/kernel/sys_sparc.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.33 2000/01/11 17:33:25 jj Exp $
+/* $Id: sys_sparc.c,v 1.34 2000/01/21 11:39:06 jj Exp $
* linux/arch/sparc64/kernel/sys_sparc.c
*
* This file contains various random system calls that
@@ -223,11 +223,18 @@ c_sys_nis_syscall (struct pt_regs *regs)
asmlinkage void
sparc_breakpoint (struct pt_regs *regs)
{
+ siginfo_t info;
+
lock_kernel();
#ifdef DEBUG_SPARC_BREAKPOINT
printk ("TRAP: Entering kernel PC=%lx, nPC=%lx\n", regs->tpc, regs->tnpc);
#endif
- force_sig(SIGTRAP, current);
+ info.si_signo = SIGTRAP;
+ info.si_errno = 0;
+ info.si_code = TRAP_BRKPT;
+ info.si_addr = (void *)regs->tpc;
+ info.si_trapno = 0;
+ force_sig_info(SIGTRAP, &info, current);
#ifdef DEBUG_SPARC_BREAKPOINT
printk ("TRAP: Returning to space: PC=%lx nPC=%lx\n", regs->tpc, regs->tnpc);
#endif
@@ -241,7 +248,7 @@ asmlinkage int sys_getdomainname(char *name, int len)
int nlen;
int err = -EFAULT;
- down(&uts_sem);
+ down_read(&uts_sem);
nlen = strlen(system_utsname.domainname) + 1;
@@ -253,7 +260,7 @@ asmlinkage int sys_getdomainname(char *name, int len)
goto done;
err = 0;
done:
- up(&uts_sem);
+ up_read(&uts_sem);
return err;
}
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index 408368060..61b9a3397 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.130 2000/01/14 09:40:07 jj Exp $
+/* $Id: sys_sparc32.c,v 1.131 2000/01/21 11:38:54 jj Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -2082,7 +2082,7 @@ sys32_rt_sigtimedwait(sigset_t32 *uthese, siginfo_t32 *uinfo,
sigset_t s;
sigset_t32 s32;
struct timespec t;
- int ret, err, i;
+ int ret;
mm_segment_t old_fs = get_fs();
siginfo_t info;
@@ -2104,42 +2104,8 @@ sys32_rt_sigtimedwait(sigset_t32 *uthese, siginfo_t32 *uinfo,
ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize);
set_fs (old_fs);
if (ret >= 0 && uinfo) {
- err = put_user (info.si_signo, &uinfo->si_signo);
- err |= __put_user (info.si_errno, &uinfo->si_errno);
- err |= __put_user (info.si_code, &uinfo->si_code);
- if (info.si_code < 0)
- err |= __copy_to_user (uinfo->_sifields._pad, info._sifields._pad, SI_PAD_SIZE);
- else {
- i = info.si_signo;
- if (info.si_code == SI_USER)
- i = SIGRTMIN;
- switch (i) {
- case SIGPOLL:
- err |= __put_user (info.si_band, &uinfo->si_band);
- err |= __put_user (info.si_fd, &uinfo->si_fd);
- break;
- case SIGCHLD:
- err |= __put_user (info.si_pid, &uinfo->si_pid);
- err |= __put_user (info.si_uid, &uinfo->si_uid);
- err |= __put_user (info.si_status, &uinfo->si_status);
- err |= __put_user (info.si_utime, &uinfo->si_utime);
- err |= __put_user (info.si_stime, &uinfo->si_stime);
- break;
- case SIGSEGV:
- case SIGILL:
- case SIGFPE:
- case SIGBUS:
- case SIGEMT:
- err |= __put_user ((long)info.si_addr, &uinfo->si_addr);
- err |= __put_user (info.si_trapno, &uinfo->si_trapno);
- break;
- default:
- err |= __put_user (info.si_pid, &uinfo->si_pid);
- err |= __put_user (info.si_uid, &uinfo->si_uid);
- break;
- }
- }
- if (err)
+ extern int copy_siginfo_to_user32(siginfo_t32 *, siginfo_t *);
+ if (copy_siginfo_to_user32(uinfo, &info))
ret = -EFAULT;
}
return ret;
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
index ffc72b74d..6beb0531f 100644
--- a/arch/sparc64/kernel/sys_sunos32.c
+++ b/arch/sparc64/kernel/sys_sunos32.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.35 2000/01/06 23:51:50 davem Exp $
+/* $Id: sys_sunos32.c,v 1.37 2000/01/21 11:39:03 jj Exp $
* sys_sunos32.c: SunOS binary compatability layer on sparc64.
*
* Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -323,6 +323,7 @@ asmlinkage u32 sunos_sigblock(u32 blk_mask)
spin_lock_irq(&current->sigmask_lock);
old = (u32) current->blocked.sig[0];
current->blocked.sig[0] |= (blk_mask & _BLOCKABLE);
+ recalc_sigpending(current);
spin_unlock_irq(&current->sigmask_lock);
return old;
}
@@ -334,6 +335,7 @@ asmlinkage u32 sunos_sigsetmask(u32 newmask)
spin_lock_irq(&current->sigmask_lock);
retval = (u32) current->blocked.sig[0];
current->blocked.sig[0] = (newmask & _BLOCKABLE);
+ recalc_sigpending(current);
spin_unlock_irq(&current->sigmask_lock);
return retval;
}
@@ -541,29 +543,36 @@ asmlinkage int sunos_uname(struct sunos_utsname *name)
{
int ret;
- down(&uts_sem);
+ down_read(&uts_sem);
ret = copy_to_user(&name->sname[0], &system_utsname.sysname[0], sizeof(name->sname) - 1);
ret |= copy_to_user(&name->nname[0], &system_utsname.nodename[0], sizeof(name->nname) - 1);
ret |= put_user('\0', &name->nname[8]);
ret |= copy_to_user(&name->rel[0], &system_utsname.release[0], sizeof(name->rel) - 1);
ret |= copy_to_user(&name->ver[0], &system_utsname.version[0], sizeof(name->ver) - 1);
ret |= copy_to_user(&name->mach[0], &system_utsname.machine[0], sizeof(name->mach) - 1);
- up(&uts_sem);
+ up_read(&uts_sem);
return ret;
}
asmlinkage int sunos_nosys(void)
{
struct pt_regs *regs;
+ siginfo_t info;
+ static int cnt;
lock_kernel();
regs = current->thread.kregs;
- current->thread.sig_address = regs->tpc;
- current->thread.sig_desc = regs->u_regs[UREG_G1];
- send_sig(SIGSYS, current, 1);
- printk("Process makes ni_syscall number %d, register dump:\n",
- (int) regs->u_regs[UREG_G1]);
- show_regs(regs);
+ info.si_signo = SIGSYS;
+ info.si_errno = 0;
+ info.si_code = __SI_FAULT|0x100;
+ info.si_addr = (void *)regs->tpc;
+ info.si_trapno = regs->u_regs[UREG_G1];
+ send_sig_info(SIGSYS, &info, current);
+ if (cnt++ < 4) {
+ printk("Process makes ni_syscall number %d, register dump:\n",
+ (int) regs->u_regs[UREG_G1]);
+ show_regs(regs);
+ }
unlock_kernel();
return -ENOSYS;
}
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index b66a116b4..2c61f6623 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.65 2000/01/14 07:12:34 davem Exp $
+/* $Id: systbls.S,v 1.66 2000/01/16 06:20:48 davem Exp $
* systbls.S: System call entry point tables for OS compatibility.
* The native Linux system call table lives here also.
*
@@ -34,15 +34,15 @@ sys_call_table32:
/*60*/ .word sys_umask, sys_chroot, sys32_newfstat, sys_fstat64, sys_getpagesize
.word sys_msync, sys_vfork, sys32_pread, sys32_pwrite, sys_geteuid
/*70*/ .word sys_getegid, sys32_mmap, sys_setreuid, sys_munmap, sys_mprotect
- .word sys_setregid, sys_vhangup, sys32_truncate64, sys_getgroups, sys32_getgroups16
+ .word sys_nis_syscall, sys_vhangup, sys32_truncate64, sys_nis_syscall, sys32_getgroups16
/*80*/ .word sys32_setgroups16, sys_getpgrp, sys_setgroups, sys32_setitimer, sys32_ftruncate64
.word sys_swapon, sys32_getitimer, sys_setuid, sys_sethostname, sys_setgid
/*90*/ .word sys_dup2, sys_setfsuid, sys32_fcntl, sys32_select, sys_setfsgid
.word sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
/*100*/ .word sys_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending
.word sys32_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_setresuid, sys_getresuid
-/*110*/ .word sys_setresgid, sys_getresgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
- .word sys_nis_syscall, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
+/*110*/ .word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall
+ .word sys_getgroups, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
/*120*/ .word sys32_readv, sys32_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod
.word sys_nis_syscall, sys32_setreuid16, sys32_setregid16, sys_rename, sys_truncate
/*130*/ .word sys_ftruncate, sys_flock, sys_lstat64, sys_nis_syscall, sys_nis_syscall
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 845809709..29032a901 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -1,8 +1,8 @@
-/* $Id: traps.c,v 1.64 1999/12/19 23:53:13 davem Exp $
+/* $Id: traps.c,v 1.65 2000/01/21 11:39:01 jj Exp $
* arch/sparc64/kernel/traps.c
*
* Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1997,1999 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997,1999,2000 Jakub Jelinek (jakub@redhat.com)
*/
/*
@@ -253,6 +253,8 @@ void rtrap_check(struct pt_regs *regs)
void bad_trap (struct pt_regs *regs, long lvl)
{
+ siginfo_t info;
+
lock_kernel ();
if (lvl < 0x100) {
char buffer[24];
@@ -262,9 +264,12 @@ void bad_trap (struct pt_regs *regs, long lvl)
}
if (regs->tstate & TSTATE_PRIV)
die_if_kernel ("Kernel bad trap", regs);
- current->thread.sig_desc = SUBSIG_BADTRAP(lvl - 0x100);
- current->thread.sig_address = regs->tpc;
- force_sig(SIGILL, current);
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = ILL_ILLTRP;
+ info.si_addr = (void *)regs->tpc;
+ info.si_trapno = lvl - 0x100;
+ force_sig_info(SIGILL, &info, current);
unlock_kernel ();
}
@@ -281,6 +286,8 @@ void bad_trap_tl1 (struct pt_regs *regs, long lvl)
void instruction_access_exception (struct pt_regs *regs,
unsigned long sfsr, unsigned long sfar)
{
+ siginfo_t info;
+
lock_kernel();
if (regs->tstate & TSTATE_PRIV) {
#if 1
@@ -289,15 +296,20 @@ void instruction_access_exception (struct pt_regs *regs,
#endif
die_if_kernel("Iax", regs);
}
- current->thread.sig_desc = SUBSIG_ILLINST;
- current->thread.sig_address = regs->tpc;
- force_sig(SIGILL, current);
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = SEGV_MAPERR;
+ info.si_addr = (void *)regs->tpc;
+ info.si_trapno = 0;
+ force_sig_info(SIGSEGV, &info, current);
unlock_kernel();
}
void data_access_exception (struct pt_regs *regs,
unsigned long sfsr, unsigned long sfar)
{
+ siginfo_t info;
+
if (regs->tstate & TSTATE_PRIV) {
/* Test if this comes from uaccess places. */
unsigned long fixup, g2;
@@ -326,8 +338,13 @@ void data_access_exception (struct pt_regs *regs,
else
rtrap_check(regs);
#endif
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = SEGV_MAPERR;
+ info.si_addr = (void *)sfar;
+ info.si_trapno = 0;
lock_kernel();
- force_sig(SIGSEGV, current);
+ force_sig_info(SIGSEGV, &info, current);
unlock_kernel();
}
@@ -361,6 +378,22 @@ static __inline__ void clean_and_reenable_l1_caches(void)
: "memory");
}
+void do_iae(struct pt_regs *regs)
+{
+ siginfo_t info;
+
+ clean_and_reenable_l1_caches();
+
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_OBJERR;
+ info.si_addr = (void *)0;
+ info.si_trapno = 0;
+ lock_kernel();
+ force_sig_info(SIGBUS, &info, current);
+ unlock_kernel();
+}
+
void do_dae(struct pt_regs *regs)
{
#ifdef CONFIG_PCI
@@ -381,19 +414,7 @@ void do_dae(struct pt_regs *regs)
return;
}
#endif
- clean_and_reenable_l1_caches();
- lock_kernel();
- force_sig(SIGSEGV, current);
- unlock_kernel();
-}
-
-void do_iae(struct pt_regs *regs)
-{
- clean_and_reenable_l1_caches();
-
- lock_kernel();
- force_sig(SIGSEGV, current);
- unlock_kernel();
+ do_iae(regs);
}
static char ecc_syndrome_table[] = {
@@ -521,22 +542,26 @@ void do_fpe_common(struct pt_regs *regs)
regs->tnpc += 4;
} else {
unsigned long fsr = current->thread.xfsr[0];
+ siginfo_t info;
- current->thread.sig_address = regs->tpc;
- current->thread.sig_desc = SUBSIG_FPERROR;
+ info.si_signo = SIGFPE;
+ info.si_errno = 0;
+ info.si_addr = (void *)regs->tpc;
+ info.si_trapno = 0;
+ info.si_code = __SI_FAULT;
if ((fsr & 0x1c000) == (1 << 14)) {
- if (fsr & 0x01)
- current->thread.sig_desc = SUBSIG_FPINEXACT;
- else if (fsr & 0x02)
- current->thread.sig_desc = SUBSIG_FPDIVZERO;
- else if (fsr & 0x04)
- current->thread.sig_desc = SUBSIG_FPUNFLOW;
+ if (fsr & 0x10)
+ info.si_code = FPE_FLTINV;
else if (fsr & 0x08)
- current->thread.sig_desc = SUBSIG_FPOVFLOW;
- else if (fsr & 0x10)
- current->thread.sig_desc = SUBSIG_FPINTOVFL;
+ info.si_code = FPE_FLTOVF;
+ else if (fsr & 0x04)
+ info.si_code = FPE_FLTUND;
+ else if (fsr & 0x02)
+ info.si_code = FPE_FLTDIV;
+ else if (fsr & 0x01)
+ info.si_code = FPE_FLTRES;
}
- send_sig(SIGFPE, current, 1);
+ send_sig_info(SIGFPE, &info, current);
}
}
@@ -570,24 +595,34 @@ void do_fpother(struct pt_regs *regs)
void do_tof(struct pt_regs *regs)
{
+ siginfo_t info;
+
if(regs->tstate & TSTATE_PRIV)
die_if_kernel("Penguin overflow trap from kernel mode", regs);
- current->thread.sig_address = regs->tpc;
- current->thread.sig_desc = SUBSIG_TAG; /* as good as any */
- send_sig(SIGEMT, current, 1);
+ info.si_signo = SIGEMT;
+ info.si_errno = 0;
+ info.si_code = EMT_TAGOVF;
+ info.si_addr = (void *)regs->tpc;
+ info.si_trapno = 0;
+ send_sig_info(SIGEMT, &info, current);
}
void do_div0(struct pt_regs *regs)
{
- current->thread.sig_address = regs->tpc;
- current->thread.sig_desc = SUBSIG_IDIVZERO;
- send_sig(SIGFPE, current, 1);
+ siginfo_t info;
+
+ info.si_signo = SIGFPE;
+ info.si_errno = 0;
+ info.si_code = FPE_INTDIV;
+ info.si_addr = (void *)regs->tpc;
+ info.si_trapno = 0;
+ send_sig_info(SIGFPE, &info, current);
}
void instruction_dump (unsigned int *pc)
{
int i;
-
+
if((((unsigned long) pc) & 3))
return;
@@ -671,6 +706,7 @@ void do_illegal_instruction(struct pt_regs *regs)
unsigned long pc = regs->tpc;
unsigned long tstate = regs->tstate;
u32 insn;
+ siginfo_t info;
if(tstate & TSTATE_PRIV)
die_if_kernel("Kernel illegal instruction", regs);
@@ -685,56 +721,48 @@ void do_illegal_instruction(struct pt_regs *regs)
return;
}
}
- current->thread.sig_address = pc;
- current->thread.sig_desc = SUBSIG_ILLINST;
- send_sig(SIGILL, current, 1);
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = ILL_ILLOPC;
+ info.si_addr = (void *)pc;
+ info.si_trapno = 0;
+ send_sig_info(SIGILL, &info, current);
}
void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr)
{
+ siginfo_t info;
+
if(regs->tstate & TSTATE_PRIV) {
extern void kernel_unaligned_trap(struct pt_regs *regs,
unsigned int insn,
unsigned long sfar, unsigned long sfsr);
return kernel_unaligned_trap(regs, *((unsigned int *)regs->tpc), sfar, sfsr);
- } else {
- current->thread.sig_address = regs->tpc;
- current->thread.sig_desc = SUBSIG_PRIVINST;
- send_sig(SIGBUS, current, 1);
}
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_ADRALN;
+ info.si_addr = (void *)sfar;
+ info.si_trapno = 0;
+ send_sig_info(SIGBUS, &info, current);
}
void do_privop(struct pt_regs *regs)
{
- current->thread.sig_address = regs->tpc;
- current->thread.sig_desc = SUBSIG_PRIVINST;
- send_sig(SIGILL, current, 1);
-}
-
-void do_privact(struct pt_regs *regs)
-{
- current->thread.sig_address = regs->tpc;
- current->thread.sig_desc = SUBSIG_PRIVINST;
- send_sig(SIGILL, current, 1);
-}
+ siginfo_t info;
-void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
- unsigned long tstate)
-{
- if(tstate & TSTATE_PRIV)
- die_if_kernel("Penguin instruction from Penguin mode??!?!", regs);
- current->thread.sig_address = pc;
- current->thread.sig_desc = SUBSIG_PRIVINST;
- send_sig(SIGILL, current, 1);
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = ILL_PRVOPC;
+ info.si_addr = (void *)regs->tpc;
+ info.si_trapno = 0;
+ send_sig_info(SIGILL, &info, current);
}
-void handle_hw_divzero(struct pt_regs *regs, unsigned long pc,
- unsigned long npc, unsigned long psr)
+void do_privact(struct pt_regs *regs)
{
- current->thread.sig_address = regs->tpc;
- current->thread.sig_desc = SUBSIG_IDIVZERO;
- send_sig(SIGFPE, current, 1);
+ do_privop(regs);
}
/* Trap level 1 stuff or other traps we should never see... */
diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile
index 90d1c4e7c..f3067cad6 100644
--- a/arch/sparc64/lib/Makefile
+++ b/arch/sparc64/lib/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.19 1999/07/03 22:11:08 davem Exp $
+# $Id: Makefile,v 1.20 2000/01/19 04:06:03 davem Exp $
# Makefile for Sparc library files..
#
@@ -6,8 +6,8 @@ CFLAGS := $(CFLAGS)
OBJS = PeeCeeI.o blockops.o debuglocks.o strlen.o strncmp.o \
memscan.o strncpy_from_user.o strlen_user.o memcmp.o checksum.o \
- VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o VISsave.o \
- atomic.o rwlock.o
+ VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o \
+ VIScsumcopyusr.o VISsave.o atomic.o rwlock.o
lib.a: $(OBJS)
$(AR) rcs lib.a $(OBJS)
diff --git a/arch/sparc64/lib/VIScsumcopy.S b/arch/sparc64/lib/VIScsumcopy.S
index dbf89b4f6..3f89eea29 100644
--- a/arch/sparc64/lib/VIScsumcopy.S
+++ b/arch/sparc64/lib/VIScsumcopy.S
@@ -1,4 +1,4 @@
-/* $Id: VIScsumcopy.S,v 1.6 1999/05/25 16:53:03 jj Exp $
+/* $Id: VIScsumcopy.S,v 1.7 2000/01/19 04:06:03 davem Exp $
* VIScsumcopy.S: High bandwidth IP checksumming with simultaneous
* copying utilizing the UltraSparc Visual Instruction Set.
*
@@ -75,7 +75,7 @@
membar #Sync
-#define DO_THE_TRICK(f0,f2,f4,f6,f8,f10,f12,f14,F0,F2,F4,F6,F8,F10,F12,F14,DUMMY1,A0,A2,A4,A6,A8,A10,A12,A14,B14,DYMMY2,LOAD,STORE1,STORE2,STORE3,STORE4,STORE5,STORE6,STORE7,STORE8,DUMMY3,BRANCH...) \
+#define DO_THE_TRICK(f0,f2,f4,f6,f8,f10,f12,f14,F0,F2,F4,F6,F8,F10,F12,F14,DUMMY1,A0,A2,A4,A6,A8,A10,A12,A14,B14,DUMMY2,LOAD,STORE1,STORE2,STORE3,STORE4,STORE5,STORE6,STORE7,STORE8,DUMMY3,BRANCH...) \
LOAD /* Load Group */; \
faligndata %A14, %F0, %A14 /* FPA Group */; \
inc %x5 /* IEU0 */; \
diff --git a/arch/sparc64/lib/VIScsumcopyusr.S b/arch/sparc64/lib/VIScsumcopyusr.S
new file mode 100644
index 000000000..17bbe78b1
--- /dev/null
+++ b/arch/sparc64/lib/VIScsumcopyusr.S
@@ -0,0 +1,914 @@
+/* $Id: VIScsumcopyusr.S,v 1.1 2000/01/19 04:06:04 davem Exp $
+ * VIScsumcopyusr.S: High bandwidth IP checksumming with simultaneous
+ * copying utilizing the UltraSparc Visual Instruction Set.
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 2000 David S. Miller (davem@redhat.com)
+ *
+ * Based on older sparc32/sparc64 checksum.S, which is:
+ *
+ * Copyright(C) 1995 Linus Torvalds
+ * Copyright(C) 1995 Miguel de Icaza
+ * Copyright(C) 1996,1997 David S. Miller
+ * derived from:
+ * Linux/Alpha checksum c-code
+ * Linux/ix86 inline checksum assembly
+ * RFC1071 Computing the Internet Checksum (esp. Jacobsons m68k code)
+ * David Mosberger-Tang for optimized reference c-code
+ * BSD4.4 portable checksum routine
+ */
+
+#ifdef __sparc_v9__
+#define STACKOFF 0x7ff+128
+#else
+#define STACKOFF 64
+#endif
+
+#ifdef __KERNEL__
+#include <asm/head.h>
+#include <asm/asi.h>
+#include <asm/page.h>
+#include <asm/visasm.h>
+#define ASI_BLK_XOR 0
+#define ASI_BLK_XOR1 (ASI_BLK_P ^ (ASI_BLK_P >> 3) ^ ASI_P)
+#define ASI_BLK_OR (ASI_BLK_P & ~ASI_P)
+#else
+#define ASI_P 0x80
+#define ASI_BLK_P 0xf0
+#define FRPS_FEF 0x04
+#define FPRS_DU 0x02
+#define FPRS_DL 0x01
+#define ASI_BLK_XOR (ASI_BLK_P ^ ASI_P)
+#endif
+
+#define src o0
+#define dst o1
+#define len o2
+#define sum o3
+#define x1 g1
+#define x2 g2
+#define x3 o4
+#define x4 g4
+#define x5 g5
+#define x6 g7
+#define x7 g3
+#define x8 o5
+
+/* Dobrou noc, SunSoft engineers. Spete sladce.
+ * This has a couple of tricks in and those
+ * tricks are UltraLinux trade secrets :))
+ * Once AGAIN, the SunSoft engineers are caught
+ * asleep at the keyboard :)).
+ * The main loop does about 20 superscalar cycles
+ * per 64bytes checksummed/copied.
+ */
+
+#define LDBLK(O0) \
+ ldda [%src] ASI_BLK_P, %O0 /* Load Group */
+
+#define STBLK \
+ stda %f48, [%dst] %asi /* Store */
+
+#ifdef __KERNEL__
+#define STBLK_XORASI(tmpreg1,tmpreg2) \
+ stda %f48, [%dst] %asi /* Store */; \
+ rd %asi, %tmpreg1; \
+ srl %tmpreg1, 3, %tmpreg2; \
+ xor %tmpreg1, ASI_BLK_XOR1, %tmpreg1; \
+ wr %tmpreg1, %tmpreg2, %asi;
+#else
+#define STBLK_XORASI(tmpreg1,tmpreg2) \
+ stda %f48, [%dst] %asi /* Store */; \
+ rd %asi, %tmpreg1; \
+ wr %tmpreg1, ASI_BLK_XOR, %asi;
+#endif
+
+#define ST(fx,off) \
+ stda %fx, [%dst + off] %asi /* Store */
+
+#define SYNC \
+ membar #Sync
+
+
+#define DO_THE_TRICK(f0,f2,f4,f6,f8,f10,f12,f14,F0,F2,F4,F6,F8,F10,F12,F14,DUMMY1,A0,A2,A4,A6,A8,A10,A12,A14,B14,DUMMY2,LOAD,STORE1,STORE2,STORE3,STORE4,STORE5,STORE6,STORE7,STORE8,DUMMY3,BRANCH...) \
+ LOAD /* Load Group */; \
+ faligndata %A14, %F0, %A14 /* FPA Group */; \
+ inc %x5 /* IEU0 */; \
+ STORE1 /* Store (optional) */; \
+ faligndata %F0, %F2, %A0 /* FPA Group */; \
+ srl %x5, 1, %x5 /* IEU0 */; \
+ add %sum, %x4, %sum /* IEU1 */; \
+ fpadd32 %F0, %f0, %F0 /* FPA Group */; \
+ inc %x6 /* IEU0 */; \
+ STORE2 /* Store (optional) */; \
+ faligndata %F2, %F4, %A2 /* FPA Group */; \
+ srl %x6, 1, %x6 /* IEU0 */; \
+ add %sum, %x5, %sum /* IEU1 */; \
+ fpadd32 %F2, %f2, %F2 /* FPA Group */; \
+ add %src, 64, %src /* IEU0 */; \
+ add %dst, 64, %dst /* IEU1 */; \
+ fcmpgt32 %f0, %F0, %x1 /* FPM Group */; \
+ inc %x7 /* IEU0 */; \
+ STORE3 /* Store (optional) */; \
+ faligndata %F4, %F6, %A4 /* FPA */; \
+ srl %x7, 1, %x7 /* IEU0 Group */; \
+ add %sum, %x6, %sum /* IEU1 */; \
+ fpadd32 %F4, %f4, %F4 /* FPA */; \
+ fcmpgt32 %f2, %F2, %x2 /* FPM Group */; \
+ inc %x8 /* IEU0 */; \
+ STORE4 /* Store (optional) */; \
+ faligndata %F6, %F8, %A6 /* FPA */; \
+ srl %x8, 1, %x8 /* IEU0 Group */; \
+ add %sum, %x7, %sum /* IEU1 */; \
+ fpadd32 %F6, %f6, %F6 /* FPA */; \
+ fcmpgt32 %f4, %F4, %x3 /* FPM Group */; \
+ inc %x1 /* IEU0 */; \
+ STORE5 /* Store (optional) */; \
+ faligndata %F8, %F10, %A8 /* FPA */; \
+ srl %x1, 1, %x1 /* IEU0 Group */; \
+ add %sum, %x8, %sum /* IEU1 */; \
+ fpadd32 %F8, %f8, %F8 /* FPA */; \
+ fcmpgt32 %f6, %F6, %x4 /* FPM Group */; \
+ inc %x2 /* IEU0 */; \
+ STORE6 /* Store (optional) */; \
+ faligndata %F10, %F12, %A10 /* FPA */; \
+ srl %x2, 1, %x2 /* IEU0 Group */; \
+ add %sum, %x1, %sum /* IEU1 */; \
+ fpadd32 %F10, %f10, %F10 /* FPA */; \
+ fcmpgt32 %f8, %F8, %x5 /* FPM Group */; \
+ inc %x3 /* IEU0 */; \
+ STORE7 /* Store (optional) */; \
+ faligndata %F12, %F14, %A12 /* FPA */; \
+ srl %x3, 1, %x3 /* IEU0 Group */; \
+ add %sum, %x2, %sum /* IEU1 */; \
+ fpadd32 %F12, %f12, %F12 /* FPA */; \
+ fcmpgt32 %f10, %F10, %x6 /* FPM Group */; \
+ inc %x4 /* IEU0 */; \
+ STORE8 /* Store (optional) */; \
+ fmovd %F14, %B14 /* FPA */; \
+ srl %x4, 1, %x4 /* IEU0 Group */; \
+ add %sum, %x3, %sum /* IEU1 */; \
+ fpadd32 %F14, %f14, %F14 /* FPA */; \
+ fcmpgt32 %f12, %F12, %x7 /* FPM Group */; \
+ subcc %len, 64, %len /* IEU1 */; \
+ BRANCH /* CTI */; \
+ fcmpgt32 %f14, %F14, %x8 /* FPM Group */; \
+
+#define END_THE_TRICK(f0,f2,f4,f6,f8,f10,f12,f14,FA,FB,S0,S1,S2,S3,T0,T1,U0,fz) \
+ inc %x5 /* IEU0 Group */; \
+ fpadd32 %f2, %f0, %S0 /* FPA */; \
+ srl %x5, 1, %x5 /* IEU0 Group */; \
+ add %sum, %x4, %sum /* IEU1 */; \
+ fpadd32 %f6, %f4, %S1 /* FPA */; \
+ inc %x6 /* IEU0 Group */; \
+ add %sum, %x5, %sum /* IEU1 */; \
+ fcmpgt32 %f0, %S0, %x1 /* FPM Group */; \
+ srl %x6, 1, %x6 /* IEU0 */; \
+ inc %x7 /* IEU1 */; \
+ fpadd32 %f10, %f8, %S2 /* FPA */; \
+ fcmpgt32 %f4, %S1, %x2 /* FPM Group */; \
+ srl %x7, 1, %x7 /* IEU0 */; \
+ add %sum, %x6, %sum /* IEU1 */; \
+ fpadd32 %f14, %f12, %S3 /* FPA */; \
+ inc %x8 /* IEU0 Group */; \
+ add %sum, %x7, %sum /* IEU1 */; \
+ fzero %fz /* FPA */; \
+ fcmpgt32 %f8, %S2, %x3 /* FPM Group */; \
+ srl %x8, 1, %x8 /* IEU0 */; \
+ inc %x1 /* IEU1 */; \
+ fpadd32 %S0, %S1, %T0 /* FPA */; \
+ fcmpgt32 %f12, %S3, %x4 /* FPM Group */; \
+ srl %x1, 1, %x1 /* IEU0 */; \
+ add %sum, %x8, %sum /* IEU1 */; \
+ fpadd32 %S2, %S3, %T1 /* FPA */; \
+ inc %x2 /* IEU0 Group */; \
+ add %sum, %x1, %sum /* IEU1 */; \
+ fcmpgt32 %S0, %T0, %x5 /* FPM Group */; \
+ srl %x2, 1, %x2 /* IEU0 */; \
+ inc %x3 /* IEU1 */; \
+ fcmpgt32 %S2, %T1, %x6 /* FPM Group */; \
+ srl %x3, 1, %x3 /* IEU0 */; \
+ add %sum, %x2, %sum /* IEU1 */; \
+ inc %x4 /* IEU0 Group */; \
+ add %sum, %x3, %sum /* IEU1 */; \
+ fcmpgt32 %fz, %f2, %x7 /* FPM Group */; \
+ srl %x4, 1, %x4 /* IEU0 */; \
+ inc %x5 /* IEU1 */; \
+ fpadd32 %T0, %T1, %U0 /* FPA */; \
+ fcmpgt32 %fz, %f6, %x8 /* FPM Group */; \
+ srl %x5, 1, %x5 /* IEU0 */; \
+ add %sum, %x4, %sum /* IEU1 */; \
+ inc %x6 /* IEU0 Group */; \
+ add %sum, %x5, %sum /* IEU1 */; \
+ fcmpgt32 %fz, %f10, %x1 /* FPM Group */; \
+ srl %x6, 1, %x6 /* IEU0 */; \
+ inc %x7 /* IEU1 */; \
+ fcmpgt32 %fz, %f14, %x2 /* FPM Group */; \
+ ba,pt %xcc, ett /* CTI */; \
+ fmovd %FA, %FB /* FPA */; \
+
+#define END_THE_TRICK1(f0,f2,f4,f6,f8,f10,f12,f14,FA,FB) \
+ END_THE_TRICK(f0,f2,f4,f6,f8,f10,f12,f14,FA,FB,f48,f50,f52,f54,f56,f58,f60,f62)
+
+#define END_THE_TRICK2(S0,S1,S2,S3,T0,T1,U0,U1,V0,fz) \
+ fpadd32 %U0, %U1, %V0 /* FPA Group */; \
+ srl %x7, 1, %x7 /* IEU0 */; \
+ add %sum, %x6, %sum /* IEU1 */; \
+ std %V0, [%sp + STACKOFF] /* Store Group */; \
+ inc %x8 /* IEU0 */; \
+ sub %sum, %x7, %sum /* IEU1 */; \
+ fcmpgt32 %fz, %S1, %x3 /* FPM Group */; \
+ srl %x8, 1, %x8 /* IEU0 */; \
+ inc %x1 /* IEU1 */; \
+ fcmpgt32 %fz, %S3, %x4 /* FPM Group */; \
+ srl %x1, 1, %x1 /* IEU0 */; \
+ sub %sum, %x8, %sum /* IEU1 */; \
+ ldx [%sp + STACKOFF], %x8 /* Load Group */; \
+ inc %x2 /* IEU0 */; \
+ sub %sum, %x1, %sum /* IEU1 */; \
+ fcmpgt32 %fz, %T1, %x5 /* FPM Group */; \
+ srl %x2, 1, %x2 /* IEU0 */; \
+ inc %x3 /* IEU1 */; \
+ fcmpgt32 %T0, %U0, %x6 /* FPM Group */; \
+ srl %x3, 1, %x3 /* IEU0 */; \
+ sub %sum, %x2, %sum /* IEU1 */; \
+ inc %x4 /* IEU0 Group */; \
+ sub %sum, %x3, %sum /* IEU1 */; \
+ fcmpgt32 %fz, %U1, %x7 /* FPM Group */; \
+ srl %x4, 1, %x4 /* IEU0 */; \
+ inc %x5 /* IEU1 */; \
+ fcmpgt32 %U0, %V0, %x1 /* FPM Group */; \
+ srl %x5, 1, %x5 /* IEU0 */; \
+ sub %sum, %x4, %sum /* IEU1 */; \
+ fcmpgt32 %fz, %V0, %x2 /* FPM Group */; \
+ inc %x6 /* IEU0 */; \
+ sub %sum, %x5, %sum /* IEU1 */; \
+ srl %x6, 1, %x6 /* IEU0 Group */; \
+ inc %x7 /* IEU1 */; \
+ srl %x7, 1, %x7 /* IEU0 Group */; \
+ add %sum, %x6, %sum /* IEU1 */; \
+ inc %x1 /* IEU0 Group */; \
+ sub %sum, %x7, %sum /* IEU1 */; \
+ srl %x1, 1, %x1 /* IEU0 Group */; \
+ inc %x2 /* IEU1 */; \
+ srl %x2, 1, %x2 /* IEU0 Group */; \
+ add %sum, %x1, %sum /* IEU1 */; \
+ sub %sum, %x2, %sum /* IEU0 Group */; \
+ addcc %sum, %x8, %sum /* IEU Group */; \
+ bcs,a,pn %xcc, 33f /* CTI */; \
+ add %sum, 1, %sum /* IEU0 */; \
+33: /* That's it */;
+
+ .text
+ .globl csum_partial_copy_user_vis
+ .align 32
+/* %asi should be either ASI_P or ASI_AIUS for csum_partial_copy resp. csum_partial_copy_from_user */
+/* This assumes that !((%src^%dst)&3) && !((%src|%dst)&1) && %len >= 256 */
+csum_partial_copy_user_vis:
+ andcc %dst, 7, %g0 /* IEU1 Group */
+ be,pt %icc, 4f /* CTI */
+ and %dst, 0x38, %o4 /* IEU0 */
+ mov 1, %g5 /* IEU0 Group */
+ andcc %dst, 2, %g0 /* IEU1 */
+ be,pt %icc, 1f /* CTI */
+ and %dst, 4, %g7 /* IEU0 Group */
+ lduh [%src], %g2 /* Load */
+ sub %len, 2, %len /* IEU0 Group */
+ add %dst, 2, %dst /* IEU1 */
+ andcc %dst, 4, %g7 /* IEU1 Group */
+ sll %g5, 16, %g5 /* IEU0 */
+ stha %g2, [%dst - 2] %asi /* Store Group */
+ sll %g2, 16, %g2 /* IEU0 */
+ add %src, 2, %src /* IEU1 */
+ addcc %g2, %sum, %sum /* IEU1 Group */
+ bcs,a,pn %icc, 1f /* CTI */
+ add %sum, %g5, %sum /* IEU0 */
+1: lduw [%src], %g2 /* Load */
+ brz,a,pn %g7, 4f /* CTI+IEU1 Group */
+ and %dst, 0x38, %o4 /* IEU0 */
+ add %dst, 4, %dst /* IEU0 Group */
+ sub %len, 4, %len /* IEU1 */
+ addcc %g2, %sum, %sum /* IEU1 Group */
+ bcs,a,pn %icc, 1f /* CTI */
+ add %sum, 1, %sum /* IEU0 */
+1: and %dst, 0x38, %o4 /* IEU0 Group */
+ stwa %g2, [%dst - 4] %asi /* Store */
+ add %src, 4, %src /* IEU1 */
+4:
+#ifdef __KERNEL__
+ VISEntry
+#endif
+ mov %src, %g7 /* IEU1 Group */
+ fzero %f48 /* FPA */
+ alignaddr %src, %g0, %src /* Single Group */
+ subcc %g7, %src, %g7 /* IEU1 Group */
+ be,pt %xcc, 1f /* CTI */
+ mov 0x40, %g1 /* IEU0 */
+ lduw [%src], %g2 /* Load Group */
+ subcc %sum, %g2, %sum /* IEU1 Group+load stall */
+ bcs,a,pn %icc, 1f /* CTI */
+ sub %sum, 1, %sum /* IEU0 */
+1: srl %sum, 0, %sum /* IEU0 Group */
+ clr %g5 /* IEU1 */
+ brz,pn %o4, 3f /* CTI+IEU1 Group */
+ sub %g1, %o4, %g1 /* IEU0 */
+ ldd [%src], %f0 /* Load */
+ clr %o4 /* IEU0 Group */
+ andcc %dst, 8, %g0 /* IEU1 */
+ be,pn %icc, 1f /* CTI */
+ ldd [%src + 8], %f2 /* Load Group */
+ add %src, 8, %src /* IEU0 */
+ sub %len, 8, %len /* IEU1 */
+ fpadd32 %f0, %f48, %f50 /* FPA */
+ addcc %dst, 8, %dst /* IEU1 Group */
+ faligndata %f0, %f2, %f16 /* FPA */
+ fcmpgt32 %f48, %f50, %o4 /* FPM Group */
+ fmovd %f2, %f0 /* FPA Group */
+ ldd [%src + 8], %f2 /* Load */
+ stda %f16, [%dst - 8] %asi /* Store */
+ fmovd %f50, %f48 /* FPA */
+1: andcc %g1, 0x10, %g0 /* IEU1 Group */
+ be,pn %icc, 1f /* CTI */
+ and %g1, 0x20, %g1 /* IEU0 */
+ fpadd32 %f0, %f48, %f50 /* FPA */
+ ldd [%src + 16], %f4 /* Load Group */
+ add %src, 16, %src /* IEU0 */
+ add %dst, 16, %dst /* IEU1 */
+ faligndata %f0, %f2, %f16 /* FPA */
+ fcmpgt32 %f48, %f50, %g5 /* FPM Group */
+ sub %len, 16, %len /* IEU0 */
+ inc %o4 /* IEU1 */
+ stda %f16, [%dst - 16] %asi /* Store Group */
+ fpadd32 %f2, %f50, %f48 /* FPA */
+ srl %o4, 1, %o5 /* IEU0 */
+ faligndata %f2, %f4, %f18 /* FPA Group */
+ stda %f18, [%dst - 8] %asi /* Store */
+ fcmpgt32 %f50, %f48, %o4 /* FPM Group */
+ add %o5, %sum, %sum /* IEU0 */
+ ldd [%src + 8], %f2 /* Load */
+ fmovd %f4, %f0 /* FPA */
+1: brz,a,pn %g1, 4f /* CTI+IEU1 Group */
+ rd %asi, %g2 /* LSU Group + 4 bubbles */
+ inc %g5 /* IEU0 */
+ fpadd32 %f0, %f48, %f50 /* FPA */
+ ldd [%src + 16], %f4 /* Load Group */
+ srl %g5, 1, %g5 /* IEU0 */
+ add %dst, 32, %dst /* IEU1 */
+ faligndata %f0, %f2, %f16 /* FPA */
+ fcmpgt32 %f48, %f50, %o5 /* FPM Group */
+ inc %o4 /* IEU0 */
+ ldd [%src + 24], %f6 /* Load */
+ srl %o4, 1, %o4 /* IEU0 Group */
+ add %g5, %sum, %sum /* IEU1 */
+ ldd [%src + 32], %f8 /* Load */
+ fpadd32 %f2, %f50, %f48 /* FPA */
+ faligndata %f2, %f4, %f18 /* FPA Group */
+ sub %len, 32, %len /* IEU0 */
+ stda %f16, [%dst - 32] %asi /* Store */
+ fcmpgt32 %f50, %f48, %g3 /* FPM Group */
+ inc %o5 /* IEU0 */
+ add %o4, %sum, %sum /* IEU1 */
+ fpadd32 %f4, %f48, %f50 /* FPA */
+ faligndata %f4, %f6, %f20 /* FPA Group */
+ srl %o5, 1, %o5 /* IEU0 */
+ fcmpgt32 %f48, %f50, %g5 /* FPM Group */
+ add %o5, %sum, %sum /* IEU0 */
+ stda %f18, [%dst - 24] %asi /* Store */
+ fpadd32 %f6, %f50, %f48 /* FPA */
+ inc %g3 /* IEU0 Group */
+ stda %f20, [%dst - 16] %asi /* Store */
+ add %src, 32, %src /* IEU1 */
+ faligndata %f6, %f8, %f22 /* FPA */
+ fcmpgt32 %f50, %f48, %o4 /* FPM Group */
+ srl %g3, 1, %g3 /* IEU0 */
+ stda %f22, [%dst - 8] %asi /* Store */
+ add %g3, %sum, %sum /* IEU0 Group */
+3: rd %asi, %g2 /* LSU Group + 4 bubbles */
+#ifdef __KERNEL__
+4: sethi %hi(vis0s), %g7 /* IEU0 Group */
+ or %g2, ASI_BLK_OR, %g2 /* IEU1 */
+#else
+4: rd %pc, %g7 /* LSU Group + 4 bubbles */
+#endif
+ inc %g5 /* IEU0 Group */
+ and %src, 0x38, %g3 /* IEU1 */
+ membar #StoreLoad /* LSU Group */
+ srl %g5, 1, %g5 /* IEU0 */
+ inc %o4 /* IEU1 */
+ sll %g3, 8, %g3 /* IEU0 Group */
+ sub %len, 0xc0, %len /* IEU1 */
+ addcc %g5, %sum, %sum /* IEU1 Group */
+ srl %o4, 1, %o4 /* IEU0 */
+ add %g7, %g3, %g7 /* IEU0 Group */
+ add %o4, %sum, %sum /* IEU1 */
+#ifdef __KERNEL__
+ jmpl %g7 + %lo(vis0s), %g0 /* CTI+IEU1 Group */
+#else
+ jmpl %g7 + (vis0s - 4b), %g0 /* CTI+IEU1 Group */
+#endif
+ fzero %f32 /* FPA */
+
+ .align 2048
+vis0s: wr %g2, ASI_BLK_XOR, %asi /* LSU Group */
+ ldda [%src] ASI_BLK_P, %f0 /* Load Group */
+ add %src, 64, %src /* IEU0 Group */
+ ldda [%src] ASI_BLK_P, %f16 /* Load Group */
+ add %src, 64, %src /* IEU0 Group */
+ fmovd %f48, %f62 /* FPA Group f0 available */
+ faligndata %f0, %f2, %f48 /* FPA Group f2 available */
+ fcmpgt32 %f32, %f2, %x1 /* FPM Group f4 available */
+ fpadd32 %f0, %f62, %f0 /* FPA */
+ fcmpgt32 %f32, %f4, %x2 /* FPM Group f6 available */
+ faligndata %f2, %f4, %f50 /* FPA */
+ fcmpgt32 %f62, %f0, %x3 /* FPM Group f8 available */
+ faligndata %f4, %f6, %f52 /* FPA */
+ fcmpgt32 %f32, %f6, %x4 /* FPM Group f10 available */
+ inc %x1 /* IEU0 */
+ faligndata %f6, %f8, %f54 /* FPA */
+ fcmpgt32 %f32, %f8, %x5 /* FPM Group f12 available */
+ srl %x1, 1, %x1 /* IEU0 */
+ inc %x2 /* IEU1 */
+ faligndata %f8, %f10, %f56 /* FPA */
+ fcmpgt32 %f32, %f10, %x6 /* FPM Group f14 available */
+ srl %x2, 1, %x2 /* IEU0 */
+ add %sum, %x1, %sum /* IEU1 */
+ faligndata %f10, %f12, %f58 /* FPA */
+ fcmpgt32 %f32, %f12, %x7 /* FPM Group */
+ inc %x3 /* IEU0 */
+ add %sum, %x2, %sum /* IEU1 */
+ faligndata %f12, %f14, %f60 /* FPA */
+ fcmpgt32 %f32, %f14, %x8 /* FPM Group */
+ srl %x3, 1, %x3 /* IEU0 */
+ inc %x4 /* IEU1 */
+ fmovd %f14, %f62 /* FPA */
+ srl %x4, 1, %x4 /* IEU0 Group */
+ add %sum, %x3, %sum /* IEU1 */
+vis0: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30,
+ ,f48,f50,f52,f54,f56,f58,f60,f62,f62,
+ ,LDBLK(f32), STBLK,,,,,,,,
+ ,bcs,pn %icc, vis0e1)
+ DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46,
+ ,f48,f50,f52,f54,f56,f58,f60,f62,f62,
+ ,LDBLK(f0), STBLK,,,,,,,,
+ ,bcs,pn %icc, vis0e2)
+ DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14,
+ ,f48,f50,f52,f54,f56,f58,f60,f62,f62,
+ ,LDBLK(f16), STBLK,,,,,,,,
+ ,bcc,pt %icc, vis0)
+vis0e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30,
+ ,f48,f50,f52,f54,f56,f58,f60,f62,f32,
+ ,SYNC, STBLK_XORASI(x1,x2),ST(f48,64),ST(f50,8),ST(f52,16),ST(f54,24),ST(f56,32),ST(f58,40),ST(f60,48),
+ ,add %dst, 56, %dst; add %len, 192 - 8*8, %len; ba,pt %icc, e2)
+vis0e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46,
+ ,f48,f50,f52,f54,f56,f58,f60,f62,f0,
+ ,SYNC, STBLK_XORASI(x1,x2),ST(f48,64),ST(f50,8),ST(f52,16),ST(f54,24),ST(f56,32),ST(f58,40),ST(f60,48),
+ ,add %dst, 56, %dst; add %len, 192 - 8*8, %len; ba,pt %icc, e3)
+vis0e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14,
+ ,f48,f50,f52,f54,f56,f58,f60,f62,f16,
+ ,SYNC, STBLK_XORASI(x1,x2),ST(f48,64),ST(f50,8),ST(f52,16),ST(f54,24),ST(f56,32),ST(f58,40),ST(f60,48),
+ ,add %dst, 56, %dst; add %len, 192 - 8*8, %len; ba,pt %icc, e1)
+ .align 2048
+vis1s: wr %g2, ASI_BLK_XOR, %asi /* LSU Group */
+ sub %src, 8, %src /* IEU0 Group */
+ ldda [%src] ASI_BLK_P, %f0 /* Load Group */
+ add %src, 64, %src /* IEU0 Group */
+ ldda [%src] ASI_BLK_P, %f16 /* Load Group */
+ add %src, 64, %src /* IEU0 Group */
+ fmovd %f0, %f58 /* FPA Group */
+ fmovd %f48, %f0 /* FPA Group */
+ fcmpgt32 %f32, %f2, %x2 /* FPM Group */
+ faligndata %f2, %f4, %f48 /* FPA */
+ fcmpgt32 %f32, %f4, %x3 /* FPM Group */
+ faligndata %f4, %f6, %f50 /* FPA */
+ fcmpgt32 %f32, %f6, %x4 /* FPM Group */
+ faligndata %f6, %f8, %f52 /* FPA */
+ fcmpgt32 %f32, %f8, %x5 /* FPM Group */
+ inc %x2 /* IEU1 */
+ faligndata %f8, %f10, %f54 /* FPA */
+ fcmpgt32 %f32, %f10, %x6 /* FPM Group */
+ srl %x2, 1, %x2 /* IEU0 */
+ faligndata %f10, %f12, %f56 /* FPA */
+ fcmpgt32 %f32, %f12, %x7 /* FPM Group */
+ inc %x3 /* IEU0 */
+ add %sum, %x2, %sum /* IEU1 */
+ faligndata %f12, %f14, %f58 /* FPA */
+ fcmpgt32 %f32, %f14, %x8 /* FPM Group */
+ srl %x3, 1, %x3 /* IEU0 */
+ inc %x4 /* IEU1 */
+ fmovd %f14, %f60 /* FPA */
+ srl %x4, 1, %x4 /* IEU0 Group */
+ add %sum, %x3, %sum /* IEU1 */
+vis1: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30,
+ ,f62,f48,f50,f52,f54,f56,f58,f60,f60,
+ ,LDBLK(f32), ,STBLK,,,,,,,
+ ,bcs,pn %icc, vis1e1)
+ DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46,
+ ,f62,f48,f50,f52,f54,f56,f58,f60,f60,
+ ,LDBLK(f0), ,STBLK,,,,,,,
+ ,bcs,pn %icc, vis1e2)
+ DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14,
+ ,f62,f48,f50,f52,f54,f56,f58,f60,f60,
+ ,LDBLK(f16), ,STBLK,,,,,,,
+ ,bcc,pt %icc, vis1)
+vis1e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30,
+ ,f62,f48,f50,f52,f54,f56,f58,f60,f32,
+ ,SYNC, ,STBLK_XORASI(x1,x2),ST(f48,0),ST(f50,8),ST(f52,16),ST(f54,24),ST(f56,32),ST(f58,40),
+ ,add %dst, 48, %dst; add %len, 192 - 7*8, %len; ba,pt %icc, e2)
+vis1e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46,
+ ,f62,f48,f50,f52,f54,f56,f58,f60,f0,
+ ,SYNC, ,STBLK_XORASI(x1,x2),ST(f48,0),ST(f50,8),ST(f52,16),ST(f54,24),ST(f56,32),ST(f58,40),
+ ,add %dst, 48, %dst; add %len, 192 - 7*8, %len; ba,pt %icc, e3)
+vis1e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14,
+ ,f62,f48,f50,f52,f54,f56,f58,f60,f16,
+ ,SYNC, ,STBLK_XORASI(x1,x2),ST(f48,0),ST(f50,8),ST(f52,16),ST(f54,24),ST(f56,32),ST(f58,40),
+ ,add %dst, 48, %dst; add %len, 192 - 7*8, %len; ba,pt %icc, e1)
+ .align 2048
+vis2s: wr %g2, ASI_BLK_XOR, %asi /* LSU Group */
+ sub %src, 16, %src /* IEU0 Group */
+ ldda [%src] ASI_BLK_P, %f0 /* Load Group */
+ add %src, 64, %src /* IEU0 Group */
+ ldda [%src] ASI_BLK_P, %f16 /* Load Group */
+ add %src, 64, %src /* IEU0 Group */
+ fmovd %f0, %f56 /* FPA Group */
+ fmovd %f48, %f0 /* FPA Group */
+ sub %dst, 64, %dst /* IEU0 */
+ fpsub32 %f2, %f2, %f2 /* FPA Group */
+ fcmpgt32 %f32, %f4, %x3 /* FPM Group */
+ faligndata %f4, %f6, %f48 /* FPA */
+ fcmpgt32 %f32, %f6, %x4 /* FPM Group */
+ faligndata %f6, %f8, %f50 /* FPA */
+ fcmpgt32 %f32, %f8, %x5 /* FPM Group */
+ faligndata %f8, %f10, %f52 /* FPA */
+ fcmpgt32 %f32, %f10, %x6 /* FPM Group */
+ faligndata %f10, %f12, %f54 /* FPA */
+ fcmpgt32 %f32, %f12, %x7 /* FPM Group */
+ inc %x3 /* IEU0 */
+ faligndata %f12, %f14, %f56 /* FPA */
+ fcmpgt32 %f32, %f14, %x8 /* FPM Group */
+ srl %x3, 1, %x3 /* IEU0 */
+ inc %x4 /* IEU1 */
+ fmovd %f14, %f58 /* FPA */
+ srl %x4, 1, %x4 /* IEU0 Group */
+ add %sum, %x3, %sum /* IEU1 */
+vis2: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30,
+ ,f60,f62,f48,f50,f52,f54,f56,f58,f58,
+ ,LDBLK(f32), ,,STBLK,,,,,,
+ ,bcs,pn %icc, vis2e1)
+ DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46,
+ ,f60,f62,f48,f50,f52,f54,f56,f58,f58,
+ ,LDBLK(f0), ,,STBLK,,,,,,
+ ,bcs,pn %icc, vis2e2)
+ DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14,
+ ,f60,f62,f48,f50,f52,f54,f56,f58,f58,
+ ,LDBLK(f16), ,,STBLK,,,,,,
+ ,bcc,pt %icc, vis2)
+vis2e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30,
+ ,f60,f62,f48,f50,f52,f54,f56,f58,f32,
+ ,SYNC, ,,STBLK_XORASI(x2,x3),ST(f48,64),ST(f50,72),ST(f52,80),ST(f54,88),ST(f56,96),
+ ,add %dst, 104, %dst; add %len, 192 - 6*8, %len; ba,pt %icc, e2)
+vis2e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46,
+ ,f60,f62,f48,f50,f52,f54,f56,f58,f0,
+ ,SYNC, ,,STBLK_XORASI(x2,x3),ST(f48,64),ST(f50,72),ST(f52,80),ST(f54,88),ST(f56,96),
+ ,add %dst, 104, %dst; add %len, 192 - 6*8, %len; ba,pt %icc, e3)
+vis2e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14,
+ ,f60,f62,f48,f50,f52,f54,f56,f58,f16,
+ ,SYNC, ,,STBLK_XORASI(x2,x3),ST(f48,64),ST(f50,72),ST(f52,80),ST(f54,88),ST(f56,96),
+ ,add %dst, 104, %dst; add %len, 192 - 6*8, %len; ba,pt %icc, e1)
+ .align 2048
+vis3s: wr %g2, ASI_BLK_XOR, %asi /* LSU Group */
+ sub %src, 24, %src /* IEU0 Group */
+ ldda [%src] ASI_BLK_P, %f0 /* Load Group */
+ add %src, 64, %src /* IEU0 Group */
+ ldda [%src] ASI_BLK_P, %f16 /* Load Group */
+ add %src, 64, %src /* IEU0 Group */
+ fmovd %f0, %f54 /* FPA Group */
+ fmovd %f48, %f0 /* FPA Group */
+ sub %dst, 64, %dst /* IEU0 */
+ fpsub32 %f2, %f2, %f2 /* FPA Group */
+ fpsub32 %f4, %f4, %f4 /* FPA Group */
+ fcmpgt32 %f32, %f6, %x4 /* FPM Group */
+ faligndata %f6, %f8, %f48 /* FPA */
+ fcmpgt32 %f32, %f8, %x5 /* FPM Group */
+ faligndata %f8, %f10, %f50 /* FPA */
+ fcmpgt32 %f32, %f10, %x6 /* FPM Group */
+ faligndata %f10, %f12, %f52 /* FPA */
+ fcmpgt32 %f32, %f12, %x7 /* FPM Group */
+ faligndata %f12, %f14, %f54 /* FPA */
+ fcmpgt32 %f32, %f14, %x8 /* FPM Group */
+ fmovd %f14, %f56 /* FPA */
+ inc %x4 /* IEU0 */
+ srl %x4, 1, %x4 /* IEU0 Group */
+vis3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30,
+ ,f58,f60,f62,f48,f50,f52,f54,f56,f56,
+ ,LDBLK(f32), ,,,STBLK,,,,,
+ ,bcs,pn %icc, vis3e1)
+ DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46,
+ ,f58,f60,f62,f48,f50,f52,f54,f56,f56,
+ ,LDBLK(f0), ,,,STBLK,,,,,
+ ,bcs,pn %icc, vis3e2)
+ DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14,
+ ,f58,f60,f62,f48,f50,f52,f54,f56,f56,
+ ,LDBLK(f16), ,,,STBLK,,,,,
+ ,bcc,pt %icc, vis3)
+vis3e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30,
+ ,f58,f60,f62,f48,f50,f52,f54,f56,f32,
+ ,SYNC, ,,,STBLK_XORASI(x3,x4),ST(f48,64),ST(f50,72),ST(f52,80),ST(f54,88),
+ ,add %dst, 96, %dst; add %len, 192 - 5*8, %len; ba,pt %icc, e2)
+vis3e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46,
+ ,f58,f60,f62,f48,f50,f52,f54,f56,f0,
+ ,SYNC, ,,,STBLK_XORASI(x3,x4),ST(f48,64),ST(f50,72),ST(f52,80),ST(f54,88),
+ ,add %dst, 96, %dst; add %len, 192 - 5*8, %len; ba,pt %icc, e3)
+vis3e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14,
+ ,f58,f60,f62,f48,f50,f52,f54,f56,f16,
+ ,SYNC, ,,,STBLK_XORASI(x3,x4),ST(f48,64),ST(f50,72),ST(f52,80),ST(f54,88),
+ ,add %dst, 96, %dst; add %len, 192 - 5*8, %len; ba,pt %icc, e1)
+ .align 2048
+vis4s: wr %g2, ASI_BLK_XOR, %asi /* LSU Group */
+ sub %src, 32, %src /* IEU0 Group */
+ ldda [%src] ASI_BLK_P, %f0 /* Load Group */
+ add %src, 64, %src /* IEU0 Group */
+ ldda [%src] ASI_BLK_P, %f16 /* Load Group */
+ add %src, 64, %src /* IEU0 Group */
+ fmovd %f0, %f52 /* FPA Group */
+ fmovd %f48, %f0 /* FPA Group */
+ sub %dst, 64, %dst /* IEU0 */
+ fpsub32 %f2, %f2, %f2 /* FPA Group */
+ fpsub32 %f4, %f4, %f4 /* FPA Group */
+ fpsub32 %f6, %f6, %f6 /* FPA Group */
+ clr %x4 /* IEU0 */
+ fcmpgt32 %f32, %f8, %x5 /* FPM Group */
+ faligndata %f8, %f10, %f48 /* FPA */
+ fcmpgt32 %f32, %f10, %x6 /* FPM Group */
+ faligndata %f10, %f12, %f50 /* FPA */
+ fcmpgt32 %f32, %f12, %x7 /* FPM Group */
+ faligndata %f12, %f14, %f52 /* FPA */
+ fcmpgt32 %f32, %f14, %x8 /* FPM Group */
+ fmovd %f14, %f54 /* FPA */
+vis4: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30,
+ ,f56,f58,f60,f62,f48,f50,f52,f54,f54,
+ ,LDBLK(f32), ,,,,STBLK,,,,
+ ,bcs,pn %icc, vis4e1)
+ DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46,
+ ,f56,f58,f60,f62,f48,f50,f52,f54,f54,
+ ,LDBLK(f0), ,,,,STBLK,,,,
+ ,bcs,pn %icc, vis4e2)
+ DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14,
+ ,f56,f58,f60,f62,f48,f50,f52,f54,f54,
+ ,LDBLK(f16), ,,,,STBLK,,,,
+ ,bcc,pt %icc, vis4)
+vis4e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30,
+ ,f56,f58,f60,f62,f48,f50,f52,f54,f32,
+ ,SYNC, ,,,,STBLK_XORASI(x4,x5),ST(f48,64),ST(f50,72),ST(f52,80),
+ ,add %dst, 88, %dst; add %len, 192 - 4*8, %len; ba,pt %icc, e2)
+vis4e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46,
+ ,f56,f58,f60,f62,f48,f50,f52,f54,f0,
+ ,SYNC, ,,,,STBLK_XORASI(x4,x5),ST(f48,64),ST(f50,72),ST(f52,80),
+ ,add %dst, 88, %dst; add %len, 192 - 4*8, %len; ba,pt %icc, e3)
+vis4e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14,
+ ,f56,f58,f60,f62,f48,f50,f52,f54,f16,
+ ,SYNC, ,,,,STBLK_XORASI(x4,x5),ST(f48,64),ST(f50,72),ST(f52,80),
+ ,add %dst, 88, %dst; add %len, 192 - 4*8, %len; ba,pt %icc, e1)
+ .align 2048
+vis5s: ldd [%src+0], %f10 /* Load Group */
+ ldd [%src+8], %f12 /* Load Group */
+ ldd [%src+16], %f14 /* Load Group */
+ add %src, 24, %src /* IEU0 Group */
+ wr %g2, ASI_BLK_XOR, %asi /* LSU Group */
+ ldda [%src] ASI_BLK_P, %f16 /* Load Group */
+ add %src, 64, %src /* IEU0 Group */
+ fmovd %f48, %f0 /* FPA Group */
+ fmuld %f32, %f32, %f2 /* FPM */
+ clr %x4 /* IEU0 */
+ faddd %f32, %f32, %f4 /* FPA Group */
+ fmuld %f32, %f32, %f6 /* FPM */
+ clr %x5 /* IEU0 */
+ faddd %f32, %f32, %f8 /* FPA Group */
+ fcmpgt32 %f32, %f10, %x6 /* FPM Group */
+ sub %dst, 64, %dst /* IEU0 */
+ faligndata %f10, %f12, %f48 /* FPA */
+ fcmpgt32 %f32, %f12, %x7 /* FPM Group */
+ faligndata %f12, %f14, %f50 /* FPA */
+ fcmpgt32 %f32, %f14, %x8 /* FPM Group */
+ fmovd %f14, %f52 /* FPA */
+vis5: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30,
+ ,f54,f56,f58,f60,f62,f48,f50,f52,f52,
+ ,LDBLK(f32), ,,,,,STBLK,,,
+ ,bcs,pn %icc, vis5e1)
+ DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46,
+ ,f54,f56,f58,f60,f62,f48,f50,f52,f52,
+ ,LDBLK(f0), ,,,,,STBLK,,,
+ ,bcs,pn %icc, vis5e2)
+ DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14,
+ ,f54,f56,f58,f60,f62,f48,f50,f52,f52,
+ ,LDBLK(f16), ,,,,,STBLK,,,
+ ,bcc,pt %icc, vis5)
+vis5e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30,
+ ,f54,f56,f58,f60,f62,f48,f50,f52,f32,
+ ,SYNC, ,,,,,STBLK_XORASI(x5,x6),ST(f48,64),ST(f50,72),
+ ,add %dst, 80, %dst; add %len, 192 - 3*8, %len; ba,pt %icc, e2)
+vis5e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46,
+ ,f54,f56,f58,f60,f62,f48,f50,f52,f0,
+ ,SYNC, ,,,,,STBLK_XORASI(x5,x6),ST(f48,64),ST(f50,72),
+ ,add %dst, 80, %dst; add %len, 192 - 3*8, %len; ba,pt %icc, e3)
+vis5e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14,
+ ,f54,f56,f58,f60,f62,f48,f50,f52,f16,
+ ,SYNC, ,,,,,STBLK_XORASI(x5,x6),ST(f48,64),ST(f50,72),
+ ,add %dst, 80, %dst; add %len, 192 - 3*8, %len; ba,pt %icc, e1)
+ .align 2048
+vis6s: ldd [%src+0], %f12 /* Load Group */
+ ldd [%src+8], %f14 /* Load Group */
+ add %src, 16, %src /* IEU0 Group */
+ wr %g2, ASI_BLK_XOR, %asi /* LSU Group */
+ ldda [%src] ASI_BLK_P, %f16 /* Load Group */
+ add %src, 64, %src /* IEU0 Group */
+ fmovd %f48, %f0 /* FPA Group */
+ fmuld %f32, %f32, %f2 /* FPM */
+ clr %x4 /* IEU0 */
+ faddd %f32, %f32, %f4 /* FPA Group */
+ fmuld %f32, %f32, %f6 /* FPM */
+ clr %x5 /* IEU0 */
+ faddd %f32, %f32, %f8 /* FPA Group */
+ fmuld %f32, %f32, %f10 /* FPM */
+ clr %x6 /* IEU0 */
+ fcmpgt32 %f32, %f12, %x7 /* FPM Group */
+ sub %dst, 64, %dst /* IEU0 */
+ fcmpgt32 %f32, %f14, %x8 /* FPM Group */
+ faligndata %f12, %f14, %f48 /* FPA */
+ fmovd %f14, %f50 /* FPA Group */
+vis6: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30,
+ ,f52,f54,f56,f58,f60,f62,f48,f50,f50,
+ ,LDBLK(f32), ,,,,,,STBLK,,
+ ,bcs,pn %icc, vis6e1)
+ DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46,
+ ,f52,f54,f56,f58,f60,f62,f48,f50,f50,
+ ,LDBLK(f0), ,,,,,,STBLK,,
+ ,bcs,pn %icc, vis6e2)
+ DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14,
+ ,f52,f54,f56,f58,f60,f62,f48,f50,f50,
+ ,LDBLK(f16), ,,,,,,STBLK,,
+ ,bcc,pt %icc, vis6)
+vis6e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30,
+ ,f52,f54,f56,f58,f60,f62,f48,f50,f32,
+ ,SYNC, ,,,,,,STBLK_XORASI(x6,x7),ST(f48,64),
+ ,add %dst, 72, %dst; add %len, 192 - 2*8, %len; ba,pt %icc, e2)
+vis6e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46,
+ ,f52,f54,f56,f58,f60,f62,f48,f50,f0,
+ ,SYNC, ,,,,,,STBLK_XORASI(x6,x7),ST(f48,64),
+ ,add %dst, 72, %dst; add %len, 192 - 2*8, %len; ba,pt %icc, e3)
+vis6e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14,
+ ,f52,f54,f56,f58,f60,f62,f48,f50,f16,
+ ,SYNC, ,,,,,,STBLK_XORASI(x6,x7),ST(f48,64),
+ ,add %dst, 72, %dst; add %len, 192 - 2*8, %len; ba,pt %icc, e1)
+ .align 2048
+vis7s: ldd [%src+0], %f14 /* Load Group */
+ add %src, 8, %src /* IEU0 Group */
+ wr %g2, ASI_BLK_XOR, %asi /* LSU Group */
+ ldda [%src] ASI_BLK_P, %f16 /* Load Group */
+ add %src, 64, %src /* IEU0 Group */
+ fmovd %f48, %f0 /* FPA Group */
+ fmuld %f32, %f32, %f2 /* FPM */
+ clr %x4 /* IEU0 */
+ faddd %f32, %f32, %f4 /* FPA Group */
+ fmuld %f32, %f32, %f6 /* FPM */
+ clr %x5 /* IEU0 */
+ faddd %f32, %f32, %f8 /* FPA Group */
+ fmuld %f32, %f32, %f10 /* FPM */
+ clr %x6 /* IEU0 */
+ faddd %f32, %f32, %f12 /* FPA Group */
+ clr %x7 /* IEU0 */
+ fcmpgt32 %f32, %f14, %x8 /* FPM Group */
+ sub %dst, 64, %dst /* IEU0 */
+ fmovd %f14, %f48 /* FPA */
+vis7: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30,
+ ,f50,f52,f54,f56,f58,f60,f62,f48,f48,
+ ,LDBLK(f32), ,,,,,,,STBLK,
+ ,bcs,pn %icc, vis7e1)
+ DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46,
+ ,f50,f52,f54,f56,f58,f60,f62,f48,f48,
+ ,LDBLK(f0), ,,,,,,,STBLK,
+ ,bcs,pn %icc, vis7e2)
+ DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14,
+ ,f50,f52,f54,f56,f58,f60,f62,f48,f48,
+ ,LDBLK(f16), ,,,,,,,STBLK,
+ ,bcc,pt %icc, vis7)
+vis7e3: DO_THE_TRICK( f0,f2,f4,f6,f8,f10,f12,f14,f16,f18,f20,f22,f24,f26,f28,f30,
+ ,f50,f52,f54,f56,f58,f60,f62,f48,f32,
+ ,SYNC, ,,,,,,,STBLK_XORASI(x7,x8),
+ ,add %dst, 64, %dst; add %len, 192 - 1*8, %len; ba,pt %icc, e2)
+vis7e1: DO_THE_TRICK( f16,f18,f20,f22,f24,f26,f28,f30,f32,f34,f36,f38,f40,f42,f44,f46,
+ ,f50,f52,f54,f56,f58,f60,f62,f48,f0,
+ ,SYNC, ,,,,,,,STBLK_XORASI(x7,x8),
+ ,add %dst, 64, %dst; add %len, 192 - 1*8, %len; ba,pt %icc, e3)
+vis7e2: DO_THE_TRICK( f32,f34,f36,f38,f40,f42,f44,f46,f0,f2,f4,f6,f8,f10,f12,f14,
+ ,f50,f52,f54,f56,f58,f60,f62,f48,f16,
+ ,SYNC, ,,,,,,,STBLK_XORASI(x7,x8),
+ ,add %dst, 64, %dst; add %len, 192 - 1*8, %len; ba,pt %icc, e1)
+e1: END_THE_TRICK1( f0,f2,f4,f6,f8,f10,f12,f14,f16,f6)
+e2: END_THE_TRICK1( f16,f18,f20,f22,f24,f26,f28,f30,f32,f6)
+e3: END_THE_TRICK1( f32,f34,f36,f38,f40,f42,f44,f46,f0,f6)
+ett: rd %gsr, %x3 /* LSU Group+4bubbles */
+ andcc %x3, 7, %x3 /* IEU1 Group */
+ add %dst, 8, %dst /* IEU0 */
+ bne,pn %icc, 1f /* CTI */
+ fzero %f10 /* FPA */
+ brz,a,pn %len, 2f /* CTI+IEU1 Group */
+ stda %f6, [%dst - 8] %asi /* Store */
+1: cmp %len, 8 /* IEU1 */
+ blu,pn %icc, 3f /* CTI */
+ sub %src, 64, %src /* IEU0 Group */
+1: ldd [%src], %f2 /* Load Group */
+ fpadd32 %f10, %f2, %f12 /* FPA Group+load stall */
+ add %src, 8, %src /* IEU0 */
+ add %dst, 8, %dst /* IEU1 */
+ faligndata %f6, %f2, %f14 /* FPA Group */
+ fcmpgt32 %f10, %f12, %x5 /* FPM Group */
+ stda %f14, [%dst - 16] %asi /* Store */
+ fmovd %f2, %f6 /* FPA */
+ fmovd %f12, %f10 /* FPA Group */
+ sub %len, 8, %len /* IEU1 */
+ fzero %f16 /* FPA Group - FPU nop */
+ fzero %f18 /* FPA Group - FPU nop */
+ inc %x5 /* IEU0 */
+ srl %x5, 1, %x5 /* IEU0 Group (regdep) */
+ cmp %len, 8 /* IEU1 */
+ bgeu,pt %icc, 1b /* CTI */
+ add %x5, %sum, %sum /* IEU0 Group */
+3: brz,a,pt %x3, 2f /* CTI+IEU1 */
+ stda %f6, [%dst - 8] %asi /* Store Group */
+ sta %f7, [%dst - 8] %asi /* Store Group */
+ sub %dst, 4, %dst /* IEU0 */
+ add %len, 4, %len /* IEU1 */
+2:
+#ifdef __KERNEL__
+ sub %sp, 8, %sp /* IEU0 Group */
+#endif
+ END_THE_TRICK2( f48,f50,f52,f54,f56,f58,f60,f10,f12,f62)
+ membar #Sync /* LSU Group */
+#ifdef __KERNEL__
+ VISExit
+ add %sp, 8, %sp /* IEU0 Group */
+#endif
+23: brnz,pn %len, 26f /* CTI+IEU1 Group */
+24: sllx %sum, 32, %g1 /* IEU0 */
+25: addcc %sum, %g1, %src /* IEU1 Group */
+ srlx %src, 32, %src /* IEU0 Group (regdep) */
+ bcs,a,pn %xcc, 1f /* CTI */
+ add %src, 1, %src /* IEU1 */
+#ifndef __KERNEL__
+1: retl /* CTI Group brk forced */
+ srl %src, 0, %src /* IEU0 */
+#else
+1: sethi %uhi(PAGE_OFFSET), %g4 /* IEU0 Group */
+ retl /* CTI Group brk forced */
+ sllx %g4, 32, %g4 /* IEU0 */
+#endif
+26: andcc %len, 8, %g0 /* IEU1 Group */
+ be,pn %icc, 1f /* CTI */
+ lduw [%src], %o4 /* Load */
+ lduw [%src+4], %g2 /* Load Group */
+ add %src, 8, %src /* IEU0 */
+ add %dst, 8, %dst /* IEU1 */
+ sllx %o4, 32, %g5 /* IEU0 Group */
+ stwa %o4, [%dst - 8] %asi /* Store */
+ or %g5, %g2, %g5 /* IEU0 Group */
+ stwa %g2, [%dst - 4] %asi /* Store */
+ addcc %g5, %sum, %sum /* IEU1 Group */
+ bcs,a,pn %xcc, 1f /* CTI */
+ add %sum, 1, %sum /* IEU0 */
+1: andcc %len, 4, %g0 /* IEU1 Group */
+ be,a,pn %icc, 1f /* CTI */
+ clr %g2 /* IEU0 */
+ lduw [%src], %g7 /* Load */
+ add %src, 4, %src /* IEU0 Group */
+ add %dst, 4, %dst /* IEU1 */
+ sllx %g7, 32, %g2 /* IEU0 Group */
+ stwa %g7, [%dst - 4] %asi /* Store */
+1: andcc %len, 2, %g0 /* IEU1 */
+ be,a,pn %icc, 1f /* CTI */
+ clr %g3 /* IEU0 Group */
+ lduh [%src], %g7 /* Load */
+ add %src, 2, %src /* IEU1 */
+ add %dst, 2, %dst /* IEU0 Group */
+ sll %g7, 16, %g3 /* IEU0 Group */
+ stha %g7, [%dst - 2] %asi /* Store */
+1: andcc %len, 1, %g0 /* IEU1 */
+ be,a,pn %icc, 1f /* CTI */
+ clr %o5 /* IEU0 Group */
+ ldub [%src], %g7 /* Load */
+ sll %g7, 8, %o5 /* IEU0 Group */
+ stba %g7, [%dst] %asi /* Store */
+1: or %g2, %g3, %g3 /* IEU1 */
+ or %o5, %g3, %g3 /* IEU0 Group (regdep) */
+ addcc %g3, %sum, %sum /* IEU1 Group (regdep) */
+ bcs,a,pn %xcc, 1f /* CTI */
+ add %sum, 1, %sum /* IEU0 */
+1: ba,pt %xcc, 25b /* CTI Group */
+ sllx %sum, 32, %g1 /* IEU0 */
+
+#ifdef __KERNEL__
+end:
+
+ .section __ex_table
+ .align 4
+ .word csum_partial_copy_user_vis, 0, end, cpc_handler
+#endif
diff --git a/arch/sparc64/lib/checksum.S b/arch/sparc64/lib/checksum.S
index 07d10ba42..4e962ed47 100644
--- a/arch/sparc64/lib/checksum.S
+++ b/arch/sparc64/lib/checksum.S
@@ -2,7 +2,7 @@
*
* Copyright(C) 1995 Linus Torvalds
* Copyright(C) 1995 Miguel de Icaza
- * Copyright(C) 1996 David S. Miller
+ * Copyright(C) 1996, 2000 David S. Miller
* Copyright(C) 1997 Jakub Jelinek
*
* derived from:
@@ -263,6 +263,238 @@ ccslow: mov 0, %g5
srl %o0, 0, %o0
cpc_end:
+ /* Now the version with userspace as the destination */
+#define CSUMCOPY_LASTCHUNK_USER(off, t0, t1) \
+ ldx [%src - off - 0x08], t0; \
+ ldx [%src - off - 0x00], t1; \
+ nop; nop; \
+ addcc t0, %sum, %sum; \
+ stwa t0, [%dst - off - 0x04] %asi; \
+ srlx t0, 32, t0; \
+ bcc,pt %xcc, 51f; \
+ stwa t0, [%dst - off - 0x08] %asi; \
+ add %sum, 1, %sum; \
+51: addcc t1, %sum, %sum; \
+ stwa t1, [%dst - off + 0x04] %asi; \
+ srlx t1, 32, t1; \
+ bcc,pt %xcc, 52f; \
+ stwa t1, [%dst - off - 0x00] %asi; \
+ add %sum, 1, %sum; \
+52:
+
+cpc_user_start:
+cc_user_end_cruft:
+ andcc %g7, 8, %g0 ! IEU1 Group
+ be,pn %icc, 1f ! CTI
+ and %g7, 4, %g5 ! IEU0
+ ldx [%src + 0x00], %g2 ! Load Group
+ add %dst, 8, %dst ! IEU0
+ add %src, 8, %src ! IEU1
+ addcc %g2, %sum, %sum ! IEU1 Group + 2 bubbles
+ stwa %g2, [%dst - 0x04] %asi ! Store
+ srlx %g2, 32, %g2 ! IEU0
+ bcc,pt %xcc, 1f ! CTI Group
+ stwa %g2, [%dst - 0x08] %asi ! Store
+ add %sum, 1, %sum ! IEU0
+1: brz,pt %g5, 1f ! CTI Group
+ clr %g2 ! IEU0
+ lduw [%src + 0x00], %g2 ! Load
+ add %dst, 4, %dst ! IEU0 Group
+ add %src, 4, %src ! IEU1
+ stwa %g2, [%dst - 0x04] %asi ! Store Group + 2 bubbles
+ sllx %g2, 32, %g2 ! IEU0
+1: andcc %g7, 2, %g0 ! IEU1
+ be,pn %icc, 1f ! CTI Group
+ clr %o4 ! IEU1
+ lduh [%src + 0x00], %o4 ! Load
+ add %src, 2, %src ! IEU0 Group
+ add %dst, 2, %dst ! IEU1
+ stha %o4, [%dst - 0x2] %asi ! Store Group + 2 bubbles
+ sll %o4, 16, %o4 ! IEU0
+1: andcc %g7, 1, %g0 ! IEU1
+ be,pn %icc, 1f ! CTI Group
+ clr %o5 ! IEU0
+ ldub [%src + 0x00], %o5 ! Load
+ stba %o5, [%dst + 0x00] %asi ! Store Group + 2 bubbles
+ sll %o5, 8, %o5 ! IEU0
+1: or %g2, %o4, %o4 ! IEU1
+ or %o5, %o4, %o4 ! IEU0 Group
+ addcc %o4, %sum, %sum ! IEU1
+ bcc,pt %xcc, ccuserfold ! CTI
+ sethi %uhi(PAGE_OFFSET), %g4 ! IEU0 Group
+ b,pt %xcc, ccuserfold ! CTI
+ add %sum, 1, %sum ! IEU1
+
+cc_user_fixit:
+ cmp %len, 6 ! IEU1 Group
+ bl,a,pn %icc, ccuserte ! CTI
+ andcc %len, 0xf, %g7 ! IEU1 Group
+ andcc %src, 2, %g0 ! IEU1 Group
+ be,pn %icc, 1f ! CTI
+ andcc %src, 0x4, %g0 ! IEU1 Group
+ lduh [%src + 0x00], %g4 ! Load
+ sub %len, 2, %len ! IEU0
+ add %src, 2, %src ! IEU0 Group
+ add %dst, 2, %dst ! IEU1
+ sll %g4, 16, %g3 ! IEU0 Group + 1 bubble
+ addcc %g3, %sum, %sum ! IEU1
+ bcc,pt %xcc, 0f ! CTI
+ srl %sum, 16, %g3 ! IEU0 Group
+ add %g3, 1, %g3 ! IEU0 4 clocks (mispredict)
+0: andcc %src, 0x4, %g0 ! IEU1 Group
+ stha %g4, [%dst - 0x2] %asi ! Store
+ sll %sum, 16, %sum ! IEU0
+ sll %g3, 16, %g3 ! IEU0 Group
+ srl %sum, 16, %sum ! IEU0 Group
+ or %g3, %sum, %sum ! IEU0 Group (regdep)
+1: be,pt %icc, ccusermerge ! CTI
+ andcc %len, 0xf0, %g1 ! IEU1
+ lduw [%src + 0x00], %g4 ! Load Group
+ sub %len, 4, %len ! IEU0
+ add %src, 4, %src ! IEU1
+ add %dst, 4, %dst ! IEU0 Group
+ addcc %g4, %sum, %sum ! IEU1 Group + 1 bubble
+ stwa %g4, [%dst - 0x4] %asi ! Store
+ bcc,pt %xcc, ccusermerge ! CTI
+ andcc %len, 0xf0, %g1 ! IEU1 Group
+ b,pt %xcc, ccusermerge ! CTI 4 clocks (mispredict)
+ add %sum, 1, %sum ! IEU0
+
+ .align 32
+ .globl csum_partial_copy_user_sparc64
+csum_partial_copy_user_sparc64: /* %o0=src, %o1=dest, %o2=len, %o3=sum */
+ xorcc %src, %dst, %o4 ! IEU1 Group
+ srl %sum, 0, %sum ! IEU0
+ andcc %o4, 3, %g0 ! IEU1 Group
+ srl %len, 0, %len ! IEU0
+ bne,pn %icc, ccuserslow ! CTI
+ andcc %src, 1, %g0 ! IEU1 Group
+ bne,pn %icc, ccuserslow ! CTI
+ cmp %len, 256 ! IEU1 Group
+ bgeu,pt %icc, csum_partial_copy_user_vis ! CTI
+ andcc %src, 7, %g0 ! IEU1 Group
+ bne,pn %icc, cc_user_fixit ! CTI
+ andcc %len, 0xf0, %g1 ! IEU1 Group
+ccusermerge:
+ be,pn %icc, ccuserte ! CTI
+ andcc %len, 0xf, %g7 ! IEU1 Group
+ sll %g1, 2, %o4 ! IEU0
+13: sethi %hi(12f), %o5 ! IEU0 Group
+ add %src, %g1, %src ! IEU1
+ sub %o5, %o4, %o5 ! IEU0 Group
+ jmpl %o5 + %lo(12f), %g0 ! CTI Group brk forced
+ add %dst, %g1, %dst ! IEU0 Group
+ccusertbl:
+ CSUMCOPY_LASTCHUNK_USER(0xe8,%g2,%g3)
+ CSUMCOPY_LASTCHUNK_USER(0xd8,%g2,%g3)
+ CSUMCOPY_LASTCHUNK_USER(0xc8,%g2,%g3)
+ CSUMCOPY_LASTCHUNK_USER(0xb8,%g2,%g3)
+ CSUMCOPY_LASTCHUNK_USER(0xa8,%g2,%g3)
+ CSUMCOPY_LASTCHUNK_USER(0x98,%g2,%g3)
+ CSUMCOPY_LASTCHUNK_USER(0x88,%g2,%g3)
+ CSUMCOPY_LASTCHUNK_USER(0x78,%g2,%g3)
+ CSUMCOPY_LASTCHUNK_USER(0x68,%g2,%g3)
+ CSUMCOPY_LASTCHUNK_USER(0x58,%g2,%g3)
+ CSUMCOPY_LASTCHUNK_USER(0x48,%g2,%g3)
+ CSUMCOPY_LASTCHUNK_USER(0x38,%g2,%g3)
+ CSUMCOPY_LASTCHUNK_USER(0x28,%g2,%g3)
+ CSUMCOPY_LASTCHUNK_USER(0x18,%g2,%g3)
+ CSUMCOPY_LASTCHUNK_USER(0x08,%g2,%g3)
+12:
+ andcc %len, 0xf, %g7 ! IEU1 Group
+ccuserte:
+ bne,pn %icc, cc_user_end_cruft ! CTI
+ sethi %uhi(PAGE_OFFSET), %g4 ! IEU0
+ccuserfold:
+ sllx %sum, 32, %o0 ! IEU0 Group
+ addcc %sum, %o0, %o0 ! IEU1 Group (regdep)
+ srlx %o0, 32, %o0 ! IEU0 Group (regdep)
+ bcs,a,pn %xcc, 1f ! CTI
+ add %o0, 1, %o0 ! IEU1 4 clocks (mispredict)
+1: retl ! CTI Group brk forced
+ sllx %g4, 32, %g4 ! IEU0 Group
+
+ccuserslow:
+ mov 0, %g5
+ brlez,pn %len, 4f
+ andcc %src, 1, %o5
+ be,a,pt %icc, 1f
+ srl %len, 1, %g7
+ sub %len, 1, %len
+ ldub [%src], %g5
+ add %src, 1, %src
+ stba %g5, [%dst] %asi
+ srl %len, 1, %g7
+ add %dst, 1, %dst
+1: brz,a,pn %g7, 3f
+ andcc %len, 1, %g0
+ andcc %src, 2, %g0
+ be,a,pt %icc, 1f
+ srl %g7, 1, %g7
+ lduh [%src], %o4
+ sub %len, 2, %len
+ srl %o4, 8, %g2
+ sub %g7, 1, %g7
+ stba %g2, [%dst] %asi
+ add %o4, %g5, %g5
+ stba %o4, [%dst + 1] %asi
+ add %src, 2, %src
+ srl %g7, 1, %g7
+ add %dst, 2, %dst
+1: brz,a,pn %g7, 2f
+ andcc %len, 2, %g0
+ lduw [%src], %o4
+5: srl %o4, 24, %g2
+ srl %o4, 16, %g3
+ stba %g2, [%dst] %asi
+ srl %o4, 8, %g2
+ stba %g3, [%dst + 1] %asi
+ add %src, 4, %src
+ stba %g2, [%dst + 2] %asi
+ addcc %o4, %g5, %g5
+ stba %o4, [%dst + 3] %asi
+ addc %g5, %g0, %g5
+ add %dst, 4, %dst
+ subcc %g7, 1, %g7
+ bne,a,pt %icc, 5b
+ lduw [%src], %o4
+ sll %g5, 16, %g2
+ srl %g5, 16, %g5
+ srl %g2, 16, %g2
+ andcc %len, 2, %g0
+ add %g2, %g5, %g5
+2: be,a,pt %icc, 3f
+ andcc %len, 1, %g0
+ lduh [%src], %o4
+ andcc %len, 1, %g0
+ srl %o4, 8, %g2
+ add %src, 2, %src
+ stba %g2, [%dst] %asi
+ add %g5, %o4, %g5
+ stba %o4, [%dst + 1] %asi
+ add %dst, 2, %dst
+3: be,a,pt %icc, 1f
+ sll %g5, 16, %o4
+ ldub [%src], %g2
+ sll %g2, 8, %o4
+ stba %g2, [%dst] %asi
+ add %g5, %o4, %g5
+ sll %g5, 16, %o4
+1: addcc %o4, %g5, %g5
+ srl %g5, 16, %o4
+ addc %g0, %o4, %g5
+ brz,pt %o5, 4f
+ srl %g5, 8, %o4
+ and %g5, 0xff, %g2
+ and %o4, 0xff, %o4
+ sll %g2, 8, %g2
+ or %g2, %o4, %g5
+4: addcc %sum, %g5, %sum
+ addc %g0, %sum, %o0
+ retl
+ srl %o0, 0, %o0
+cpc_user_end:
+
.globl cpc_handler
cpc_handler:
ldx [%sp + 0x7ff + 128], %g1
@@ -277,5 +509,5 @@ cpc_handler:
.section __ex_table
.align 4
- .word cpc_start, 0, cpc_end, cpc_handler
-
+ .word cpc_start, 0, cpc_end, cpc_handler
+ .word cpc_user_start, 0, cpc_user_end, cpc_handler
diff --git a/arch/sparc64/mm/asyncd.c b/arch/sparc64/mm/asyncd.c
index f23a04ede..b87efd590 100644
--- a/arch/sparc64/mm/asyncd.c
+++ b/arch/sparc64/mm/asyncd.c
@@ -1,4 +1,4 @@
-/* $Id: asyncd.c,v 1.11 2000/01/08 20:22:19 davem Exp $
+/* $Id: asyncd.c,v 1.12 2000/01/21 11:39:13 jj Exp $
* The asyncd kernel daemon. This handles paging on behalf of
* processes that receive page faults due to remote (async) memory
* accesses.
@@ -20,6 +20,7 @@
#include <linux/fs.h>
#include <linux/config.h>
#include <linux/interrupt.h>
+#include <linux/signal.h>
#include <asm/dma.h>
#include <asm/system.h> /* for cli()/sti() */
@@ -113,6 +114,7 @@ static int fault_in_page(int taskid,
{
static unsigned last_address;
static int last_task, loop_counter;
+ siginfo_t info;
#warning Need some fixing here... -DaveM
struct task_struct *tsk = current /* XXX task[taskid] */;
pgd_t *pgd;
@@ -181,9 +183,12 @@ no_memory:
bad_area:
stats.failure++;
- tsk->thread.sig_address = address;
- tsk->thread.sig_desc = SUBSIG_NOMAPPING;
- send_sig(SIGSEGV, tsk, 1);
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ info.si_code = SEGV_MAPERR;
+ info.si_addr = (void *)address;
+ info.si_trapno = 0;
+ send_sig_info(SIGSEGV, &info, tsk);
return 1;
}
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index 1835b874f..226246980 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.40 1999/12/01 10:44:53 davem Exp $
+/* $Id: fault.c,v 1.42 2000/01/21 11:39:13 jj Exp $
* arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -149,10 +149,13 @@ asmlinkage void do_sparc64_fault(struct pt_regs *regs, unsigned long address, in
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
unsigned int insn = 0;
+ siginfo_t info;
#ifdef DEBUG_LOCKUPS
static unsigned long lastaddr, lastpc;
static int lastwrite, lockcnt;
#endif
+
+ info.si_code = SEGV_MAPERR;
/*
* If we're in an interrupt or have no user
* context, we must not take the fault..
@@ -233,6 +236,7 @@ asmlinkage void do_sparc64_fault(struct pt_regs *regs, unsigned long address, in
* we can handle it..
*/
good_area:
+ info.si_code = SEGV_ACCERR;
if(write) {
if(!(vma->vm_flags & VM_WRITE))
goto bad_area;
@@ -242,8 +246,14 @@ good_area:
goto bad_area;
}
current->mm->segments = (void *) (address & PAGE_SIZE);
- if (!handle_mm_fault(current, vma, address, write))
- goto do_sigbus;
+ {
+ int fault = handle_mm_fault(current, vma, address, write);
+
+ if (fault < 0)
+ goto out_of_memory;
+ if (!fault)
+ goto do_sigbus;
+ }
up(&mm->mmap_sem);
return;
/*
@@ -324,20 +334,45 @@ do_kernel_fault:
while(1)
barrier();
#endif
- current->thread.sig_address = address;
- current->thread.sig_desc = SUBSIG_NOMAPPING;
- force_sig(SIGSEGV, current);
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ /* info.si_code set above to make clear whether
+ this was a SEGV_MAPERR or SEGV_ACCERR fault. */
+ info.si_addr = (void *)address;
+ info.si_trapno = 0;
+ force_sig_info (SIGSEGV, &info, current);
return;
}
unhandled_fault (address, current, regs);
}
return;
+/*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+out_of_memory:
+ up(&mm->mmap_sem);
+ printk("VM: killing process %s\n", current->comm);
+ if (!(regs->tstate & TSTATE_PRIV))
+ do_exit(SIGKILL);
+ goto do_kernel_fault;
+
do_sigbus:
up(&mm->mmap_sem);
- current->thread.sig_address = address;
- current->thread.sig_desc = SUBSIG_MISCERROR;
- force_sig(SIGBUS, current);
+
+ /*
+ * Send a sigbus, regardless of whether we were in kernel
+ * or user mode.
+ */
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_ADRERR;
+ info.si_addr = (void *)address;
+ info.si_trapno = 0;
+ force_sig_info (SIGBUS, &info, current);
+
+ /* Kernel mode? Handle exceptions or die */
if (regs->tstate & TSTATE_PRIV)
goto do_kernel_fault;
}
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 1be2716f5..b4306d9ab 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.143 1999/12/16 16:15:14 davem Exp $
+/* $Id: init.c,v 1.144 2000/01/23 07:16:11 davem Exp $
* arch/sparc64/mm/init.c
*
* Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
@@ -40,8 +40,6 @@ unsigned long *sparc64_valid_addr_bitmap;
/* Ugly, but necessary... -DaveM */
unsigned long phys_base;
-static unsigned long totalram_pages = 0;
-
/* get_new_mmu_context() uses "cache + 1". */
spinlock_t ctx_alloc_lock = SPIN_LOCK_UNLOCKED;
unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1;
@@ -125,7 +123,7 @@ void show_mem(void)
show_free_areas();
printk("Free swap: %6dkB\n",
nr_swap_pages << (PAGE_SHIFT-10));
- printk("%ld pages of RAM\n", totalram_pages);
+ printk("%ld pages of RAM\n", num_physpages);
printk("%d free pages\n", nr_free_pages());
printk("%d pages in page table cache\n",pgtable_cache_size);
#ifndef __SMP__
@@ -1088,7 +1086,6 @@ void __init free_mem_map_range(struct page *first, struct page *last)
ClearPageReserved(mem_map + MAP_NR(first));
set_page_count(mem_map + MAP_NR(first), 1);
free_page((unsigned long)first);
- totalram_pages++;
num_physpages++;
first = (struct page *)((unsigned long)first + PAGE_SIZE);
@@ -1180,7 +1177,7 @@ void __init mem_init(void)
#ifdef DEBUG_BOOTMEM
prom_printf("mem_init: Calling free_all_bootmem().\n");
#endif
- num_physpages = totalram_pages = free_all_bootmem();
+ num_physpages = free_all_bootmem();
#if 0
free_unused_mem_map();
#endif
@@ -1202,7 +1199,6 @@ void __init mem_init(void)
memset(empty_pg_dir, 0, sizeof(empty_pg_dir));
addr += alias_base;
free_pgd_fast((pgd_t *)addr);
- totalram_pages++;
num_physpages++;
}
#endif
@@ -1245,14 +1241,13 @@ void free_initmem (void)
ClearPageReserved(p);
set_page_count(p, 1);
__free_page(p);
- totalram_pages++;
num_physpages++;
}
}
void si_meminfo(struct sysinfo *val)
{
- val->totalram = totalram_pages;
+ val->totalram = num_physpages;
val->sharedram = 0;
val->freeram = nr_free_pages();
val->bufferram = atomic_read(&buffermem_pages);
diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
index 04e676907..450d2fc9e 100644
--- a/arch/sparc64/solaris/misc.c
+++ b/arch/sparc64/solaris/misc.c
@@ -242,8 +242,10 @@ asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2)
/* Let's cheat */
set_utsfield(((struct sol_uname *)A(buf))->sysname,
"SunOS", 1, 0);
+ down_read(&uts_sem);
set_utsfield(((struct sol_uname *)A(buf))->nodename,
system_utsname.nodename, 1, 1);
+ up_read(&uts_sem);
set_utsfield(((struct sol_uname *)A(buf))->release,
"2.6", 0, 0);
set_utsfield(((struct sol_uname *)A(buf))->version,
@@ -263,7 +265,7 @@ asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2)
asmlinkage int solaris_utsname(u32 buf)
{
/* Why should we not lie a bit? */
- down(&uts_sem);
+ down_read(&uts_sem);
set_utsfield(((struct sol_utsname *)A(buf))->sysname,
"SunOS", 0, 0);
set_utsfield(((struct sol_utsname *)A(buf))->nodename,
@@ -274,7 +276,7 @@ asmlinkage int solaris_utsname(u32 buf)
"Generic", 0, 0);
set_utsfield(((struct sol_utsname *)A(buf))->machine,
machine(), 0, 0);
- up(&uts_sem);
+ up_read(&uts_sem);
return 0;
}
@@ -300,8 +302,10 @@ asmlinkage int solaris_sysinfo(int cmd, u32 buf, s32 count)
case SI_SYSNAME: r = "SunOS"; break;
case SI_HOSTNAME:
r = buffer + 256;
+ down_read(&uts_sem);
for (p = system_utsname.nodename, q = buffer;
q < r && *p && *p != '.'; *q++ = *p++);
+ up_read(&uts_sem);
*q = 0;
r = buffer;
break;