diff options
Diffstat (limited to 'arch/m68k/kernel')
-rw-r--r-- | arch/m68k/kernel/Makefile | 4 | ||||
-rw-r--r-- | arch/m68k/kernel/dma.c | 129 | ||||
-rw-r--r-- | arch/m68k/kernel/entry.S | 104 | ||||
-rw-r--r-- | arch/m68k/kernel/ints.c | 382 | ||||
-rw-r--r-- | arch/m68k/kernel/m68k_ksyms.c | 2 | ||||
-rw-r--r-- | arch/m68k/kernel/setup.c | 3 | ||||
-rw-r--r-- | arch/m68k/kernel/signal.c | 2 | ||||
-rw-r--r-- | arch/m68k/kernel/traps.c | 188 |
8 files changed, 523 insertions, 291 deletions
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile index 458925c471a..dae609797dc 100644 --- a/arch/m68k/kernel/Makefile +++ b/arch/m68k/kernel/Makefile @@ -9,8 +9,8 @@ else endif extra-y += vmlinux.lds -obj-y := entry.o process.o traps.o ints.o signal.o ptrace.o \ - sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o +obj-y := entry.o process.o traps.o ints.o dma.o signal.o ptrace.o \ + sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o obj-$(CONFIG_PCI) += bios32.o obj-$(CONFIG_MODULES) += module.o diff --git a/arch/m68k/kernel/dma.c b/arch/m68k/kernel/dma.c new file mode 100644 index 00000000000..fc449f8b204 --- /dev/null +++ b/arch/m68k/kernel/dma.c @@ -0,0 +1,129 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#undef DEBUG + +#include <linux/dma-mapping.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/vmalloc.h> + +#include <asm/pgalloc.h> +#include <asm/scatterlist.h> + +void *dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *handle, int flag) +{ + struct page *page, **map; + pgprot_t pgprot; + void *addr; + int i, order; + + pr_debug("dma_alloc_coherent: %d,%x\n", size, flag); + + size = PAGE_ALIGN(size); + order = get_order(size); + + page = alloc_pages(flag, order); + if (!page) + return NULL; + + *handle = page_to_phys(page); + map = kmalloc(sizeof(struct page *) << order, flag & ~__GFP_DMA); + if (!map) { + __free_pages(page, order); + return NULL; + } + split_page(page, order); + + order = 1 << order; + size >>= PAGE_SHIFT; + map[0] = page; + for (i = 1; i < size; i++) + map[i] = page + i; + for (; i < order; i++) + __free_page(page + i); + pgprot = __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY); + if (CPU_IS_040_OR_060) + pgprot_val(pgprot) |= _PAGE_GLOBAL040 | _PAGE_NOCACHE_S; + else + pgprot_val(pgprot) |= _PAGE_NOCACHE030; + addr = vmap(map, size, flag, pgprot); + kfree(map); + + return addr; +} +EXPORT_SYMBOL(dma_alloc_coherent); + +void dma_free_coherent(struct device *dev, size_t size, + void *addr, dma_addr_t handle) +{ + pr_debug("dma_free_coherent: %p, %x\n", addr, handle); + vfree(addr); +} +EXPORT_SYMBOL(dma_free_coherent); + +inline void dma_sync_single_for_device(struct device *dev, dma_addr_t handle, size_t size, + enum dma_data_direction dir) +{ + switch (dir) { + case DMA_TO_DEVICE: + cache_push(handle, size); + break; + case DMA_FROM_DEVICE: + cache_clear(handle, size); + break; + default: + if (printk_ratelimit()) + printk("dma_sync_single_for_device: unsupported dir %u\n", dir); + break; + } +} +EXPORT_SYMBOL(dma_sync_single_for_device); + +void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction dir) +{ + int i; + + for (i = 0; i < nents; sg++, i++) + dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir); +} +EXPORT_SYMBOL(dma_sync_sg_for_device); + +dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size, + enum dma_data_direction dir) +{ + dma_addr_t handle = virt_to_bus(addr); + + dma_sync_single_for_device(dev, handle, size, dir); + return handle; +} +EXPORT_SYMBOL(dma_map_single); + +dma_addr_t dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, + enum dma_data_direction dir) +{ + dma_addr_t handle = page_to_phys(page) + offset; + + dma_sync_single_for_device(dev, handle, size, dir); + return handle; +} +EXPORT_SYMBOL(dma_map_page); + +int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction dir) +{ + int i; + + for (i = 0; i < nents; sg++, i++) { + sg->dma_address = page_to_phys(sg->page) + sg->offset; + dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir); + } + return nents; +} +EXPORT_SYMBOL(dma_map_sg); diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 320fde05dc6..449b62b30f4 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S @@ -45,9 +45,11 @@ #include <asm/asm-offsets.h> .globl system_call, buserr, trap, resume -.globl inthandler, sys_call_table +.globl sys_call_table .globl sys_fork, sys_clone, sys_vfork .globl ret_from_interrupt, bad_interrupt +.globl auto_irqhandler_fixup +.globl user_irqvec_fixup, user_irqhandler_fixup .text ENTRY(buserr) @@ -191,65 +193,29 @@ do_delayed_trace: jbra resume_userspace -#if 0 -#ifdef CONFIG_AMIGA -ami_inthandler: - addql #1,irq_stat+CPUSTAT_LOCAL_IRQ_COUNT - SAVE_ALL_INT - GET_CURRENT(%d0) +/* This is the main interrupt handler for autovector interrupts */ - bfextu %sp@(PT_VECTOR){#4,#12},%d0 - movel %d0,%a0 - addql #1,%a0@(kstat+STAT_IRQ-VECOFF(VEC_SPUR)) - movel %a0@(autoirq_list-VECOFF(VEC_SPUR)),%a0 - -| amiga vector int handler get the req mask instead of irq vector - lea CUSTOMBASE,%a1 - movew %a1@(C_INTREQR),%d0 - andw %a1@(C_INTENAR),%d0 - -| prepare stack (push frame pointer, dev_id & req mask) - pea %sp@ - movel %a0@(IRQ_DEVID),%sp@- - movel %d0,%sp@- - pea %pc@(ret_from_interrupt:w) - jbra @(IRQ_HANDLER,%a0)@(0) - -ENTRY(nmi_handler) - rte -#endif -#endif - -/* -** This is the main interrupt handler, responsible for calling process_int() -*/ -inthandler: +ENTRY(auto_inthandler) SAVE_ALL_INT GET_CURRENT(%d0) - addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+2) + addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) | put exception # in d0 - bfextu %sp@(PT_VECTOR){#4,#10},%d0 + bfextu %sp@(PT_VECTOR){#4,#10},%d0 + subw #VEC_SPUR,%d0 movel %sp,%sp@- movel %d0,%sp@- | put vector # on stack -#if defined(MACH_Q40_ONLY) && defined(CONFIG_BLK_DEV_FD) - btstb #4,0xff000000 | Q40 floppy needs very special treatment ... - jbeq 1f - btstb #3,0xff000004 - jbeq 1f - jbsr floppy_hardint - jbra 3f -1: -#endif - jbsr process_int | process the IRQ -3: addql #8,%sp | pop parameters off stack +auto_irqhandler_fixup = . + 2 + jsr m68k_handle_int | process the IRQ + addql #8,%sp | pop parameters off stack ret_from_interrupt: - subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+2) - jeq 1f -2: - RESTORE_ALL -1: + subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + jeq ret_from_last_interrupt +2: RESTORE_ALL + + ALIGN +ret_from_last_interrupt: moveq #(~ALLOWINT>>8)&0xff,%d0 andb %sp@(PT_SR),%d0 jne 2b @@ -260,12 +226,42 @@ ret_from_interrupt: pea ret_from_exception jra do_softirq +/* Handler for user defined interrupt vectors */ + +ENTRY(user_inthandler) + SAVE_ALL_INT + GET_CURRENT(%d0) + addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + | put exception # in d0 + bfextu %sp@(PT_VECTOR){#4,#10},%d0 +user_irqvec_fixup = . + 2 + subw #VEC_USER,%d0 + + movel %sp,%sp@- + movel %d0,%sp@- | put vector # on stack +user_irqhandler_fixup = . + 2 + jsr m68k_handle_int | process the IRQ + addql #8,%sp | pop parameters off stack + + subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + jeq ret_from_last_interrupt + RESTORE_ALL /* Handler for uninitialized and spurious interrupts */ -bad_interrupt: - addql #1,num_spurious - rte +ENTRY(bad_inthandler) + SAVE_ALL_INT + GET_CURRENT(%d0) + addqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + + movel %sp,%sp@- + jsr handle_badint + addql #4,%sp + + subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) + jeq ret_from_last_interrupt + RESTORE_ALL + ENTRY(sys_fork) SAVE_SWITCH_STACK diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c index 514d323ad53..5a8344b9354 100644 --- a/arch/m68k/kernel/ints.c +++ b/arch/m68k/kernel/ints.c @@ -39,47 +39,40 @@ #include <asm/traps.h> #include <asm/page.h> #include <asm/machdep.h> +#include <asm/cacheflush.h> #ifdef CONFIG_Q40 #include <asm/q40ints.h> #endif +extern u32 auto_irqhandler_fixup[]; +extern u32 user_irqhandler_fixup[]; +extern u16 user_irqvec_fixup[]; + /* table for system interrupt handlers */ -static irq_handler_t irq_list[SYS_IRQS]; - -static const char *default_names[SYS_IRQS] = { - [0] = "spurious int", - [1] = "int1 handler", - [2] = "int2 handler", - [3] = "int3 handler", - [4] = "int4 handler", - [5] = "int5 handler", - [6] = "int6 handler", - [7] = "int7 handler" +static struct irq_node *irq_list[NR_IRQS]; +static struct irq_controller *irq_controller[NR_IRQS]; +static int irq_depth[NR_IRQS]; + +static int m68k_first_user_vec; + +static struct irq_controller auto_irq_controller = { + .name = "auto", + .lock = SPIN_LOCK_UNLOCKED, + .startup = m68k_irq_startup, + .shutdown = m68k_irq_shutdown, }; -/* The number of spurious interrupts */ -volatile unsigned int num_spurious; +static struct irq_controller user_irq_controller = { + .name = "user", + .lock = SPIN_LOCK_UNLOCKED, + .startup = m68k_irq_startup, + .shutdown = m68k_irq_shutdown, +}; #define NUM_IRQ_NODES 100 static irq_node_t nodes[NUM_IRQ_NODES]; -static void dummy_enable_irq(unsigned int irq); -static void dummy_disable_irq(unsigned int irq); -static int dummy_request_irq(unsigned int irq, - irqreturn_t (*handler) (int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id); -static void dummy_free_irq(unsigned int irq, void *dev_id); - -void (*enable_irq) (unsigned int) = dummy_enable_irq; -void (*disable_irq) (unsigned int) = dummy_disable_irq; - -int (*mach_request_irq) (unsigned int, irqreturn_t (*)(int, void *, struct pt_regs *), - unsigned long, const char *, void *) = dummy_request_irq; -void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq; - -void init_irq_proc(void); - /* * void init_IRQ(void) * @@ -95,18 +88,76 @@ void __init init_IRQ(void) { int i; - for (i = 0; i < SYS_IRQS; i++) { - if (mach_default_handler) - irq_list[i].handler = (*mach_default_handler)[i]; - irq_list[i].flags = 0; - irq_list[i].dev_id = NULL; - irq_list[i].devname = default_names[i]; + /* assembly irq entry code relies on this... */ + if (HARDIRQ_MASK != 0x00ff0000) { + extern void hardirq_mask_is_broken(void); + hardirq_mask_is_broken(); } - for (i = 0; i < NUM_IRQ_NODES; i++) - nodes[i].handler = NULL; + for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++) + irq_controller[i] = &auto_irq_controller; + + mach_init_IRQ(); +} + +/** + * m68k_setup_auto_interrupt + * @handler: called from auto vector interrupts + * + * setup the handler to be called from auto vector interrupts instead of the + * standard m68k_handle_int(), it will be called with irq numbers in the range + * from IRQ_AUTO_1 - IRQ_AUTO_7. + */ +void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *)) +{ + if (handler) + *auto_irqhandler_fixup = (u32)handler; + flush_icache(); +} + +/** + * m68k_setup_user_interrupt + * @vec: first user vector interrupt to handle + * @cnt: number of active user vector interrupts + * @handler: called from user vector interrupts + * + * setup user vector interrupts, this includes activating the specified range + * of interrupts, only then these interrupts can be requested (note: this is + * different from auto vector interrupts). An optional handler can be installed + * to be called instead of the default m68k_handle_int(), it will be called + * with irq numbers starting from IRQ_USER. + */ +void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, + void (*handler)(unsigned int, struct pt_regs *)) +{ + int i; + + m68k_first_user_vec = vec; + for (i = 0; i < cnt; i++) + irq_controller[IRQ_USER + i] = &user_irq_controller; + *user_irqvec_fixup = vec - IRQ_USER; + if (handler) + *user_irqhandler_fixup = (u32)handler; + flush_icache(); +} + +/** + * m68k_setup_irq_controller + * @contr: irq controller which controls specified irq + * @irq: first irq to be managed by the controller + * + * Change the controller for the specified range of irq, which will be used to + * manage these irq. auto/user irq already have a default controller, which can + * be changed as well, but the controller probably should use m68k_irq_startup/ + * m68k_irq_shutdown. + */ +void m68k_setup_irq_controller(struct irq_controller *contr, unsigned int irq, + unsigned int cnt) +{ + int i; - mach_init_IRQ (); + for (i = 0; i < cnt; i++) + irq_controller[irq + i] = contr; } irq_node_t *new_irq_node(void) @@ -114,84 +165,183 @@ irq_node_t *new_irq_node(void) irq_node_t *node; short i; - for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) - if (!node->handler) + for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) { + if (!node->handler) { + memset(node, 0, sizeof(*node)); return node; + } + } printk ("new_irq_node: out of nodes\n"); return NULL; } -/* - * We will keep these functions until I have convinced Linus to move - * the declaration of them from include/linux/sched.h to - * include/asm/irq.h. - */ +int setup_irq(unsigned int irq, struct irq_node *node) +{ + struct irq_controller *contr; + struct irq_node **prev; + unsigned long flags; + + if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { + printk("%s: Incorrect IRQ %d from %s\n", + __FUNCTION__, irq, node->devname); + return -ENXIO; + } + + spin_lock_irqsave(&contr->lock, flags); + + prev = irq_list + irq; + if (*prev) { + /* Can't share interrupts unless both agree to */ + if (!((*prev)->flags & node->flags & SA_SHIRQ)) { + spin_unlock_irqrestore(&contr->lock, flags); + return -EBUSY; + } + while (*prev) + prev = &(*prev)->next; + } + + if (!irq_list[irq]) { + if (contr->startup) + contr->startup(irq); + else + contr->enable(irq); + } + node->next = NULL; + *prev = node; + + spin_unlock_irqrestore(&contr->lock, flags); + + return 0; +} + int request_irq(unsigned int irq, irqreturn_t (*handler) (int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id) { - return mach_request_irq(irq, handler, flags, devname, dev_id); + struct irq_node *node; + int res; + + node = new_irq_node(); + if (!node) + return -ENOMEM; + + node->handler = handler; + node->flags = flags; + node->dev_id = dev_id; + node->devname = devname; + + res = setup_irq(irq, node); + if (res) + node->handler = NULL; + + return res; } EXPORT_SYMBOL(request_irq); void free_irq(unsigned int irq, void *dev_id) { - mach_free_irq(irq, dev_id); + struct irq_controller *contr; + struct irq_node **p, *node; + unsigned long flags; + + if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { + printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq); + return; + } + + spin_lock_irqsave(&contr->lock, flags); + + p = irq_list + irq; + while ((node = *p)) { + if (node->dev_id == dev_id) + break; + p = &node->next; + } + + if (node) { + *p = node->next; + node->handler = NULL; + } else + printk("%s: Removing probably wrong IRQ %d\n", + __FUNCTION__, irq); + + if (!irq_list[irq]) { + if (contr->shutdown) + contr->shutdown(irq); + else + contr->disable(irq); + } + + spin_unlock_irqrestore(&contr->lock, flags); } EXPORT_SYMBOL(free_irq); -int cpu_request_irq(unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id) +void enable_irq(unsigned int irq) { - if (irq < IRQ1 || irq > IRQ7) { - printk("%s: Incorrect IRQ %d from %s\n", - __FUNCTION__, irq, devname); - return -ENXIO; - } + struct irq_controller *contr; + unsigned long flags; -#if 0 - if (!(irq_list[irq].flags & IRQ_FLG_STD)) { - if (irq_list[irq].flags & IRQ_FLG_LOCK) { - printk("%s: IRQ %d from %s is not replaceable\n", - __FUNCTION__, irq, irq_list[irq].devname); - return -EBUSY; - } - if (!(flags & IRQ_FLG_REPLACE)) { - printk("%s: %s can't replace IRQ %d from %s\n", - __FUNCTION__, devname, irq, irq_list[irq].devname); - return -EBUSY; - } + if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { + printk("%s: Incorrect IRQ %d\n", + __FUNCTION__, irq); + return; } -#endif - irq_list[irq].handler = handler; - irq_list[irq].flags = flags; - irq_list[irq].dev_id = dev_id; - irq_list[irq].devname = devname; - return 0; + spin_lock_irqsave(&contr->lock, flags); + if (irq_depth[irq]) { + if (!--irq_depth[irq]) { + if (contr->enable) + contr->enable(irq); + } + } else + WARN_ON(1); + spin_unlock_irqrestore(&contr->lock, flags); } -void cpu_free_irq(unsigned int irq, void *dev_id) +EXPORT_SYMBOL(enable_irq); + +void disable_irq(unsigned int irq) { - if (irq < IRQ1 || irq > IRQ7) { - printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq); + struct irq_controller *contr; + unsigned long flags; + + if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { + printk("%s: Incorrect IRQ %d\n", + __FUNCTION__, irq); return; } - if (irq_list[irq].dev_id != dev_id) - printk("%s: Removing probably wrong IRQ %d from %s\n", - __FUNCTION__, irq, irq_list[irq].devname); + spin_lock_irqsave(&contr->lock, flags); + if (!irq_depth[irq]++) { + if (contr->disable) + contr->disable(irq); + } + spin_unlock_irqrestore(&contr->lock, flags); +} - irq_list[irq].handler = (*mach_default_handler)[irq]; - irq_list[irq].flags = 0; - irq_list[irq].dev_id = NULL; - irq_list[irq].devname = default_names[irq]; +EXPORT_SYMBOL(disable_irq); + +int m68k_irq_startup(unsigned int irq) +{ + if (irq <= IRQ_AUTO_7) + vectors[VEC_SPUR + irq] = auto_inthandler; + else + vectors[m68k_first_user_vec + irq - IRQ_USER] = user_inthandler; + return 0; } +void m68k_irq_shutdown(unsigned int irq) +{ + if (irq <= IRQ_AUTO_7) + vectors[VEC_SPUR + irq] = bad_inthandler; + else + vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler; +} + + /* * Do we need these probe functions on the m68k? * @@ -219,58 +369,50 @@ int probe_irq_off (unsigned long irqs) EXPORT_SYMBOL(probe_irq_off); -static void dummy_enable_irq(unsigned int irq) -{ - printk("calling uninitialized enable_irq()\n"); -} - -static void dummy_disable_irq(unsigned int irq) +unsigned int irq_canonicalize(unsigned int irq) { - printk("calling uninitialized disable_irq()\n"); +#ifdef CONFIG_Q40 + if (MACH_IS_Q40 && irq == 11) + irq = 10; +#endif + return irq; } -static int dummy_request_irq(unsigned int irq, - irqreturn_t (*handler) (int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id) -{ - printk("calling uninitialized request_irq()\n"); - return 0; -} +EXPORT_SYMBOL(irq_canonicalize); -static void dummy_free_irq(unsigned int irq, void *dev_id) +asmlinkage void m68k_handle_int(unsigned int irq, struct pt_regs *regs) { - printk("calling uninitialized disable_irq()\n"); + struct irq_node *node; + + kstat_cpu(0).irqs[irq]++; + node = irq_list[irq]; + do { + node->handler(irq, node->dev_id, regs); + node = node->next; + } while (node); } -asmlinkage void process_int(unsigned long vec, struct pt_regs *fp) +asmlinkage void handle_badint(struct pt_regs *regs) { - if (vec >= VEC_INT1 && vec <= VEC_INT7 && !MACH_IS_BVME6000) { - vec -= VEC_SPUR; - kstat_cpu(0).irqs[vec]++; - irq_list[vec].handler(vec, irq_list[vec].dev_id, fp); - } else { - if (mach_process_int) - mach_process_int(vec, fp); - else - panic("Can't process interrupt vector %ld\n", vec); - return; - } + kstat_cpu(0).irqs[0]++; + printk("unexpected interrupt from %u\n", regs->vector); } int show_interrupts(struct seq_file *p, void *v) { + struct irq_controller *contr; + struct irq_node *node; int i = *(loff_t *) v; /* autovector interrupts */ - if (i < SYS_IRQS) { - if (mach_default_handler) { - seq_printf(p, "auto %2d: %10u ", i, - i ? kstat_cpu(0).irqs[i] : num_spurious); - seq_puts(p, " "); - seq_printf(p, "%s\n", irq_list[i].devname); - } - } else if (i == SYS_IRQS) - mach_get_irq_list(p, v); + if (irq_list[i]) { + contr = irq_controller[i]; + node = irq_list[i]; + seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, kstat_cpu(0).irqs[i], node->devname); + while ((node = node->next)) + seq_printf(p, ", %s", node->devname); + seq_puts(p, "\n"); + } return 0; } diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c index 5b7952ea2ba..1f5e1b5aeda 100644 --- a/arch/m68k/kernel/m68k_ksyms.c +++ b/arch/m68k/kernel/m68k_ksyms.c @@ -57,8 +57,6 @@ EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(strnlen); EXPORT_SYMBOL(strrchr); EXPORT_SYMBOL(strstr); -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(kernel_thread); #ifdef CONFIG_VME EXPORT_SYMBOL(vme_brdtype); diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c index 750d5b3c971..214a95f9f3a 100644 --- a/arch/m68k/kernel/setup.c +++ b/arch/m68k/kernel/setup.c @@ -68,11 +68,8 @@ char m68k_debug_device[6] = ""; void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *)) __initdata = NULL; /* machine dependent irq functions */ void (*mach_init_IRQ) (void) __initdata = NULL; -irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *); void (*mach_get_model) (char *model); int (*mach_get_hardware_list) (char *buffer); -int (*mach_get_irq_list) (struct seq_file *, void *); -irqreturn_t (*mach_process_int) (int, struct pt_regs *); /* machine dependent timer functions */ unsigned long (*mach_gettimeoffset) (void); int (*mach_hwclk) (int, struct rtc_time*); diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index 866917bfa02..f9af893cd28 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c @@ -763,7 +763,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { - if (!on_sig_stack(usp)) + if (!sas_ss_flags(usp)) usp = current->sas_ss_sp + current->sas_ss_size; } return (void __user *)((usp - frame_size) & -8UL); diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index cdf58fbb3e7..e86de7b061c 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c @@ -45,7 +45,6 @@ asmlinkage void system_call(void); asmlinkage void buserr(void); asmlinkage void trap(void); -asmlinkage void inthandler(void); asmlinkage void nmihandler(void); #ifdef CONFIG_M68KFPU_EMU asmlinkage void fpu_emu(void); @@ -53,51 +52,7 @@ asmlinkage void fpu_emu(void); e_vector vectors[256] = { [VEC_BUSERR] = buserr, - [VEC_ADDRERR] = trap, - [VEC_ILLEGAL] = trap, - [VEC_ZERODIV] = trap, - [VEC_CHK] = trap, - [VEC_TRAP] = trap, - [VEC_PRIV] = trap, - [VEC_TRACE] = trap, - [VEC_LINE10] = trap, - [VEC_LINE11] = trap, - [VEC_RESV12] = trap, - [VEC_COPROC] = trap, - [VEC_FORMAT] = trap, - [VEC_UNINT] = trap, - [VEC_RESV16] = trap, - [VEC_RESV17] = trap, - [VEC_RESV18] = trap, - [VEC_RESV19] = trap, - [VEC_RESV20] = trap, - [VEC_RESV21] = trap, - [VEC_RESV22] = trap, - [VEC_RESV23] = trap, - [VEC_SPUR] = inthandler, - [VEC_INT1] = inthandler, - [VEC_INT2] = inthandler, - [VEC_INT3] = inthandler, - [VEC_INT4] = inthandler, - [VEC_INT5] = inthandler, - [VEC_INT6] = inthandler, - [VEC_INT7] = inthandler, [VEC_SYS] = system_call, - [VEC_TRAP1] = trap, - [VEC_TRAP2] = trap, - [VEC_TRAP3] = trap, - [VEC_TRAP4] = trap, - [VEC_TRAP5] = trap, - [VEC_TRAP6] = trap, - [VEC_TRAP7] = trap, - [VEC_TRAP8] = trap, - [VEC_TRAP9] = trap, - [VEC_TRAP10] = trap, - [VEC_TRAP11] = trap, - [VEC_TRAP12] = trap, - [VEC_TRAP13] = trap, - [VEC_TRAP14] = trap, - [VEC_TRAP15] = trap, }; /* nmi handler for the Amiga */ @@ -114,7 +69,7 @@ void __init base_trap_init(void) if(MACH_IS_SUN3X) { extern e_vector *sun3x_prom_vbr; - __asm__ volatile ("movec %%vbr, %0" : "=r" ((void*)sun3x_prom_vbr)); + __asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr)); } /* setup the exception vector table */ @@ -132,12 +87,15 @@ void __init trap_init (void) { int i; - for (i = 48; i < 64; i++) + for (i = VEC_SPUR; i <= VEC_INT7; i++) + vectors[i] = bad_inthandler; + + for (i = 0; i < VEC_USER; i++) if (!vectors[i]) vectors[i] = trap; - for (i = 64; i < 256; i++) - vectors[i] = inthandler; + for (i = VEC_USER; i < 256; i++) + vectors[i] = bad_inthandler; #ifdef CONFIG_M68KFPU_EMU if (FPU_IS_EMU) @@ -927,71 +885,94 @@ void show_trace(unsigned long *stack) void show_registers(struct pt_regs *regs) { struct frame *fp = (struct frame *)regs; + mm_segment_t old_fs = get_fs(); + u16 c, *cp; unsigned long addr; int i; + print_modules(); + printk("PC: [<%08lx>]",regs->pc); + print_symbol(" %s", regs->pc); + printk("\nSR: %04x SP: %p a2: %08lx\n", + regs->sr, regs, regs->a2); + printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", + regs->d0, regs->d1, regs->d2, regs->d3); + printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", + regs->d4, regs->d5, regs->a0, regs->a1); + + printk("Process %s (pid: %d, task=%p)\n", + current->comm, current->pid, current); addr = (unsigned long)&fp->un; - printk("Frame format=%X ", fp->ptregs.format); - switch (fp->ptregs.format) { + printk("Frame format=%X ", regs->format); + switch (regs->format) { case 0x2: - printk("instr addr=%08lx\n", fp->un.fmt2.iaddr); - addr += sizeof(fp->un.fmt2); - break; + printk("instr addr=%08lx\n", fp->un.fmt2.iaddr); + addr += sizeof(fp->un.fmt2); + break; case 0x3: - printk("eff addr=%08lx\n", fp->un.fmt3.effaddr); - addr += sizeof(fp->un.fmt3); - break; + printk("eff addr=%08lx\n", fp->un.fmt3.effaddr); + addr += sizeof(fp->un.fmt3); + break; case 0x4: - printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n" - : "eff addr=%08lx pc=%08lx\n"), - fp->un.fmt4.effaddr, fp->un.fmt4.pc); - addr += sizeof(fp->un.fmt4); - break; + printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n" + : "eff addr=%08lx pc=%08lx\n"), + fp->un.fmt4.effaddr, fp->un.fmt4.pc); + addr += sizeof(fp->un.fmt4); + break; case 0x7: - printk("eff addr=%08lx ssw=%04x faddr=%08lx\n", - fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr); - printk("wb 1 stat/addr/data: %04x %08lx %08lx\n", - fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0); - printk("wb 2 stat/addr/data: %04x %08lx %08lx\n", - fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d); - printk("wb 3 stat/addr/data: %04x %08lx %08lx\n", - fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d); - printk("push data: %08lx %08lx %08lx %08lx\n", - fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2, - fp->un.fmt7.pd3); - addr += sizeof(fp->un.fmt7); - break; + printk("eff addr=%08lx ssw=%04x faddr=%08lx\n", + fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr); + printk("wb 1 stat/addr/data: %04x %08lx %08lx\n", + fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0); + printk("wb 2 stat/addr/data: %04x %08lx %08lx\n", + fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d); + printk("wb 3 stat/addr/data: %04x %08lx %08lx\n", + fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d); + printk("push data: %08lx %08lx %08lx %08lx\n", + fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2, + fp->un.fmt7.pd3); + addr += sizeof(fp->un.fmt7); + break; case 0x9: - printk("instr addr=%08lx\n", fp->un.fmt9.iaddr); - addr += sizeof(fp->un.fmt9); - break; + printk("instr addr=%08lx\n", fp->un.fmt9.iaddr); + addr += sizeof(fp->un.fmt9); + break; case 0xa: - printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", - fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb, - fp->un.fmta.daddr, fp->un.fmta.dobuf); - addr += sizeof(fp->un.fmta); - break; + printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", + fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb, + fp->un.fmta.daddr, fp->un.fmta.dobuf); + addr += sizeof(fp->un.fmta); + break; case 0xb: - printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", - fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb, - fp->un.fmtb.daddr, fp->un.fmtb.dobuf); - printk("baddr=%08lx dibuf=%08lx ver=%x\n", - fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver); - addr += sizeof(fp->un.fmtb); - break; + printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", + fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb, + fp->un.fmtb.daddr, fp->un.fmtb.dobuf); + printk("baddr=%08lx dibuf=%08lx ver=%x\n", + fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver); + addr += sizeof(fp->un.fmtb); + break; default: - printk("\n"); + printk("\n"); } show_stack(NULL, (unsigned long *)addr); - printk("Code: "); - for (i = 0; i < 10; i++) - printk("%04x ", 0xffff & ((short *) fp->ptregs.pc)[i]); + printk("Code:"); + set_fs(KERNEL_DS); + cp = (u16 *)regs->pc; + for (i = -8; i < 16; i++) { + if (get_user(c, cp + i) && i >= 0) { + printk(" Bad PC value."); + break; + } + printk(i ? " %04x" : " <%04x>", c); + } + set_fs(old_fs); printk ("\n"); } void show_stack(struct task_struct *task, unsigned long *stack) { + unsigned long *p; unsigned long *endstack; int i; @@ -1004,12 +985,13 @@ void show_stack(struct task_struct *task, unsigned long *stack) endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE); printk("Stack from %08lx:", (unsigned long)stack); + p = stack; for (i = 0; i < kstack_depth_to_print; i++) { - if (stack + 1 > endstack) + if (p + 1 > endstack) break; if (i % 8 == 0) printk("\n "); - printk(" %08lx", *stack++); + printk(" %08lx", *p++); } printk("\n"); show_trace(stack); @@ -1188,19 +1170,7 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr) console_verbose(); printk("%s: %08x\n",str,nr); - print_modules(); - printk("PC: [<%08lx>]",fp->pc); - print_symbol(" %s\n", fp->pc); - printk("\nSR: %04x SP: %p a2: %08lx\n", - fp->sr, fp, fp->a2); - printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", - fp->d0, fp->d1, fp->d2, fp->d3); - printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", - fp->d4, fp->d5, fp->a0, fp->a1); - - printk("Process %s (pid: %d, stackpage=%08lx)\n", - current->comm, current->pid, PAGE_SIZE+(unsigned long)current); - show_stack(NULL, (unsigned long *)fp); + show_registers(fp); do_exit(SIGSEGV); } |