From e7a7472e5f157197ba895b97d2515384e29c443a Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 29 Apr 2005 22:46:40 +0100 Subject: [PATCH] --- yaml --- r: 606 b: refs/heads/master c: 587897f51fac04988de497a553215fdf41e6d5f6 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/arch/arm/configs/ixdp2800_defconfig | 2 +- trunk/arch/arm/kernel/entry-armv.S | 213 +----------------- trunk/arch/arm/kernel/traps.c | 58 +---- trunk/arch/arm/mach-ixp2000/ixdp2800.c | 147 ++---------- trunk/arch/arm/mach-ixp2000/pci.c | 8 +- trunk/arch/arm/mm/Kconfig | 14 -- trunk/arch/arm/mm/abort-ev6.S | 16 -- trunk/arch/arm/mm/mm-armv.c | 5 +- trunk/arch/i386/kernel/entry.S | 8 +- trunk/arch/i386/kernel/traps.c | 1 - trunk/drivers/cpufreq/cpufreq.c | 94 +------- trunk/drivers/serial/imx.c | 68 +++++- trunk/include/asm-arm/arch-ixp2000/platform.h | 1 - trunk/include/asm-arm/io.h | 28 +-- trunk/include/asm-arm/unistd.h | 3 +- trunk/include/linux/cpufreq.h | 5 +- trunk/kernel/exit.c | 2 + 18 files changed, 115 insertions(+), 560 deletions(-) diff --git a/[refs] b/[refs] index c779539891d2..4d2af8b8fb22 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: dd96a8e056e7b3e480197ff2cdf106b46455d779 +refs/heads/master: 587897f51fac04988de497a553215fdf41e6d5f6 diff --git a/trunk/arch/arm/configs/ixdp2800_defconfig b/trunk/arch/arm/configs/ixdp2800_defconfig index 7be3521f91fc..d36f99192962 100644 --- a/trunk/arch/arm/configs/ixdp2800_defconfig +++ b/trunk/arch/arm/configs/ixdp2800_defconfig @@ -133,7 +133,7 @@ CONFIG_ALIGNMENT_TRAP=y # CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="console=ttyS0,9600 root=/dev/nfs ip=bootp mem=64M@0x0" +CONFIG_CMDLINE="console=ttyS0,9600 root=/dev/nfs ip=bootp mem=64M@0x0 pci=firmware" # CONFIG_XIP_KERNEL is not set # diff --git a/trunk/arch/arm/kernel/entry-armv.S b/trunk/arch/arm/kernel/entry-armv.S index 080df907f242..2a5c3fe09a95 100644 --- a/trunk/arch/arm/kernel/entry-armv.S +++ b/trunk/arch/arm/kernel/entry-armv.S @@ -269,12 +269,6 @@ __pabt_svc: add r5, sp, #S_PC ldmia r7, {r2 - r4} @ Get USR pc, cpsr -#if __LINUX_ARM_ARCH__ < 6 - @ make sure our user space atomic helper is aborted - cmp r2, #VIRT_OFFSET - bichs r3, r3, #PSR_Z_BIT -#endif - @ @ We are now ready to fill in the remaining blanks on the stack: @ @@ -505,12 +499,8 @@ ENTRY(__switch_to) mra r4, r5, acc0 stmia ip, {r4, r5} #endif -#ifdef CONFIG_HAS_TLS_REG - mcr p15, 0, r3, c13, c0, 3 @ set TLS register -#else mov r4, #0xffff0fff - str r3, [r4, #-15] @ TLS val at 0xffff0ff0 -#endif + str r3, [r4, #-3] @ Set TLS ptr mcr p15, 0, r6, c3, c0, 0 @ Set domain register #ifdef CONFIG_VFP @ Always disable VFP so we can lazily save/restore the old @@ -529,207 +519,6 @@ ENTRY(__switch_to) ldmib r2, {r4 - sl, fp, sp, pc} @ Load all regs saved previously __INIT - -/* - * User helpers. - * - * These are segment of kernel provided user code reachable from user space - * at a fixed address in kernel memory. This is used to provide user space - * with some operations which require kernel help because of unimplemented - * native feature and/or instructions in many ARM CPUs. The idea is for - * this code to be executed directly in user mode for best efficiency but - * which is too intimate with the kernel counter part to be left to user - * libraries. In fact this code might even differ from one CPU to another - * depending on the available instruction set and restrictions like on - * SMP systems. In other words, the kernel reserves the right to change - * this code as needed without warning. Only the entry points and their - * results are guaranteed to be stable. - * - * Each segment is 32-byte aligned and will be moved to the top of the high - * vector page. New segments (if ever needed) must be added in front of - * existing ones. This mechanism should be used only for things that are - * really small and justified, and not be abused freely. - * - * User space is expected to implement those things inline when optimizing - * for a processor that has the necessary native support, but only if such - * resulting binaries are already to be incompatible with earlier ARM - * processors due to the use of unsupported instructions other than what - * is provided here. In other words don't make binaries unable to run on - * earlier processors just for the sake of not using these kernel helpers - * if your compiled code is not going to use the new instructions for other - * purpose. - */ - - .align 5 - .globl __kuser_helper_start -__kuser_helper_start: - -/* - * Reference prototype: - * - * int __kernel_cmpxchg(int oldval, int newval, int *ptr) - * - * Input: - * - * r0 = oldval - * r1 = newval - * r2 = ptr - * lr = return address - * - * Output: - * - * r0 = returned value (zero or non-zero) - * C flag = set if r0 == 0, clear if r0 != 0 - * - * Clobbered: - * - * r3, ip, flags - * - * Definition and user space usage example: - * - * typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr); - * #define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0) - * - * Atomically store newval in *ptr if *ptr is equal to oldval for user space. - * Return zero if *ptr was changed or non-zero if no exchange happened. - * The C flag is also set if *ptr was changed to allow for assembly - * optimization in the calling code. - * - * For example, a user space atomic_add implementation could look like this: - * - * #define atomic_add(ptr, val) \ - * ({ register unsigned int *__ptr asm("r2") = (ptr); \ - * register unsigned int __result asm("r1"); \ - * asm volatile ( \ - * "1: @ atomic_add\n\t" \ - * "ldr r0, [r2]\n\t" \ - * "mov r3, #0xffff0fff\n\t" \ - * "add lr, pc, #4\n\t" \ - * "add r1, r0, %2\n\t" \ - * "add pc, r3, #(0xffff0fc0 - 0xffff0fff)\n\t" \ - * "bcc 1b" \ - * : "=&r" (__result) \ - * : "r" (__ptr), "rIL" (val) \ - * : "r0","r3","ip","lr","cc","memory" ); \ - * __result; }) - */ - -__kuser_cmpxchg: @ 0xffff0fc0 - -#if __LINUX_ARM_ARCH__ < 6 - -#ifdef CONFIG_SMP /* sanity check */ -#error "CONFIG_SMP on a machine supporting pre-ARMv6 processors?" -#endif - - /* - * Theory of operation: - * - * We set the Z flag before loading oldval. If ever an exception - * occurs we can not be sure the loaded value will still be the same - * when the exception returns, therefore the user exception handler - * will clear the Z flag whenever the interrupted user code was - * actually from the kernel address space (see the usr_entry macro). - * - * The post-increment on the str is used to prevent a race with an - * exception happening just after the str instruction which would - * clear the Z flag although the exchange was done. - */ - teq ip, ip @ set Z flag - ldr ip, [r2] @ load current val - add r3, r2, #1 @ prepare store ptr - teqeq ip, r0 @ compare with oldval if still allowed - streq r1, [r3, #-1]! @ store newval if still allowed - subs r0, r2, r3 @ if r2 == r3 the str occured - mov pc, lr - -#else - - ldrex r3, [r2] - subs r3, r3, r0 - strexeq r3, r1, [r2] - rsbs r0, r3, #0 - mov pc, lr - -#endif - - .align 5 - -/* - * Reference prototype: - * - * int __kernel_get_tls(void) - * - * Input: - * - * lr = return address - * - * Output: - * - * r0 = TLS value - * - * Clobbered: - * - * the Z flag might be lost - * - * Definition and user space usage example: - * - * typedef int (__kernel_get_tls_t)(void); - * #define __kernel_get_tls (*(__kernel_get_tls_t *)0xffff0fe0) - * - * Get the TLS value as previously set via the __ARM_NR_set_tls syscall. - * - * This could be used as follows: - * - * #define __kernel_get_tls() \ - * ({ register unsigned int __val asm("r0"); \ - * asm( "mov r0, #0xffff0fff; mov lr, pc; sub pc, r0, #31" \ - * : "=r" (__val) : : "lr","cc" ); \ - * __val; }) - */ - -__kuser_get_tls: @ 0xffff0fe0 - -#ifndef CONFIG_HAS_TLS_REG - -#ifdef CONFIG_SMP /* sanity check */ -#error "CONFIG_SMP without CONFIG_HAS_TLS_REG is wrong" -#endif - - ldr r0, [pc, #(16 - 8)] @ TLS stored at 0xffff0ff0 - mov pc, lr - -#else - - mrc p15, 0, r0, c13, c0, 3 @ read TLS register - mov pc, lr - -#endif - - .rep 5 - .word 0 @ pad up to __kuser_helper_version - .endr - -/* - * Reference declaration: - * - * extern unsigned int __kernel_helper_version; - * - * Definition and user space usage example: - * - * #define __kernel_helper_version (*(unsigned int *)0xffff0ffc) - * - * User space may read this to determine the curent number of helpers - * available. - */ - -__kuser_helper_version: @ 0xffff0ffc - .word ((__kuser_helper_end - __kuser_helper_start) >> 5) - - .globl __kuser_helper_end -__kuser_helper_end: - - /* * Vector stubs. * diff --git a/trunk/arch/arm/kernel/traps.c b/trunk/arch/arm/kernel/traps.c index 3a001fe5540b..0078aeb85737 100644 --- a/trunk/arch/arm/kernel/traps.c +++ b/trunk/arch/arm/kernel/traps.c @@ -450,17 +450,13 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) case NR(set_tls): thread->tp_value = regs->ARM_r0; -#ifdef CONFIG_HAS_TLS_REG - asm ("mcr p15, 0, %0, c13, c0, 3" : : "r" (regs->ARM_r0) ); -#else /* - * User space must never try to access this directly. - * Expect your app to break eventually if you do so. - * The user helper at 0xffff0fe0 must be used instead. - * (see entry-armv.S for details) + * Our user accessible TLS ptr is located at 0xffff0ffc. + * On SMP read access to this address must raise a fault + * and be emulated from the data abort handler. + * m */ - *((unsigned int *)0xffff0ff0) = regs->ARM_r0; -#endif + *((unsigned long *)0xffff0ffc) = thread->tp_value; return 0; default: @@ -497,41 +493,6 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) return 0; } -#if defined(CONFIG_CPU_32v6) && !defined(CONFIG_HAS_TLS_REG) - -/* - * We might be running on an ARMv6+ processor which should have the TLS - * register, but for some reason we can't use it and have to emulate it. - */ - -static int get_tp_trap(struct pt_regs *regs, unsigned int instr) -{ - int reg = (instr >> 12) & 15; - if (reg == 15) - return 1; - regs->uregs[reg] = current_thread_info()->tp_value; - regs->ARM_pc += 4; - return 0; -} - -static struct undef_hook arm_mrc_hook = { - .instr_mask = 0x0fff0fff, - .instr_val = 0x0e1d0f70, - .cpsr_mask = PSR_T_BIT, - .cpsr_val = 0, - .fn = get_tp_trap, -}; - -static int __init arm_mrc_hook_init(void) -{ - register_undef_hook(&arm_mrc_hook); - return 0; -} - -late_initcall(arm_mrc_hook_init); - -#endif - void __bad_xchg(volatile void *ptr, int size) { printk("xchg: bad data size: pc 0x%p, ptr 0x%p, size %d\n", @@ -619,17 +580,14 @@ void __init trap_init(void) { extern char __stubs_start[], __stubs_end[]; extern char __vectors_start[], __vectors_end[]; - extern char __kuser_helper_start[], __kuser_helper_end[]; - int kuser_sz = __kuser_helper_end - __kuser_helper_start; /* - * Copy the vectors, stubs and kuser helpers (in entry-armv.S) - * into the vector page, mapped at 0xffff0000, and ensure these - * are visible to the instruction stream. + * Copy the vectors and stubs (in entry-armv.S) into the + * vector page, mapped at 0xffff0000, and ensure these are + * visible to the instruction stream. */ memcpy((void *)0xffff0000, __vectors_start, __vectors_end - __vectors_start); memcpy((void *)0xffff0200, __stubs_start, __stubs_end - __stubs_start); - memcpy((void *)0xffff1000 - kuser_sz, __kuser_helper_start, kuser_sz); flush_icache_range(0xffff0000, 0xffff0000 + PAGE_SIZE); modify_domain(DOMAIN_USER, DOMAIN_CLIENT); } diff --git a/trunk/arch/arm/mach-ixp2000/ixdp2800.c b/trunk/arch/arm/mach-ixp2000/ixdp2800.c index aec13c7108a9..c4683aaff84a 100644 --- a/trunk/arch/arm/mach-ixp2000/ixdp2800.c +++ b/trunk/arch/arm/mach-ixp2000/ixdp2800.c @@ -65,102 +65,19 @@ static struct sys_timer ixdp2800_timer = { /************************************************************************* * IXDP2800 PCI *************************************************************************/ -static void __init ixdp2800_slave_disable_pci_master(void) -{ - *IXP2000_PCI_CMDSTAT &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); -} - -static void __init ixdp2800_master_wait_for_slave(void) -{ - volatile u32 *addr; - - printk(KERN_INFO "IXDP2800: waiting for slave NPU to configure " - "its BAR sizes\n"); - - addr = ixp2000_pci_config_addr(0, IXDP2X00_SLAVE_NPU_DEVFN, - PCI_BASE_ADDRESS_1); - do { - *addr = 0xffffffff; - cpu_relax(); - } while (*addr != 0xfe000008); - - addr = ixp2000_pci_config_addr(0, IXDP2X00_SLAVE_NPU_DEVFN, - PCI_BASE_ADDRESS_2); - do { - *addr = 0xffffffff; - cpu_relax(); - } while (*addr != 0xc0000008); - - /* - * Configure the slave's SDRAM BAR by hand. - */ - *addr = 0x40000008; -} - -static void __init ixdp2800_slave_wait_for_master_enable(void) -{ - printk(KERN_INFO "IXDP2800: waiting for master NPU to enable us\n"); - - while ((*IXP2000_PCI_CMDSTAT & PCI_COMMAND_MASTER) == 0) - cpu_relax(); -} - void __init ixdp2800_pci_preinit(void) { printk("ixdp2x00_pci_preinit called\n"); - *IXP2000_PCI_ADDR_EXT = 0x0001e000; - - if (!ixdp2x00_master_npu()) - ixdp2800_slave_disable_pci_master(); + *IXP2000_PCI_ADDR_EXT = 0x0000e000; - *IXP2000_PCI_SRAM_BASE_ADDR_MASK = (0x2000000 - 1) & ~0x3ffff; *IXP2000_PCI_DRAM_BASE_ADDR_MASK = (0x40000000 - 1) & ~0xfffff; + *IXP2000_PCI_SRAM_BASE_ADDR_MASK = (0x2000000 - 1) & ~0x3ffff; ixp2000_pci_preinit(); - - if (ixdp2x00_master_npu()) { - /* - * Wait until the slave set its SRAM/SDRAM BAR sizes - * correctly before we proceed to scan and enumerate - * the bus. - */ - ixdp2800_master_wait_for_slave(); - - /* - * We configure the SDRAM BARs by hand because they - * are 1G and fall outside of the regular allocated - * PCI address space. - */ - *IXP2000_PCI_SDRAM_BAR = 0x00000008; - } else { - /* - * Wait for the master to complete scanning the bus - * and assigning resources before we proceed to scan - * the bus ourselves. Set pci=firmware to honor the - * master's resource assignment. - */ - ixdp2800_slave_wait_for_master_enable(); - pcibios_setup("firmware"); - } } -/* - * We assign the SDRAM BARs for the two IXP2800 CPUs by hand, outside - * of the regular PCI window, because there's only 512M of outbound PCI - * memory window on each IXP, while we need 1G for each of the BARs. - */ -static void __devinit ixp2800_pci_fixup(struct pci_dev *dev) -{ - if (machine_is_ixdp2800()) { - dev->resource[2].start = 0; - dev->resource[2].end = 0; - dev->resource[2].flags = 0; - } -} -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IXP2800, ixp2800_pci_fixup); - -static int __init ixdp2800_pci_setup(int nr, struct pci_sys_data *sys) +int ixdp2800_pci_setup(int nr, struct pci_sys_data *sys) { sys->mem_offset = 0x00000000; @@ -212,47 +129,22 @@ static int __init ixdp2800_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) } else return IRQ_IXP2000_PCIB; /* Slave NIC interrupt */ } -static void __init ixdp2800_master_enable_slave(void) -{ - volatile u32 *addr; - - printk(KERN_INFO "IXDP2800: enabling slave NPU\n"); - - addr = (volatile u32 *)ixp2000_pci_config_addr(0, - IXDP2X00_SLAVE_NPU_DEVFN, - PCI_COMMAND); - - *addr |= PCI_COMMAND_MASTER; -} - -static void __init ixdp2800_master_wait_for_slave_bus_scan(void) +static void ixdp2800_pci_postinit(void) { - volatile u32 *addr; - - printk(KERN_INFO "IXDP2800: waiting for slave to finish bus scan\n"); - - addr = (volatile u32 *)ixp2000_pci_config_addr(0, - IXDP2X00_SLAVE_NPU_DEVFN, - PCI_COMMAND); - while ((*addr & PCI_COMMAND_MEMORY) == 0) - cpu_relax(); -} + struct pci_dev *dev; -static void __init ixdp2800_slave_signal_bus_scan_completion(void) -{ - printk(KERN_INFO "IXDP2800: bus scan done, signaling master\n"); - *IXP2000_PCI_CMDSTAT |= PCI_COMMAND_MEMORY; -} + if (ixdp2x00_master_npu()) { + dev = pci_find_slot(1, IXDP2800_SLAVE_ENET_DEVFN); + pci_remove_bus_device(dev); + } else { + dev = pci_find_slot(1, IXDP2800_MASTER_ENET_DEVFN); + pci_remove_bus_device(dev); -static void __init ixdp2800_pci_postinit(void) -{ - if (!ixdp2x00_master_npu()) { ixdp2x00_slave_pci_postinit(); - ixdp2800_slave_signal_bus_scan_completion(); } } -struct __initdata hw_pci ixdp2800_pci __initdata = { +struct hw_pci ixdp2800_pci __initdata = { .nr_controllers = 1, .setup = ixdp2800_pci_setup, .preinit = ixdp2800_pci_preinit, @@ -263,21 +155,8 @@ struct __initdata hw_pci ixdp2800_pci __initdata = { int __init ixdp2800_pci_init(void) { - if (machine_is_ixdp2800()) { - struct pci_dev *dev; - + if (machine_is_ixdp2800()) pci_common_init(&ixdp2800_pci); - if (ixdp2x00_master_npu()) { - dev = pci_find_slot(1, IXDP2800_SLAVE_ENET_DEVFN); - pci_remove_bus_device(dev); - - ixdp2800_master_enable_slave(); - ixdp2800_master_wait_for_slave_bus_scan(); - } else { - dev = pci_find_slot(1, IXDP2800_MASTER_ENET_DEVFN); - pci_remove_bus_device(dev); - } - } return 0; } diff --git a/trunk/arch/arm/mach-ixp2000/pci.c b/trunk/arch/arm/mach-ixp2000/pci.c index 5ff2f2718c58..831f8ffb6b61 100644 --- a/trunk/arch/arm/mach-ixp2000/pci.c +++ b/trunk/arch/arm/mach-ixp2000/pci.c @@ -37,7 +37,7 @@ static int pci_master_aborts = 0; static int clear_master_aborts(void); -u32 * +static u32 * ixp2000_pci_config_addr(unsigned int bus_nr, unsigned int devfn, int where) { u32 *paddress; @@ -208,15 +208,15 @@ ixp2000_pci_preinit(void) * use our own resource space. */ static struct resource ixp2000_pci_mem_space = { - .start = 0xe0000000, + .start = 0x00000000, .end = 0xffffffff, .flags = IORESOURCE_MEM, .name = "PCI Mem Space" }; static struct resource ixp2000_pci_io_space = { - .start = 0x00010000, - .end = 0x0001ffff, + .start = 0x00000000, + .end = 0xffffffff, .flags = IORESOURCE_IO, .name = "PCI I/O Space" }; diff --git a/trunk/arch/arm/mm/Kconfig b/trunk/arch/arm/mm/Kconfig index 007766a0644c..5b670c9ac5ef 100644 --- a/trunk/arch/arm/mm/Kconfig +++ b/trunk/arch/arm/mm/Kconfig @@ -409,17 +409,3 @@ config CPU_BPREDICT_DISABLE depends on CPU_ARM1020 help Say Y here to disable branch prediction. If unsure, say N. - -config HAS_TLS_REG - bool - depends on CPU_32v6 && !CPU_32v5 && !CPU_32v4 && !CPU_32v3 - help - This selects support for the CP15 thread register. - It is defined to be available on ARMv6 or later. However - if the kernel is configured to support multiple CPUs including - a pre-ARMv6 processors, or if a given ARMv6 processor doesn't - implement the thread register for some reason, then access to - this register from user space must be trapped and emulated. - If user space is relying on the __kuser_get_tls code then - there should not be any impact. - diff --git a/trunk/arch/arm/mm/abort-ev6.S b/trunk/arch/arm/mm/abort-ev6.S index 8f76f3df7b4c..38b2cbb89beb 100644 --- a/trunk/arch/arm/mm/abort-ev6.S +++ b/trunk/arch/arm/mm/abort-ev6.S @@ -1,6 +1,5 @@ #include #include -#include "abort-macro.S" /* * Function: v6_early_abort * @@ -14,26 +13,11 @@ * : sp = pointer to registers * * Purpose : obtain information about current aborted instruction. - * Note: we read user space. This means we might cause a data - * abort here if the I-TLB and D-TLB aren't seeing the same - * picture. Unfortunately, this does happen. We live with it. */ .align 5 ENTRY(v6_early_abort) mrc p15, 0, r1, c5, c0, 0 @ get FSR mrc p15, 0, r0, c6, c0, 0 @ get FAR -/* - * Faulty SWP instruction on 1136 doesn't set bit 11 in DFSR. - * The test below covers all the write situations, including Java bytecodes - */ - bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR - tst r3, #PSR_J_BIT @ Java? - movne pc, lr - do_thumb_abort - ldreq r3, [r2] @ read aborted ARM instruction - do_ldrd_abort - tst r3, #1 << 20 @ L = 0 -> write - orreq r1, r1, #1 << 11 @ yes. mov pc, lr diff --git a/trunk/arch/arm/mm/mm-armv.c b/trunk/arch/arm/mm/mm-armv.c index 585dfb8e20b9..f5a87db8b498 100644 --- a/trunk/arch/arm/mm/mm-armv.c +++ b/trunk/arch/arm/mm/mm-armv.c @@ -411,10 +411,9 @@ static void __init build_mem_type_table(void) mem_types[MT_MEMORY].prot_sect &= ~PMD_BIT4; mem_types[MT_ROM].prot_sect &= ~PMD_BIT4; /* - * Mark cache clean areas and XIP ROM read only - * from SVC mode and no access from userspace. + * Mark cache clean areas read only from SVC mode + * and no access from userspace. */ - mem_types[MT_ROM].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE; } diff --git a/trunk/arch/i386/kernel/entry.S b/trunk/arch/i386/kernel/entry.S index fe1918cc68d1..3c73dc865ead 100644 --- a/trunk/arch/i386/kernel/entry.S +++ b/trunk/arch/i386/kernel/entry.S @@ -260,9 +260,11 @@ restore_nocheck: .section .fixup,"ax" iret_exc: sti - pushl $0 # no error code - pushl $do_iret_error - jmp error_code + movl $__USER_DS, %edx + movl %edx, %ds + movl %edx, %es + movl $11,%eax + call do_exit .previous .section __ex_table,"a" .align 4 diff --git a/trunk/arch/i386/kernel/traps.c b/trunk/arch/i386/kernel/traps.c index d70819481f6e..6c0e383915b6 100644 --- a/trunk/arch/i386/kernel/traps.c +++ b/trunk/arch/i386/kernel/traps.c @@ -451,7 +451,6 @@ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) DO_ERROR(12, SIGBUS, "stack segment", stack_segment) DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0) -DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0) fastcall void do_general_protection(struct pt_regs * regs, long error_code) { diff --git a/trunk/drivers/cpufreq/cpufreq.c b/trunk/drivers/cpufreq/cpufreq.c index 4fc0cb79f18f..b30001f31610 100644 --- a/trunk/drivers/cpufreq/cpufreq.c +++ b/trunk/drivers/cpufreq/cpufreq.c @@ -223,7 +223,7 @@ static inline void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci) } if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) || (val == CPUFREQ_POSTCHANGE && ci->old > ci->new) || - (val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) { + (val == CPUFREQ_RESUMECHANGE)) { loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq, ci->new); dprintk("scaling loops_per_jiffy to %lu for frequency %u kHz\n", loops_per_jiffy, ci->new); } @@ -865,91 +865,12 @@ unsigned int cpufreq_get(unsigned int cpu) EXPORT_SYMBOL(cpufreq_get); -/** - * cpufreq_suspend - let the low level driver prepare for suspend - */ - -static int cpufreq_suspend(struct sys_device * sysdev, u32 state) -{ - int cpu = sysdev->id; - unsigned int ret = 0; - unsigned int cur_freq = 0; - struct cpufreq_policy *cpu_policy; - - dprintk("resuming cpu %u\n", cpu); - - if (!cpu_online(cpu)) - return 0; - - /* we may be lax here as interrupts are off. Nonetheless - * we need to grab the correct cpu policy, as to check - * whether we really run on this CPU. - */ - - cpu_policy = cpufreq_cpu_get(cpu); - if (!cpu_policy) - return -EINVAL; - - /* only handle each CPU group once */ - if (unlikely(cpu_policy->cpu != cpu)) { - cpufreq_cpu_put(cpu_policy); - return 0; - } - - if (cpufreq_driver->suspend) { - ret = cpufreq_driver->suspend(cpu_policy, state); - if (ret) { - printk(KERN_ERR "cpufreq: suspend failed in ->suspend " - "step on CPU %u\n", cpu_policy->cpu); - cpufreq_cpu_put(cpu_policy); - return ret; - } - } - - - if (cpufreq_driver->flags & CPUFREQ_CONST_LOOPS) - goto out; - - if (cpufreq_driver->get) - cur_freq = cpufreq_driver->get(cpu_policy->cpu); - - if (!cur_freq || !cpu_policy->cur) { - printk(KERN_ERR "cpufreq: suspend failed to assert current " - "frequency is what timing core thinks it is.\n"); - goto out; - } - - if (unlikely(cur_freq != cpu_policy->cur)) { - struct cpufreq_freqs freqs; - - if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN)) - printk(KERN_DEBUG "Warning: CPU frequency is %u, " - "cpufreq assumed %u kHz.\n", - cur_freq, cpu_policy->cur); - - freqs.cpu = cpu; - freqs.old = cpu_policy->cur; - freqs.new = cur_freq; - - notifier_call_chain(&cpufreq_transition_notifier_list, - CPUFREQ_SUSPENDCHANGE, &freqs); - adjust_jiffies(CPUFREQ_SUSPENDCHANGE, &freqs); - - cpu_policy->cur = cur_freq; - } - - out: - cpufreq_cpu_put(cpu_policy); - return 0; -} - /** * cpufreq_resume - restore proper CPU frequency handling after resume * * 1.) resume CPUfreq hardware support (cpufreq_driver->resume()) * 2.) if ->target and !CPUFREQ_CONST_LOOPS: verify we're in sync - * 3.) schedule call cpufreq_update_policy() ASAP as interrupts are - * restored. + * 3.) schedule call cpufreq_update_policy() ASAP as interrupts are restored. */ static int cpufreq_resume(struct sys_device * sysdev) { @@ -994,9 +915,7 @@ static int cpufreq_resume(struct sys_device * sysdev) cur_freq = cpufreq_driver->get(cpu_policy->cpu); if (!cur_freq || !cpu_policy->cur) { - printk(KERN_ERR "cpufreq: resume failed to assert " - "current frequency is what timing core " - "thinks it is.\n"); + printk(KERN_ERR "cpufreq: resume failed to assert current frequency is what timing core thinks it is.\n"); goto out; } @@ -1004,15 +923,13 @@ static int cpufreq_resume(struct sys_device * sysdev) struct cpufreq_freqs freqs; printk(KERN_WARNING "Warning: CPU frequency is %u, " - "cpufreq assumed %u kHz.\n", - cur_freq, cpu_policy->cur); + "cpufreq assumed %u kHz.\n", cur_freq, cpu_policy->cur); freqs.cpu = cpu; freqs.old = cpu_policy->cur; freqs.new = cur_freq; - notifier_call_chain(&cpufreq_transition_notifier_list, - CPUFREQ_RESUMECHANGE, &freqs); + notifier_call_chain(&cpufreq_transition_notifier_list, CPUFREQ_RESUMECHANGE, &freqs); adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs); cpu_policy->cur = cur_freq; @@ -1028,7 +945,6 @@ static int cpufreq_resume(struct sys_device * sysdev) static struct sysdev_driver cpufreq_sysdev_driver = { .add = cpufreq_add_dev, .remove = cpufreq_remove_dev, - .suspend = cpufreq_suspend, .resume = cpufreq_resume, }; diff --git a/trunk/drivers/serial/imx.c b/trunk/drivers/serial/imx.c index c682c6308cde..01a8726a3f97 100644 --- a/trunk/drivers/serial/imx.c +++ b/trunk/drivers/serial/imx.c @@ -321,18 +321,39 @@ static void imx_break_ctl(struct uart_port *port, int break_state) #define TXTL 2 /* reset default */ #define RXTL 1 /* reset default */ +static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode) +{ + unsigned int val; + unsigned int ufcr_rfdiv; + + /* set receiver / transmitter trigger level. + * RFDIV is set such way to satisfy requested uartclk value + */ + val = TXTL<<10 | RXTL; + ufcr_rfdiv = (imx_get_perclk1() + sport->port.uartclk / 2) / sport->port.uartclk; + + if(!ufcr_rfdiv) + ufcr_rfdiv = 1; + + if(ufcr_rfdiv >= 7) + ufcr_rfdiv = 6; + else + ufcr_rfdiv = 6 - ufcr_rfdiv; + + val |= UFCR_RFDIV & (ufcr_rfdiv << 7); + + UFCR((u32)sport->port.membase) = val; + + return 0; +} + static int imx_startup(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; int retval; - unsigned int val; unsigned long flags; - /* set receiver / transmitter trigger level. We assume - * that RFDIV has been set by the arch setup or by the bootloader. - */ - val = (UFCR((u32)sport->port.membase) & UFCR_RFDIV) | TXTL<<10 | RXTL; - UFCR((u32)sport->port.membase) = val; + imx_setup_ufcr(sport, 0); /* disable the DREN bit (Data Ready interrupt enable) before * requesting IRQs @@ -737,9 +758,12 @@ static void __init imx_console_get_options(struct imx_port *sport, int *baud, int *parity, int *bits) { + if ( UCR1((u32)sport->port.membase) | UCR1_UARTEN ) { /* ok, the port was enabled */ unsigned int ucr2, ubir,ubmr, uartclk; + unsigned int baud_raw; + unsigned int ucfr_rfdiv; ucr2 = UCR2((u32)sport->port.membase); @@ -758,9 +782,35 @@ imx_console_get_options(struct imx_port *sport, int *baud, ubir = UBIR((u32)sport->port.membase) & 0xffff; ubmr = UBMR((u32)sport->port.membase) & 0xffff; - uartclk = sport->port.uartclk; - *baud = ((uartclk/16) * (ubir + 1)) / (ubmr + 1); + + ucfr_rfdiv = (UFCR((u32)sport->port.membase) & UFCR_RFDIV) >> 7; + if (ucfr_rfdiv == 6) + ucfr_rfdiv = 7; + else + ucfr_rfdiv = 6 - ucfr_rfdiv; + + uartclk = imx_get_perclk1(); + uartclk /= ucfr_rfdiv; + + { /* + * The next code provides exact computation of + * baud_raw = round(((uartclk/16) * (ubir + 1)) / (ubmr + 1)) + * without need of float support or long long division, + * which would be required to prevent 32bit arithmetic overflow + */ + unsigned int mul = ubir + 1; + unsigned int div = 16 * (ubmr + 1); + unsigned int rem = uartclk % div; + + baud_raw = (uartclk / div) * mul; + baud_raw += (rem * mul + div / 2) / div; + *baud = (baud_raw + 50) / 100 * 100; + } + + if(*baud != baud_raw) + printk(KERN_INFO "Serial: Console IMX rounded baud rate from %d to %d\n", + baud_raw, *baud); } } @@ -787,6 +837,8 @@ imx_console_setup(struct console *co, char *options) else imx_console_get_options(sport, &baud, &parity, &bits); + imx_setup_ufcr(sport, 0); + return uart_set_options(&sport->port, co, baud, parity, bits, flow); } diff --git a/trunk/include/asm-arm/arch-ixp2000/platform.h b/trunk/include/asm-arm/arch-ixp2000/platform.h index 901bba6d02b4..509e44d528d8 100644 --- a/trunk/include/asm-arm/arch-ixp2000/platform.h +++ b/trunk/include/asm-arm/arch-ixp2000/platform.h @@ -121,7 +121,6 @@ unsigned long ixp2000_gettimeoffset(void); struct pci_sys_data; -u32 *ixp2000_pci_config_addr(unsigned int bus, unsigned int devfn, int where); void ixp2000_pci_preinit(void); int ixp2000_pci_setup(int, struct pci_sys_data*); struct pci_bus* ixp2000_pci_scan_bus(int, struct pci_sys_data*); diff --git a/trunk/include/asm-arm/io.h b/trunk/include/asm-arm/io.h index 658ffa384fda..69bc7a3e8160 100644 --- a/trunk/include/asm-arm/io.h +++ b/trunk/include/asm-arm/io.h @@ -99,16 +99,12 @@ extern void __readwrite_bug(const char *fn); */ #ifdef __io #define outb(v,p) __raw_writeb(v,__io(p)) -#define outw(v,p) __raw_writew((__force __u16) \ - cpu_to_le16(v),__io(p)) -#define outl(v,p) __raw_writel((__force __u32) \ - cpu_to_le32(v),__io(p)) +#define outw(v,p) __raw_writew(cpu_to_le16(v),__io(p)) +#define outl(v,p) __raw_writel(cpu_to_le32(v),__io(p)) -#define inb(p) ({ __u8 __v = __raw_readb(__io(p)); __v; }) -#define inw(p) ({ __u16 __v = le16_to_cpu((__force __le16) \ - __raw_readw(__io(p))); __v; }) -#define inl(p) ({ __u32 __v = le32_to_cpu((__force __le32) \ - __raw_readl(__io(p))); __v; }) +#define inb(p) ({ unsigned int __v = __raw_readb(__io(p)); __v; }) +#define inw(p) ({ unsigned int __v = le16_to_cpu(__raw_readw(__io(p))); __v; }) +#define inl(p) ({ unsigned int __v = le32_to_cpu(__raw_readl(__io(p))); __v; }) #define outsb(p,d,l) __raw_writesb(__io(p),d,l) #define outsw(p,d,l) __raw_writesw(__io(p),d,l) @@ -153,11 +149,9 @@ extern void _memset_io(void __iomem *, int, size_t); * IO port primitives for more information. */ #ifdef __mem_pci -#define readb(c) ({ __u8 __v = __raw_readb(__mem_pci(c)); __v; }) -#define readw(c) ({ __u16 __v = le16_to_cpu((__force __le16) \ - __raw_readw(__mem_pci(c))); __v; }) -#define readl(c) ({ __u32 __v = le32_to_cpu((__force __le32) \ - __raw_readl(__mem_pci(c))); __v; }) +#define readb(c) ({ unsigned int __v = __raw_readb(__mem_pci(c)); __v; }) +#define readw(c) ({ unsigned int __v = le16_to_cpu(__raw_readw(__mem_pci(c))); __v; }) +#define readl(c) ({ unsigned int __v = le32_to_cpu(__raw_readl(__mem_pci(c))); __v; }) #define readb_relaxed(addr) readb(addr) #define readw_relaxed(addr) readw(addr) #define readl_relaxed(addr) readl(addr) @@ -167,10 +161,8 @@ extern void _memset_io(void __iomem *, int, size_t); #define readsl(p,d,l) __raw_readsl(__mem_pci(p),d,l) #define writeb(v,c) __raw_writeb(v,__mem_pci(c)) -#define writew(v,c) __raw_writew((__force __u16) \ - cpu_to_le16(v),__mem_pci(c)) -#define writel(v,c) __raw_writel((__force __u32) \ - cpu_to_le32(v),__mem_pci(c)) +#define writew(v,c) __raw_writew(cpu_to_le16(v),__mem_pci(c)) +#define writel(v,c) __raw_writel(cpu_to_le32(v),__mem_pci(c)) #define writesb(p,d,l) __raw_writesb(__mem_pci(p),d,l) #define writesw(p,d,l) __raw_writesw(__mem_pci(p),d,l) diff --git a/trunk/include/asm-arm/unistd.h b/trunk/include/asm-arm/unistd.h index ace27480886e..a19ec09eaa01 100644 --- a/trunk/include/asm-arm/unistd.h +++ b/trunk/include/asm-arm/unistd.h @@ -359,7 +359,8 @@ #define __ARM_NR_cacheflush (__ARM_NR_BASE+2) #define __ARM_NR_usr26 (__ARM_NR_BASE+3) #define __ARM_NR_usr32 (__ARM_NR_BASE+4) -#define __ARM_NR_set_tls (__ARM_NR_BASE+5) + +#define __ARM_NR_set_tls (__ARM_NR_BASE+0x800) #define __sys2(x) #x #define __sys1(x) __sys2(x) diff --git a/trunk/include/linux/cpufreq.h b/trunk/include/linux/cpufreq.h index f21af067d015..910eca35583d 100644 --- a/trunk/include/linux/cpufreq.h +++ b/trunk/include/linux/cpufreq.h @@ -103,7 +103,6 @@ struct cpufreq_policy { #define CPUFREQ_PRECHANGE (0) #define CPUFREQ_POSTCHANGE (1) #define CPUFREQ_RESUMECHANGE (8) -#define CPUFREQ_SUSPENDCHANGE (9) struct cpufreq_freqs { unsigned int cpu; /* cpu nr */ @@ -201,7 +200,6 @@ struct cpufreq_driver { /* optional */ int (*exit) (struct cpufreq_policy *policy); - int (*suspend) (struct cpufreq_policy *policy, u32 state); int (*resume) (struct cpufreq_policy *policy); struct freq_attr **attr; }; @@ -213,8 +211,7 @@ struct cpufreq_driver { #define CPUFREQ_CONST_LOOPS 0x02 /* loops_per_jiffy or other kernel * "constants" aren't affected by * frequency transitions */ -#define CPUFREQ_PM_NO_WARN 0x04 /* don't warn on suspend/resume speed - * mismatches */ + int cpufreq_register_driver(struct cpufreq_driver *driver_data); int cpufreq_unregister_driver(struct cpufreq_driver *driver_data); diff --git a/trunk/kernel/exit.c b/trunk/kernel/exit.c index 93851bcd9584..39d35935b371 100644 --- a/trunk/kernel/exit.c +++ b/trunk/kernel/exit.c @@ -517,6 +517,8 @@ static inline void choose_new_parent(task_t *p, task_t *reaper, task_t *child_re */ BUG_ON(p == reaper || reaper->exit_state >= EXIT_ZOMBIE); p->real_parent = reaper; + if (p->parent == p->real_parent) + BUG(); } static inline void reparent_thread(task_t *p, task_t *father, int traced)