Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Sat, 18 Aug 2007 16:34:28 +0000 (09:34 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Sat, 18 Aug 2007 16:34:28 +0000 (09:34 -0700)
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6:
  [MATH-EMU]: Fix underflow exception reporting.
  [SPARC64]: Create a HWCAP_SPARC_N2 and report it to userspace on Niagara-2.
  [SPARC64]: SMP trampoline needs to avoid %tick_cmpr on sun4v too.
  [SPARC64]: Do not touch %tick_cmpr on sun4v cpus.
  [SPARC64]: Niagara-2 optimized copies.
  [SPARC64]: Allow userspace to get at the machine description.
  [SPARC32]: Remove superfluous 'kernel_end' alignment on sun4c.
  [SPARC32]: Fix bogus ramdisk image location check.
  [SPARC32]: Remove iommu from struct sbus_bus and use archdata like sparc64.

21 files changed:
arch/sparc/kernel/ebus.c
arch/sparc/mm/init.c
arch/sparc/mm/io-unit.c
arch/sparc/mm/iommu.c
arch/sparc/mm/sun4c.c
arch/sparc64/kernel/head.S
arch/sparc64/kernel/mdesc.c
arch/sparc64/kernel/trampoline.S
arch/sparc64/lib/Makefile
arch/sparc64/lib/NG2copy_from_user.S [new file with mode: 0644]
arch/sparc64/lib/NG2copy_to_user.S [new file with mode: 0644]
arch/sparc64/lib/NG2memcpy.S [new file with mode: 0644]
arch/sparc64/lib/NG2page.S [new file with mode: 0644]
arch/sparc64/lib/NG2patch.S [new file with mode: 0644]
arch/sparc64/lib/NGpage.S
include/asm-sparc/sbus.h
include/asm-sparc/sfp-machine.h
include/asm-sparc64/elf.h
include/asm-sparc64/sfp-machine.h
include/math-emu/op-common.h
include/math-emu/soft-fp.h

index ac352eb6dff3beb4753cefc885078c87284c053e..e2d02fd13f35f6284d7f54fe4352d60b9279dd12 100644 (file)
@@ -238,6 +238,7 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d
        sd = &dev->ofdev.dev.archdata;
        sd->prom_node = dp;
        sd->op = &dev->ofdev;
+       sd->iommu = dev->bus->ofdev.dev.parent->archdata.iommu;
 
        dev->ofdev.node = dp;
        dev->ofdev.dev.parent = &dev->bus->ofdev.dev;
index a1bef07755a920076d186880269af56f5f9348db..c13e6cd279ac0bae8ad49043b9c11f73310f349e 100644 (file)
@@ -206,8 +206,7 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
 #ifdef CONFIG_BLK_DEV_INITRD
        /* Now have to check initial ramdisk, so that bootmap does not overwrite it */
        if (sparc_ramdisk_image) {
-               if (sparc_ramdisk_image >= (unsigned long)&_end - 2 * PAGE_SIZE)
-                       sparc_ramdisk_image -= KERNBASE;
+               sparc_ramdisk_image -= KERNBASE;
                initrd_start = sparc_ramdisk_image + phys_base;
                initrd_end = initrd_start + sparc_ramdisk_size;
                if (initrd_end > end_of_phys_memory) {
index 4ccda77d08d6bf7d180036f09d452b2813784676..7c89893b1fe8789e71a05694660540ac943bb4c8 100644 (file)
@@ -66,7 +66,7 @@ iounit_init(int sbi_node, int io_node, struct sbus_bus *sbus)
        }
        if(!xpt) panic("Cannot map External Page Table.");
        
-       sbus->iommu = (struct iommu_struct *)iounit;
+       sbus->ofdev.dev.archdata.iommu = iounit;
        iounit->page_table = xpt;
        spin_lock_init(&iounit->lock);
        
@@ -127,7 +127,7 @@ nexti:      scan = find_next_zero_bit(iounit->bmap, limit, scan);
 static __u32 iounit_get_scsi_one(char *vaddr, unsigned long len, struct sbus_bus *sbus)
 {
        unsigned long ret, flags;
-       struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
+       struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu;
        
        spin_lock_irqsave(&iounit->lock, flags);
        ret = iounit_get_area(iounit, (unsigned long)vaddr, len);
@@ -138,7 +138,7 @@ static __u32 iounit_get_scsi_one(char *vaddr, unsigned long len, struct sbus_bus
 static void iounit_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
 {
        unsigned long flags;
-       struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
+       struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu;
 
        /* FIXME: Cache some resolved pages - often several sg entries are to the same page */
        spin_lock_irqsave(&iounit->lock, flags);
@@ -153,7 +153,7 @@ static void iounit_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus
 static void iounit_release_scsi_one(__u32 vaddr, unsigned long len, struct sbus_bus *sbus)
 {
        unsigned long flags;
-       struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
+       struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu;
        
        spin_lock_irqsave(&iounit->lock, flags);
        len = ((vaddr & ~PAGE_MASK) + len + (PAGE_SIZE-1)) >> PAGE_SHIFT;
@@ -168,7 +168,7 @@ static void iounit_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_
 {
        unsigned long flags;
        unsigned long vaddr, len;
-       struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
+       struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu;
 
        spin_lock_irqsave(&iounit->lock, flags);
        while (sz != 0) {
@@ -211,7 +211,7 @@ static int iounit_map_dma_area(dma_addr_t *pba, unsigned long va, __u32 addr, in
                        i = ((addr - IOUNIT_DMA_BASE) >> PAGE_SHIFT);
 
                        for_each_sbus(sbus) {
-                               struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
+                               struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu;
 
                                iopte = (iopte_t *)(iounit->page_table + i);
                                *iopte = MKIOPTE(__pa(page));
@@ -235,7 +235,7 @@ static void iounit_unmap_dma_area(unsigned long addr, int len)
 static struct page *iounit_translate_dvma(unsigned long addr)
 {
        struct sbus_bus *sbus = sbus_root;      /* They are all the same */
-       struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
+       struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu;
        int i;
        iopte_t *iopte;
 
@@ -279,7 +279,7 @@ __u32 iounit_map_dma_init(struct sbus_bus *sbus, int size)
        unsigned long rotor, scan, limit;
        unsigned long flags;
        __u32 ret;
-       struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
+       struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu;
 
         npages = (size + (PAGE_SIZE-1)) >> PAGE_SHIFT;
        i = 0x0213;
@@ -315,7 +315,7 @@ nexti:      scan = find_next_zero_bit(iounit->bmap, limit, scan);
 __u32 iounit_map_dma_page(__u32 vaddr, void *addr, struct sbus_bus *sbus)
 {
        int scan = (vaddr - IOUNIT_DMA_BASE) >> PAGE_SHIFT;
-       struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
+       struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu;
        
        iounit->page_table[scan] = MKIOPTE(__pa(((unsigned long)addr) & PAGE_MASK));
        return vaddr + (((unsigned long)addr) & ~PAGE_MASK);
index be042efd1ba4311b6060a92f565f492e6fe04c6d..52e907af9d29e7b248a09b60987432cfe017cb9a 100644 (file)
@@ -132,7 +132,7 @@ iommu_init(int iommund, struct sbus_bus *sbus)
            impl, vers, iommu->page_table,
            (int)(IOMMU_NPTES*sizeof(iopte_t)), (int)IOMMU_NPTES);
 
-       sbus->iommu = iommu;
+       sbus->ofdev.dev.archdata.iommu = iommu;
 }
 
 /* This begs to be btfixup-ed by srmmu. */
@@ -166,7 +166,7 @@ static void iommu_flush_iotlb(iopte_t *iopte, unsigned int niopte)
 
 static u32 iommu_get_one(struct page *page, int npages, struct sbus_bus *sbus)
 {
-       struct iommu_struct *iommu = sbus->iommu;
+       struct iommu_struct *iommu = sbus->ofdev.dev.archdata.iommu;
        int ioptex;
        iopte_t *iopte, *iopte0;
        unsigned int busa, busa0;
@@ -291,7 +291,7 @@ static void iommu_get_scsi_sgl_pflush(struct scatterlist *sg, int sz, struct sbu
 
 static void iommu_release_one(u32 busa, int npages, struct sbus_bus *sbus)
 {
-       struct iommu_struct *iommu = sbus->iommu;
+       struct iommu_struct *iommu = sbus->ofdev.dev.archdata.iommu;
        int ioptex;
        int i;
 
@@ -334,7 +334,7 @@ static int iommu_map_dma_area(dma_addr_t *pba, unsigned long va,
     unsigned long addr, int len)
 {
        unsigned long page, end;
-       struct iommu_struct *iommu = sbus_root->iommu;
+       struct iommu_struct *iommu = sbus_root->ofdev.dev.archdata.iommu;
        iopte_t *iopte = iommu->page_table;
        iopte_t *first;
        int ioptex;
@@ -399,7 +399,7 @@ static int iommu_map_dma_area(dma_addr_t *pba, unsigned long va,
 
 static void iommu_unmap_dma_area(unsigned long busa, int len)
 {
-       struct iommu_struct *iommu = sbus_root->iommu;
+       struct iommu_struct *iommu = sbus_root->ofdev.dev.archdata.iommu;
        iopte_t *iopte = iommu->page_table;
        unsigned long end;
        int ioptex = (busa - iommu->start) >> PAGE_SHIFT;
@@ -420,7 +420,7 @@ static void iommu_unmap_dma_area(unsigned long busa, int len)
 
 static struct page *iommu_translate_dvma(unsigned long busa)
 {
-       struct iommu_struct *iommu = sbus_root->iommu;
+       struct iommu_struct *iommu = sbus_root->ofdev.dev.archdata.iommu;
        iopte_t *iopte = iommu->page_table;
 
        iopte += ((busa - iommu->start) >> PAGE_SHIFT);
index 79d60d86f6f8785b11dbf09c75bb8ef6ecc5f3ae..005a3e72d4f2dbf468b6a31a47d85c8ed507ebab 100644 (file)
@@ -268,7 +268,6 @@ static inline void sun4c_init_clean_mmu(unsigned long kernel_end)
        unsigned char savectx, ctx;
 
        savectx = sun4c_get_context();
-       kernel_end = SUN4C_REAL_PGDIR_ALIGN(kernel_end);
        for (ctx = 0; ctx < num_contexts; ctx++) {
                sun4c_set_context(ctx);
                for (vaddr = 0; vaddr < 0x20000000; vaddr += SUN4C_REAL_PGDIR_SIZE)
@@ -2064,7 +2063,6 @@ void __init sun4c_paging_init(void)
        unsigned long end_pfn, pages_avail;
 
        kernel_end = (unsigned long) &end;
-       kernel_end += (SUN4C_REAL_PGDIR_SIZE * 4);
        kernel_end = SUN4C_REAL_PGDIR_ALIGN(kernel_end);
 
        pages_avail = 0;
index ac18bd8e273f5badb0df5bcd5d467f5349e50568..63144ad476f6663c1ab3ed98fd252503fc89ebdb 100644 (file)
@@ -501,7 +501,7 @@ niagara_tlb_fixup:
        cmp     %g1, SUN4V_CHIP_NIAGARA1
        be,pt   %xcc, niagara_patch
         cmp    %g1, SUN4V_CHIP_NIAGARA2
-       be,pt   %xcc, niagara_patch
+       be,pt   %xcc, niagara2_patch
         nop
 
        call    generic_patch_copyops
@@ -512,6 +512,15 @@ niagara_tlb_fixup:
         nop
 
        ba,a,pt %xcc, 80f
+niagara2_patch:
+       call    niagara2_patch_copyops
+        nop
+       call    niagara_patch_bzero
+        nop
+       call    niagara2_patch_pageops
+        nop
+
+       ba,a,pt %xcc, 80f
 
 niagara_patch:
        call    niagara_patch_copyops
@@ -706,12 +715,13 @@ setup_trap_table:
 
        membar  #Sync
 
+       BRANCH_IF_SUN4V(o2, 1f)
+
        /* Kill PROM timer */
        sethi   %hi(0x80000000), %o2
        sllx    %o2, 32, %o2
        wr      %o2, 0, %tick_cmpr
 
-       BRANCH_IF_SUN4V(o2, 1f)
        BRANCH_IF_ANY_CHEETAH(o2, o3, 1f)
 
        ba,pt   %xcc, 2f
index 95059c2ec414804e50d63681b60ddd2ccfaa4be4..9f22e4ff6015771e8c39106f7df2baff3c315633 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
+#include <linux/miscdevice.h>
 
 #include <asm/hypervisor.h>
 #include <asm/mdesc.h>
@@ -836,6 +837,43 @@ void __devinit mdesc_fill_in_cpu_data(cpumask_t mask)
        mdesc_release(hp);
 }
 
+static ssize_t mdesc_read(struct file *file, char __user *buf,
+                         size_t len, loff_t *offp)
+{
+       struct mdesc_handle *hp = mdesc_grab();
+       int err;
+
+       if (!hp)
+               return -ENODEV;
+
+       err = hp->handle_size;
+       if (len < hp->handle_size)
+               err = -EMSGSIZE;
+       else if (copy_to_user(buf, &hp->mdesc, hp->handle_size))
+               err = -EFAULT;
+       mdesc_release(hp);
+
+       return err;
+}
+
+static const struct file_operations mdesc_fops = {
+       .read   = mdesc_read,
+       .owner  = THIS_MODULE,
+};
+
+static struct miscdevice mdesc_misc = {
+       .minor  = MISC_DYNAMIC_MINOR,
+       .name   = "mdesc",
+       .fops   = &mdesc_fops,
+};
+
+static int __init mdesc_misc_init(void)
+{
+       return misc_register(&mdesc_misc);
+}
+
+__initcall(mdesc_misc_init);
+
 void __init sun4v_mdesc_init(void)
 {
        struct mdesc_handle *hp;
index 9448595f9063f346202575ee5a0a2d72caef797b..9533a25ce5d2191f9ceb251695c0141acc78071c 100644 (file)
@@ -95,14 +95,13 @@ spitfire_startup:
        membar          #Sync
 
 startup_continue:
+       mov             %o0, %l0
+       BRANCH_IF_SUN4V(g1, niagara_lock_tlb)
+
        sethi           %hi(0x80000000), %g2
        sllx            %g2, 32, %g2
        wr              %g2, 0, %tick_cmpr
 
-       mov             %o0, %l0
-
-       BRANCH_IF_SUN4V(g1, niagara_lock_tlb)
-
        /* Call OBP by hand to lock KERNBASE into i/d tlbs.
         * We lock 2 consequetive entries if we are 'bigkernel'.
         */
index f95fbfa3eeb86b8a9389eb273514226c7b1a5bd5..f095e13910bc9ebf69646cec413297c89f08ff08 100644 (file)
@@ -13,6 +13,8 @@ lib-y := PeeCeeI.o copy_page.o clear_page.o strlen.o strncmp.o \
         U3memcpy.o U3copy_from_user.o U3copy_to_user.o U3patch.o \
         NGmemcpy.o NGcopy_from_user.o NGcopy_to_user.o NGpatch.o \
         NGpage.o NGbzero.o \
+        NG2memcpy.o NG2copy_from_user.o NG2copy_to_user.o NG2patch.o \
+        NG2page.o \
         GENmemcpy.o GENcopy_from_user.o GENcopy_to_user.o GENpatch.o \
         GENpage.o GENbzero.o \
         copy_in_user.o user_fixup.o memmove.o \
diff --git a/arch/sparc64/lib/NG2copy_from_user.S b/arch/sparc64/lib/NG2copy_from_user.S
new file mode 100644 (file)
index 0000000..c77ef5f
--- /dev/null
@@ -0,0 +1,40 @@
+/* NG2copy_from_user.S: Niagara-2 optimized copy from userspace.
+ *
+ * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
+ */
+
+#define EX_LD(x)               \
+98:    x;                      \
+       .section .fixup;        \
+       .align 4;               \
+99:    wr      %g0, ASI_AIUS, %asi;\
+       retl;                   \
+        mov    1, %o0;         \
+       .section __ex_table,"a";\
+       .align 4;               \
+       .word 98b, 99b;         \
+       .text;                  \
+       .align 4;
+
+#ifndef ASI_AIUS
+#define ASI_AIUS       0x11
+#endif
+
+#ifndef ASI_BLK_AIUS_4V
+#define ASI_BLK_AIUS_4V        0x17
+#endif
+
+#define FUNC_NAME              NG2copy_from_user
+#define LOAD(type,addr,dest)   type##a [addr] %asi, dest
+#define LOAD_BLK(addr,dest)    ldda [addr] ASI_BLK_AIUS_4V, dest
+#define EX_RETVAL(x)           0
+
+#ifdef __KERNEL__
+#define PREAMBLE                                       \
+       rd              %asi, %g1;                      \
+       cmp             %g1, ASI_AIUS;                  \
+       bne,pn          %icc, memcpy_user_stub;         \
+        nop
+#endif
+
+#include "NG2memcpy.S"
diff --git a/arch/sparc64/lib/NG2copy_to_user.S b/arch/sparc64/lib/NG2copy_to_user.S
new file mode 100644 (file)
index 0000000..4bd4093
--- /dev/null
@@ -0,0 +1,49 @@
+/* NG2copy_to_user.S: Niagara-2 optimized copy to userspace.
+ *
+ * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
+ */
+
+#define EX_ST(x)               \
+98:    x;                      \
+       .section .fixup;        \
+       .align 4;               \
+99:    wr      %g0, ASI_AIUS, %asi;\
+       retl;                   \
+        mov    1, %o0;         \
+       .section __ex_table,"a";\
+       .align 4;               \
+       .word 98b, 99b;         \
+       .text;                  \
+       .align 4;
+
+#ifndef ASI_AIUS
+#define ASI_AIUS       0x11
+#endif
+
+#ifndef ASI_BLK_AIUS_4V
+#define ASI_BLK_AIUS_4V        0x17
+#endif
+
+#ifndef ASI_BLK_INIT_QUAD_LDD_AIUS
+#define ASI_BLK_INIT_QUAD_LDD_AIUS 0x23
+#endif
+
+#define FUNC_NAME              NG2copy_to_user
+#define STORE(type,src,addr)   type##a src, [addr] ASI_AIUS
+#define STORE_ASI              ASI_BLK_INIT_QUAD_LDD_AIUS
+#define STORE_BLK(src,addr)    stda src, [addr] ASI_BLK_AIUS_4V
+#define EX_RETVAL(x)           0
+
+#ifdef __KERNEL__
+       /* Writing to %asi is _expensive_ so we hardcode it.
+        * Reading %asi to check for KERNEL_DS is comparatively
+        * cheap.
+        */
+#define PREAMBLE                                       \
+       rd              %asi, %g1;                      \
+       cmp             %g1, ASI_AIUS;                  \
+       bne,pn          %icc, memcpy_user_stub;         \
+        nop
+#endif
+
+#include "NG2memcpy.S"
diff --git a/arch/sparc64/lib/NG2memcpy.S b/arch/sparc64/lib/NG2memcpy.S
new file mode 100644 (file)
index 0000000..0aed756
--- /dev/null
@@ -0,0 +1,520 @@
+/* NG2memcpy.S: Niagara-2 optimized memcpy.
+ *
+ * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
+ */
+
+#ifdef __KERNEL__
+#include <asm/visasm.h>
+#include <asm/asi.h>
+#define GLOBAL_SPARE   %g7
+#else
+#define ASI_PNF 0x82
+#define ASI_BLK_P 0xf0
+#define ASI_BLK_INIT_QUAD_LDD_P 0xe2
+#define FPRS_FEF  0x04
+#ifdef MEMCPY_DEBUG
+#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs; \
+                    clr %g1; clr %g2; clr %g3; subcc %g0, %g0, %g0;
+#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
+#else
+#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs
+#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs
+#endif
+#define GLOBAL_SPARE   %g5
+#endif
+
+#ifndef STORE_ASI
+#ifndef SIMULATE_NIAGARA_ON_NON_NIAGARA
+#define STORE_ASI      ASI_BLK_INIT_QUAD_LDD_P
+#else
+#define STORE_ASI      0x80            /* ASI_P */
+#endif
+#endif
+
+#ifndef EX_LD
+#define EX_LD(x)       x
+#endif
+
+#ifndef EX_ST
+#define EX_ST(x)       x
+#endif
+
+#ifndef EX_RETVAL
+#define EX_RETVAL(x)   x
+#endif
+
+#ifndef LOAD
+#define LOAD(type,addr,dest)   type [addr], dest
+#endif
+
+#ifndef LOAD_BLK
+#define LOAD_BLK(addr,dest)    ldda [addr] ASI_BLK_P, dest
+#endif
+
+#ifndef STORE
+#ifndef MEMCPY_DEBUG
+#define STORE(type,src,addr)   type src, [addr]
+#else
+#define STORE(type,src,addr)   type##a src, [addr] 0x80
+#endif
+#endif
+
+#ifndef STORE_BLK
+#define STORE_BLK(src,addr)    stda src, [addr] ASI_BLK_P
+#endif
+
+#ifndef STORE_INIT
+#define STORE_INIT(src,addr)   stxa src, [addr] STORE_ASI
+#endif
+
+#ifndef FUNC_NAME
+#define FUNC_NAME      NG2memcpy
+#endif
+
+#ifndef PREAMBLE
+#define PREAMBLE
+#endif
+
+#ifndef XCC
+#define XCC xcc
+#endif
+
+#define FREG_FROB(x0, x1, x2, x3, x4, x5, x6, x7, x8) \
+       faligndata      %x0, %x1, %f0; \
+       faligndata      %x1, %x2, %f2; \
+       faligndata      %x2, %x3, %f4; \
+       faligndata      %x3, %x4, %f6; \
+       faligndata      %x4, %x5, %f8; \
+       faligndata      %x5, %x6, %f10; \
+       faligndata      %x6, %x7, %f12; \
+       faligndata      %x7, %x8, %f14;
+
+#define FREG_MOVE_1(x0) \
+       fmovd           %x0, %f0;
+#define FREG_MOVE_2(x0, x1) \
+       fmovd           %x0, %f0; \
+       fmovd           %x1, %f2;
+#define FREG_MOVE_3(x0, x1, x2) \
+       fmovd           %x0, %f0; \
+       fmovd           %x1, %f2; \
+       fmovd           %x2, %f4;
+#define FREG_MOVE_4(x0, x1, x2, x3) \
+       fmovd           %x0, %f0; \
+       fmovd           %x1, %f2; \
+       fmovd           %x2, %f4; \
+       fmovd           %x3, %f6;
+#define FREG_MOVE_5(x0, x1, x2, x3, x4) \
+       fmovd           %x0, %f0; \
+       fmovd           %x1, %f2; \
+       fmovd           %x2, %f4; \
+       fmovd           %x3, %f6; \
+       fmovd           %x4, %f8;
+#define FREG_MOVE_6(x0, x1, x2, x3, x4, x5) \
+       fmovd           %x0, %f0; \
+       fmovd           %x1, %f2; \
+       fmovd           %x2, %f4; \
+       fmovd           %x3, %f6; \
+       fmovd           %x4, %f8; \
+       fmovd           %x5, %f10;
+#define FREG_MOVE_7(x0, x1, x2, x3, x4, x5, x6) \
+       fmovd           %x0, %f0; \
+       fmovd           %x1, %f2; \
+       fmovd           %x2, %f4; \
+       fmovd           %x3, %f6; \
+       fmovd           %x4, %f8; \
+       fmovd           %x5, %f10; \
+       fmovd           %x6, %f12;
+#define FREG_MOVE_8(x0, x1, x2, x3, x4, x5, x6, x7) \
+       fmovd           %x0, %f0; \
+       fmovd           %x1, %f2; \
+       fmovd           %x2, %f4; \
+       fmovd           %x3, %f6; \
+       fmovd           %x4, %f8; \
+       fmovd           %x5, %f10; \
+       fmovd           %x6, %f12; \
+       fmovd           %x7, %f14;
+#define FREG_LOAD_1(base, x0) \
+       EX_LD(LOAD(ldd, base + 0x00, %x0))
+#define FREG_LOAD_2(base, x0, x1) \
+       EX_LD(LOAD(ldd, base + 0x00, %x0)); \
+       EX_LD(LOAD(ldd, base + 0x08, %x1));
+#define FREG_LOAD_3(base, x0, x1, x2) \
+       EX_LD(LOAD(ldd, base + 0x00, %x0)); \
+       EX_LD(LOAD(ldd, base + 0x08, %x1)); \
+       EX_LD(LOAD(ldd, base + 0x10, %x2));
+#define FREG_LOAD_4(base, x0, x1, x2, x3) \
+       EX_LD(LOAD(ldd, base + 0x00, %x0)); \
+       EX_LD(LOAD(ldd, base + 0x08, %x1)); \
+       EX_LD(LOAD(ldd, base + 0x10, %x2)); \
+       EX_LD(LOAD(ldd, base + 0x18, %x3));
+#define FREG_LOAD_5(base, x0, x1, x2, x3, x4) \
+       EX_LD(LOAD(ldd, base + 0x00, %x0)); \
+       EX_LD(LOAD(ldd, base + 0x08, %x1)); \
+       EX_LD(LOAD(ldd, base + 0x10, %x2)); \
+       EX_LD(LOAD(ldd, base + 0x18, %x3)); \
+       EX_LD(LOAD(ldd, base + 0x20, %x4));
+#define FREG_LOAD_6(base, x0, x1, x2, x3, x4, x5) \
+       EX_LD(LOAD(ldd, base + 0x00, %x0)); \
+       EX_LD(LOAD(ldd, base + 0x08, %x1)); \
+       EX_LD(LOAD(ldd, base + 0x10, %x2)); \
+       EX_LD(LOAD(ldd, base + 0x18, %x3)); \
+       EX_LD(LOAD(ldd, base + 0x20, %x4)); \
+       EX_LD(LOAD(ldd, base + 0x28, %x5));
+#define FREG_LOAD_7(base, x0, x1, x2, x3, x4, x5, x6) \
+       EX_LD(LOAD(ldd, base + 0x00, %x0)); \
+       EX_LD(LOAD(ldd, base + 0x08, %x1)); \
+       EX_LD(LOAD(ldd, base + 0x10, %x2)); \
+       EX_LD(LOAD(ldd, base + 0x18, %x3)); \
+       EX_LD(LOAD(ldd, base + 0x20, %x4)); \
+       EX_LD(LOAD(ldd, base + 0x28, %x5)); \
+       EX_LD(LOAD(ldd, base + 0x30, %x6));
+
+       .register       %g2,#scratch
+       .register       %g3,#scratch
+
+       .text
+       .align          64
+
+       .globl  FUNC_NAME
+       .type   FUNC_NAME,#function
+FUNC_NAME:     /* %o0=dst, %o1=src, %o2=len */
+       srlx            %o2, 31, %g2
+       cmp             %g2, 0
+       tne             %xcc, 5
+       PREAMBLE
+       mov             %o0, GLOBAL_SPARE
+       cmp             %o2, 0
+       be,pn           %XCC, 85f
+        or             %o0, %o1, %o3
+       cmp             %o2, 16
+       blu,a,pn        %XCC, 80f
+        or             %o3, %o2, %o3
+
+       /* 2 blocks (128 bytes) is the minimum we can do the block
+        * copy with.  We need to ensure that we'll iterate at least
+        * once in the block copy loop.  At worst we'll need to align
+        * the destination to a 64-byte boundary which can chew up
+        * to (64 - 1) bytes from the length before we perform the
+        * block copy loop.
+        *
+        * However, the cut-off point, performance wise, is around
+        * 4 64-byte blocks.
+        */
+       cmp             %o2, (4 * 64)
+       blu,pt          %XCC, 75f
+        andcc          %o3, 0x7, %g0
+
+       /* %o0: dst
+        * %o1: src
+        * %o2: len  (known to be >= 128)
+        *
+        * The block copy loops can use %o4, %g2, %g3 as
+        * temporaries while copying the data.  %o5 must
+        * be preserved between VISEntryHalf and VISExitHalf
+        */
+
+       LOAD(prefetch, %o1 + 0x000, #one_read)
+       LOAD(prefetch, %o1 + 0x040, #one_read)
+       LOAD(prefetch, %o1 + 0x080, #one_read)
+
+       /* Align destination on 64-byte boundary.  */
+       andcc           %o0, (64 - 1), %o4
+       be,pt           %XCC, 2f
+        sub            %o4, 64, %o4
+       sub             %g0, %o4, %o4   ! bytes to align dst
+       sub             %o2, %o4, %o2
+1:     subcc           %o4, 1, %o4
+       EX_LD(LOAD(ldub, %o1, %g1))
+       EX_ST(STORE(stb, %g1, %o0))
+       add             %o1, 1, %o1
+       bne,pt          %XCC, 1b
+       add             %o0, 1, %o0
+
+2:
+       /* Clobbers o5/g1/g2/g3/g7/icc/xcc.  We must preserve
+        * o5 from here until we hit VISExitHalf.
+        */
+       VISEntryHalf
+
+       alignaddr       %o1, %g0, %g0
+
+       add             %o1, (64 - 1), %o4
+       andn            %o4, (64 - 1), %o4
+       andn            %o2, (64 - 1), %g1
+       sub             %o2, %g1, %o2
+
+       and             %o1, (64 - 1), %g2
+       add             %o1, %g1, %o1
+       sub             %o0, %o4, %g3
+       brz,pt          %g2, 190f
+        cmp            %g2, 32
+       blu,a           5f
+        cmp            %g2, 16
+       cmp             %g2, 48
+       blu,a           4f
+        cmp            %g2, 40
+       cmp             %g2, 56
+       blu             170f
+        nop
+       ba,a,pt         %xcc, 180f
+
+4:     /* 32 <= low bits < 48 */
+       blu             150f
+        nop
+       ba,a,pt         %xcc, 160f
+5:     /* 0 < low bits < 32 */
+       blu,a           6f
+        cmp            %g2, 8
+       cmp             %g2, 24
+       blu             130f
+        nop
+       ba,a,pt         %xcc, 140f
+6:     /* 0 < low bits < 16 */
+       bgeu            120f
+        nop
+       /* fall through for 0 < low bits < 8 */
+110:   sub             %o4, 64, %g2
+       EX_LD(LOAD_BLK(%g2, %f0))
+1:     EX_ST(STORE_INIT(%g0, %o4 + %g3))
+       EX_LD(LOAD_BLK(%o4, %f16))
+       FREG_FROB(f0, f2, f4, f6, f8, f10, f12, f14, f16)
+       EX_ST(STORE_BLK(%f0, %o4 + %g3))
+       FREG_MOVE_8(f16, f18, f20, f22, f24, f26, f28, f30)
+       subcc           %g1, 64, %g1
+       add             %o4, 64, %o4
+       bne,pt          %xcc, 1b
+        LOAD(prefetch, %o4 + 64, #one_read)
+       ba,pt           %xcc, 195f
+        nop
+
+120:   sub             %o4, 56, %g2
+       FREG_LOAD_7(%g2, f0, f2, f4, f6, f8, f10, f12)
+1:     EX_ST(STORE_INIT(%g0, %o4 + %g3))
+       EX_LD(LOAD_BLK(%o4, %f16))
+       FREG_FROB(f0, f2, f4, f6, f8, f10, f12, f16, f18)
+       EX_ST(STORE_BLK(%f0, %o4 + %g3))
+       FREG_MOVE_7(f18, f20, f22, f24, f26, f28, f30)
+       subcc           %g1, 64, %g1
+       add             %o4, 64, %o4
+       bne,pt          %xcc, 1b
+        LOAD(prefetch, %o4 + 64, #one_read)
+       ba,pt           %xcc, 195f
+        nop
+
+130:   sub             %o4, 48, %g2
+       FREG_LOAD_6(%g2, f0, f2, f4, f6, f8, f10)
+1:     EX_ST(STORE_INIT(%g0, %o4 + %g3))
+       EX_LD(LOAD_BLK(%o4, %f16))
+       FREG_FROB(f0, f2, f4, f6, f8, f10, f16, f18, f20)
+       EX_ST(STORE_BLK(%f0, %o4 + %g3))
+       FREG_MOVE_6(f20, f22, f24, f26, f28, f30)
+       subcc           %g1, 64, %g1
+       add             %o4, 64, %o4
+       bne,pt          %xcc, 1b
+        LOAD(prefetch, %o4 + 64, #one_read)
+       ba,pt           %xcc, 195f
+        nop
+
+140:   sub             %o4, 40, %g2
+       FREG_LOAD_5(%g2, f0, f2, f4, f6, f8)
+1:     EX_ST(STORE_INIT(%g0, %o4 + %g3))
+       EX_LD(LOAD_BLK(%o4, %f16))
+       FREG_FROB(f0, f2, f4, f6, f8, f16, f18, f20, f22)
+       EX_ST(STORE_BLK(%f0, %o4 + %g3))
+       FREG_MOVE_5(f22, f24, f26, f28, f30)
+       subcc           %g1, 64, %g1
+       add             %o4, 64, %o4
+       bne,pt          %xcc, 1b
+        LOAD(prefetch, %o4 + 64, #one_read)
+       ba,pt           %xcc, 195f
+        nop
+
+150:   sub             %o4, 32, %g2
+       FREG_LOAD_4(%g2, f0, f2, f4, f6)
+1:     EX_ST(STORE_INIT(%g0, %o4 + %g3))
+       EX_LD(LOAD_BLK(%o4, %f16))
+       FREG_FROB(f0, f2, f4, f6, f16, f18, f20, f22, f24)
+       EX_ST(STORE_BLK(%f0, %o4 + %g3))
+       FREG_MOVE_4(f24, f26, f28, f30)
+       subcc           %g1, 64, %g1
+       add             %o4, 64, %o4
+       bne,pt          %xcc, 1b
+        LOAD(prefetch, %o4 + 64, #one_read)
+       ba,pt           %xcc, 195f
+        nop
+
+160:   sub             %o4, 24, %g2
+       FREG_LOAD_3(%g2, f0, f2, f4)
+1:     EX_ST(STORE_INIT(%g0, %o4 + %g3))
+       EX_LD(LOAD_BLK(%o4, %f16))
+       FREG_FROB(f0, f2, f4, f16, f18, f20, f22, f24, f26)
+       EX_ST(STORE_BLK(%f0, %o4 + %g3))
+       FREG_MOVE_3(f26, f28, f30)
+       subcc           %g1, 64, %g1
+       add             %o4, 64, %o4
+       bne,pt          %xcc, 1b
+        LOAD(prefetch, %o4 + 64, #one_read)
+       ba,pt           %xcc, 195f
+        nop
+
+170:   sub             %o4, 16, %g2
+       FREG_LOAD_2(%g2, f0, f2)
+1:     EX_ST(STORE_INIT(%g0, %o4 + %g3))
+       EX_LD(LOAD_BLK(%o4, %f16))
+       FREG_FROB(f0, f2, f16, f18, f20, f22, f24, f26, f28)
+       EX_ST(STORE_BLK(%f0, %o4 + %g3))
+       FREG_MOVE_2(f28, f30)
+       subcc           %g1, 64, %g1
+       add             %o4, 64, %o4
+       bne,pt          %xcc, 1b
+        LOAD(prefetch, %o4 + 64, #one_read)
+       ba,pt           %xcc, 195f
+        nop
+
+180:   sub             %o4, 8, %g2
+       FREG_LOAD_1(%g2, f0)
+1:     EX_ST(STORE_INIT(%g0, %o4 + %g3))
+       EX_LD(LOAD_BLK(%o4, %f16))
+       FREG_FROB(f0, f16, f18, f20, f22, f24, f26, f28, f30)
+       EX_ST(STORE_BLK(%f0, %o4 + %g3))
+       FREG_MOVE_1(f30)
+       subcc           %g1, 64, %g1
+       add             %o4, 64, %o4
+       bne,pt          %xcc, 1b
+        LOAD(prefetch, %o4 + 64, #one_read)
+       ba,pt           %xcc, 195f
+        nop
+
+190:
+1:     EX_ST(STORE_INIT(%g0, %o4 + %g3))
+       subcc           %g1, 64, %g1
+       EX_LD(LOAD_BLK(%o4, %f0))
+       EX_ST(STORE_BLK(%f0, %o4 + %g3))
+       add             %o4, 64, %o4
+       bne,pt          %xcc, 1b
+        LOAD(prefetch, %o4 + 64, #one_read)
+
+195:
+       add             %o4, %g3, %o0
+       membar          #Sync
+
+       VISExitHalf
+
+       /* %o2 contains any final bytes still needed to be copied
+        * over. If anything is left, we copy it one byte at a time.
+        */
+       brz,pt          %o2, 85f
+        sub            %o0, %o1, %o3
+       ba,a,pt         %XCC, 90f
+
+       .align          64
+75: /* 16 < len <= 64 */
+       bne,pn          %XCC, 75f
+        sub            %o0, %o1, %o3
+
+72:
+       andn            %o2, 0xf, %o4
+       and             %o2, 0xf, %o2
+1:     subcc           %o4, 0x10, %o4
+       EX_LD(LOAD(ldx, %o1, %o5))
+       add             %o1, 0x08, %o1
+       EX_LD(LOAD(ldx, %o1, %g1))
+       sub             %o1, 0x08, %o1
+       EX_ST(STORE(stx, %o5, %o1 + %o3))
+       add             %o1, 0x8, %o1
+       EX_ST(STORE(stx, %g1, %o1 + %o3))
+       bgu,pt          %XCC, 1b
+        add            %o1, 0x8, %o1
+73:    andcc           %o2, 0x8, %g0
+       be,pt           %XCC, 1f
+        nop
+       sub             %o2, 0x8, %o2
+       EX_LD(LOAD(ldx, %o1, %o5))
+       EX_ST(STORE(stx, %o5, %o1 + %o3))
+       add             %o1, 0x8, %o1
+1:     andcc           %o2, 0x4, %g0
+       be,pt           %XCC, 1f
+        nop
+       sub             %o2, 0x4, %o2
+       EX_LD(LOAD(lduw, %o1, %o5))
+       EX_ST(STORE(stw, %o5, %o1 + %o3))
+       add             %o1, 0x4, %o1
+1:     cmp             %o2, 0
+       be,pt           %XCC, 85f
+        nop
+       ba,pt           %xcc, 90f
+        nop
+
+75:
+       andcc           %o0, 0x7, %g1
+       sub             %g1, 0x8, %g1
+       be,pn           %icc, 2f
+        sub            %g0, %g1, %g1
+       sub             %o2, %g1, %o2
+
+1:     subcc           %g1, 1, %g1
+       EX_LD(LOAD(ldub, %o1, %o5))
+       EX_ST(STORE(stb, %o5, %o1 + %o3))
+       bgu,pt          %icc, 1b
+        add            %o1, 1, %o1
+
+2:     add             %o1, %o3, %o0
+       andcc           %o1, 0x7, %g1
+       bne,pt          %icc, 8f
+        sll            %g1, 3, %g1
+
+       cmp             %o2, 16
+       bgeu,pt         %icc, 72b
+        nop
+       ba,a,pt         %xcc, 73b
+
+8:     mov             64, %o3
+       andn            %o1, 0x7, %o1
+       EX_LD(LOAD(ldx, %o1, %g2))
+       sub             %o3, %g1, %o3
+       andn            %o2, 0x7, %o4
+       sllx            %g2, %g1, %g2
+1:     add             %o1, 0x8, %o1
+       EX_LD(LOAD(ldx, %o1, %g3))
+       subcc           %o4, 0x8, %o4
+       srlx            %g3, %o3, %o5
+       or              %o5, %g2, %o5
+       EX_ST(STORE(stx, %o5, %o0))
+       add             %o0, 0x8, %o0
+       bgu,pt          %icc, 1b
+        sllx           %g3, %g1, %g2
+
+       srl             %g1, 3, %g1
+       andcc           %o2, 0x7, %o2
+       be,pn           %icc, 85f
+        add            %o1, %g1, %o1
+       ba,pt           %xcc, 90f
+        sub            %o0, %o1, %o3
+
+       .align          64
+80: /* 0 < len <= 16 */
+       andcc           %o3, 0x3, %g0
+       bne,pn          %XCC, 90f
+        sub            %o0, %o1, %o3
+
+1:
+       subcc           %o2, 4, %o2
+       EX_LD(LOAD(lduw, %o1, %g1))
+       EX_ST(STORE(stw, %g1, %o1 + %o3))
+       bgu,pt          %XCC, 1b
+        add            %o1, 4, %o1
+
+85:    retl
+        mov            EX_RETVAL(GLOBAL_SPARE), %o0
+
+       .align          32
+90:
+       subcc           %o2, 1, %o2
+       EX_LD(LOAD(ldub, %o1, %g1))
+       EX_ST(STORE(stb, %g1, %o1 + %o3))
+       bgu,pt          %XCC, 90b
+        add            %o1, 1, %o1
+       retl
+        mov            EX_RETVAL(GLOBAL_SPARE), %o0
+
+       .size           FUNC_NAME, .-FUNC_NAME
diff --git a/arch/sparc64/lib/NG2page.S b/arch/sparc64/lib/NG2page.S
new file mode 100644 (file)
index 0000000..73b6b7c
--- /dev/null
@@ -0,0 +1,61 @@
+/* NG2page.S: Niagara-2 optimized clear and copy page.
+ *
+ * Copyright (C) 2007 (davem@davemloft.net)
+ */
+
+#include <asm/asi.h>
+#include <asm/page.h>
+#include <asm/visasm.h>
+
+       .text
+       .align  32
+
+       /* This is heavily simplified from the sun4u variants
+        * because Niagara-2 does not have any D-cache aliasing issues.
+        */
+NG2copy_user_page:     /* %o0=dest, %o1=src, %o2=vaddr */
+       prefetch        [%o1 + 0x00], #one_read
+       prefetch        [%o1 + 0x40], #one_read
+       VISEntryHalf
+       set             PAGE_SIZE, %g7
+       sub             %o0, %o1, %g3
+1:     stxa            %g0, [%o1 + %g3] ASI_BLK_INIT_QUAD_LDD_P
+       subcc           %g7, 64, %g7
+       ldda            [%o1] ASI_BLK_P, %f0
+       stda            %f0, [%o1 + %g3] ASI_BLK_P
+       add             %o1, 64, %o1
+       bne,pt          %xcc, 1b
+        prefetch       [%o1 + 0x40], #one_read
+       membar          #Sync
+       VISExitHalf
+       retl
+        nop
+
+#define BRANCH_ALWAYS  0x10680000
+#define NOP            0x01000000
+#define NG_DO_PATCH(OLD, NEW)  \
+       sethi   %hi(NEW), %g1; \
+       or      %g1, %lo(NEW), %g1; \
+       sethi   %hi(OLD), %g2; \
+       or      %g2, %lo(OLD), %g2; \
+       sub     %g1, %g2, %g1; \
+       sethi   %hi(BRANCH_ALWAYS), %g3; \
+       sll     %g1, 11, %g1; \
+       srl     %g1, 11 + 2, %g1; \
+       or      %g3, %lo(BRANCH_ALWAYS), %g3; \
+       or      %g3, %g1, %g3; \
+       stw     %g3, [%g2]; \
+       sethi   %hi(NOP), %g3; \
+       or      %g3, %lo(NOP), %g3; \
+       stw     %g3, [%g2 + 0x4]; \
+       flush   %g2;
+
+       .globl  niagara2_patch_pageops
+       .type   niagara2_patch_pageops,#function
+niagara2_patch_pageops:
+       NG_DO_PATCH(copy_user_page, NG2copy_user_page)
+       NG_DO_PATCH(_clear_page, NGclear_page)
+       NG_DO_PATCH(clear_user_page, NGclear_user_page)
+       retl
+        nop
+       .size   niagara2_patch_pageops,.-niagara2_patch_pageops
diff --git a/arch/sparc64/lib/NG2patch.S b/arch/sparc64/lib/NG2patch.S
new file mode 100644 (file)
index 0000000..28c36f0
--- /dev/null
@@ -0,0 +1,33 @@
+/* NG2patch.S: Patch Ultra-I routines with Niagara-2 variant.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#define BRANCH_ALWAYS  0x10680000
+#define NOP            0x01000000
+#define NG_DO_PATCH(OLD, NEW)  \
+       sethi   %hi(NEW), %g1; \
+       or      %g1, %lo(NEW), %g1; \
+       sethi   %hi(OLD), %g2; \
+       or      %g2, %lo(OLD), %g2; \
+       sub     %g1, %g2, %g1; \
+       sethi   %hi(BRANCH_ALWAYS), %g3; \
+       sll     %g1, 11, %g1; \
+       srl     %g1, 11 + 2, %g1; \
+       or      %g3, %lo(BRANCH_ALWAYS), %g3; \
+       or      %g3, %g1, %g3; \
+       stw     %g3, [%g2]; \
+       sethi   %hi(NOP), %g3; \
+       or      %g3, %lo(NOP), %g3; \
+       stw     %g3, [%g2 + 0x4]; \
+       flush   %g2;
+
+       .globl  niagara2_patch_copyops
+       .type   niagara2_patch_copyops,#function
+niagara2_patch_copyops:
+       NG_DO_PATCH(memcpy, NG2memcpy)
+       NG_DO_PATCH(___copy_from_user, NG2copy_from_user)
+       NG_DO_PATCH(___copy_to_user, NG2copy_to_user)
+       retl
+        nop
+       .size   niagara2_patch_copyops,.-niagara2_patch_copyops
index 8ce3a0c9c537ed4ac862afda0cca7f41ed4c0b98..428920de05baeb4f87b80a93d3a09480ef19ffec 100644 (file)
@@ -45,6 +45,7 @@ NGcopy_user_page:     /* %o0=dest, %o1=src, %o2=vaddr */
        retl
         nop
 
+       .globl          NGclear_page, NGclear_user_page
 NGclear_page:          /* %o0=dest */
 NGclear_user_page:     /* %o0=dest, %o1=vaddr */
        mov             8, %g1
index d036e4419d7958a1245c631cd19d4ea76f3a9a65..27d076c46964a9fd537f7b8cca8c7169b9c8aa13 100644 (file)
@@ -68,7 +68,6 @@ struct sbus_dev {
 /* This struct describes the SBus(s) found on this machine. */
 struct sbus_bus {
        struct of_device        ofdev;
-       void                    *iommu;         /* Opaque IOMMU cookie */
        struct sbus_dev         *devices;       /* Link to devices on this SBus */
        struct sbus_bus         *next;          /* next SBus, if more than one SBus */
        int                     prom_node;      /* PROM device tree node for this SBus */
index ecfc86a4a725caee13da26b328f2992975534a92..266a42b8f99fad61d7f907bad23d306b4846846d 100644 (file)
@@ -203,4 +203,10 @@ extern struct task_struct *last_task_used_math;
 #define FP_INHIBIT_RESULTS ((last_task_used_math->thread.fsr >> 23) & _fex)
 #endif
 
+#ifdef CONFIG_SMP
+#define FP_TRAPPING_EXCEPTIONS ((current->thread.fsr >> 23) & 0x1f)
+#else
+#define FP_TRAPPING_EXCEPTIONS ((last_task_used_math->thread.fsr >> 23) & 0x1f)
+#endif
+
 #endif
index 303d85e2f82ee003b1a6866b766ebb1731975d0d..8653e86650097b4de2d7635a6231a1e684fd082c 100644 (file)
@@ -70,6 +70,7 @@
 #define HWCAP_SPARC_V9         16
 #define HWCAP_SPARC_ULTRA3     32
 #define HWCAP_SPARC_BLKINIT    64
+#define HWCAP_SPARC_N2         128
 
 /*
  * These are used to set parameters in the core dumps.
@@ -155,8 +156,13 @@ static inline unsigned int sparc64_elf_hwcap(void)
 
        if (tlb_type == cheetah || tlb_type == cheetah_plus)
                cap |= HWCAP_SPARC_ULTRA3;
-       else if (tlb_type == hypervisor)
-               cap |= HWCAP_SPARC_BLKINIT;
+       else if (tlb_type == hypervisor) {
+               if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 ||
+                   sun4v_chip_type == SUN4V_CHIP_NIAGARA2)
+                       cap |= HWCAP_SPARC_BLKINIT;
+               if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2)
+                       cap |= HWCAP_SPARC_N2;
+       }
 
        return cap;
 }
index 89d42431efb58e0cba76b903623c678cdfaf1e67..c9331b02d9c85df91a829906c1dfa5b1c79af04e 100644 (file)
@@ -88,4 +88,6 @@
 
 #define FP_INHIBIT_RESULTS ((current_thread_info()->xfsr[0] >> 23) & _fex)
 
+#define FP_TRAPPING_EXCEPTIONS ((current_thread_info()->xfsr[0] >> 23) & 0x1f)
+
 #endif
index 93780abd01bc60a4d23e09f90f90a684de2ebe52..bb46e7645d537234bdc44221bccfa8e0e332e4c5 100644 (file)
@@ -145,13 +145,16 @@ do {                                                              \
              {                                                 \
                X##_e = 1;                                      \
                _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);        \
+               FP_SET_EXCEPTION(FP_EX_INEXACT);                \
              }                                                 \
            else                                                \
              {                                                 \
                X##_e = 0;                                      \
                _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);             \
-               FP_SET_EXCEPTION(FP_EX_UNDERFLOW);              \
              }                                                 \
+           if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) ||          \
+               (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW))     \
+               FP_SET_EXCEPTION(FP_EX_UNDERFLOW);              \
          }                                                     \
        else                                                    \
          {                                                     \
index d02eb64a865bb4acbe81a148584fd92341cd14ae..a0721ef5c2f9e24b2c9c3317aa10fd9bb1b4d4a1 100644 (file)
 #define FP_INHIBIT_RESULTS 0
 #endif
 
+#ifndef FP_TRAPPING_EXCEPTIONS
+#define FP_TRAPPING_EXCPETIONS 0
+#endif
+
 #define FP_SET_EXCEPTION(ex)                           \
   _fex |= (ex)
   
 #define FP_UNSET_EXCEPTION(ex)                         \
   _fex &= ~(ex)
 
+#define FP_CUR_EXCEPTIONS                              \
+  (_fex)
+
 #define FP_CLEAR_EXCEPTIONS                            \
   _fex = 0