Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 14 Oct 2014 01:49:02 +0000 (03:49 +0200)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 14 Oct 2014 01:49:02 +0000 (03:49 +0200)
Pull UML update from Richard Weinberger:
 "Besides of fixes this contains also support for CONFIG_STACKTRACE by
  Daniel Walter"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml:
  um: net: Eliminate NULL test after alloc_bootmem
  um: Add support for CONFIG_STACKTRACE
  um: ubd: Fix for processes stuck in D state forever
  um: delete unnecessary bootmem struct page array
  um: remove csum_partial_copy_generic_i386 to clean up exception table

arch/um/Kconfig.common
arch/um/drivers/net_kern.c
arch/um/drivers/ubd_kern.c
arch/um/include/asm/stacktrace.h [new file with mode: 0644]
arch/um/include/shared/mem_user.h
arch/um/kernel/Makefile
arch/um/kernel/physmem.c
arch/um/kernel/stacktrace.c [new file with mode: 0644]
arch/um/kernel/sysrq.c
arch/um/kernel/um_arch.c
arch/x86/um/checksum_32.S

index 6915d28cf118f6c406ff53b20802a36e6ddfcbe0..87bc86821bc9b81380f46ac38557ad537fd0a442 100644 (file)
@@ -39,7 +39,8 @@ config LOCKDEP_SUPPORT
 
 config STACKTRACE_SUPPORT
        bool
-       default n
+       default y
+       select STACKTRACE
 
 config GENERIC_CALIBRATE_DELAY
        bool
index 7d26d9c0b2fb85cd96ca25953f2bb84d4022be9d..f70dd540655de57bdcddf8c0e2ab1fc6e0e611ba 100644 (file)
@@ -659,10 +659,6 @@ static int __init eth_setup(char *str)
        }
 
        new = alloc_bootmem(sizeof(*new));
-       if (new == NULL) {
-               printk(KERN_ERR "eth_init : alloc_bootmem failed\n");
-               return 1;
-       }
 
        INIT_LIST_HEAD(&new->list);
        new->index = n;
