]> Pileus Git - ~andy/linux/commitdiff
Merge tag 'xtensa-next-20130508' of git://github.com/czankel/xtensa-linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 9 May 2013 21:38:16 +0000 (14:38 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 9 May 2013 21:38:16 +0000 (14:38 -0700)
Pull xtensa updates from Chris Zankel:
 "Support for the latest MMU architecture that allows for a larger
  accessible memory region, and various bug-fixes"

* tag 'xtensa-next-20130508' of git://github.com/czankel/xtensa-linux:
  xtensa: Switch to asm-generic/linkage.h
  xtensa: fix redboot load address
  xtensa: ISS: fix timer_lock usage in rs_open
  xtensa: disable IRQs while IRQ handler is running
  xtensa: enable lockdep support
  xtensa: fix arch_irqs_disabled_flags implementation
  xtensa: add irq flags trace support
  xtensa: provide custom CALLER_ADDR* implementations
  xtensa: add stacktrace support
  xtensa: clean up stpill_registers
  xtensa: don't use a7 in simcalls
  xtensa: don't attempt to use unconfigured timers
  xtensa: provide default platform_pcibios_init implementation
  xtensa: remove KCORE_ELF again
  xtensa: document MMUv3 setup sequence
  xtensa: add MMU v3 support
  xtensa: fix ibreakenable register update
  xtensa: fix oprofile building as module

1  2 
arch/xtensa/Kconfig
arch/xtensa/kernel/traps.c
arch/xtensa/platforms/iss/simdisk.c

diff --combined arch/xtensa/Kconfig
index acdfc615cca2a5f2a729c9fdea9480abf2d901af,a065da819f891a3e5d1b0bfbe73e9ca1f2b1009f..0a1b95f81a32b165ae27421fbddf2423a4da4ca9
@@@ -1,11 -1,9 +1,9 @@@
- config FRAME_POINTER
-       def_bool n
  config ZONE_DMA
        def_bool y
  
  config XTENSA
        def_bool y
+       select ARCH_WANT_FRAME_POINTERS
        select HAVE_IDE
        select GENERIC_ATOMIC64
        select HAVE_GENERIC_HARDIRQS
@@@ -33,6 -31,9 +31,6 @@@ config RWSEM_XCHGADD_ALGORITH
  config GENERIC_HWEIGHT
        def_bool y
  
 -config GENERIC_GPIO
 -      bool
 -
  config ARCH_HAS_ILOG2_U32
        def_bool n
  
@@@ -49,6 -50,15 +47,15 @@@ config H
  source "init/Kconfig"
  source "kernel/Kconfig.freezer"
  
+ config LOCKDEP_SUPPORT
+       def_bool y
+ config STACKTRACE_SUPPORT
+       def_bool y
+ config TRACE_IRQFLAGS_SUPPORT
+       def_bool y
  config MMU
        def_bool n
  
@@@ -100,6 -110,35 +107,35 @@@ config MATH_EMULATIO
        help
        Can we use information of configuration file?
  
+ config INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
+       bool "Initialize Xtensa MMU inside the Linux kernel code"
+       default y
+       help
+         Earlier version initialized the MMU in the exception vector
+         before jumping to _startup in head.S and had an advantage that
+         it was possible to place a software breakpoint at 'reset' and
+         then enter your normal kernel breakpoints once the MMU was mapped
+         to the kernel mappings (0XC0000000).
+         This unfortunately doesn't work for U-Boot and likley also wont
+         work for using KEXEC to have a hot kernel ready for doing a
+         KDUMP.
+         So now the MMU is initialized in head.S but it's necessary to
+         use hardware breakpoints (gdb 'hbreak' cmd) to break at _startup.
+         xt-gdb can't place a Software Breakpoint in the  0XD region prior
+         to mapping the MMU and after mapping even if the area of low memory
+         was mapped gdb wouldn't remove the breakpoint on hitting it as the
+         PC wouldn't match. Since Hardware Breakpoints are recommended for
+         Linux configurations it seems reasonable to just assume they exist
+         and leave this older mechanism for unfortunate souls that choose
+         not to follow Tensilica's recommendation.
+         Selecting this will cause U-Boot to set the KERNEL Load and Entry
+         address at 0x00003000 instead of the mapped std of 0xD0003000.
+         If in doubt, say Y.
  endmenu
  
  config XTENSA_CALIBRATE_CCOUNT
@@@ -249,21 -288,6 +285,6 @@@ endmen
  
  menu "Executable file formats"
  
