diff options
Diffstat (limited to 'arch/frv')
-rw-r--r-- | arch/frv/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/frv/kernel/asm-offsets.c | 9 | ||||
-rw-r--r-- | arch/frv/kernel/frv_ksyms.c | 1 | ||||
-rw-r--r-- | arch/frv/kernel/pm.c | 8 | ||||
-rw-r--r-- | arch/frv/kernel/semaphore.c | 155 | ||||
-rw-r--r-- | arch/frv/kernel/signal.c | 4 | ||||
-rw-r--r-- | arch/frv/kernel/traps.c | 38 | ||||
-rw-r--r-- | arch/frv/mb93090-mb00/pci-frv.h | 2 | ||||
-rw-r--r-- | arch/frv/mb93090-mb00/pci-iomap.c | 4 | ||||
-rw-r--r-- | arch/frv/mb93090-mb00/pci-vdk.c | 53 | ||||
-rw-r--r-- | arch/frv/mm/Makefile | 2 | ||||
-rw-r--r-- | arch/frv/mm/highmem.c | 3 | ||||
-rw-r--r-- | arch/frv/mm/unaligned.c | 217 |
13 files changed, 25 insertions, 473 deletions
diff --git a/arch/frv/kernel/Makefile b/arch/frv/kernel/Makefile index e8f73ed28b5..c36f70b6699 100644 --- a/arch/frv/kernel/Makefile +++ b/arch/frv/kernel/Makefile @@ -9,7 +9,7 @@ extra-y:= head.o init_task.o vmlinux.lds obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o kernel_thread.o \ kernel_execve.o process.o traps.o ptrace.o signal.o dma.o \ - sys_frv.o time.o semaphore.o setup.o frv_ksyms.o \ + sys_frv.o time.o setup.o frv_ksyms.o \ debug-stub.o irq.o sleep.o uaccess.o obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-io.o diff --git a/arch/frv/kernel/asm-offsets.c b/arch/frv/kernel/asm-offsets.c index fbb19fc1af4..9de96843a27 100644 --- a/arch/frv/kernel/asm-offsets.c +++ b/arch/frv/kernel/asm-offsets.c @@ -7,15 +7,13 @@ #include <linux/sched.h> #include <linux/signal.h> #include <linux/personality.h> +#include <linux/kbuild.h> #include <asm/registers.h> #include <asm/ucontext.h> #include <asm/processor.h> #include <asm/thread_info.h> #include <asm/gdb-stub.h> -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - #define DEF_PTREG(sym, reg) \ asm volatile("\n->" #sym " %0 offsetof(struct pt_regs, " #reg ")" \ : : "i" (offsetof(struct pt_regs, reg))) @@ -32,11 +30,6 @@ asm volatile("\n->" #sym " %0 offsetof(struct frv_frame0, " #reg ")" \ : : "i" (offsetof(struct frv_frame0, reg))) -#define BLANK() asm volatile("\n->" : : ) - -#define OFFSET(sym, str, mem) \ - DEFINE(sym, offsetof(struct str, mem)); - void foo(void) { /* offsets into the thread_info structure */ diff --git a/arch/frv/kernel/frv_ksyms.c b/arch/frv/kernel/frv_ksyms.c index f772704b3d2..0316b3c50ef 100644 --- a/arch/frv/kernel/frv_ksyms.c +++ b/arch/frv/kernel/frv_ksyms.c @@ -12,7 +12,6 @@ #include <asm/pgalloc.h> #include <asm/irq.h> #include <asm/io.h> -#include <asm/semaphore.h> #include <asm/checksum.h> #include <asm/hardirq.h> #include <asm/cacheflush.h> diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c index c57ce3f1f2e..73f3aeefd20 100644 --- a/arch/frv/kernel/pm.c +++ b/arch/frv/kernel/pm.c @@ -163,14 +163,11 @@ static int sysctl_pm_do_suspend(ctl_table *ctl, int write, struct file *filp, if ((mode != 1) && (mode != 5)) return -EINVAL; - retval = pm_send_all(PM_SUSPEND, (void *)3); - if (retval == 0) { if (mode == 5) retval = pm_do_bus_sleep(); else retval = pm_do_suspend(); - pm_send_all(PM_RESUME, (void *)0); } return retval; @@ -183,9 +180,6 @@ static int try_set_cmode(int new_cmode) if (!(clock_cmodes_permitted & (1<<new_cmode))) return -EINVAL; - /* tell all the drivers we're suspending */ - pm_send_all(PM_SUSPEND, (void *)3); - /* now change cmode */ local_irq_disable(); frv_dma_pause_all(); @@ -201,8 +195,6 @@ static int try_set_cmode(int new_cmode) frv_dma_resume_all(); local_irq_enable(); - /* tell all the drivers we're resuming */ - pm_send_all(PM_RESUME, (void *)0); return 0; } diff --git a/arch/frv/kernel/semaphore.c b/arch/frv/kernel/semaphore.c deleted file mode 100644 index 7ee3a147b47..00000000000 --- a/arch/frv/kernel/semaphore.c +++ /dev/null @@ -1,155 +0,0 @@ -/* semaphore.c: FR-V semaphores - * - * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - Derived from lib/rwsem-spinlock.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include <linux/sched.h> -#include <linux/module.h> -#include <asm/semaphore.h> - -struct sem_waiter { - struct list_head list; - struct task_struct *task; -}; - -#ifdef CONFIG_DEBUG_SEMAPHORE -void semtrace(struct semaphore *sem, const char *str) -{ - if (sem->debug) - printk("[%d] %s({%d,%d})\n", - current->pid, - str, - sem->counter, - list_empty(&sem->wait_list) ? 0 : 1); -} -#else -#define semtrace(SEM,STR) do { } while(0) -#endif - -/* - * wait for a token to be granted from a semaphore - * - entered with lock held and interrupts disabled - */ -void __down(struct semaphore *sem, unsigned long flags) -{ - struct task_struct *tsk = current; - struct sem_waiter waiter; - - semtrace(sem, "Entering __down"); - - /* set up my own style of waitqueue */ - waiter.task = tsk; - get_task_struct(tsk); - - list_add_tail(&waiter.list, &sem->wait_list); - - /* we don't need to touch the semaphore struct anymore */ - spin_unlock_irqrestore(&sem->wait_lock, flags); - - /* wait to be given the semaphore */ - set_task_state(tsk, TASK_UNINTERRUPTIBLE); - - for (;;) { - if (list_empty(&waiter.list)) - break; - schedule(); - set_task_state(tsk, TASK_UNINTERRUPTIBLE); - } - - tsk->state = TASK_RUNNING; - semtrace(sem, "Leaving __down"); -} - -EXPORT_SYMBOL(__down); - -/* - * interruptibly wait for a token to be granted from a semaphore - * - entered with lock held and interrupts disabled - */ -int __down_interruptible(struct semaphore *sem, unsigned long flags) -{ - struct task_struct *tsk = current; - struct sem_waiter waiter; - int ret; - - semtrace(sem,"Entering __down_interruptible"); - - /* set up my own style of waitqueue */ - waiter.task = tsk; - get_task_struct(tsk); - - list_add_tail(&waiter.list, &sem->wait_list); - - /* we don't need to touch the semaphore struct anymore */ - set_task_state(tsk, TASK_INTERRUPTIBLE); - - spin_unlock_irqrestore(&sem->wait_lock, flags); - - /* wait to be given the semaphore */ - ret = 0; - for (;;) { - if (list_empty(&waiter.list)) - break; - if (unlikely(signal_pending(current))) - goto interrupted; - schedule(); - set_task_state(tsk, TASK_INTERRUPTIBLE); - } - - out: - tsk->state = TASK_RUNNING; - semtrace(sem, "Leaving __down_interruptible"); - return ret; - - interrupted: - spin_lock_irqsave(&sem->wait_lock, flags); - - if (!list_empty(&waiter.list)) { - list_del(&waiter.list); - ret = -EINTR; - } - - spin_unlock_irqrestore(&sem->wait_lock, flags); - if (ret == -EINTR) - put_task_struct(current); - goto out; -} - -EXPORT_SYMBOL(__down_interruptible); - -/* - * release a single token back to a semaphore - * - entered with lock held and interrupts disabled - */ -void __up(struct semaphore *sem) -{ - struct task_struct *tsk; - struct sem_waiter *waiter; - - semtrace(sem,"Entering __up"); - - /* grant the token to the process at the front of the queue */ - waiter = list_entry(sem->wait_list.next, struct sem_waiter, list); - - /* We must be careful not to touch 'waiter' after we set ->task = NULL. - * It is allocated on the waiter's stack and may become invalid at - * any time after that point (due to a wakeup from another source). - */ - list_del_init(&waiter->list); - tsk = waiter->task; - mb(); - waiter->task = NULL; - wake_up_process(tsk); - put_task_struct(tsk); - - semtrace(sem,"Leaving __up"); -} - -EXPORT_SYMBOL(__up); diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index d64bcaff54c..3bdb368292a 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c @@ -297,7 +297,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) __frame->lr = (unsigned long) &frame->retcode; __frame->gr8 = sig; - if (get_personality & FDPIC_FUNCPTRS) { + if (current->personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; __get_user(__frame->pc, &funcptr->text); @@ -396,7 +396,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, __frame->gr8 = sig; __frame->gr9 = (unsigned long) &frame->info; - if (get_personality & FDPIC_FUNCPTRS) { + if (current->personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; __get_user(__frame->pc, &funcptr->text); diff --git a/arch/frv/kernel/traps.c b/arch/frv/kernel/traps.c index 7089c2428b3..1d2dfe67d44 100644 --- a/arch/frv/kernel/traps.c +++ b/arch/frv/kernel/traps.c @@ -49,7 +49,7 @@ asmlinkage void insn_access_error(unsigned long esfr1, unsigned long epcr0, unsi info.si_signo = SIGSEGV; info.si_code = SEGV_ACCERR; info.si_errno = 0; - info.si_addr = (void *) ((epcr0 & EPCR0_V) ? (epcr0 & EPCR0_PC) : __frame->pc); + info.si_addr = (void __user *) ((epcr0 & EPCR0_V) ? (epcr0 & EPCR0_PC) : __frame->pc); force_sig_info(info.si_signo, &info, current); } /* end insn_access_error() */ @@ -73,7 +73,7 @@ asmlinkage void illegal_instruction(unsigned long esfr1, unsigned long epcr0, un epcr0, esr0, esfr1); info.si_errno = 0; - info.si_addr = (void *) ((epcr0 & EPCR0_V) ? (epcr0 & EPCR0_PC) : __frame->pc); + info.si_addr = (void __user *) ((epcr0 & EPCR0_V) ? (epcr0 & EPCR0_PC) : __frame->pc); switch (__frame->tbr & TBR_TT) { case TBR_TT_ILLEGAL_INSTR: @@ -111,7 +111,8 @@ asmlinkage void atomic_operation(unsigned long esfr1, unsigned long epcr0, unsigned long esr0) { static DEFINE_SPINLOCK(atomic_op_lock); - unsigned long x, y, z, *p; + unsigned long x, y, z; + unsigned long __user *p; mm_segment_t oldfs; siginfo_t info; int ret; @@ -128,7 +129,7 @@ asmlinkage void atomic_operation(unsigned long esfr1, unsigned long epcr0, * u32 __atomic_user_cmpxchg32(u32 *ptr, u32 test, u32 new) */ case TBR_TT_ATOMIC_CMPXCHG32: - p = (unsigned long *) __frame->gr8; + p = (unsigned long __user *) __frame->gr8; x = __frame->gr9; y = __frame->gr10; @@ -158,7 +159,7 @@ asmlinkage void atomic_operation(unsigned long esfr1, unsigned long epcr0, * u32 __atomic_kernel_xchg32(void *v, u32 new) */ case TBR_TT_ATOMIC_XCHG32: - p = (unsigned long *) __frame->gr8; + p = (unsigned long __user *) __frame->gr8; y = __frame->gr9; for (;;) { @@ -181,7 +182,7 @@ asmlinkage void atomic_operation(unsigned long esfr1, unsigned long epcr0, * ulong __atomic_kernel_XOR_return(ulong i, ulong *v) */ case TBR_TT_ATOMIC_XOR: - p = (unsigned long *) __frame->gr8; + p = (unsigned long __user *) __frame->gr8; x = __frame->gr9; for (;;) { @@ -205,7 +206,7 @@ asmlinkage void atomic_operation(unsigned long esfr1, unsigned long epcr0, * ulong __atomic_kernel_OR_return(ulong i, ulong *v) */ case TBR_TT_ATOMIC_OR: - p = (unsigned long *) __frame->gr8; + p = (unsigned long __user *) __frame->gr8; x = __frame->gr9; for (;;) { @@ -229,7 +230,7 @@ asmlinkage void atomic_operation(unsigned long esfr1, unsigned long epcr0, * ulong __atomic_kernel_AND_return(ulong i, ulong *v) */ case TBR_TT_ATOMIC_AND: - p = (unsigned long *) __frame->gr8; + p = (unsigned long __user *) __frame->gr8; x = __frame->gr9; for (;;) { @@ -253,7 +254,7 @@ asmlinkage void atomic_operation(unsigned long esfr1, unsigned long epcr0, * int __atomic_user_sub_return(atomic_t *v, int i) */ case TBR_TT_ATOMIC_SUB: - p = (unsigned long *) __frame->gr8; + p = (unsigned long __user *) __frame->gr8; x = __frame->gr9; for (;;) { @@ -277,7 +278,7 @@ asmlinkage void atomic_operation(unsigned long esfr1, unsigned long epcr0, * int __atomic_user_add_return(atomic_t *v, int i) */ case TBR_TT_ATOMIC_ADD: - p = (unsigned long *) __frame->gr8; + p = (unsigned long __user *) __frame->gr8; x = __frame->gr9; for (;;) { @@ -322,7 +323,7 @@ error: info.si_signo = SIGSEGV; info.si_code = SEGV_ACCERR; info.si_errno = 0; - info.si_addr = (void *) __frame->pc; + info.si_addr = (void __user *) __frame->pc; force_sig_info(info.si_signo, &info, current); } @@ -343,7 +344,7 @@ asmlinkage void media_exception(unsigned long msr0, unsigned long msr1) info.si_signo = SIGFPE; info.si_code = FPE_MDAOVF; info.si_errno = 0; - info.si_addr = (void *) __frame->pc; + info.si_addr = (void __user *) __frame->pc; force_sig_info(info.si_signo, &info, current); } /* end media_exception() */ @@ -361,11 +362,8 @@ asmlinkage void memory_access_exception(unsigned long esr0, #ifdef CONFIG_MMU unsigned long fixup; - if ((esr0 & ESRx_EC) == ESRx_EC_DATA_ACCESS) - if (handle_misalignment(esr0, ear0, epcr0) == 0) - return; - - if ((fixup = search_exception_table(__frame->pc)) != 0) { + fixup = search_exception_table(__frame->pc); + if (fixup) { __frame->pc = fixup; return; } @@ -383,7 +381,7 @@ asmlinkage void memory_access_exception(unsigned long esr0, info.si_addr = NULL; if ((esr0 & (ESRx_VALID | ESR0_EAV)) == (ESRx_VALID | ESR0_EAV)) - info.si_addr = (void *) ear0; + info.si_addr = (void __user *) ear0; force_sig_info(info.si_signo, &info, current); @@ -412,7 +410,7 @@ asmlinkage void data_access_error(unsigned long esfr1, unsigned long esr15, unsi info.si_signo = SIGSEGV; info.si_code = SEGV_ACCERR; info.si_errno = 0; - info.si_addr = (void *) + info.si_addr = (void __user *) (((esr15 & (ESRx_VALID|ESR15_EAV)) == (ESRx_VALID|ESR15_EAV)) ? ear15 : 0); force_sig_info(info.si_signo, &info, current); @@ -446,7 +444,7 @@ asmlinkage void division_exception(unsigned long esfr1, unsigned long esr0, unsi info.si_signo = SIGFPE; info.si_code = FPE_INTDIV; info.si_errno = 0; - info.si_addr = (void *) __frame->pc; + info.si_addr = (void __user *) __frame->pc; force_sig_info(info.si_signo, &info, current); } /* end division_exception() */ diff --git a/arch/frv/mb93090-mb00/pci-frv.h b/arch/frv/mb93090-mb00/pci-frv.h index 7481797ab38..0c7bf39dc72 100644 --- a/arch/frv/mb93090-mb00/pci-frv.h +++ b/arch/frv/mb93090-mb00/pci-frv.h @@ -17,8 +17,6 @@ #define PCI_PROBE_BIOS 0x0001 #define PCI_PROBE_CONF1 0x0002 #define PCI_PROBE_CONF2 0x0004 -#define PCI_NO_SORT 0x0100 -#define PCI_BIOS_SORT 0x0200 #define PCI_NO_CHECKS 0x0400 #define PCI_ASSIGN_ROMS 0x1000 #define PCI_BIOS_IRQ_SCAN 0x2000 diff --git a/arch/frv/mb93090-mb00/pci-iomap.c b/arch/frv/mb93090-mb00/pci-iomap.c index 068fa04bd52..35f6df28351 100644 --- a/arch/frv/mb93090-mb00/pci-iomap.c +++ b/arch/frv/mb93090-mb00/pci-iomap.c @@ -13,8 +13,8 @@ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) { - unsigned long start = pci_resource_start(dev, bar); - unsigned long len = pci_resource_len(dev, bar); + resource_size_t start = pci_resource_start(dev, bar); + resource_size_t len = pci_resource_len(dev, bar); unsigned long flags = pci_resource_flags(dev, bar); if (!len || !start) diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c index 6d51f133fb2..f003cfa68b7 100644 --- a/arch/frv/mb93090-mb00/pci-vdk.c +++ b/arch/frv/mb93090-mb00/pci-vdk.c @@ -199,58 +199,6 @@ static struct pci_ops * __init pci_check_direct(void) } /* - * Several buggy motherboards address only 16 devices and mirror - * them to next 16 IDs. We try to detect this `feature' on all - * primary buses (those containing host bridges as they are - * expected to be unique) and remove the ghost devices. - */ - -static void __init pcibios_fixup_ghosts(struct pci_bus *b) -{ - struct list_head *ln, *mn; - struct pci_dev *d, *e; - int mirror = PCI_DEVFN(16,0); - int seen_host_bridge = 0; - int i; - - for (ln=b->devices.next; ln != &b->devices; ln=ln->next) { - d = pci_dev_b(ln); - if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST) - seen_host_bridge++; - for (mn=ln->next; mn != &b->devices; mn=mn->next) { - e = pci_dev_b(mn); - if (e->devfn != d->devfn + mirror || - e->vendor != d->vendor || - e->device != d->device || - e->class != d->class) - continue; - for(i=0; i<PCI_NUM_RESOURCES; i++) - if (e->resource[i].start != d->resource[i].start || - e->resource[i].end != d->resource[i].end || - e->resource[i].flags != d->resource[i].flags) - continue; - break; - } - if (mn == &b->devices) - return; - } - if (!seen_host_bridge) - return; - printk("PCI: Ignoring ghost devices on bus %02x\n", b->number); - - ln = &b->devices; - while (ln->next != &b->devices) { - d = pci_dev_b(ln->next); - if (d->devfn >= mirror) { - list_del(&d->global_list); - list_del(&d->bus_list); - kfree(d); - } else - ln = ln->next; - } -} - -/* * Discover remaining PCI buses in case there are peer host bridges. * We use the number of last PCI bus provided by the PCI BIOS. */ @@ -356,7 +304,6 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) #if 0 printk("### PCIBIOS_FIXUP_BUS(%d)\n",bus->number); #endif - pcibios_fixup_ghosts(bus); pci_read_bridge_bases(bus); if (bus->number == 0) { diff --git a/arch/frv/mm/Makefile b/arch/frv/mm/Makefile index fb8b1d860f4..1bca5ab8a6a 100644 --- a/arch/frv/mm/Makefile +++ b/arch/frv/mm/Makefile @@ -6,4 +6,4 @@ obj-y := init.o kmap.o obj-$(CONFIG_MMU) += \ pgalloc.o highmem.o fault.o extable.o cache-page.o tlb-flush.o tlb-miss.o \ - mmu-context.o dma-alloc.o unaligned.o elf-fdpic.o + mmu-context.o dma-alloc.o elf-fdpic.o diff --git a/arch/frv/mm/highmem.c b/arch/frv/mm/highmem.c index 7f77db7fabc..eadd0765807 100644 --- a/arch/frv/mm/highmem.c +++ b/arch/frv/mm/highmem.c @@ -36,6 +36,3 @@ struct page *kmap_atomic_to_page(void *ptr) { return virt_to_page(ptr); } - - -EXPORT_SYMBOL(kmap_atomic_to_page); diff --git a/arch/frv/mm/unaligned.c b/arch/frv/mm/unaligned.c deleted file mode 100644 index 8f0375fc15a..00000000000 --- a/arch/frv/mm/unaligned.c +++ /dev/null @@ -1,217 +0,0 @@ -/* unaligned.c: unalignment fixup handler for CPUs on which it is supported (FR451 only) - * - * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include <linux/sched.h> -#include <linux/signal.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/types.h> -#include <linux/user.h> -#include <linux/string.h> -#include <linux/linkage.h> -#include <linux/init.h> - -#include <asm/setup.h> -#include <asm/system.h> -#include <asm/uaccess.h> - -#if 0 -#define kdebug(fmt, ...) printk("FDPIC "fmt"\n" ,##__VA_ARGS__ ) -#else -#define kdebug(fmt, ...) do {} while(0) -#endif - -#define _MA_SIGNED 0x01 -#define _MA_HALF 0x02 -#define _MA_WORD 0x04 -#define _MA_DWORD 0x08 -#define _MA_SZ_MASK 0x0e -#define _MA_LOAD 0x10 -#define _MA_STORE 0x20 -#define _MA_UPDATE 0x40 -#define _MA_IMM 0x80 - -#define _MA_LDxU _MA_LOAD | _MA_UPDATE -#define _MA_LDxI _MA_LOAD | _MA_IMM -#define _MA_STxU _MA_STORE | _MA_UPDATE -#define _MA_STxI _MA_STORE | _MA_IMM - -static const uint8_t tbl_LDGRk_reg[0x40] = { - [0x02] = _MA_LOAD | _MA_HALF | _MA_SIGNED, /* LDSH @(GRi,GRj),GRk */ - [0x03] = _MA_LOAD | _MA_HALF, /* LDUH @(GRi,GRj),GRk */ - [0x04] = _MA_LOAD | _MA_WORD, /* LD @(GRi,GRj),GRk */ - [0x05] = _MA_LOAD | _MA_DWORD, /* LDD @(GRi,GRj),GRk */ - [0x12] = _MA_LDxU | _MA_HALF | _MA_SIGNED, /* LDSHU @(GRi,GRj),GRk */ - [0x13] = _MA_LDxU | _MA_HALF, /* LDUHU @(GRi,GRj),GRk */ - [0x14] = _MA_LDxU | _MA_WORD, /* LDU @(GRi,GRj),GRk */ - [0x15] = _MA_LDxU | _MA_DWORD, /* LDDU @(GRi,GRj),GRk */ -}; - -static const uint8_t tbl_STGRk_reg[0x40] = { - [0x01] = _MA_STORE | _MA_HALF, /* STH @(GRi,GRj),GRk */ - [0x02] = _MA_STORE | _MA_WORD, /* ST @(GRi,GRj),GRk */ - [0x03] = _MA_STORE | _MA_DWORD, /* STD @(GRi,GRj),GRk */ - [0x11] = _MA_STxU | _MA_HALF, /* STHU @(GRi,GRj),GRk */ - [0x12] = _MA_STxU | _MA_WORD, /* STU @(GRi,GRj),GRk */ - [0x13] = _MA_STxU | _MA_DWORD, /* STDU @(GRi,GRj),GRk */ -}; - -static const uint8_t tbl_LDSTGRk_imm[0x80] = { - [0x31] = _MA_LDxI | _MA_HALF | _MA_SIGNED, /* LDSHI @(GRi,d12),GRk */ - [0x32] = _MA_LDxI | _MA_WORD, /* LDI @(GRi,d12),GRk */ - [0x33] = _MA_LDxI | _MA_DWORD, /* LDDI @(GRi,d12),GRk */ - [0x36] = _MA_LDxI | _MA_HALF, /* LDUHI @(GRi,d12),GRk */ - [0x51] = _MA_STxI | _MA_HALF, /* STHI @(GRi,d12),GRk */ - [0x52] = _MA_STxI | _MA_WORD, /* STI @(GRi,d12),GRk */ - [0x53] = _MA_STxI | _MA_DWORD, /* STDI @(GRi,d12),GRk */ -}; - - -/*****************************************************************************/ -/* - * see if we can handle the exception by fixing up a misaligned memory access - */ -int handle_misalignment(unsigned long esr0, unsigned long ear0, unsigned long epcr0) -{ - unsigned long insn, addr, *greg; - int GRi, GRj, GRk, D12, op; - - union { - uint64_t _64; - uint32_t _32[2]; - uint16_t _16; - uint8_t _8[8]; - } x; - - if (!(esr0 & ESR0_EAV) || !(epcr0 & EPCR0_V) || !(ear0 & 7)) - return -EAGAIN; - - epcr0 &= EPCR0_PC; - - if (__frame->pc != epcr0) { - kdebug("MISALIGN: Execution not halted on excepting instruction\n"); - BUG(); - } - - if (__get_user(insn, (unsigned long *) epcr0) < 0) - return -EFAULT; - - /* determine the instruction type first */ - switch ((insn >> 18) & 0x7f) { - case 0x2: - /* LDx @(GRi,GRj),GRk */ - op = tbl_LDGRk_reg[(insn >> 6) & 0x3f]; - break; - - case 0x3: - /* STx GRk,@(GRi,GRj) */ - op = tbl_STGRk_reg[(insn >> 6) & 0x3f]; - break; - - default: - op = tbl_LDSTGRk_imm[(insn >> 18) & 0x7f]; - break; - } - - if (!op) - return -EAGAIN; - - kdebug("MISALIGN: pc=%08lx insn=%08lx ad=%08lx op=%02x\n", epcr0, insn, ear0, op); - - memset(&x, 0xba, 8); - - /* validate the instruction parameters */ - greg = (unsigned long *) &__frame->tbr; - - GRi = (insn >> 12) & 0x3f; - GRk = (insn >> 25) & 0x3f; - - if (GRi > 31 || GRk > 31) - return -ENOENT; - - if (op & _MA_DWORD && GRk & 1) - return -EINVAL; - - if (op & _MA_IMM) { - D12 = insn & 0xfff; - asm ("slli %0,#20,%0 ! srai %0,#20,%0" : "=r"(D12) : "0"(D12)); /* sign extend */ - addr = (GRi ? greg[GRi] : 0) + D12; - } - else { - GRj = (insn >> 0) & 0x3f; - if (GRj > 31) - return -ENOENT; - addr = (GRi ? greg[GRi] : 0) + (GRj ? greg[GRj] : 0); - } - - if (addr != ear0) { - kdebug("MISALIGN: Calculated addr (%08lx) does not match EAR0 (%08lx)\n", - addr, ear0); - return -EFAULT; - } - - /* check the address is okay */ - if (user_mode(__frame) && ___range_ok(ear0, 8) < 0) - return -EFAULT; - - /* perform the memory op */ - if (op & _MA_STORE) { - /* perform a store */ - x._32[0] = 0; - if (GRk != 0) { - if (op & _MA_HALF) { - x._16 = greg[GRk]; - } - else { - x._32[0] = greg[GRk]; - } - } - if (op & _MA_DWORD) - x._32[1] = greg[GRk + 1]; - - kdebug("MISALIGN: Store GR%d { %08x:%08x } -> %08lx (%dB)\n", - GRk, x._32[1], x._32[0], addr, op & _MA_SZ_MASK); - - if (__memcpy_user((void *) addr, &x, op & _MA_SZ_MASK) != 0) - return -EFAULT; - } - else { - /* perform a load */ - if (__memcpy_user(&x, (void *) addr, op & _MA_SZ_MASK) != 0) - return -EFAULT; - - if (op & _MA_HALF) { - if (op & _MA_SIGNED) - asm ("slli %0,#16,%0 ! srai %0,#16,%0" - : "=r"(x._32[0]) : "0"(x._16)); - else - asm ("sethi #0,%0" - : "=r"(x._32[0]) : "0"(x._16)); - } - - kdebug("MISALIGN: Load %08lx (%dB) -> GR%d, { %08x:%08x }\n", - addr, op & _MA_SZ_MASK, GRk, x._32[1], x._32[0]); - - if (GRk != 0) - greg[GRk] = x._32[0]; - if (op & _MA_DWORD) - greg[GRk + 1] = x._32[1]; - } - - /* update the base pointer if required */ - if (op & _MA_UPDATE) - greg[GRi] = addr; - - /* well... we've done that insn */ - __frame->pc = __frame->pc + 4; - - return 0; -} /* end handle_misalignment() */ |