index 3716e69525546c984f8e730a458c6e22a4cc35af..e8ab93c3e638e160e300f016588184b12cc26bd8 100644 (file)
@@ -1277,7 +1277,7 @@ static void do_ubd_request(struct request_queue *q)
 
        while(1){
                struct ubd *dev = q->queuedata;
-               if(dev->end_sg == 0){
+               if(dev->request == NULL){
                        struct request *req = blk_fetch_request(q);
                        if(req == NULL)
                                return;
@@ -1299,7 +1299,8 @@ static void do_ubd_request(struct request_queue *q)
                                return;
                        }
                        prepare_flush_request(req, io_req);
-                       submit_request(io_req, dev);
+                       if (submit_request(io_req, dev) == false)
+                               return;
                }
 
                while(dev->start_sg < dev->end_sg){
diff --git a/arch/um/include/asm/stacktrace.h b/arch/um/include/asm/stacktrace.h
new file mode 100644 (file)
index 0000000..9a86432
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef _ASM_UML_STACKTRACE_H
+#define _ASM_UML_STACKTRACE_H
+
+#include <linux/uaccess.h>
+#include <linux/ptrace.h>
+
+struct stack_frame {
+       struct stack_frame *next_frame;
+       unsigned long return_address;
+};
+
+struct stacktrace_ops {
+       void (*address)(void *data, unsigned long address, int reliable);
+};
+
+#ifdef CONFIG_FRAME_POINTER
+static inline unsigned long
+get_frame_pointer(struct task_struct *task, struct pt_regs *segv_regs)
+{
+       if (!task || task == current)
+               return segv_regs ? PT_REGS_BP(segv_regs) : current_bp();
+       return KSTK_EBP(task);
+}
+#else
+static inline unsigned long
+get_frame_pointer(struct task_struct *task, struct pt_regs *segv_regs)
+{
+       return 0;
+}
+#endif
+
+static inline unsigned long
+*get_stack_pointer(struct task_struct *task, struct pt_regs *segv_regs)
+{
+       if (!task || task == current)
+               return segv_regs ? (unsigned long *)PT_REGS_SP(segv_regs) : current_sp();
+       return (unsigned long *)KSTK_ESP(task);
+}
+
+void dump_trace(struct task_struct *tsk, const struct stacktrace_ops *ops, void *data);
+
+#endif /* _ASM_UML_STACKTRACE_H */
index 46384acd547b7590bd75e4f564cf203327e2e522..cb84414e3e6663eb280c555d88ec447c5c6cad27 100644 (file)
@@ -49,7 +49,7 @@ extern int iomem_size;
 extern int init_mem_user(void);
 extern void setup_memory(void *entry);
 extern unsigned long find_iomem(char *driver, unsigned long *len_out);
-extern int init_maps(unsigned long physmem, unsigned long iomem,
+extern void mem_total_pages(unsigned long physmem, unsigned long iomem,
                     unsigned long highmem);
 extern unsigned long get_vm(unsigned long len);
 extern void setup_physmem(unsigned long start, unsigned long usable,
index d8b78a03855c6a1ad4c7ada6c96938f5e62ee02a..2d840a070c8bb56fc2f54d1bba6a25843ad59a6a 100644 (file)
@@ -19,6 +19,7 @@ obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
 obj-$(CONFIG_GPROF)    += gprof_syms.o
 obj-$(CONFIG_GCOV)     += gmon_syms.o
 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+obj-$(CONFIG_STACKTRACE) += stacktrace.o
 
 USER_OBJS := config.o
 
index 30fdd5d0067b26c91fb8c831da5a1d4008c79e22..549ecf3f5857441c95e4344b6aabc99ce4723f7f 100644 (file)
@@ -22,39 +22,19 @@ EXPORT_SYMBOL(high_physmem);
 
 extern unsigned long long physmem_size;
 
-int __init init_maps(unsigned long physmem, unsigned long iomem,
+void __init mem_total_pages(unsigned long physmem, unsigned long iomem,
                     unsigned long highmem)
 {
-       struct page *p, *map;
-       unsigned long phys_len, phys_pages, highmem_len, highmem_pages;
-       unsigned long iomem_len, iomem_pages, total_len, total_pages;
-       int i;
-
-       phys_pages = physmem >> PAGE_SHIFT;
-       phys_len = phys_pages * sizeof(struct page);
-
-       iomem_pages = iomem >> PAGE_SHIFT;
-       iomem_len = iomem_pages * sizeof(struct page);
+       unsigned long phys_pages, highmem_pages;
+       unsigned long iomem_pages, total_pages;
 
+       phys_pages    = physmem >> PAGE_SHIFT;
+       iomem_pages   = iomem   >> PAGE_SHIFT;
        highmem_pages = highmem >> PAGE_SHIFT;
-       highmem_len = highmem_pages * sizeof(struct page);
-
-       total_pages = phys_pages + iomem_pages + highmem_pages;
-       total_len = phys_len + iomem_len + highmem_len;
 
-       map = alloc_bootmem_low_pages(total_len);
-       if (map == NULL)
-               return -ENOMEM;
-
-       for (i = 0; i < total_pages; i++) {
-               p = &map[i];
-               memset(p, 0, sizeof(struct page));
-               SetPageReserved(p);
-               INIT_LIST_HEAD(&p->lru);
-       }
+       total_pages   = phys_pages + iomem_pages + highmem_pages;
 
        max_mapnr = total_pages;
-       return 0;
 }
 
 void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
diff --git a/arch/um/kernel/stacktrace.c b/arch/um/kernel/stacktrace.c
new file mode 100644 (file)
index 0000000..ebe7bcf
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+ * Copyright (C) 2013 Richard Weinberger <richard@nod.at>
+ * Copyright (C) 2014 Google Inc., Author: Daniel Walter <dwalter@google.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kallsyms.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <asm/stacktrace.h>
+
+void dump_trace(struct task_struct *tsk,
+               const struct stacktrace_ops *ops,
+               void *data)
+{
+       int reliable = 0;
+       unsigned long *sp, bp, addr;
+       struct pt_regs *segv_regs = tsk->thread.segv_regs;
+       struct stack_frame *frame;
+
+       bp = get_frame_pointer(tsk, segv_regs);
+       sp = get_stack_pointer(tsk, segv_regs);
+
+       frame = (struct stack_frame *)bp;
+       while (((long) sp & (THREAD_SIZE-1)) != 0) {
+               addr = *sp;
+               if (__kernel_text_address(addr)) {
+                       reliable = 0;
+                       if ((unsigned long) sp == bp + sizeof(long)) {
+                               frame = frame ? frame->next_frame : NULL;
+                               bp = (unsigned long)frame;
+                               reliable = 1;
+                       }
+                       ops->address(data, addr, reliable);
+               }
+               sp++;
+       }
+}
+
+static void save_addr(void *data, unsigned long address, int reliable)
+{
+       struct stack_trace *trace = data;
+
+       if (!reliable)
+               return;
+       if (trace->nr_entries >= trace->max_entries)
+               return;
+
+       trace->entries[trace->nr_entries++] = address;
+}
+
+static const struct stacktrace_ops dump_ops = {
+       .address = save_addr
+};
+
+static void __save_stack_trace(struct task_struct *tsk, struct stack_trace *trace)
+{
+       dump_trace(tsk, &dump_ops, trace);
+       if (trace->nr_entries < trace->max_entries)
+               trace->entries[trace->nr_entries++] = ULONG_MAX;
+}
+
+void save_stack_trace(struct stack_trace *trace)
+{
+       __save_stack_trace(current, trace);
+}
+EXPORT_SYMBOL_GPL(save_stack_trace);
+
+void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
+{
+       __save_stack_trace(tsk, trace);
+}
+EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
index 799d7e413bf57247f258b25ad6306a91b363e67c..894c8d303cda7c753b000bb3edba035974930b84 100644 (file)
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <asm/sysrq.h>
+#include <asm/stacktrace.h>
 #include <os.h>
 
-struct stack_frame {
-       struct stack_frame *next_frame;
-       unsigned long return_address;
-};
-
-static void do_stack_trace(unsigned long *sp, unsigned long bp)
+static void _print_addr(void *data, unsigned long address, int reliable)
 {
-       int reliable;
-       unsigned long addr;
-       struct stack_frame *frame = (struct stack_frame *)bp;
-
-       printk(KERN_INFO "Call Trace:\n");
-       while (((long) sp & (THREAD_SIZE-1)) != 0) {
-               addr = *sp;
-               if (__kernel_text_address(addr)) {
-                       reliable = 0;
-                       if ((unsigned long) sp == bp + sizeof(long)) {
-                               frame = frame ? frame->next_frame : NULL;
-                               bp = (unsigned long)frame;
-                               reliable = 1;
-                       }
-
-                       printk(KERN_INFO " [<%08lx>]", addr);
-                       printk(KERN_CONT " %s", reliable ? "" : "? ");
-                       print_symbol(KERN_CONT "%s", addr);
-                       printk(KERN_CONT "\n");
-               }
-               sp++;
-       }
-       printk(KERN_INFO "\n");
+       pr_info(" [<%08lx>]", address);
+       pr_cont(" %s", reliable ? "" : "? ");
+       print_symbol("%s", address);
+       pr_cont("\n");
 }
 
-static unsigned long get_frame_pointer(struct task_struct *task,
-                                      struct pt_regs *segv_regs)
-{
-       if (!task || task == current)
-               return segv_regs ? PT_REGS_BP(segv_regs) : current_bp();
-       else
-               return KSTK_EBP(task);
-}
-
-static unsigned long *get_stack_pointer(struct task_struct *task,
-                                       struct pt_regs *segv_regs)
-{
-       if (!task || task == current)
-               return segv_regs ? (unsigned long *)PT_REGS_SP(segv_regs) : current_sp();
-       else
-               return (unsigned long *)KSTK_ESP(task);
-}
+static const struct stacktrace_ops stackops = {
+       .address = _print_addr
+};
 
 void show_stack(struct task_struct *task, unsigned long *stack)
 {
@@ -71,7 +34,7 @@ void show_stack(struct task_struct *task, unsigned long *stack)
        int i;
 
        if (!segv_regs && os_is_signal_stack()) {
-               printk(KERN_ERR "Received SIGSEGV in SIGSEGV handler,"
+               pr_err("Received SIGSEGV in SIGSEGV handler,"
                                " aborting stack trace!\n");
                return;
        }
@@ -83,16 +46,18 @@ void show_stack(struct task_struct *task, unsigned long *stack)
        if (!stack)
                sp = get_stack_pointer(task, segv_regs);
 
-       printk(KERN_INFO "Stack:\n");
+       pr_info("Stack:\n");
        stack = sp;
        for (i = 0; i < 3 * STACKSLOTS_PER_LINE; i++) {
                if (kstack_end(stack))
                        break;
                if (i && ((i % STACKSLOTS_PER_LINE) == 0))
-                       printk(KERN_CONT "\n");
-               printk(KERN_CONT " %08lx", *stack++);
+                       pr_cont("\n");
+               pr_cont(" %08lx", *stack++);
        }
-       printk(KERN_CONT "\n");
+       pr_cont("\n");
 
-       do_stack_trace(sp, bp);
+       pr_info("Call Trace:\n");
+       dump_trace(current, &stackops, NULL);
+       pr_info("\n");
 }
index 016adf0985d522ccfb5f22e6d287bb60dfdb4e61..9274eae6ae7b81fb976f059ea9d8afb6b420722a 100644 (file)
@@ -348,12 +348,7 @@ int __init linux_main(int argc, char **argv)
        start_vm = VMALLOC_START;
 
        setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
-       if (init_maps(physmem_size, iomem_size, highmem)) {
-               printf("Failed to allocate mem_map for %Lu bytes of physical "
-                      "memory and %Lu bytes of highmem\n", physmem_size,
-                      highmem);
-               exit(1);
-       }
+       mem_total_pages(physmem_size, iomem_size, highmem);
 
        virtmem_size = physmem_size;
        stack = (unsigned long) argv;
index 8d0c420465cce0cf897278e03f25904a51cd92ff..fa4b8b9841ff7071a993e61d2b55ca3bc8b35575 100644 (file)
@@ -214,242 +214,3 @@ csum_partial:
        ret
                                
 #endif
-
-/*
-unsigned int csum_partial_copy_generic (const char *src, char *dst,
-                                 int len, int sum, int *src_err_ptr, int *dst_err_ptr)
- */ 
-
-/*
- * Copy from ds while checksumming, otherwise like csum_partial
- *
- * The macros SRC and DST specify the type of access for the instruction.
- * thus we can call a custom exception handler for all access types.
- *
- * FIXME: could someone double-check whether I haven't mixed up some SRC and
- *       DST definitions? It's damn hard to trigger all cases.  I hope I got
- *       them all but there's no guarantee.
- */
-
-#define SRC(y...)                      \
-       9999: y;                        \
-       _ASM_EXTABLE(9999b, 6001f)
-
-#define DST(y...)                      \
-       9999: y;                        \
-       _ASM_EXTABLE(9999b, 6002f)
-
-.align 4
-
-#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
-
-#define ARGBASE 16             
-#define FP             12
-
-csum_partial_copy_generic_i386:
-       subl  $4,%esp   
-       pushl %edi
-       pushl %esi
-       pushl %ebx
-       movl ARGBASE+16(%esp),%eax      # sum
-       movl ARGBASE+12(%esp),%ecx      # len
-       movl ARGBASE+4(%esp),%esi       # src
-       movl ARGBASE+8(%esp),%edi       # dst
-
-       testl $2, %edi                  # Check alignment. 
-       jz 2f                           # Jump if alignment is ok.
-       subl $2, %ecx                   # Alignment uses up two bytes.
-       jae 1f                          # Jump if we had at least two bytes.
-       addl $2, %ecx                   # ecx was < 2.  Deal with it.
-       jmp 4f
-SRC(1: movw (%esi), %bx        )
-       addl $2, %esi
-DST(   movw %bx, (%edi)        )
-       addl $2, %edi
-       addw %bx, %ax   
-       adcl $0, %eax
-2:
-       movl %ecx, FP(%esp)
-       shrl $5, %ecx
-       jz 2f
-       testl %esi, %esi
-SRC(1: movl (%esi), %ebx       )
-SRC(   movl 4(%esi), %edx      )
-       adcl %ebx, %eax
-DST(   movl %ebx, (%edi)       )
-       adcl %edx, %eax
-DST(   movl %edx, 4(%edi)      )
-
-SRC(   movl 8(%esi), %ebx      )
-SRC(   movl 12(%esi), %edx     )
-       adcl %ebx, %eax
-DST(   movl %ebx, 8(%edi)      )
-       adcl %edx, %eax
-DST(   movl %edx, 12(%edi)     )
-
-SRC(   movl 16(%esi), %ebx     )
-SRC(   movl 20(%esi), %edx     )
-       adcl %ebx, %eax
-DST(   movl %ebx, 16(%edi)     )
-       adcl %edx, %eax
-DST(   movl %edx, 20(%edi)     )
-
-SRC(   movl 24(%esi), %ebx     )
-SRC(   movl 28(%esi), %edx     )
-       adcl %ebx, %eax
-DST(   movl %ebx, 24(%edi)     )
-       adcl %edx, %eax
-DST(   movl %edx, 28(%edi)     )
-
-       lea 32(%esi), %esi
-       lea 32(%edi), %edi
-       dec %ecx
-       jne 1b
-       adcl $0, %eax
-2:     movl FP(%esp), %edx
-       movl %edx, %ecx
-       andl $0x1c, %edx
-       je 4f
-       shrl $2, %edx                   # This clears CF
-SRC(3: movl (%esi), %ebx       )
-       adcl %ebx, %eax
-DST(   movl %ebx, (%edi)       )
-       lea 4(%esi), %esi
-       lea 4(%edi), %edi
-       dec %edx
-       jne 3b
-       adcl $0, %eax
-4:     andl $3, %ecx
-       jz 7f
-       cmpl $2, %ecx
-       jb 5f
-SRC(   movw (%esi), %cx        )
-       leal 2(%esi), %esi
-DST(   movw %cx, (%edi)        )
-       leal 2(%edi), %edi
-       je 6f
-       shll $16,%ecx
-SRC(5: movb (%esi), %cl        )
-DST(   movb %cl, (%edi)        )
-6:     addl %ecx, %eax
-       adcl $0, %eax
-7:
-5000:
-
-# Exception handler:
-.section .fixup, "ax"                                                  
-
-6001:
-       movl ARGBASE+20(%esp), %ebx     # src_err_ptr
-       movl $-EFAULT, (%ebx)
-
-       # zero the complete destination - computing the rest
-       # is too much work 
-       movl ARGBASE+8(%esp), %edi      # dst
-       movl ARGBASE+12(%esp), %ecx     # len
-       xorl %eax,%eax
-       rep ; stosb
-
-       jmp 5000b
-
-6002:
-       movl ARGBASE+24(%esp), %ebx     # dst_err_ptr
-       movl $-EFAULT,(%ebx)
-       jmp 5000b
-
-.previous
-
-       popl %ebx
-       popl %esi
-       popl %edi
-       popl %ecx                       # equivalent to addl $4,%esp
-       ret     
-
-#else
-
-/* Version for PentiumII/PPro */
-
-#define ROUND1(x) \
-       SRC(movl x(%esi), %ebx  )       ;       \
-       addl %ebx, %eax                 ;       \
-       DST(movl %ebx, x(%edi)  )       ; 
-
-#define ROUND(x) \
-       SRC(movl x(%esi), %ebx  )       ;       \
-       adcl %ebx, %eax                 ;       \
-       DST(movl %ebx, x(%edi)  )       ;
-
-#define ARGBASE 12
-               
-csum_partial_copy_generic_i386:
-       pushl %ebx
-       pushl %edi
-       pushl %esi
-       movl ARGBASE+4(%esp),%esi       #src
-       movl ARGBASE+8(%esp),%edi       #dst    
-       movl ARGBASE+12(%esp),%ecx      #len
-       movl ARGBASE+16(%esp),%eax      #sum
-#      movl %ecx, %edx  
-       movl %ecx, %ebx  
-       movl %esi, %edx
-       shrl $6, %ecx     
-       andl $0x3c, %ebx  
-       negl %ebx
-       subl %ebx, %esi  
-       subl %ebx, %edi  
-       lea  -1(%esi),%edx
-       andl $-32,%edx
-       lea 3f(%ebx,%ebx), %ebx
-       testl %esi, %esi 
-       jmp *%ebx
-1:     addl $64,%esi
-       addl $64,%edi 
-       SRC(movb -32(%edx),%bl) ; SRC(movb (%edx),%bl)
-       ROUND1(-64) ROUND(-60) ROUND(-56) ROUND(-52)    
-       ROUND (-48) ROUND(-44) ROUND(-40) ROUND(-36)    
-       ROUND (-32) ROUND(-28) ROUND(-24) ROUND(-20)    
-       ROUND (-16) ROUND(-12) ROUND(-8)  ROUND(-4)     
-3:     adcl $0,%eax
-       addl $64, %edx
-       dec %ecx
-       jge 1b
-4:     movl ARGBASE+12(%esp),%edx      #len
-       andl $3, %edx
-       jz 7f
-       cmpl $2, %edx
-       jb 5f
-SRC(   movw (%esi), %dx         )
-       leal 2(%esi), %esi
-DST(   movw %dx, (%edi)         )
-       leal 2(%edi), %edi
-       je 6f
-       shll $16,%edx
-5:
-SRC(   movb (%esi), %dl         )
-DST(   movb %dl, (%edi)         )
-6:     addl %edx, %eax
-       adcl $0, %eax
-7:
-.section .fixup, "ax"
-6001:  movl    ARGBASE+20(%esp), %ebx  # src_err_ptr   
-       movl $-EFAULT, (%ebx)
-       # zero the complete destination (computing the rest is too much work)
-       movl ARGBASE+8(%esp),%edi       # dst
-       movl ARGBASE+12(%esp),%ecx      # len
-       xorl %eax,%eax
-       rep; stosb
-       jmp 7b
-6002:  movl ARGBASE+24(%esp), %ebx     # dst_err_ptr
-       movl $-EFAULT, (%ebx)
-       jmp  7b                 
-.previous                              
-
-       popl %esi
-       popl %edi
-       popl %ebx
-       ret
-                               
-#undef ROUND
-#undef ROUND1          
-               
-#endif