Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
authorLinus Torvalds <torvalds@woody.osdl.org>
Sun, 10 Dec 2006 18:00:00 +0000 (10:00 -0800)
committerLinus Torvalds <torvalds@woody.osdl.org>
Sun, 10 Dec 2006 18:00:00 +0000 (10:00 -0800)
* master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6:
  [SPARC64]: Fix several kprobes bugs.
  [SPARC64]: Update defconfig.
  [SPARC64]: dma remove extra brackets
  [SPARC{32,64}]: Propagate ptrace_traceme() return value.
  [SPARC64]: Replace kmalloc+memset with kzalloc
  [SPARC]: Check kzalloc() return value in SUN4D irq/iommu init.
  [SPARC]: Replace kmalloc+memset with kzalloc
  [SPARC64]: Run ctrl-alt-del action for sun4v powerdown request.
  [SPARC64]: Unaligned accesses to userspace are hard errors.
  [SPARC64]: Call do_mathemu on illegal instruction traps too.
  [SPARC64]: Update defconfig.
  [SPARC64]: Add irqtrace/stacktrace/lockdep support.

30 files changed:
arch/sparc/kernel/ioport.c
arch/sparc/kernel/of_device.c
arch/sparc/kernel/ptrace.c
arch/sparc/kernel/sun4d_irq.c
arch/sparc/mm/io-unit.c
arch/sparc64/Kconfig
arch/sparc64/Kconfig.debug
arch/sparc64/defconfig
arch/sparc64/kernel/Makefile
arch/sparc64/kernel/chmc.c
arch/sparc64/kernel/entry.S
arch/sparc64/kernel/head.S
arch/sparc64/kernel/isa.c
arch/sparc64/kernel/kprobes.c
arch/sparc64/kernel/of_device.c
arch/sparc64/kernel/pci_sun4v.c
arch/sparc64/kernel/ptrace.c
arch/sparc64/kernel/rtrap.S
arch/sparc64/kernel/stacktrace.c [new file with mode: 0644]
arch/sparc64/kernel/sun4v_ivec.S
arch/sparc64/kernel/traps.c
arch/sparc64/kernel/unaligned.c
arch/sparc64/kernel/visemul.c
arch/sparc64/mm/ultra.S
include/asm-sparc64/dma.h
include/asm-sparc64/irqflags.h [new file with mode: 0644]
include/asm-sparc64/kprobes.h
include/asm-sparc64/rwsem.h
include/asm-sparc64/system.h
include/asm-sparc64/ttable.h

index 54d51b4..cbbc988 100644 (file)
@@ -317,9 +317,8 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, long len, u32 *dma_addrp)
        if ((va = __get_free_pages(GFP_KERNEL|__GFP_COMP, order)) == 0)
                goto err_nopages;
 
-       if ((res = kmalloc(sizeof(struct resource), GFP_KERNEL)) == NULL)
+       if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL)
                goto err_nomem;
-       memset((char*)res, 0, sizeof(struct resource));
 
        if (allocate_resource(&_sparc_dvma, res, len_total,
            _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
@@ -589,12 +588,11 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t len, dma_addr_t *pba)
                return NULL;
        }
 
-       if ((res = kmalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) {
+       if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) {
                free_pages(va, order);
                printk("pci_alloc_consistent: no core\n");
                return NULL;
        }
-       memset((char*)res, 0, sizeof(struct resource));
 
        if (allocate_resource(&_sparc_dvma, res, len_total,
            _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
index 46200c4..dab6169 100644 (file)
@@ -793,10 +793,9 @@ struct of_device* of_platform_device_create(struct device_node *np,
 {
        struct of_device *dev;
 
-       dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (!dev)
                return NULL;
-       memset(dev, 0, sizeof(*dev));
 
        dev->dev.parent = parent;
        dev->dev.bus = bus;
index 1baf13e..003f8ee 100644 (file)
@@ -289,7 +289,10 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
 
        if (request == PTRACE_TRACEME) {
                ret = ptrace_traceme();
-               pt_succ_return(regs, 0);
+               if (ret < 0)
+                       pt_error_return(regs, -ret);
+               else
+                       pt_succ_return(regs, 0);
                goto out;
        }
 
index d4f9da8..cf1b8ba 100644 (file)
@@ -545,8 +545,11 @@ void __init sun4d_init_sbi_irq(void)
        nsbi = 0;
        for_each_sbus(sbus)
                nsbi++;
-       sbus_actions = (struct sbus_action *)kmalloc (nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC);
-       memset (sbus_actions, 0, (nsbi * 8 * 4 * sizeof(struct sbus_action)));
+       sbus_actions = kzalloc (nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC);
+       if (!sbus_actions) {
+               prom_printf("SUN4D: Cannot allocate sbus_actions, halting.\n");
+               prom_halt();
+       }
        for_each_sbus(sbus) {
 #ifdef CONFIG_SMP      
                extern unsigned char boot_cpu_id;
index 2bb1309..4ccda77 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/dma.h>
+#include <asm/oplib.h>
 
 /* #define IOUNIT_DEBUG */
 #ifdef IOUNIT_DEBUG
@@ -41,9 +42,12 @@ iounit_init(int sbi_node, int io_node, struct sbus_bus *sbus)
        struct linux_prom_registers iommu_promregs[PROMREG_MAX];
        struct resource r;
 
-       iounit = kmalloc(sizeof(struct iounit_struct), GFP_ATOMIC);
+       iounit = kzalloc(sizeof(struct iounit_struct), GFP_ATOMIC);
+       if (!iounit) {
+               prom_printf("SUN4D: Cannot alloc iounit, halting.\n");
+               prom_halt();
+       }
 
-       memset(iounit, 0, sizeof(*iounit));
        iounit->limit[0] = IOUNIT_BMAP1_START;
        iounit->limit[1] = IOUNIT_BMAP2_START;
        iounit->limit[2] = IOUNIT_BMAPM_START;
index d391d11..d41f66a 100644 (file)
@@ -26,6 +26,14 @@ config MMU
        bool
        default y
 
+config STACKTRACE_SUPPORT
+       bool
+       default y
+
+config LOCKDEP_SUPPORT
+       bool
+       default y
+
 config TIME_INTERPOLATION
        bool
        default y
index afe0a77..1f130f3 100644 (file)
@@ -1,5 +1,9 @@
 menu "Kernel hacking"
 
+config TRACE_IRQFLAGS_SUPPORT
+       bool
+       default y
+
 source "lib/Kconfig.debug"
 
 config DEBUG_STACK_USAGE
index 2f4612f..0f0d38f 100644 (file)
@@ -1,24 +1,29 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.19-rc2
-# Tue Oct 17 19:29:20 2006
+# Linux kernel version: 2.6.19
+# Sat Dec  9 15:41:30 2006
 #
 CONFIG_SPARC=y
 CONFIG_SPARC64=y
 CONFIG_64BIT=y
 CONFIG_MMU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
 CONFIG_TIME_INTERPOLATION=y
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_AUDIT_ARCH=y
 CONFIG_SPARC64_PAGE_SIZE_8KB=y
 # CONFIG_SPARC64_PAGE_SIZE_64KB is not set
 # CONFIG_SPARC64_PAGE_SIZE_512KB is not set
 # CONFIG_SPARC64_PAGE_SIZE_4MB is not set
 CONFIG_SECCOMP=y
-# CONFIG_HZ_100 is not set
-CONFIG_HZ_250=y
+CONFIG_HZ_100=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
 # CONFIG_HZ_1000 is not set
-CONFIG_HZ=250
+CONFIG_HZ=100
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -42,13 +47,14 @@ CONFIG_POSIX_MQUEUE=y
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 # CONFIG_EMBEDDED is not set
 CONFIG_UID16=y
-# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -203,6 +209,7 @@ CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
 CONFIG_IPV6=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
@@ -219,7 +226,6 @@ CONFIG_INET6_XFRM_MODE_BEET=m
 # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
 CONFIG_IPV6_SIT=m
 CONFIG_IPV6_TUNNEL=m
-# CONFIG_IPV6_SUBTREES is not set
 # CONFIG_IPV6_MULTIPLE_TABLES is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
@@ -238,6 +244,8 @@ CONFIG_IP_DCCP_CCID2=m
 # CONFIG_IP_DCCP_CCID2_DEBUG is not set
 CONFIG_IP_DCCP_CCID3=m
 CONFIG_IP_DCCP_TFRC_LIB=m
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_CCID3_RTO=100
 
 #
 # DCCP Kernel Hacking
@@ -405,6 +413,7 @@ CONFIG_IDEDMA_AUTO=y
 #
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
+# CONFIG_SCSI_TGT is not set
 CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
@@ -425,6 +434,7 @@ CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
 
 #
 # SCSI Transports
@@ -468,6 +478,7 @@ CONFIG_ISCSI_TCP=m
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SUNESP is not set
+# CONFIG_SCSI_SRP is not set
 
 #
 # Serial ATA (prod) and Parallel ATA (experimental) drivers
@@ -598,6 +609,7 @@ CONFIG_BNX2=m
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -724,10 +736,6 @@ CONFIG_RTC=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -1038,6 +1046,11 @@ CONFIG_SND_SUN_CS4231=m
 #
 # CONFIG_SOUND_PRIME is not set
 
+#
+# HID Devices
+#
+CONFIG_HID=y
+
 #
 # USB support
 #
@@ -1053,6 +1066,7 @@ CONFIG_USB=y
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -1089,8 +1103,7 @@ CONFIG_USB_UHCI_HCD=m
 # USB Input Devices
 #
 CONFIG_USB_HID=y
-CONFIG_USB_HIDINPUT=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_USB_HID_POWERBOOK is not set
 # CONFIG_HID_FF is not set
 CONFIG_USB_HIDDEV=y
 # CONFIG_USB_AIPTEK is not set
@@ -1119,6 +1132,7 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET_MII is not set
 # CONFIG_USB_USBNET is not set
 # CONFIG_USB_MON is not set
 
@@ -1363,6 +1377,11 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
 
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
 #
 # Instrumentation Support
 #
@@ -1373,6 +1392,7 @@ CONFIG_KPROBES=y
 #
 # Kernel hacking
 #
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 CONFIG_PRINTK_TIME=y
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
@@ -1387,6 +1407,8 @@ CONFIG_SCHEDSTATS=y
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_MUTEXES is not set
 # CONFIG_DEBUG_RWSEMS is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1420,8 +1442,9 @@ CONFIG_CRYPTO=y
 CONFIG_CRYPTO_ALGAPI=y
 CONFIG_CRYPTO_BLKCIPHER=y
 CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_MD5=y
@@ -1430,8 +1453,10 @@ CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_GF128MUL=m
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
@@ -1456,6 +1481,7 @@ CONFIG_CRYPTO_TEST=m
 #
 # Library routines
 #
+CONFIG_BITREVERSE=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC16=m
 CONFIG_CRC32=y
index e1eabeb..eff0c01 100644 (file)
@@ -14,6 +14,7 @@ obj-y         := process.o setup.o cpu.o idprom.o \
                   power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \
                   visemul.o prom.o of_device.o
 
+obj-$(CONFIG_STACKTRACE) += stacktrace.o
 obj-$(CONFIG_PCI)       += ebus.o isa.o pci_common.o pci_iommu.o \
                            pci_psycho.o pci_sabre.o pci_schizo.o \
                            pci_sun4v.o pci_sun4v_asm.o
index 259f37e..9699abe 100644 (file)
@@ -341,7 +341,7 @@ static void fetch_decode_regs(struct mctrl_info *mp)
 
 static int init_one_mctrl(struct device_node *dp)
 {
-       struct mctrl_info *mp = kmalloc(sizeof(*mp), GFP_KERNEL);
+       struct mctrl_info *mp = kzalloc(sizeof(*mp), GFP_KERNEL);
        int portid = of_getintprop_default(dp, "portid", -1);
        struct linux_prom64_registers *regs;
        void *pval;
@@ -349,7 +349,6 @@ static int init_one_mctrl(struct device_node *dp)
 
        if (!mp)
                return -1;
-       memset(mp, 0, sizeof(*mp));
        if (portid == -1)
                goto fail;
 
index 6f28bec..c15a3ed 100644 (file)
@@ -597,7 +597,12 @@ __spitfire_cee_trap_continue:
 1:     ba,pt           %xcc, etrap_irq
         rd             %pc, %g7
 
-2:     mov             %l4, %o1
+2:
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call    trace_hardirqs_off
+        nop
+#endif
+       mov             %l4, %o1
        mov             %l5, %o2
        call            spitfire_access_error
         add            %sp, PTREGS_OFF, %o0
@@ -824,6 +829,10 @@ do_cheetah_plus_data_parity:
        wrpr            %g0, 15, %pil
        ba,pt           %xcc, etrap_irq
         rd             %pc, %g7
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        mov             0x0, %o0
        call            cheetah_plus_parity_error
         add            %sp, PTREGS_OFF, %o1
@@ -855,6 +864,10 @@ do_cheetah_plus_insn_parity:
        wrpr            %g0, 15, %pil
        ba,pt           %xcc, etrap_irq
         rd             %pc, %g7
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        mov             0x1, %o0
        call            cheetah_plus_parity_error
         add            %sp, PTREGS_OFF, %o1
@@ -1183,6 +1196,10 @@ c_fast_ecc:
        wrpr            %g0, 15, %pil
        ba,pt           %xcc, etrap_irq
         rd             %pc, %g7
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        mov             %l4, %o1
        mov             %l5, %o2
        call            cheetah_fecc_handler
@@ -1211,6 +1228,10 @@ c_cee:
        wrpr            %g0, 15, %pil
        ba,pt           %xcc, etrap_irq
         rd             %pc, %g7
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        mov             %l4, %o1
        mov             %l5, %o2
        call            cheetah_cee_handler
@@ -1239,6 +1260,10 @@ c_deferred:
        wrpr            %g0, 15, %pil
        ba,pt           %xcc, etrap_irq
         rd             %pc, %g7
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        mov             %l4, %o1
        mov             %l5, %o2
        call            cheetah_deferred_handler
index c8e9dc9..03ffaf8 100644 (file)
@@ -489,6 +489,14 @@ tlb_fixup_done:
        call    __bzero
         sub    %o1, %o0, %o1
 
+#ifdef CONFIG_LOCKDEP
+       /* We have this call this super early, as even prom_init can grab
+        * spinlocks and thus call into the lockdep code.
+        */
+       call    lockdep_init
+        nop
+#endif
+
        mov     %l6, %o1                        ! OpenPROM stack
        call    prom_init
         mov    %l7, %o0                        ! OpenPROM cif handler
index f028e68..ad1c4f5 100644 (file)
@@ -72,14 +72,12 @@ static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev)
                struct linux_prom_registers *regs;
                struct sparc_isa_device *isa_dev;
 
-               isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
+               isa_dev = kzalloc(sizeof(*isa_dev), GFP_KERNEL);
                if (!isa_dev) {
                        fatal_err("cannot allocate child isa_dev");
                        prom_halt();
                }
 
-               memset(isa_dev, 0, sizeof(*isa_dev));
-
                /* Link it in to parent. */
                isa_dev->next = parent_isa_dev->child;
                parent_isa_dev->child = isa_dev;
@@ -104,14 +102,12 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
                struct linux_prom_registers *regs;
                struct sparc_isa_device *isa_dev;
 
-               isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
+               isa_dev = kzalloc(sizeof(*isa_dev), GFP_KERNEL);
                if (!isa_dev) {
                        printk(KERN_DEBUG "ISA: cannot allocate isa_dev");
                        return;
                }
 
-               memset(isa_dev, 0, sizeof(*isa_dev));
-
                isa_dev->ofdev.node = dp;
                isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev;
                isa_dev->ofdev.dev.bus = &isa_bus_type;
@@ -180,14 +176,12 @@ void __init isa_init(void)
                pbm = pdev_cookie->pbm;
                dp = pdev_cookie->prom_node;
 
-               isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL);
+               isa_br = kzalloc(sizeof(*isa_br), GFP_KERNEL);
                if (!isa_br) {
                        printk(KERN_DEBUG "isa: cannot allocate sparc_isa_bridge");
                        return;
                }
 
-               memset(isa_br, 0, sizeof(*isa_br));
-
                isa_br->ofdev.node = dp;
                isa_br->ofdev.dev.parent = &pdev->dev;
                isa_br->ofdev.dev.bus = &isa_bus_type;
index 8e75ed7..ae221f0 100644 (file)
@@ -45,7 +45,11 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 int __kprobes arch_prepare_kprobe(struct kprobe *p)
 {
        p->ainsn.insn[0] = *p->addr;
+       flushi(&p->ainsn.insn[0]);
+
        p->ainsn.insn[1] = BREAKPOINT_INSTRUCTION_2;
+       flushi(&p->ainsn.insn[1]);
+
        p->opcode = *p->addr;
        return 0;
 }
@@ -185,16 +189,19 @@ no_kprobe:
 /* If INSN is a relative control transfer instruction,
  * return the corrected branch destination value.
  *
- * The original INSN location was REAL_PC, it actually
- * executed at PC and produced destination address NPC.
+ * regs->tpc and regs->tnpc still hold the values of the
+ * program counters at the time of trap due to the execution
+ * of the BREAKPOINT_INSTRUCTION_2 at p->ainsn.insn[1]
+ * 
  */
-static unsigned long __kprobes relbranch_fixup(u32 insn, unsigned long real_pc,
-                                              unsigned long pc,
-                                              unsigned long npc)
+static unsigned long __kprobes relbranch_fixup(u32 insn, struct kprobe *p,
+                                              struct pt_regs *regs)
 {
+       unsigned long real_pc = (unsigned long) p->addr;
+
        /* Branch not taken, no mods necessary.  */
-       if (npc == pc + 0x4UL)
-               return real_pc + 0x4UL;
+       if (regs->tnpc == regs->tpc + 0x4UL)
+               return real_pc + 0x8UL;
 
        /* The three cases are call, branch w/prediction,
         * and traditional branch.
@@ -202,14 +209,21 @@ static unsigned long __kprobes relbranch_fixup(u32 insn, unsigned long real_pc,
        if ((insn & 0xc0000000) == 0x40000000 ||
            (insn & 0xc1c00000) == 0x00400000 ||
            (insn & 0xc1c00000) == 0x00800000) {
+               unsigned long ainsn_addr;
+
+               ainsn_addr = (unsigned long) &p->ainsn.insn[0];
+
                /* The instruction did all the work for us
                 * already, just apply the offset to the correct
                 * instruction location.
                 */
-               return (real_pc + (npc - pc));
+               return (real_pc + (regs->tnpc - ainsn_addr));
        }
 
-       return real_pc + 0x4UL;
+       /* It is jmpl or some other absolute PC modification instruction,
+        * leave NPC as-is.
+        */
+       return regs->tnpc;
 }
 
 /* If INSN is an instruction which writes it's PC location
@@ -220,12 +234,12 @@ static void __kprobes retpc_fixup(struct pt_regs *regs, u32 insn,
 {
        unsigned long *slot = NULL;
 
-       /* Simplest cast is call, which always uses %o7 */
+       /* Simplest case is 'call', which always uses %o7 */
        if ((insn & 0xc0000000) == 0x40000000) {
                slot = &regs->u_regs[UREG_I7];
        }
 
-       /* Jmpl encodes the register inside of the opcode */
+       /* 'jmpl' encodes the register inside of the opcode */
        if ((insn & 0xc1f80000) == 0x81c00000) {
                unsigned long rd = ((insn >> 25) & 0x1f);
 
@@ -247,11 +261,11 @@ static void __kprobes retpc_fixup(struct pt_regs *regs, u32 insn,
 
 /*
  * Called after single-stepping.  p->addr is the address of the
- * instruction whose first byte has been replaced by the breakpoint
+ * instruction which has been replaced by the breakpoint
  * instruction.  To avoid the SMP problems that can occur when we
  * temporarily put back the original opcode to single-step, we
  * single-stepped a copy of the instruction.  The address of this
- * copy is p->ainsn.insn.
+ * copy is &p->ainsn.insn[0].
  *
  * This function prepares to return from the post-single-step
  * breakpoint trap.
@@ -261,11 +275,11 @@ static void __kprobes resume_execution(struct kprobe *p,
 {
        u32 insn = p->ainsn.insn[0];
 
+       regs->tnpc = relbranch_fixup(insn, p, regs);
+
+       /* This assignment must occur after relbranch_fixup() */
        regs->tpc = kcb->kprobe_orig_tnpc;
-       regs->tnpc = relbranch_fixup(insn,
-                                    (unsigned long) p->addr,
-                                    (unsigned long) &p->ainsn.insn[0],
-                                    regs->tnpc);
+
        retpc_fixup(regs, insn, (unsigned long) p->addr);
 
        regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
@@ -430,17 +444,8 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
        struct jprobe *jp = container_of(p, struct jprobe, kp);
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
-       kcb->jprobe_saved_regs_location = regs;
        memcpy(&(kcb->jprobe_saved_regs), regs, sizeof(*regs));
 
-       /* Save a whole stack frame, this gets arguments
-        * pushed onto the stack after using up all the
-        * arg registers.
-        */
-       memcpy(&(kcb->jprobe_saved_stack),
-              (char *) (regs->u_regs[UREG_FP] + STACK_BIAS),
-              sizeof(kcb->jprobe_saved_stack));
-
        regs->tpc  = (unsigned long) jp->entry;
        regs->tnpc = ((unsigned long) jp->entry) + 0x4UL;
        regs->tstate |= TSTATE_PIL;
@@ -450,10 +455,19 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
 
 void __kprobes jprobe_return(void)
 {
-       __asm__ __volatile__(
-               ".globl jprobe_return_trap_instruction\n"
+       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+       register unsigned long orig_fp asm("g1");
+
+       orig_fp = kcb->jprobe_saved_regs.u_regs[UREG_FP];
+       __asm__ __volatile__("\n"
+"1:    cmp             %%sp, %0\n\t"
+       "blu,a,pt       %%xcc, 1b\n\t"
+       " restore\n\t"
+       ".globl         jprobe_return_trap_instruction\n"
 "jprobe_return_trap_instruction:\n\t"
-               "ta 0x70");
+       "ta             0x70"
+       : /* no outputs */
+       : "r" (orig_fp));
 }
 
 extern void jprobe_return_trap_instruction(void);
@@ -466,26 +480,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
        if (addr == (u32 *) jprobe_return_trap_instruction) {
-               if (kcb->jprobe_saved_regs_location != regs) {
-                       printk("JPROBE: Current regs (%p) does not match "
-                              "saved regs (%p).\n",
-                              regs, kcb->jprobe_saved_regs_location);
-                       printk("JPROBE: Saved registers\n");
-                       __show_regs(kcb->jprobe_saved_regs_location);
-                       printk("JPROBE: Current registers\n");
-                       __show_regs(regs);
-                       BUG();
-               }
-               /* Restore old register state.  Do pt_regs
-                * first so that UREG_FP is the original one for
-                * the stack frame restore.
-                */
                memcpy(regs, &(kcb->jprobe_saved_regs), sizeof(*regs));
-
-               memcpy((char *) (regs->u_regs[UREG_FP] + STACK_BIAS),
-                      &(kcb->jprobe_saved_stack),
-                      sizeof(kcb->jprobe_saved_stack));
-
                preempt_enable_no_resched();
                return 1;
        }
index 8cc14fc..cec0ece 100644 (file)
@@ -1007,10 +1007,9 @@ struct of_device* of_platform_device_create(struct device_node *np,
 {
        struct of_device *dev;
 
-       dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (!dev)
                return NULL;
-       memset(dev, 0, sizeof(*dev));
 
        dev->dev.parent = parent;
        dev->dev.bus = bus;
index 03ad4c0..6b04794 100644 (file)
@@ -798,7 +798,7 @@ static struct pci_ops pci_sun4v_ops = {
 static void pbm_scan_bus(struct pci_controller_info *p,
                         struct pci_pbm_info *pbm)
 {
-       struct pcidev_cookie *cookie = kmalloc(sizeof(*cookie), GFP_KERNEL);
+       struct pcidev_cookie *cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
 
        if (!cookie) {
                prom_printf("%s: Critical allocation failure.\n", pbm->name);
@@ -806,7 +806,6 @@ static void pbm_scan_bus(struct pci_controller_info *p,
        }
 
        /* All we care about is the PBM. */
-       memset(cookie, 0, sizeof(*cookie));
        cookie->pbm = pbm;
 
        pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, p->pci_ops, pbm);
@@ -1048,12 +1047,11 @@ static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
        /* Allocate and initialize the free area map.  */
        sz = num_tsb_entries / 8;
        sz = (sz + 7UL) & ~7UL;
-       iommu->arena.map = kmalloc(sz, GFP_KERNEL);
+       iommu->arena.map = kzalloc(sz, GFP_KERNEL);
        if (!iommu->arena.map) {
                prom_printf("PCI_IOMMU: Error, kmalloc(arena.map) failed.\n");
                prom_halt();
        }
-       memset(iommu->arena.map, 0, sz);
        iommu->arena.limit = num_tsb_entries;
 
        sz = probe_existing_entries(pbm, iommu);
@@ -1164,24 +1162,20 @@ void sun4v_pci_init(struct device_node *dp, char *model_name)
                per_cpu(pci_iommu_batch, i).pglist = (u64 *) page;
        }
 
-       p = kmalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
+       p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
        if (!p)
                goto fatal_memory_error;
 
-       memset(p, 0, sizeof(*p));
-
-       iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
+       iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
        if (!iommu)
                goto fatal_memory_error;
 
-       memset(iommu, 0, sizeof(*iommu));
        p->pbm_A.iommu = iommu;
 
-       iommu = kmalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
+       iommu = kzalloc(sizeof(struct pci_iommu), GFP_ATOMIC);
        if (!iommu)
                goto fatal_memory_error;
 
-       memset(iommu, 0, sizeof(*iommu));
        p->pbm_B.iommu = iommu;
 
        p->next = pci_controller_root;
index d31975e..81111a1 100644 (file)
@@ -202,7 +202,10 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
 #endif
        if (request == PTRACE_TRACEME) {
                ret = ptrace_traceme();
-               pt_succ_return(regs, 0);
+               if (ret < 0)
+                       pt_error_return(regs, -ret);
+               else
+                       pt_succ_return(regs, 0);
                goto out;
        }
 
index 3522cd6..079d18a 100644 (file)
@@ -165,14 +165,26 @@ rtrap:
 __handle_softirq_continue:
 rtrap_xcall:
                sethi                   %hi(0xf << 20), %l4
-               andcc                   %l1, TSTATE_PRIV, %l3
                and                     %l1, %l4, %l4
+               andn                    %l1, %l4, %l1
+               srl                     %l4, 20, %l4
+#ifdef CONFIG_TRACE_IRQFLAGS
+               brnz,pn                 %l4, rtrap_no_irq_enable
+                nop
+               call                    trace_hardirqs_on
+                nop
+               wrpr                    %l4, %pil
+rtrap_no_irq_enable:
+#endif
+               andcc                   %l1, TSTATE_PRIV, %l3
                bne,pn                  %icc, to_kernel
-                andn                   %l1, %l4, %l1
+                nop
 
                /* We must hold IRQs off and atomically test schedule+signal
                 * state, then hold them off all the way back to userspace.
-                * If we are returning to kernel, none of this matters.
+                * If we are returning to kernel, none of this matters.  Note
+                * that we are disabling interrupts via PSTATE_IE, not using
+                * %pil.
                 *
                 * If we do not do this, there is a window where we would do
                 * the tests, later the signal/resched event arrives but we do
@@ -256,7 +268,6 @@ rt_continue:        ldx                     [%sp + PTREGS_OFF + PT_V9_G1], %g1
 
                ld                      [%sp + PTREGS_OFF + PT_V9_Y], %o3
                wr                      %o3, %g0, %y
-               srl                     %l4, 20, %l4
                wrpr                    %l4, 0x0, %pil
                wrpr                    %g0, 0x1, %tl
                wrpr                    %l1, %g0, %tstate
@@ -374,8 +385,8 @@ to_kernel:
                 ldx                    [%g6 + TI_FLAGS], %l5
                andcc                   %l5, _TIF_NEED_RESCHED, %g0
                be,pt                   %xcc, kern_fpucheck
-                srl                    %l4, 20, %l5
-               cmp                     %l5, 0
+                nop
+               cmp                     %l4, 0
                bne,pn                  %xcc, kern_fpucheck
                 sethi                  %hi(PREEMPT_ACTIVE), %l6
                stw                     %l6, [%g6 + TI_PRE_COUNT]
diff --git a/arch/sparc64/kernel/stacktrace.c b/arch/sparc64/kernel/stacktrace.c
new file mode 100644 (file)
index 0000000..c4d15f2
--- /dev/null
@@ -0,0 +1,41 @@
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+#include <linux/thread_info.h>
+#include <asm/ptrace.h>
+
+void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
+{
+       unsigned long ksp, fp, thread_base;
+       struct thread_info *tp;
+
+       if (!task)
+               task = current;
+       tp = task_thread_info(task);
+       if (task == current) {
+               flushw_all();
+               __asm__ __volatile__(
+                       "mov    %%fp, %0"
+                       : "=r" (ksp)
+               );
+       } else
+               ksp = tp->ksp;
+
+       fp = ksp + STACK_BIAS;
+       thread_base = (unsigned long) tp;
+       do {
+               struct reg_window *rw;
+
+               /* Bogus frame pointer? */
+               if (fp < (thread_base + sizeof(struct thread_info)) ||
+                   fp >= (thread_base + THREAD_SIZE))
+                       break;
+
+               rw = (struct reg_window *) fp;
+               if (trace->skip > 0)
+                       trace->skip--;
+               else
+                       trace->entries[trace->nr_entries++] = rw->ins[7];
+
+               fp = rw->ins[6] + STACK_BIAS;
+       } while (trace->nr_entries < trace->max_entries);
+}
index 49703c3..405855d 100644 (file)
@@ -190,7 +190,10 @@ sun4v_res_mondo:
        mov     %g1, %g4
        ba,pt   %xcc, etrap_irq
         rd     %pc, %g7
-
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        /* Log the event.  */
        add     %sp, PTREGS_OFF, %o0
        call    sun4v_resum_error
@@ -216,7 +219,10 @@ sun4v_res_mondo_queue_full:
        wrpr    %g0, 15, %pil
        ba,pt   %xcc, etrap_irq
         rd     %pc, %g7
-
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        call    sun4v_resum_overflow
         add    %sp, PTREGS_OFF, %o0
 
@@ -295,7 +301,10 @@ sun4v_nonres_mondo:
        mov     %g1, %g4
        ba,pt   %xcc, etrap_irq
         rd     %pc, %g7
-
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        /* Log the event.  */
        add     %sp, PTREGS_OFF, %o0
        call    sun4v_nonresum_error
@@ -321,7 +330,10 @@ sun4v_nonres_mondo_queue_full:
        wrpr    %g0, 15, %pil
        ba,pt   %xcc, etrap_irq
         rd     %pc, %g7
-
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        call    sun4v_nonresum_overflow
         add    %sp, PTREGS_OFF, %o0
 
index fe1796c..ad67784 100644 (file)
@@ -10,7 +10,7 @@
  */
 
 #include <linux/module.h>
-#include <linux/sched.h>  /* for jiffies */
+#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/kallsyms.h>
 #include <linux/signal.h>
@@ -1873,6 +1873,16 @@ void sun4v_resum_error(struct pt_regs *regs, unsigned long offset)
 
        put_cpu();
 
+       if (ent->err_type == SUN4V_ERR_TYPE_WARNING_RES) {
+               /* If err_type is 0x4, it's a powerdown request.  Do
+                * not do the usual resumable error log because that
+                * makes it look like some abnormal error.
+                */
+               printk(KERN_INFO "Power down request...\n");
+               kill_cad_pid(SIGINT, 1);
+               return;
+       }
+
        sun4v_log_error(regs, &local_copy, cpu,
                        KERN_ERR "RESUMABLE ERROR",
                        &sun4v_resum_oflow_cnt);
@@ -2261,8 +2271,12 @@ void die_if_kernel(char *str, struct pt_regs *regs)
        do_exit(SIGSEGV);
 }
 
+#define VIS_OPCODE_MASK        ((0x3 << 30) | (0x3f << 19))
+#define VIS_OPCODE_VAL ((0x2 << 30) | (0x36 << 19))
+
 extern int handle_popc(u32 insn, struct pt_regs *regs);
 extern int handle_ldf_stq(u32 insn, struct pt_regs *regs);
+extern int vis_emul(struct pt_regs *, unsigned int);
 
 void do_illegal_instruction(struct pt_regs *regs)
 {
@@ -2287,10 +2301,18 @@ void do_illegal_instruction(struct pt_regs *regs)
                        if (handle_ldf_stq(insn, regs))
                                return;
                } else if (tlb_type == hypervisor) {
-                       extern int vis_emul(struct pt_regs *, unsigned int);
+                       if ((insn & VIS_OPCODE_MASK) == VIS_OPCODE_VAL) {
+                               if (!vis_emul(regs, insn))
+                                       return;
+                       } else {
+                               struct fpustate *f = FPUSTATE;
 
-                       if (!vis_emul(regs, insn))
-                               return;
+                               /* XXX maybe verify XFSR bits like
+                                * XXX do_fpother() does?
+                                */
+                               if (do_mathemu(regs, f))
+                                       return;
+                       }
                }
        }
        info.si_signo = SIGILL;
index a9b7652..bc18d48 100644 (file)
@@ -243,7 +243,7 @@ static inline int ok_for_kernel(unsigned int insn)
        return !floating_point_load_or_store_p(insn);
 }
 
-static void kernel_mna_trap_fault(void)
+static void kernel_mna_trap_fault(int fixup_tstate_asi)
 {
        struct pt_regs *regs = current_thread_info()->kern_una_regs;
        unsigned int insn = current_thread_info()->kern_una_insn;
@@ -274,18 +274,15 @@ static void kernel_mna_trap_fault(void)
        regs->tpc = entry->fixup;
        regs->tnpc = regs->tpc + 4;
 
-       regs->tstate &= ~TSTATE_ASI;
-       regs->tstate |= (ASI_AIUS << 24UL);
+       if (fixup_tstate_asi) {
+               regs->tstate &= ~TSTATE_ASI;
+               regs->tstate |= (ASI_AIUS << 24UL);
+       }
 }
 
-asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
+static void log_unaligned(struct pt_regs *regs)
 {
        static unsigned long count, last_time;
-       enum direction dir = decode_direction(insn);
-       int size = decode_access_size(insn);
-
-       current_thread_info()->kern_una_regs = regs;
-       current_thread_info()->kern_una_insn = insn;
 
        if (jiffies - last_time > 5 * HZ)
                count = 0;
@@ -295,6 +292,28 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
                printk("Kernel unaligned access at TPC[%lx] ", regs->tpc);
                print_symbol("%s\n", regs->tpc);
        }
+}
+
+asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
+{
+       enum direction dir = decode_direction(insn);
+       int size = decode_access_size(insn);
+       int orig_asi, asi;
+
+       current_thread_info()->kern_una_regs = regs;
+       current_thread_info()->kern_una_insn = insn;
+
+       orig_asi = asi = decode_asi(insn, regs);
+
+       /* If this is a {get,put}_user() on an unaligned userspace pointer,
+        * just signal a fault and do not log the event.
+        */
+       if (asi == ASI_AIUS) {
+               kernel_mna_trap_fault(0);
+               return;
+       }
+
+       log_unaligned(regs);
 
        if (!ok_for_kernel(insn) || dir == both) {
                printk("Unsupported unaligned load/store trap for kernel "
@@ -302,10 +321,10 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
                unaligned_panic("Kernel does fpu/atomic "
                                "unaligned load/store.", regs);
 
-               kernel_mna_trap_fault();
+               kernel_mna_trap_fault(0);
        } else {
                unsigned long addr, *reg_addr;
-               int orig_asi, asi, err;
+               int err;
 
                addr = compute_effective_address(regs, insn,
                                                 ((insn >> 25) & 0x1f));
@@ -315,7 +334,6 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
                       regs->tpc, dirstrings[dir], addr, size,
                       regs->u_regs[UREG_RETPC]);
 #endif
-               orig_asi = asi = decode_asi(insn, regs);
                switch (asi) {
                case ASI_NL:
                case ASI_AIUPL:
@@ -365,7 +383,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
                        /* Not reached... */
                }
                if (unlikely(err))
-                       kernel_mna_trap_fault();
+                       kernel_mna_trap_fault(1);
                else
                        advance(regs);
        }
index 84fedaa..c3fd647 100644 (file)
 /* 001001100 - Permute bytes as specified by GSR.MASK  */
 #define BSHUFFLE_OPF   0x04c
 
-#define VIS_OPCODE_MASK        ((0x3 << 30) | (0x3f << 19))
-#define VIS_OPCODE_VAL ((0x2 << 30) | (0x36 << 19))
-
 #define VIS_OPF_SHIFT  5
 #define VIS_OPF_MASK   (0x1ff << VIS_OPF_SHIFT)
 
@@ -810,9 +807,6 @@ int vis_emul(struct pt_regs *regs, unsigned int insn)
        if (get_user(insn, (u32 __user *) pc))
                return -EFAULT;
 
-       if ((insn & VIS_OPCODE_MASK) != VIS_OPCODE_VAL)
-               return -EINVAL;
-
        opf = (insn & VIS_OPF_MASK) >> VIS_OPF_SHIFT;
        switch (opf) {
        default:
index d70b60a..737c269 100644 (file)
@@ -477,6 +477,10 @@ xcall_sync_tick:
        sethi           %hi(109f), %g7
        b,pt            %xcc, etrap_irq
 109:    or             %g7, %lo(109b), %g7
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        call            smp_synchronize_tick_client
         nop
        clr             %l6
@@ -508,6 +512,10 @@ xcall_report_regs:
        sethi           %hi(109f), %g7
        b,pt            %xcc, etrap_irq
 109:    or             %g7, %lo(109b), %g7
+#ifdef CONFIG_TRACE_IRQFLAGS
+       call            trace_hardirqs_off
+        nop
+#endif
        call            __show_regs
         add            %sp, PTREGS_OFF, %o0
        clr             %l6
index 27f6597..93e5a06 100644 (file)
@@ -152,9 +152,9 @@ extern void dvma_init(struct sbus_bus *);
 #define DMA_MAXEND(addr) (0x01000000UL-(((unsigned long)(addr))&0x00ffffffUL))
 
 /* Yes, I hack a lot of elisp in my spare time... */
-#define DMA_ERROR_P(regs)  (((sbus_readl((regs) + DMA_CSR) & DMA_HNDL_ERROR))
-#define DMA_IRQ_P(regs)    (((sbus_readl((regs) + DMA_CSR)) & (DMA_HNDL_INTR | DMA_HNDL_ERROR)))
-#define DMA_WRITE_P(regs)  (((sbus_readl((regs) + DMA_CSR) & DMA_ST_WRITE))
+#define DMA_ERROR_P(regs)  ((sbus_readl((regs) + DMA_CSR) & DMA_HNDL_ERROR))
+#define DMA_IRQ_P(regs)    ((sbus_readl((regs) + DMA_CSR)) & (DMA_HNDL_INTR | DMA_HNDL_ERROR))
+#define DMA_WRITE_P(regs)  ((sbus_readl((regs) + DMA_CSR) & DMA_ST_WRITE))
 #define DMA_OFF(__regs)                \
 do {   u32 tmp = sbus_readl((__regs) + DMA_CSR); \
        tmp &= ~DMA_ENABLE; \
diff --git a/include/asm-sparc64/irqflags.h b/include/asm-sparc64/irqflags.h
new file mode 100644 (file)
index 0000000..024fc54
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * include/asm-sparc64/irqflags.h
+ *
+ * IRQ flags handling
+ *
+ * This file gets included from lowlevel asm headers too, to provide
+ * wrapped versions of the local_irq_*() APIs, based on the
+ * raw_local_irq_*() functions from the lowlevel headers.
+ */
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#ifndef __ASSEMBLY__
+
+static inline unsigned long __raw_local_save_flags(void)
+{
+       unsigned long flags;
+
+       __asm__ __volatile__(
+               "rdpr   %%pil, %0"
+               : "=r" (flags)
+       );
+
+       return flags;
+}
+
+#define raw_local_save_flags(flags) \
+               do { (flags) = __raw_local_save_flags(); } while (0)
+
+static inline void raw_local_irq_restore(unsigned long flags)
+{
+       __asm__ __volatile__(
+               "wrpr   %0, %%pil"
+               : /* no output */
+               : "r" (flags)
+               : "memory"
+       );
+}
+
+static inline void raw_local_irq_disable(void)
+{
+       __asm__ __volatile__(
+               "wrpr   15, %%pil"
+               : /* no outputs */
+               : /* no inputs */
+               : "memory"
+       );
+}
+
+static inline void raw_local_irq_enable(void)
+{
+       __asm__ __volatile__(
+               "wrpr   0, %%pil"
+               : /* no outputs */
+               : /* no inputs */
+               : "memory"
+       );
+}
+
+static inline int raw_irqs_disabled_flags(unsigned long flags)
+{
+       return (flags > 0);
+}
+
+static inline int raw_irqs_disabled(void)
+{
+       unsigned long flags = __raw_local_save_flags();
+
+       return raw_irqs_disabled_flags(flags);
+}
+
+/*
+ * For spinlocks, etc:
+ */
+static inline unsigned long __raw_local_irq_save(void)
+{
+       unsigned long flags = __raw_local_save_flags();
+
+       raw_local_irq_disable();
+
+       return flags;
+}
+
+#define raw_local_irq_save(flags) \
+               do { (flags) = __raw_local_irq_save(); } while (0)
+
+#endif /* (__ASSEMBLY__) */
+
+#endif /* !(_ASM_IRQFLAGS_H) */
index c9f5c34..becc38f 100644 (file)
@@ -13,7 +13,11 @@ typedef u32 kprobe_opcode_t;
 #define JPROBE_ENTRY(pentry)   (kprobe_opcode_t *)pentry
 #define arch_remove_kprobe(p)  do {} while (0)
 #define  ARCH_INACTIVE_KPROBE_COUNT 0
-#define flush_insn_slot(p)     do { } while (0)
+
+#define flush_insn_slot(p)             \
+do {   flushi(&(p)->ainsn.insn[0]);    \
+       flushi(&(p)->ainsn.insn[1]);    \
+} while (0)
 
 /* Architecture specific copy of original instruction*/
 struct arch_specific_insn {
@@ -23,7 +27,7 @@ struct arch_specific_insn {
 
 struct prev_kprobe {
        struct kprobe *kp;
-       unsigned int status;
+       unsigned long status;
        unsigned long orig_tnpc;
        unsigned long orig_tstate_pil;
 };
@@ -33,10 +37,7 @@ struct kprobe_ctlblk {
        unsigned long kprobe_status;
        unsigned long kprobe_orig_tnpc;
        unsigned long kprobe_orig_tstate_pil;
-       long *jprobe_saved_esp;
        struct pt_regs jprobe_saved_regs;
-       struct pt_regs *jprobe_saved_regs_location;
-       struct sparc_stackf jprobe_saved_stack;
        struct prev_kprobe prev_kprobe;
 };
 
index cef5e82..1294b7c 100644 (file)
@@ -23,20 +23,33 @@ struct rw_semaphore {
        signed int count;
        spinlock_t              wait_lock;
        struct list_head        wait_list;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+       struct lockdep_map      dep_map;
+#endif
 };
 
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
+#else
+# define __RWSEM_DEP_MAP_INIT(lockname)
+#endif
+
 #define __RWSEM_INITIALIZER(name) \
-{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) }
+{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) \
+  __RWSEM_DEP_MAP_INIT(name) }
 
 #define DECLARE_RWSEM(name) \
        struct rw_semaphore name = __RWSEM_INITIALIZER(name)
 
-static __inline__ void init_rwsem(struct rw_semaphore *sem)
-{
-       sem->count = RWSEM_UNLOCKED_VALUE;
-       spin_lock_init(&sem->wait_lock);
-       INIT_LIST_HEAD(&sem->wait_list);
-}
+extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
+                        struct lock_class_key *key);
+
+#define init_rwsem(sem)                                                \
+do {                                                           \
+       static struct lock_class_key __key;                     \
+                                                               \
+       __init_rwsem((sem), #sem, &__key);                      \
+} while (0)
 
 extern void __down_read(struct rw_semaphore *sem);
 extern int __down_read_trylock(struct rw_semaphore *sem);
@@ -46,6 +59,11 @@ extern void __up_read(struct rw_semaphore *sem);
 extern void __up_write(struct rw_semaphore *sem);
 extern void __downgrade_write(struct rw_semaphore *sem);
 
+static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
+{
+       __down_write(sem);
+}
+
 static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
 {
        return atomic_add_return(delta, (atomic_t *)(&sem->count));
index a8b7432..32281ac 100644 (file)
@@ -7,6 +7,9 @@
 #include <asm/visasm.h>
 
 #ifndef __ASSEMBLY__
+
+#include <linux/irqflags.h>
+
 /*
  * Sparc (general) CPU types
  */
@@ -72,52 +75,6 @@ do { __asm__ __volatile__("ba,pt     %%xcc, 1f\n\t" \
 
 #endif
 
-#define setipl(__new_ipl) \
-       __asm__ __volatile__("wrpr      %0, %%pil"  : : "r" (__new_ipl) : "memory")
-
-#define local_irq_disable() \
-       __asm__ __volatile__("wrpr      15, %%pil" : : : "memory")
-
-#define local_irq_enable() \
-       __asm__ __volatile__("wrpr      0, %%pil" : : : "memory")
-
-#define getipl() \
-({ unsigned long retval; __asm__ __volatile__("rdpr    %%pil, %0" : "=r" (retval)); retval; })
-
-#define swap_pil(__new_pil) \
-({     unsigned long retval; \
-       __asm__ __volatile__("rdpr      %%pil, %0\n\t" \
-                            "wrpr      %1, %%pil" \
-                            : "=&r" (retval) \
-                            : "r" (__new_pil) \
-                            : "memory"); \
-       retval; \
-})
-
-#define read_pil_and_cli() \
-({     unsigned long retval; \
-       __asm__ __volatile__("rdpr      %%pil, %0\n\t" \
-                            "wrpr      15, %%pil" \
-                            : "=r" (retval) \
-                            : : "memory"); \
-       retval; \
-})
-
-#define local_save_flags(flags)                ((flags) = getipl())
-#define local_irq_save(flags)          ((flags) = read_pil_and_cli())
-#define local_irq_restore(flags)               setipl((flags))
-
-/* On sparc64 IRQ flags are the PIL register.  A value of zero
- * means all interrupt levels are enabled, any other value means
- * only IRQ levels greater than that value will be received.
- * Consequently this means that the lowest IRQ level is one.
- */
-#define irqs_disabled()                \
-({     unsigned long flags;    \
-       local_save_flags(flags);\
-       (flags > 0);            \
-})
-
 #define nop()          __asm__ __volatile__ ("nop")
 
 #define read_barrier_depends()         do { } while(0)
index f235260..c2a16e1 100644 (file)
 #endif
 #define BREAKPOINT_TRAP TRAP(breakpoint_trap)
 
+#ifdef CONFIG_TRACE_IRQFLAGS
+
+#define TRAP_IRQ(routine, level)                       \
+       rdpr    %pil, %g2;                              \
+       wrpr    %g0, 15, %pil;                          \
+       sethi   %hi(1f-4), %g7;                         \
+       ba,pt   %xcc, etrap_irq;                        \
+        or     %g7, %lo(1f-4), %g7;                    \
+       nop;                                            \
+       nop;                                            \
+       nop;                                            \
+       .subsection     2;                              \
+1:     call    trace_hardirqs_off;                     \
+        nop;                                           \
+       mov     level, %o0;                             \
+       call    routine;                                \
+        add    %sp, PTREGS_OFF, %o1;                   \
+       ba,a,pt %xcc, rtrap_irq;                        \
+       .previous;
+
+#define TICK_SMP_IRQ                                   \
+       rdpr    %pil, %g2;                              \
+       wrpr    %g0, 15, %pil;                          \
+       sethi   %hi(1f-4), %g7;                         \
+       ba,pt   %xcc, etrap_irq;                        \
+        or     %g7, %lo(1f-4), %g7;                    \
+       nop;                                            \
+       nop;                                            \
+       nop;                                            \
+       .subsection     2;                              \
+1:     call    trace_hardirqs_off;                     \
+        nop;                                           \
+       call    smp_percpu_timer_interrupt;             \
+        add    %sp, PTREGS_OFF, %o0;                   \
+       ba,a,pt %xcc, rtrap_irq;                        \
+       .previous;
+
+#else
+
 #define TRAP_IRQ(routine, level)                       \
        rdpr    %pil, %g2;                              \
        wrpr    %g0, 15, %pil;                          \
-       b,pt    %xcc, etrap_irq;                        \
+       ba,pt   %xcc, etrap_irq;                        \
         rd     %pc, %g7;                               \
        mov     level, %o0;                             \
        call    routine;                                \
        rdpr    %pil, %g2;                              \
        wrpr    %g0, 15, %pil;                          \
        sethi   %hi(109f), %g7;                         \
-       b,pt    %xcc, etrap_irq;                        \
+       ba,pt   %xcc, etrap_irq;                        \
 109:    or     %g7, %lo(109b), %g7;                    \
        call    smp_percpu_timer_interrupt;             \
         add    %sp, PTREGS_OFF, %o0;                   \
        ba,a,pt %xcc, rtrap_irq;
 
+#endif
+
 #define TRAP_IVEC TRAP_NOSAVE(do_ivec)
 
 #define BTRAP(lvl) TRAP_ARG(bad_trap, lvl)