- # only elf supported
- config KCORE_ELF
-       def_bool y
-         depends on PROC_FS
-         help
-           If you enabled support for /proc file system then the file
-           /proc/kcore will contain the kernel core image in ELF format. This
-           can be used in gdb:
-           $ cd /usr/src/linux ; gdb vmlinux /proc/kcore
-           This is especially useful if you have compiled the kernel with the
-           "-g" option to preserve debugging information. It is mainly used
-         for examining kernel data structures on the live kernel.
  source "fs/Kconfig.binfmt"
  
  endmenu
index 458186dab5dcd40c777c5dd59d0784a78e4b3893,30e53e609104dc52848139ad99ee056dc49d30ed..3e8a05c874cd2719951929ff348b4d24f34c773e
@@@ -11,7 -11,7 +11,7 @@@
   *
   * Essentially rewritten for the Xtensa architecture port.
   *
-  * Copyright (C) 2001 - 2005 Tensilica Inc.
+  * Copyright (C) 2001 - 2013 Tensilica Inc.
   *
   * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
   * Chris Zankel       <chris@zankel.net>
@@@ -32,6 -32,7 +32,7 @@@
  #include <linux/delay.h>
  #include <linux/hardirq.h>
  
+ #include <asm/stacktrace.h>
  #include <asm/ptrace.h>
  #include <asm/timex.h>
  #include <asm/uaccess.h>
