diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-18 00:24:27 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-18 00:24:27 +0000 |
commit | b9558d5f86c471a125abf1fb3a3882fb053b1f8c (patch) | |
tree | 707b53ec64e740a7da87d5f36485e3cd9b1c794e /arch/sparc64 | |
parent | b3ac367c7a3e6047abe74817db27e34e759f279f (diff) |
Merge with Linux 2.3.41.
Diffstat (limited to 'arch/sparc64')
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], ¤t->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(¤t->sigmask_lock); old = (u32) current->blocked.sig[0]; current->blocked.sig[0] |= (blk_mask & _BLOCKABLE); + recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); return old; } @@ -334,6 +335,7 @@ asmlinkage u32 sunos_sigsetmask(u32 newmask) spin_lock_irq(¤t->sigmask_lock); retval = (u32) current->blocked.sig[0]; current->blocked.sig[0] = (newmask & _BLOCKABLE); + recalc_sigpending(current); spin_unlock_irq(¤t->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; |