@@@ -195,7 -196,6 +196,6 @@@ void do_multihit(struct pt_regs *regs, 
  
  /*
   * IRQ handler.
-  * PS.INTLEVEL is the current IRQ priority level.
   */
  
  extern void do_IRQ(int, struct pt_regs *);
@@@ -212,18 -212,21 +212,21 @@@ void do_interrupt(struct pt_regs *regs
                XCHAL_INTLEVEL6_MASK,
                XCHAL_INTLEVEL7_MASK,
        };
-       unsigned level = get_sr(ps) & PS_INTLEVEL_MASK;
-       if (WARN_ON_ONCE(level >= ARRAY_SIZE(int_level_mask)))
-               return;
  
        for (;;) {
                unsigned intread = get_sr(interrupt);
                unsigned intenable = get_sr(intenable);
-               unsigned int_at_level = intread & intenable &
-                       int_level_mask[level];
+               unsigned int_at_level = intread & intenable;
+               unsigned level;
+               for (level = LOCKLEVEL; level > 0; --level) {
+                       if (int_at_level & int_level_mask[level]) {
+                               int_at_level &= int_level_mask[level];
+                               break;
+                       }
+               }
  
-               if (!int_at_level)
+               if (level == 0)
                        return;
  
                /*
@@@ -383,8 -386,6 +386,8 @@@ void show_regs(struct pt_regs * regs
  {
        int i, wmask;
  
 +      show_regs_print_info(KERN_DEFAULT);
 +
        wmask = regs->wmask & ~1;
  
        for (i = 0; i < 16; i++) {
                       regs->syscall);
  }
  
- static __always_inline unsigned long *stack_pointer(struct task_struct *task)
+ static int show_trace_cb(struct stackframe *frame, void *data)
  {
-       unsigned long *sp;
-       if (!task || task == current)
-               __asm__ __volatile__ ("mov %0, a1\n" : "=a"(sp));
-       else
-               sp = (unsigned long *)task->thread.sp;
-       return sp;
+       if (kernel_text_address(frame->pc)) {
+               printk(" [<%08lx>] ", frame->pc);
+               print_symbol("%s\n", frame->pc);
+       }
+       return 0;
  }
  
  void show_trace(struct task_struct *task, unsigned long *sp)
  {
-       unsigned long a0, a1, pc;
-       unsigned long sp_start, sp_end;
-       if (sp)
-               a1 = (unsigned long)sp;
-       else
-               a1 = (unsigned long)stack_pointer(task);
-       sp_start = a1 & ~(THREAD_SIZE-1);
-       sp_end = sp_start + THREAD_SIZE;
+       if (!sp)
+               sp = stack_pointer(task);
  
        printk("Call Trace:");
  #ifdef CONFIG_KALLSYMS
        printk("\n");
  #endif
-       spill_registers();
-       while (a1 > sp_start && a1 < sp_end) {
-               sp = (unsigned long*)a1;
-               a0 = *(sp - 4);
-               a1 = *(sp - 3);
-               if (a1 <= (unsigned long) sp)
-                       break;
-               pc = MAKE_PC_FROM_RA(a0, a1);
-               if (kernel_text_address(pc)) {
-                       printk(" [<%08lx>] ", pc);
-                       print_symbol("%s\n", pc);
-               }
-       }
+       walk_stackframe(sp, show_trace_cb, NULL);
        printk("\n");
  }
  
@@@ -483,6 -456,14 +458,6 @@@ void show_stack(struct task_struct *tas
        show_trace(task, stack);
  }
  
 -void dump_stack(void)
 -{
 -      show_stack(current, NULL);
 -}
 -
 -EXPORT_SYMBOL(dump_stack);
 -
 -
  void show_code(unsigned int *pc)
  {
        long i;
index fc3c91fd20f70ff07ff2efd791cc91d96096e89f,74f86fbab742f9378fcb90c3fb3eea73858d4b12..c0edb35424cea9ed8a077b25d682202f9d50e533
@@@ -85,7 -85,7 +85,7 @@@ static void simdisk_transfer(struct sim
        while (nbytes > 0) {
                unsigned long io;
  
-               __simc(SYS_lseek, dev->fd, offset, SEEK_SET, 0, 0);
+               simc_lseek(dev->fd, offset, SEEK_SET);
                if (write)
                        io = simc_write(dev->fd, buffer, nbytes);
                else
@@@ -139,12 -139,13 +139,12 @@@ static int simdisk_open(struct block_de
        return 0;
  }
  
 -static int simdisk_release(struct gendisk *disk, fmode_t mode)
 +static void simdisk_release(struct gendisk *disk, fmode_t mode)
  {
        struct simdisk *dev = disk->private_data;
        spin_lock(&dev->lock);
        --dev->users;
        spin_unlock(&dev->lock);
 -      return 0;
  }
  
  static const struct block_device_operations simdisk_ops = {
@@@ -176,7 -177,7 +176,7 @@@ static int simdisk_attach(struct simdis
                err = -ENODEV;
                goto out;
        }
-       dev->size = __simc(SYS_lseek, dev->fd, 0, SEEK_END, 0, 0);
+       dev->size = simc_lseek(dev->fd, 0, SEEK_END);
        set_capacity(dev->gd, dev->size >> SECTOR_SHIFT);
        dev->filename = filename;
        pr_info("SIMDISK: %s=%s\n", dev->gd->disk_name, dev->filename);
@@@ -213,32 -214,25 +213,32 @@@ static int simdisk_detach(struct simdis
        return err;
  }
  
 -static int proc_read_simdisk(char *page, char **start, off_t off,
 -              int count, int *eof, void *data)
 +static ssize_t proc_read_simdisk(struct file *file, char __user *buf,
 +                      size_t size, loff_t *ppos)
  {
 -      int len;
 -      struct simdisk *dev = (struct simdisk *) data;
 -      len = sprintf(page, "%s\n", dev->filename ? dev->filename : "");
 -      return len;
 +      struct simdisk *dev = PDE_DATA(file_inode(file));
 +      const char *s = dev->filename;
 +      if (s) {
 +              ssize_t n = simple_read_from_buffer(buf, size, ppos,
 +                                                      s, strlen(s));
 +              if (n < 0)
 +                      return n;
 +              buf += n;
 +              size -= n;
 +      }
 +      return simple_read_from_buffer(buf, size, ppos, "\n", 1);
  }
  
 -static int proc_write_simdisk(struct file *file, const char *buffer,
 -              unsigned long count, void *data)
 +static ssize_t proc_write_simdisk(struct file *file, const char __user *buf,
 +                      size_t count, loff_t *ppos)
  {
        char *tmp = kmalloc(count + 1, GFP_KERNEL);
 -      struct simdisk *dev = (struct simdisk *) data;
 +      struct simdisk *dev = PDE_DATA(file_inode(file));
        int err;
  
        if (tmp == NULL)
                return -ENOMEM;
 -      if (copy_from_user(tmp, buffer, count)) {
 +      if (copy_from_user(tmp, buf, count)) {
                err = -EFAULT;
                goto out_free;
        }
@@@ -262,12 -256,6 +262,12 @@@ out_free
        return err;
  }
  
 +static const struct file_operations fops = {
 +      .read = proc_read_simdisk,
 +      .write = proc_write_simdisk,
 +      .llseek = default_llseek,
 +};
 +
  static int __init simdisk_setup(struct simdisk *dev, int which,
                struct proc_dir_entry *procdir)
  {
        set_capacity(dev->gd, 0);
        add_disk(dev->gd);
  
 -      dev->procfile = create_proc_entry(tmp, 0644, procdir);
 -      dev->procfile->data = dev;
 -      dev->procfile->read_proc = proc_read_simdisk;
 -      dev->procfile->write_proc = proc_write_simdisk;
 +      dev->procfile = proc_create_data(tmp, 0644, procdir, &fops, dev);
        return 0;
  
  out_alloc_disk: