diff options
Diffstat (limited to 'arch')
144 files changed, 3730 insertions, 1165 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index 830c16a2b801..dc81b34c5d82 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -6,6 +6,7 @@ config OPROFILE tristate "OProfile system profiling (EXPERIMENTAL)" depends on PROFILING depends on HAVE_OPROFILE + depends on TRACING_SUPPORT select TRACING select RING_BUFFER help diff --git a/arch/alpha/include/asm/ftrace.h b/arch/alpha/include/asm/ftrace.h new file mode 100644 index 000000000000..40a8c178f10d --- /dev/null +++ b/arch/alpha/include/asm/ftrace.h @@ -0,0 +1 @@ +/* empty */ diff --git a/arch/alpha/include/asm/hardirq.h b/arch/alpha/include/asm/hardirq.h index d953e234daa8..88971460fa6c 100644 --- a/arch/alpha/include/asm/hardirq.h +++ b/arch/alpha/include/asm/hardirq.h @@ -14,17 +14,4 @@ typedef struct { void ack_bad_irq(unsigned int irq); -#define HARDIRQ_BITS 12 - -/* - * The hardirq mask has to be large enough to have - * space for potentially nestable IRQ sources in the system - * to nest on a single CPU. On Alpha, interrupts are masked at the CPU - * by IPL as well as at the system level. We only have 8 IPLs (UNIX PALcode) - * so we really only have 8 nestable IRQs, but allow some overhead - */ -#if (1 << HARDIRQ_BITS) < 16 -#error HARDIRQ_BITS is too low! -#endif - #endif /* _ALPHA_HARDIRQ_H */ diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c index 393c81641314..9e6e512f0117 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c @@ -18,7 +18,10 @@ unsigned int __machine_arch_type; -#include <linux/string.h> +#include <linux/compiler.h> /* for inline */ +#include <linux/types.h> /* for size_t */ +#include <linux/stddef.h> /* for NULL */ +#include <asm/string.h> #ifdef STANDALONE_DEBUG #define putstr printf diff --git a/arch/arm/mach-netx/include/mach/netx-regs.h b/arch/arm/mach-netx/include/mach/netx-regs.h index 08c60ff227be..5a03e7ccb01a 100644 --- a/arch/arm/mach-netx/include/mach/netx-regs.h +++ b/arch/arm/mach-netx/include/mach/netx-regs.h @@ -80,7 +80,7 @@ #define NETX_PA_XPEC(no) (NETX_IO_PHYS + NETX_OFS_XPEC(no)) #define NETX_PA_VIC (NETX_IO_PHYS + NETX_OFS_VIC) -/* virual addresses */ +/* virtual addresses */ #define NETX_VA_SYSTEM (NETX_IO_VIRT + NETX_OFS_SYSTEM) #define NETX_VA_MEMCR (NETX_IO_VIRT + NETX_OFS_MEMCR) #define NETX_VA_DPMAS (NETX_IO_VIRT + NETX_OFS_DPMAS) diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig index 3f325d3718a9..cd8de89c5fad 100644 --- a/arch/arm/mach-omap1/Kconfig +++ b/arch/arm/mach-omap1/Kconfig @@ -109,7 +109,7 @@ config MACH_OMAP_PALMZ71 help Support for the Palm Zire71 PDA. To boot the kernel, you'll need a PalmOS compatible bootloader; check out - http://hackndev.com/palm/z71 for more informations. + http://hackndev.com/palm/z71 for more information. Say Y here if you have such a PDA, say N otherwise. config MACH_OMAP_PALMTT diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index 05fe3053dcae..414a8ad97f52 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig @@ -127,13 +127,13 @@ config BOARD_HAMMERHEAD select CPU_AT32AP7000 select USB_ARCH_HAS_HCD help - The Hammerhead platform is built around a AVR32 32-bit microcontroller from Atmel. + The Hammerhead platform is built around an AVR32 32-bit microcontroller from Atmel. It offers versatile peripherals, such as ethernet, usb device, usb host etc. - The board also incooperates a power supply and is a Power over Ethernet (PoE) Powered + The board also incorporates a power supply and is a Power over Ethernet (PoE) Powered Device (PD). - Additonally, a Cyclone III FPGA from Altera is integrated on the board. The FPGA is + Additionally, a Cyclone III FPGA from Altera is integrated on the board. The FPGA is mapped into the 32-bit AVR memory bus. The FPGA offers two DDR2 SDRAM interfaces, which will cover even the most exceptional need of memory bandwidth. Together with the onboard video decoder the board is ready for video processing. diff --git a/arch/avr32/include/asm/ftrace.h b/arch/avr32/include/asm/ftrace.h new file mode 100644 index 000000000000..40a8c178f10d --- /dev/null +++ b/arch/avr32/include/asm/ftrace.h @@ -0,0 +1 @@ +/* empty */ diff --git a/arch/avr32/include/asm/hardirq.h b/arch/avr32/include/asm/hardirq.h index 267354356f60..015bc75ea798 100644 --- a/arch/avr32/include/asm/hardirq.h +++ b/arch/avr32/include/asm/hardirq.h @@ -20,15 +20,4 @@ void ack_bad_irq(unsigned int irq); #endif /* __ASSEMBLY__ */ -#define HARDIRQ_BITS 12 - -/* - * The hardirq mask has to be large enough to have - * space for potentially all IRQ sources in the system - * nesting on a single CPU: - */ -#if (1 << HARDIRQ_BITS) < NR_IRQS -# error HARDIRQ_BITS is too low! -#endif - #endif /* __ASM_AVR32_HARDIRQ_H */ diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 0c1f86e3e44a..3640cdc38aac 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -777,7 +777,7 @@ config CACHELINE_ALIGNED_L1 default n if BF54x depends on !BF531 help - If enabled, cacheline_anligned data is linked + If enabled, cacheline_aligned data is linked into L1 data memory. (less latency) config SYSCALL_TAB_L1 @@ -957,7 +957,7 @@ config MPU memory they do not own. This comes at a performance penalty and is recommended only for debugging. -comment "Asynchonous Memory Configuration" +comment "Asynchronous Memory Configuration" menu "EBIU_AMGCTL Global Control" config C_AMCKEN @@ -989,7 +989,7 @@ config C_B3PEN default n choice - prompt"Enable Asynchonous Memory Banks" + prompt "Enable Asynchronous Memory Banks" default C_AMBEN_ALL config C_AMBEN diff --git a/arch/blackfin/include/asm/ftrace.h b/arch/blackfin/include/asm/ftrace.h new file mode 100644 index 000000000000..40a8c178f10d --- /dev/null +++ b/arch/blackfin/include/asm/ftrace.h @@ -0,0 +1 @@ +/* empty */ diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig index 3462245fe9fb..7adac388a771 100644 --- a/arch/cris/Kconfig +++ b/arch/cris/Kconfig @@ -438,7 +438,7 @@ config ETRAX_SERIAL_PORT0_DMA1_IN help Enables the DMA1 input channel for ser0 (ttyS0). If you do not enable DMA, an interrupt for each character will be - used when receiveing data. + used when receiving data. Normally you want to use DMA, unless you use the DMA channel for something else. @@ -565,7 +565,7 @@ config ETRAX_SERIAL_PORT2_DMA7_IN help Enables the DMA7 input channel for ser2 (ttyS2). If you do not enable DMA, an interrupt for each character will be - used when receiveing data. + used when receiving data. Normally you want to use DMA, unless you use the DMA channel for something else. @@ -604,7 +604,7 @@ config ETRAX_SERIAL_PORT3_DMA3_IN help Enables the DMA3 input channel for ser3 (ttyS3). If you do not enable DMA, an interrupt for each character will be - used when receiveing data. + used when receiving data. Normally you want to use DMA, unless you use the DMA channel for something else. diff --git a/arch/cris/arch-v32/Kconfig b/arch/cris/arch-v32/Kconfig index 005ed2b3f7f4..21bbd93be34f 100644 --- a/arch/cris/arch-v32/Kconfig +++ b/arch/cris/arch-v32/Kconfig @@ -28,7 +28,7 @@ config ETRAX_NBR_LED_GRP_ONE help Select this if you want one Ethernet LED group. This LED group can be used for one or more Ethernet interfaces. However, it is - recomended that each Ethernet interface use a dedicated LED group. + recommended that each Ethernet interface use a dedicated LED group. config ETRAX_NBR_LED_GRP_TWO bool "Use two LED groups" diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig index 7a64fcef9d07..b9e328e688be 100644 --- a/arch/cris/arch-v32/drivers/Kconfig +++ b/arch/cris/arch-v32/drivers/Kconfig @@ -342,7 +342,7 @@ config ETRAX_SERIAL_PORT4_DMA9_IN help Enables the DMA9 input channel for ser4 (ttyS4). If you do not enable DMA, an interrupt for each character will be - used when receiveing data. + used when receiving data. Normally you want to use DMA, unless you use the DMA channel for something else. diff --git a/arch/cris/arch-v32/mach-fs/Kconfig b/arch/cris/arch-v32/mach-fs/Kconfig index f6d74475f1c6..774de82abef6 100644 --- a/arch/cris/arch-v32/mach-fs/Kconfig +++ b/arch/cris/arch-v32/mach-fs/Kconfig @@ -59,7 +59,7 @@ config ETRAX_SDRAM_GRP1_CONFIG depends on ETRAX_ARCH_V32 default "0" help - SDRAM configuration for group 1. The defult value is 0 + SDRAM configuration for group 1. The default value is 0 because group 1 is not used in the default configuration, described in the help for SDRAM_GRP0_CONFIG. diff --git a/arch/cris/include/asm/ftrace.h b/arch/cris/include/asm/ftrace.h new file mode 100644 index 000000000000..40a8c178f10d --- /dev/null +++ b/arch/cris/include/asm/ftrace.h @@ -0,0 +1 @@ +/* empty */ diff --git a/arch/h8300/include/asm/ftrace.h b/arch/h8300/include/asm/ftrace.h new file mode 100644 index 000000000000..40a8c178f10d --- /dev/null +++ b/arch/h8300/include/asm/ftrace.h @@ -0,0 +1 @@ +/* empty */ diff --git a/arch/h8300/kernel/timer/tpu.c b/arch/h8300/kernel/timer/tpu.c index ad383caae196..e7c6e614a758 100644 --- a/arch/h8300/kernel/timer/tpu.c +++ b/arch/h8300/kernel/timer/tpu.c @@ -67,7 +67,7 @@ static struct irqaction tpu_irq = { .flags = IRQF_DISABLED | IRQF_TIMER, }; -const static int __initdata divide_rate[] = { +static const int __initdata divide_rate[] = { #if CONFIG_H8300_TPU_CH == 0 1,4,16,64,0,0,0,0, #elif (CONFIG_H8300_TPU_CH == 1) || (CONFIG_H8300_TPU_CH == 5) diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 153e727a6e8e..294a3b13ecac 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -22,6 +22,9 @@ config IA64 select HAVE_OPROFILE select HAVE_KPROBES select HAVE_KRETPROBES + select HAVE_FTRACE_MCOUNT_RECORD + select HAVE_DYNAMIC_FTRACE if (!ITANIUM) + select HAVE_FUNCTION_TRACER select HAVE_DMA_ATTRS select HAVE_KVM select HAVE_ARCH_TRACEHOOK diff --git a/arch/ia64/include/asm/ftrace.h b/arch/ia64/include/asm/ftrace.h new file mode 100644 index 000000000000..d20db3c2a656 --- /dev/null +++ b/arch/ia64/include/asm/ftrace.h @@ -0,0 +1,28 @@ +#ifndef _ASM_IA64_FTRACE_H +#define _ASM_IA64_FTRACE_H + +#ifdef CONFIG_FUNCTION_TRACER +#define MCOUNT_INSN_SIZE 32 /* sizeof mcount call */ + +#ifndef __ASSEMBLY__ +extern void _mcount(unsigned long pfs, unsigned long r1, unsigned long b0, unsigned long r0); +#define mcount _mcount + +#include <asm/kprobes.h> +/* In IA64, MCOUNT_ADDR is set in link time, so it's not a constant at compile time */ +#define MCOUNT_ADDR (((struct fnptr *)mcount)->ip) +#define FTRACE_ADDR (((struct fnptr *)ftrace_caller)->ip) + +static inline unsigned long ftrace_call_adjust(unsigned long addr) +{ + /* second bundle, insn 2 */ + return addr - 0x12; +} + +struct dyn_arch_ftrace { +}; +#endif + +#endif /* CONFIG_FUNCTION_TRACER */ + +#endif /* _ASM_IA64_FTRACE_H */ diff --git a/arch/ia64/include/asm/hardirq.h b/arch/ia64/include/asm/hardirq.h index 140e495b8e0e..d514cd9edb49 100644 --- a/arch/ia64/include/asm/hardirq.h +++ b/arch/ia64/include/asm/hardirq.h @@ -20,16 +20,6 @@ #define local_softirq_pending() (local_cpu_data->softirq_pending) -#define HARDIRQ_BITS 14 - -/* - * The hardirq mask has to be large enough to have space for potentially all IRQ sources - * in the system nesting on a single CPU: - */ -#if (1 << HARDIRQ_BITS) < NR_IRQS -# error HARDIRQ_BITS is too low! -#endif - extern void __iomem *ipi_base_addr; void ack_bad_irq(unsigned int irq); diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index 5628e9a990a6..6b7edcab0cb5 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -2,6 +2,10 @@ # Makefile for the linux kernel. # +ifdef CONFIG_DYNAMIC_FTRACE +CFLAGS_REMOVE_ftrace.o = -pg +endif + extra-y := head.o init_task.o vmlinux.lds obj-y := acpi.o entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o \ @@ -28,6 +32,7 @@ obj-$(CONFIG_IA64_CYCLONE) += cyclone.o obj-$(CONFIG_CPU_FREQ) += cpufreq/ obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o +obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index ccfdeee9d89f..8dc69669586a 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -47,6 +47,7 @@ #include <asm/processor.h> #include <asm/thread_info.h> #include <asm/unistd.h> +#include <asm/ftrace.h> #include "minstate.h" @@ -1404,6 +1405,105 @@ GLOBAL_ENTRY(unw_init_running) br.ret.sptk.many rp END(unw_init_running) +#ifdef CONFIG_FUNCTION_TRACER +#ifdef CONFIG_DYNAMIC_FTRACE +GLOBAL_ENTRY(_mcount) + br ftrace_stub +END(_mcount) + +.here: + br.ret.sptk.many b0 + +GLOBAL_ENTRY(ftrace_caller) + alloc out0 = ar.pfs, 8, 0, 4, 0 + mov out3 = r0 + ;; + mov out2 = b0 + add r3 = 0x20, r3 + mov out1 = r1; + br.call.sptk.many b0 = ftrace_patch_gp + //this might be called from module, so we must patch gp +ftrace_patch_gp: + movl gp=__gp + mov b0 = r3 + ;; +.global ftrace_call; +ftrace_call: +{ + .mlx + nop.m 0x0 + movl r3 = .here;; +} + alloc loc0 = ar.pfs, 4, 4, 2, 0 + ;; + mov loc1 = b0 + mov out0 = b0 + mov loc2 = r8 + mov loc3 = r15 + ;; + adds out0 = -MCOUNT_INSN_SIZE, out0 + mov out1 = in2 + mov b6 = r3 + + br.call.sptk.many b0 = b6 + ;; + mov ar.pfs = loc0 + mov b0 = loc1 + mov r8 = loc2 + mov r15 = loc3 + br ftrace_stub + ;; +END(ftrace_caller) + +#else +GLOBAL_ENTRY(_mcount) + movl r2 = ftrace_stub + movl r3 = ftrace_trace_function;; + ld8 r3 = [r3];; + ld8 r3 = [r3];; + cmp.eq p7,p0 = r2, r3 +(p7) br.sptk.many ftrace_stub + ;; + + alloc loc0 = ar.pfs, 4, 4, 2, 0 + ;; + mov loc1 = b0 + mov out0 = b0 + mov loc2 = r8 + mov loc3 = r15 + ;; + adds out0 = -MCOUNT_INSN_SIZE, out0 + mov out1 = in2 + mov b6 = r3 + + br.call.sptk.many b0 = b6 + ;; + mov ar.pfs = loc0 + mov b0 = loc1 + mov r8 = loc2 + mov r15 = loc3 + br ftrace_stub + ;; +END(_mcount) +#endif + +GLOBAL_ENTRY(ftrace_stub) + mov r3 = b0 + movl r2 = _mcount_ret_helper + ;; + mov b6 = r2 + mov b7 = r3 + br.ret.sptk.many b6 + +_mcount_ret_helper: + mov b0 = r42 + mov r1 = r41 + mov ar.pfs = r40 + br b7 +END(ftrace_stub) + +#endif /* CONFIG_FUNCTION_TRACER */ + .rodata .align 8 .globl sys_call_table diff --git a/arch/ia64/kernel/ftrace.c b/arch/ia64/kernel/ftrace.c new file mode 100644 index 000000000000..7fc8c961b1f7 --- /dev/null +++ b/arch/ia64/kernel/ftrace.c @@ -0,0 +1,206 @@ +/* + * Dynamic function tracing support. + * + * Copyright (C) 2008 Shaohua Li <shaohua.li@intel.com> + * + * For licencing details, see COPYING. + * + * Defines low-level handling of mcount calls when the kernel + * is compiled with the -pg flag. When using dynamic ftrace, the + * mcount call-sites get patched lazily with NOP till they are + * enabled. All code mutation routines here take effect atomically. + */ + +#include <linux/uaccess.h> +#include <linux/ftrace.h> + +#include <asm/cacheflush.h> +#include <asm/patch.h> + +/* In IA64, each function will be added below two bundles with -pg option */ +static unsigned char __attribute__((aligned(8))) +ftrace_orig_code[MCOUNT_INSN_SIZE] = { + 0x02, 0x40, 0x31, 0x10, 0x80, 0x05, /* alloc r40=ar.pfs,12,8,0 */ + 0xb0, 0x02, 0x00, 0x00, 0x42, 0x40, /* mov r43=r0;; */ + 0x05, 0x00, 0xc4, 0x00, /* mov r42=b0 */ + 0x11, 0x48, 0x01, 0x02, 0x00, 0x21, /* mov r41=r1 */ + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* nop.i 0x0 */ + 0x08, 0x00, 0x00, 0x50 /* br.call.sptk.many b0 = _mcount;; */ +}; + +struct ftrace_orig_insn { + u64 dummy1, dummy2, dummy3; + u64 dummy4:64-41+13; + u64 imm20:20; + u64 dummy5:3; + u64 sign:1; + u64 dummy6:4; +}; + +/* mcount stub will be converted below for nop */ +static unsigned char ftrace_nop_code[MCOUNT_INSN_SIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MII] nop.m 0x0 */ + 0x30, 0x00, 0x00, 0x60, 0x00, 0x00, /* mov r3=ip */ + 0x00, 0x00, 0x04, 0x00, /* nop.i 0x0 */ + 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0x0 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* nop.x 0x0;; */ + 0x00, 0x00, 0x04, 0x00 +}; + +static unsigned char *ftrace_nop_replace(void) +{ + return ftrace_nop_code; +} + +/* + * mcount stub will be converted below for call + * Note: Just the last instruction is changed against nop + * */ +static unsigned char __attribute__((aligned(8))) +ftrace_call_code[MCOUNT_INSN_SIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MII] nop.m 0x0 */ + 0x30, 0x00, 0x00, 0x60, 0x00, 0x00, /* mov r3=ip */ + 0x00, 0x00, 0x04, 0x00, /* nop.i 0x0 */ + 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0x0 */ + 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, /* brl.many .;;*/ + 0xf8, 0xff, 0xff, 0xc8 +}; + +struct ftrace_call_insn { + u64 dummy1, dummy2; + u64 dummy3:48; + u64 imm39_l:16; + u64 imm39_h:23; + u64 dummy4:13; + u64 imm20:20; + u64 dummy5:3; + u64 i:1; + u64 dummy6:4; +}; + +static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) +{ + struct ftrace_call_insn *code = (void *)ftrace_call_code; + unsigned long offset = addr - (ip + 0x10); + + code->imm39_l = offset >> 24; + code->imm39_h = offset >> 40; + code->imm20 = offset >> 4; + code->i = offset >> 63; + return ftrace_call_code; +} + +static int +ftrace_modify_code(unsigned long ip, unsigned char *old_code, + unsigned char *new_code, int do_check) +{ + unsigned char replaced[MCOUNT_INSN_SIZE]; + + /* + * Note: Due to modules and __init, code can + * disappear and change, we need to protect against faulting + * as well as code changing. We do this by using the + * probe_kernel_* functions. + * + * No real locking needed, this code is run through + * kstop_machine, or before SMP starts. + */ + + if (!do_check) + goto skip_check; + + /* read the text we want to modify */ + if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE)) + return -EFAULT; + + /* Make sure it is what we expect it to be */ + if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0) + return -EINVAL; + +skip_check: + /* replace the text with the new text */ + if (probe_kernel_write(((void *)ip), new_code, MCOUNT_INSN_SIZE)) + return -EPERM; + flush_icache_range(ip, ip + MCOUNT_INSN_SIZE); + + return 0; +} + +static int ftrace_make_nop_check(struct dyn_ftrace *rec, unsigned long addr) +{ + unsigned char __attribute__((aligned(8))) replaced[MCOUNT_INSN_SIZE]; + unsigned long ip = rec->ip; + + if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE)) + return -EFAULT; + if (rec->flags & FTRACE_FL_CONVERTED) { + struct ftrace_call_insn *call_insn, *tmp_call; + + call_insn = (void *)ftrace_call_code; + tmp_call = (void *)replaced; + call_insn->imm39_l = tmp_call->imm39_l; + call_insn->imm39_h = tmp_call->imm39_h; + call_insn->imm20 = tmp_call->imm20; + call_insn->i = tmp_call->i; + if (memcmp(replaced, ftrace_call_code, MCOUNT_INSN_SIZE) != 0) + return -EINVAL; + return 0; + } else { + struct ftrace_orig_insn *call_insn, *tmp_call; + + call_insn = (void *)ftrace_orig_code; + tmp_call = (void *)replaced; + call_insn->sign = tmp_call->sign; + call_insn->imm20 = tmp_call->imm20; + if (memcmp(replaced, ftrace_orig_code, MCOUNT_INSN_SIZE) != 0) + return -EINVAL; + return 0; + } +} + +int ftrace_make_nop(struct module *mod, + struct dyn_ftrace *rec, unsigned long addr) +{ + int ret; + char *new; + + ret = ftrace_make_nop_check(rec, addr); + if (ret) + return ret; + new = ftrace_nop_replace(); + return ftrace_modify_code(rec->ip, NULL, new, 0); +} + +int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) +{ + unsigned long ip = rec->ip; + unsigned char *old, *new; + + old= ftrace_nop_replace(); + new = ftrace_call_replace(ip, addr); + return ftrace_modify_code(ip, old, new, 1); +} + +/* in IA64, _mcount can't directly call ftrace_stub. Only jump is ok */ +int ftrace_update_ftrace_func(ftrace_func_t func) +{ + unsigned long ip; + unsigned long addr = ((struct fnptr *)ftrace_call)->ip; + + if (func == ftrace_stub) + return 0; + ip = ((struct fnptr *)func)->ip; + + ia64_patch_imm64(addr + 2, ip); + + flush_icache_range(addr, addr + 16); + return 0; +} + +/* run from kstop_machine */ +int __init ftrace_dyn_arch_init(void *data) +{ + *(unsigned long *)data = 0; + + return 0; +} diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c index 6da1f20d7372..2d311864e359 100644 --- a/arch/ia64/kernel/ia64_ksyms.c +++ b/arch/ia64/kernel/ia64_ksyms.c @@ -112,3 +112,9 @@ EXPORT_SYMBOL_GPL(esi_call_phys); #endif extern char ia64_ivt[]; EXPORT_SYMBOL(ia64_ivt); + +#include <asm/ftrace.h> +#ifdef CONFIG_FUNCTION_TRACER +/* mcount is defined in assembly */ +EXPORT_SYMBOL(_mcount); +#endif diff --git a/arch/m68k/include/asm/ftrace.h b/arch/m68k/include/asm/ftrace.h new file mode 100644 index 000000000000..40a8c178f10d --- /dev/null +++ b/arch/m68k/include/asm/ftrace.h @@ -0,0 +1 @@ +/* empty */ diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index dc787190430a..998e5db8cc0f 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -134,7 +134,7 @@ config MACH_JAZZ help This a family of machines based on the MIPS R4030 chipset which was used by several vendors to build RISC/os and Windows NT workstations. - Members include the Acer PICA, MIPS Magnum 4000, MIPS Millenium and + Members include the Acer PICA, MIPS Magnum 4000, MIPS Millennium and Olivetti M700-10 workstations. config LASAT diff --git a/arch/mips/include/asm/ftrace.h b/arch/mips/include/asm/ftrace.h new file mode 100644 index 000000000000..40a8c178f10d --- /dev/null +++ b/arch/mips/include/asm/ftrace.h @@ -0,0 +1 @@ +/* empty */ diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c index 5b47d6b65275..cbcd7eb83bd1 100644 --- a/arch/mips/sgi-ip27/ip27-smp.c +++ b/arch/mips/sgi-ip27/ip27-smp.c @@ -221,7 +221,7 @@ static void __init ip27_smp_setup(void) * Assumption to be fixed: we're always booted on logical / physical * processor 0. While we're always running on logical processor 0 * this still means this is physical processor zero; it might for - * example be disabled in the firwware. + * example be disabled in the firmware. */ alloc_cpupda(0, 0); } diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 45192dce65c4..9e08d8a69fdf 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -346,7 +346,7 @@ config PHYP_DUMP help Hypervisor-assisted dump is meant to be a kdump replacement offering robustness and speed not possible without system - hypervisor assistence. + hypervisor assistance. If unsure, say "N" diff --git a/arch/powerpc/include/asm/mmzone.h b/arch/powerpc/include/asm/mmzone.h index 19f299b7e256..35acac90c8ca 100644 --- a/arch/powerpc/include/asm/mmzone.h +++ b/arch/powerpc/include/asm/mmzone.h @@ -8,6 +8,7 @@ #define _ASM_MMZONE_H_ #ifdef __KERNEL__ +#include <linux/cpumask.h> /* * generic non-linear memory support: diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c index 5b5d16b2cac8..5455943f16aa 100644 --- a/arch/powerpc/kernel/ftrace.c +++ b/arch/powerpc/kernel/ftrace.c @@ -557,7 +557,6 @@ extern void mod_return_to_handler(void); void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) { unsigned long old; - unsigned long long calltime; int faulted; struct ftrace_graph_ent trace; unsigned long return_hooker = (unsigned long)&return_to_handler; @@ -606,10 +605,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) return; } - calltime = cpu_clock(raw_smp_processor_id()); - - if (ftrace_push_return_trace(old, calltime, - self_addr, &trace.depth) == -EBUSY) { + if (ftrace_push_return_trace(old, self_addr, &trace.depth) == -EBUSY) { *parent = old; return; } diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index ffa2a9fd53d0..e3e87078d03f 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig @@ -293,7 +293,7 @@ config CPM config OF_RTC bool help - Uses information from the OF or flattened device tree to instatiate + Uses information from the OF or flattened device tree to instantiate platform devices for direct mapped RTC chips like the DS1742 or DS1743. source "arch/powerpc/sysdev/bestcomm/Kconfig" diff --git a/arch/powerpc/sysdev/bestcomm/Kconfig b/arch/powerpc/sysdev/bestcomm/Kconfig index 0b192a1c429d..29e427085efb 100644 --- a/arch/powerpc/sysdev/bestcomm/Kconfig +++ b/arch/powerpc/sysdev/bestcomm/Kconfig @@ -9,8 +9,8 @@ config PPC_BESTCOMM select PPC_LIB_RHEAP help BestComm is the name of the communication coprocessor found - on the Freescale MPC5200 family of processor. It's usage is - optionnal for some drivers (like ATA), but required for + on the Freescale MPC5200 family of processor. Its usage is + optional for some drivers (like ATA), but required for others (like FEC). If you want to use drivers that require DMA operations, diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h index 2009158a4502..72137bc907ac 100644 --- a/arch/s390/include/asm/smp.h +++ b/arch/s390/include/asm/smp.h @@ -92,12 +92,6 @@ extern void arch_send_call_function_ipi(cpumask_t mask); #endif #ifndef CONFIG_SMP -static inline void smp_send_stop(void) -{ - /* Disable all interrupts/machine checks */ - __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK); -} - #define hard_smp_processor_id() 0 #define smp_cpu_not_running(cpu) 1 #endif diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 8d50d527c595..2d52b515c241 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -640,10 +640,10 @@ config GUSA_RB depends on GUSA && CPU_SH3 || (CPU_SH4 && !CPU_SH4A) help Enabling this option will allow the kernel to implement some - atomic operations using a software implemention of load-locked/ + atomic operations using a software implementation of load-locked/ store-conditional (LLSC). On machines which do not have hardware LLSC, this should be more efficient than the other alternative of - disabling insterrupts around the atomic sequence. + disabling interrupts around the atomic sequence. endmenu diff --git a/arch/sparc/include/asm/mmzone.h b/arch/sparc/include/asm/mmzone.h index ebf5986c12ed..e8c648741ed4 100644 --- a/arch/sparc/include/asm/mmzone.h +++ b/arch/sparc/include/asm/mmzone.h @@ -3,6 +3,8 @@ #ifdef CONFIG_NEED_MULTIPLE_NODES +#include <linux/cpumask.h> + extern struct pglist_data *node_data[]; #define NODE_DATA(nid) (node_data[nid]) diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S index a46c3a21e26d..3a1b7bf03cff 100644 --- a/arch/sparc/kernel/head_64.S +++ b/arch/sparc/kernel/head_64.S @@ -686,7 +686,7 @@ tlb_fixup_done: * point. * * There used to be enormous complexity wrt. transferring - * over from the firwmare's trap table to the Linux kernel's. + * over from the firmware's trap table to the Linux kernel's. * For example, there was a chicken & egg problem wrt. building * the OBP page tables, yet needing to be on the Linux kernel * trap table (to translate PAGE_OFFSET addresses) in order to diff --git a/arch/um/include/asm/ftrace.h b/arch/um/include/asm/ftrace.h new file mode 100644 index 000000000000..40a8c178f10d --- /dev/null +++ b/arch/um/include/asm/ftrace.h @@ -0,0 +1 @@ +/* empty */ diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 3f27e5c0c9c9..5b2196ab8168 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -34,6 +34,8 @@ config X86 select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_TRACE_MCOUNT_TEST + select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE + select HAVE_FTRACE_SYSCALLS select HAVE_KVM select HAVE_ARCH_KGDB select HAVE_ARCH_TRACEHOOK @@ -1144,7 +1146,7 @@ config NODES_SHIFT depends on NEED_MULTIPLE_NODES ---help--- Specify the maximum number of NUMA Nodes available on the target - system. Increases memory reserved to accomodate various tables. + system. Increases memory reserved to accommodate various tables. config HAVE_ARCH_BOOTMEM def_bool y @@ -1322,7 +1324,7 @@ config MTRR_SANITIZER add writeback entries. Can be disabled with disable_mtrr_cleanup on the kernel command line. - The largest mtrr entry size for a continous block can be set with + The largest mtrr entry size for a continuous block can be set with mtrr_chunk_size. If unsure, say Y. diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index fb737ce5888d..6633b6e7505a 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile @@ -57,6 +57,7 @@ $(obj)/cpustr.h: $(obj)/mkcpustr FORCE # How to compile the 16-bit code. Note we always compile for -march=i386, # that way we can complain to the user if the CPU is insufficient. KBUILD_CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \ + -DDISABLE_BRANCH_PROFILING \ -Wall -Wstrict-prototypes \ -march=i386 -mregparm=3 \ -include $(srctree)/$(src)/code16gcc.h \ @@ -66,7 +67,7 @@ KBUILD_CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \ $(call cc-option, -fno-unit-at-a-time)) \ $(call cc-option, -fno-stack-protector) \ $(call cc-option, -mpreferred-stack-boundary=2) -KBUILD_CFLAGS += $(call cc-option,-m32) +KBUILD_CFLAGS += $(call cc-option, -m32) KBUILD_AFLAGS := $(KBUILD_CFLAGS) -D__ASSEMBLY__ $(obj)/bzImage: asflags-y := $(SVGA_MODE) diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 3ca4c194b8e5..65551c9f8571 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -8,6 +8,7 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma h KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 KBUILD_CFLAGS += -fno-strict-aliasing -fPIC +KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING cflags-$(CONFIG_X86_64) := -mcmodel=small KBUILD_CFLAGS += $(cflags-y) KBUILD_CFLAGS += $(call cc-option,-ffreestanding) diff --git a/arch/x86/include/asm/cacheflush.h b/arch/x86/include/asm/cacheflush.h index b3894bf52fcd..e55dfc1ad453 100644 --- a/arch/x86/include/asm/cacheflush.h +++ b/arch/x86/include/asm/cacheflush.h @@ -126,6 +126,11 @@ void clflush_cache_range(void *addr, unsigned int size); #ifdef CONFIG_DEBUG_RODATA void mark_rodata_ro(void); extern const int rodata_test_data; +void set_kernel_text_rw(void); +void set_kernel_text_ro(void); +#else +static inline void set_kernel_text_rw(void) { } +static inline void set_kernel_text_ro(void) { } #endif #ifdef CONFIG_DEBUG_RODATA_TEST diff --git a/arch/x86/include/asm/cpumask.h b/arch/x86/include/asm/cpumask.h index a7f3c75f8ad7..61c852fa346b 100644 --- a/arch/x86/include/asm/cpumask.h +++ b/arch/x86/include/asm/cpumask.h @@ -3,8 +3,6 @@ #ifndef __ASSEMBLY__ #include <linux/cpumask.h> -#ifdef CONFIG_X86_64 - extern cpumask_var_t cpu_callin_mask; extern cpumask_var_t cpu_callout_mask; extern cpumask_var_t cpu_initialized_mask; @@ -12,21 +10,5 @@ extern cpumask_var_t cpu_sibling_setup_mask; extern void setup_cpu_local_masks(void); -#else /* CONFIG_X86_32 */ - -extern cpumask_t cpu_callin_map; -extern cpumask_t cpu_callout_map; -extern cpumask_t cpu_initialized; -extern cpumask_t cpu_sibling_setup_map; - -#define cpu_callin_mask ((struct cpumask *)&cpu_callin_map) -#define cpu_callout_mask ((struct cpumask *)&cpu_callout_map) -#define cpu_initialized_mask ((struct cpumask *)&cpu_initialized) -#define cpu_sibling_setup_mask ((struct cpumask *)&cpu_sibling_setup_map) - -static inline void setup_cpu_local_masks(void) { } - -#endif /* CONFIG_X86_32 */ - #endif /* __ASSEMBLY__ */ #endif /* _ASM_X86_CPUMASK_H */ diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h index 63a79c77d220..81937a5dc77c 100644 --- a/arch/x86/include/asm/fixmap.h +++ b/arch/x86/include/asm/fixmap.h @@ -111,6 +111,8 @@ enum fixed_addresses { #ifdef CONFIG_PARAVIRT FIX_PARAVIRT_BOOTMAP, #endif + FIX_TEXT_POKE0, /* reserve 2 pages for text_poke() */ + FIX_TEXT_POKE1, __end_of_permanent_fixed_addresses, #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT FIX_OHCI1394_BASE, diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h index db24c2278be0..bd2c6511c887 100644 --- a/arch/x86/include/asm/ftrace.h +++ b/arch/x86/include/asm/ftrace.h @@ -28,6 +28,13 @@ #endif +/* FIXME: I don't want to stay hardcoded */ +#ifdef CONFIG_X86_64 +# define FTRACE_SYSCALL_MAX 296 +#else +# define FTRACE_SYSCALL_MAX 333 +#endif + #ifdef CONFIG_FUNCTION_TRACER #define MCOUNT_ADDR ((long)(mcount)) #define MCOUNT_INSN_SIZE 5 /* sizeof mcount call */ diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index a0301bfeb954..b51a1e8b0baf 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -89,12 +89,40 @@ extern void pci_iommu_alloc(void); /* MSI arch hook */ #define arch_setup_msi_irqs arch_setup_msi_irqs -#endif /* __KERNEL__ */ +#define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys) + +#if defined(CONFIG_X86_64) || defined(CONFIG_DMA_API_DEBUG) + +#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ + dma_addr_t ADDR_NAME; +#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \ + __u32 LEN_NAME; +#define pci_unmap_addr(PTR, ADDR_NAME) \ + ((PTR)->ADDR_NAME) +#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \ + (((PTR)->ADDR_NAME) = (VAL)) +#define pci_unmap_len(PTR, LEN_NAME) \ + ((PTR)->LEN_NAME) +#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ + (((PTR)->LEN_NAME) = (VAL)) -#ifdef CONFIG_X86_32 -# include "pci_32.h" #else -# include "pci_64.h" + +#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) dma_addr_t ADDR_NAME[0]; +#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) unsigned LEN_NAME[0]; +#define pci_unmap_addr(PTR, ADDR_NAME) sizeof((PTR)->ADDR_NAME) +#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \ + do { break; } while (pci_unmap_addr(PTR, ADDR_NAME)) +#define pci_unmap_len(PTR, LEN_NAME) sizeof((PTR)->LEN_NAME) +#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ + do { break; } while (pci_unmap_len(PTR, LEN_NAME)) + +#endif + +#endif /* __KERNEL__ */ + +#ifdef CONFIG_X86_64 +#include "pci_64.h" #endif /* implement the pci_ DMA API in terms of the generic device dma_ one */ @@ -112,11 +140,6 @@ static inline int __pcibus_to_node(const struct pci_bus *bus) return sd->node; } -static inline cpumask_t __pcibus_to_cpumask(struct pci_bus *bus) -{ - return node_to_cpumask(__pcibus_to_node(bus)); -} - static inline const struct cpumask * cpumask_of_pcibus(const struct pci_bus *bus) { diff --git a/arch/x86/include/asm/pci_32.h b/arch/x86/include/asm/pci_32.h deleted file mode 100644 index 6f1213a6ef4f..000000000000 --- a/arch/x86/include/asm/pci_32.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _ASM_X86_PCI_32_H -#define _ASM_X86_PCI_32_H - - -#ifdef __KERNEL__ - - -/* Dynamic DMA mapping stuff. - * i386 has everything mapped statically. - */ - -struct pci_dev; - -/* The PCI address space does equal the physical memory - * address space. The networking and block device layers use - * this boolean for bounce buffer decisions. - */ -#define PCI_DMA_BUS_IS_PHYS (1) - -/* pci_unmap_{page,single} is a nop so... */ -#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) dma_addr_t ADDR_NAME[0]; -#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) unsigned LEN_NAME[0]; -#define pci_unmap_addr(PTR, ADDR_NAME) sizeof((PTR)->ADDR_NAME) -#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \ - do { break; } while (pci_unmap_addr(PTR, ADDR_NAME)) -#define pci_unmap_len(PTR, LEN_NAME) sizeof((PTR)->LEN_NAME) -#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ - do { break; } while (pci_unmap_len(PTR, LEN_NAME)) - - -#endif /* __KERNEL__ */ - - -#endif /* _ASM_X86_PCI_32_H */ diff --git a/arch/x86/include/asm/pci_64.h b/arch/x86/include/asm/pci_64.h index 4da207982777..ae5e40f67daf 100644 --- a/arch/x86/include/asm/pci_64.h +++ b/arch/x86/include/asm/pci_64.h @@ -24,28 +24,6 @@ extern int (*pci_config_write)(int seg, int bus, int dev, int fn, extern void dma32_reserve_bootmem(void); -/* The PCI address space does equal the physical memory - * address space. The networking and block device layers use - * this boolean for bounce buffer decisions - * - * On AMD64 it mostly equals, but we set it to zero if a hardware - * IOMMU (gart) of sotware IOMMU (swiotlb) is available. - */ -#define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys) - -#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ - dma_addr_t ADDR_NAME; -#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \ - __u32 LEN_NAME; -#define pci_unmap_addr(PTR, ADDR_NAME) \ - ((PTR)->ADDR_NAME) -#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \ - (((PTR)->ADDR_NAME) = (VAL)) -#define pci_unmap_len(PTR, LEN_NAME) \ - ((PTR)->LEN_NAME) -#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ - (((PTR)->LEN_NAME) = (VAL)) - #endif /* __KERNEL__ */ #endif /* _ASM_X86_PCI_64_H */ diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index ae85a8d66a30..34c52370f2fe 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -94,7 +94,7 @@ struct cpuinfo_x86 { unsigned long loops_per_jiffy; #ifdef CONFIG_SMP /* cpus sharing the last level cache: */ - cpumask_t llc_shared_map; + cpumask_var_t llc_shared_map; #endif /* cpuid returned max cores value: */ u16 x86_max_cores; @@ -736,6 +736,7 @@ static inline void __sti_mwait(unsigned long eax, unsigned long ecx) extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx); extern void select_idle_routine(const struct cpuinfo_x86 *c); +extern void init_c1e_mask(void); extern unsigned long boot_option_idle_override; extern unsigned long idle_halt; diff --git a/arch/x86/include/asm/ptrace-abi.h b/arch/x86/include/asm/ptrace-abi.h index 8e0f8d199e05..86723035a515 100644 --- a/arch/x86/include/asm/ptrace-abi.h +++ b/arch/x86/include/asm/ptrace-abi.h @@ -80,8 +80,6 @@ #define PTRACE_SINGLEBLOCK 33 /* resume execution until next branch */ -#ifdef CONFIG_X86_PTRACE_BTS - #ifndef __ASSEMBLY__ #include <linux/types.h> @@ -140,6 +138,5 @@ struct ptrace_bts_config { BTS records are read from oldest to newest. Returns number of BTS records drained. */ -#endif /* CONFIG_X86_PTRACE_BTS */ #endif /* _ASM_X86_PTRACE_ABI_H */ diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 47d0e21f2b9e..19e0d88b966d 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -21,19 +21,19 @@ extern int smp_num_siblings; extern unsigned int num_processors; -DECLARE_PER_CPU(cpumask_t, cpu_sibling_map); -DECLARE_PER_CPU(cpumask_t, cpu_core_map); +DECLARE_PER_CPU(cpumask_var_t, cpu_sibling_map); +DECLARE_PER_CPU(cpumask_var_t, cpu_core_map); DECLARE_PER_CPU(u16, cpu_llc_id); DECLARE_PER_CPU(int, cpu_number); static inline struct cpumask *cpu_sibling_mask(int cpu) { - return &per_cpu(cpu_sibling_map, cpu); + return per_cpu(cpu_sibling_map, cpu); } static inline struct cpumask *cpu_core_mask(int cpu) { - return &per_cpu(cpu_core_map, cpu); + return per_cpu(cpu_core_map, cpu); } DECLARE_EARLY_PER_CPU(u16, x86_cpu_to_apicid); @@ -121,9 +121,10 @@ static inline void arch_send_call_function_single_ipi(int cpu) smp_ops.send_call_func_single_ipi(cpu); } -static inline void arch_send_call_function_ipi(cpumask_t mask) +#define arch_send_call_function_ipi_mask arch_send_call_function_ipi_mask +static inline void arch_send_call_function_ipi_mask(const struct cpumask *mask) { - smp_ops.send_call_func_ipi(&mask); + smp_ops.send_call_func_ipi(mask); } void cpu_disable_common(void); diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index df9d5f78385e..8820a73ae090 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -94,6 +94,7 @@ struct thread_info { #define TIF_FORCED_TF 24 /* true if TF in eflags artificially */ #define TIF_DEBUGCTLMSR 25 /* uses thread_struct.debugctlmsr */ #define TIF_DS_AREA_MSR 26 /* uses thread_struct.ds_area_msr */ +#define TIF_SYSCALL_FTRACE 27 /* for ftrace syscall instrumentation */ #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) @@ -115,15 +116,17 @@ struct thread_info { #define _TIF_FORCED_TF (1 << TIF_FORCED_TF) #define _TIF_DEBUGCTLMSR (1 << TIF_DEBUGCTLMSR) #define _TIF_DS_AREA_MSR (1 << TIF_DS_AREA_MSR) +#define _TIF_SYSCALL_FTRACE (1 << TIF_SYSCALL_FTRACE) /* work to do in syscall_trace_enter() */ #define _TIF_WORK_SYSCALL_ENTRY \ - (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_EMU | \ + (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_EMU | _TIF_SYSCALL_FTRACE | \ _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | _TIF_SINGLESTEP) /* work to do in syscall_trace_leave() */ #define _TIF_WORK_SYSCALL_EXIT \ - (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SINGLESTEP) + (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SINGLESTEP | \ + _TIF_SYSCALL_FTRACE) /* work to do on interrupt/exception return */ #define _TIF_WORK_MASK \ @@ -132,7 +135,7 @@ struct thread_info { _TIF_SINGLESTEP|_TIF_SECCOMP|_TIF_SYSCALL_EMU)) /* work to do on any return to user space */ -#define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP) +#define _TIF_ALLWORK_MASK ((0x0000FFFF & ~_TIF_SECCOMP) | _TIF_SYSCALL_FTRACE) /* Only used for 64 bit */ #define _TIF_DO_NOTIFY_MASK \ diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h index 744299c0b774..892b119dba6f 100644 --- a/arch/x86/include/asm/topology.h +++ b/arch/x86/include/asm/topology.h @@ -44,9 +44,6 @@ #ifdef CONFIG_X86_32 -/* Mappings between node number and cpus on that node. */ -extern cpumask_t node_to_cpumask_map[]; - /* Mappings between logical cpu number and node number */ extern int cpu_to_node_map[]; @@ -57,30 +54,8 @@ static inline int cpu_to_node(int cpu) } #define early_cpu_to_node(cpu) cpu_to_node(cpu) -/* Returns a bitmask of CPUs on Node 'node'. - * - * Side note: this function creates the returned cpumask on the stack - * so with a high NR_CPUS count, excessive stack space is used. The - * cpumask_of_node function should be used whenever possible. - */ -static inline cpumask_t node_to_cpumask(int node) -{ - return node_to_cpumask_map[node]; -} - -/* Returns a bitmask of CPUs on Node 'node'. */ -static inline const struct cpumask *cpumask_of_node(int node) -{ - return &node_to_cpumask_map[node]; -} - -static inline void setup_node_to_cpumask_map(void) { } - #else /* CONFIG_X86_64 */ -/* Mappings between node number and cpus on that node. */ -extern cpumask_t *node_to_cpumask_map; - /* Mappings between logical cpu number and node number */ DECLARE_EARLY_PER_CPU(int, x86_cpu_to_node_map); @@ -91,8 +66,6 @@ DECLARE_PER_CPU(int, node_number); #ifdef CONFIG_DEBUG_PER_CPU_MAPS extern int cpu_to_node(int cpu); extern int early_cpu_to_node(int cpu); -extern const cpumask_t *cpumask_of_node(int node); -extern cpumask_t node_to_cpumask(int node); #else /* !CONFIG_DEBUG_PER_CPU_MAPS */ @@ -108,42 +81,32 @@ static inline int early_cpu_to_node(int cpu) return early_per_cpu(x86_cpu_to_node_map, cpu); } -/* Returns a pointer to the cpumask of CPUs on Node 'node'. */ -static inline const cpumask_t *cpumask_of_node(int node) -{ - return &node_to_cpumask_map[node]; -} +#endif /* !CONFIG_DEBUG_PER_CPU_MAPS */ + +#endif /* CONFIG_X86_64 */ -/* Returns a bitmask of CPUs on Node 'node'. */ -static inline cpumask_t node_to_cpumask(int node) +/* Mappings between node number and cpus on that node. */ +extern cpumask_var_t node_to_cpumask_map[MAX_NUMNODES]; + +#ifdef CONFIG_DEBUG_PER_CPU_MAPS +extern const struct cpumask *cpumask_of_node(int node); +#else +/* Returns a pointer to the cpumask of CPUs on Node 'node'. */ +static inline const struct cpumask *cpumask_of_node(int node) { return node_to_cpumask_map[node]; } - -#endif /* !CONFIG_DEBUG_PER_CPU_MAPS */ +#endif extern void setup_node_to_cpumask_map(void); /* - * Replace default node_to_cpumask_ptr with optimized version - * Deprecated: use "const struct cpumask *mask = cpumask_of_node(node)" - */ -#define node_to_cpumask_ptr(v, node) \ - const cpumask_t *v = cpumask_of_node(node) - -#define node_to_cpumask_ptr_next(v, node) \ - v = cpumask_of_node(node) - -#endif /* CONFIG_X86_64 */ - -/* * Returns the number of the node containing Node 'node'. This * architecture is flat, so it is a pretty simple function! */ #define parent_node(node) (node) #define pcibus_to_node(bus) __pcibus_to_node(bus) -#define pcibus_to_cpumask(bus) __pcibus_to_cpumask(bus) #ifdef CONFIG_X86_32 extern unsigned long node_start_pfn[]; @@ -209,40 +172,24 @@ static inline int early_cpu_to_node(int cpu) return 0; } -static inline const cpumask_t *cpumask_of_node(int node) -{ - return &cpu_online_map; -} -static inline cpumask_t node_to_cpumask(int node) +static inline const struct cpumask *cpumask_of_node(int node) { - return cpu_online_map; + return cpu_online_mask; } static inline void setup_node_to_cpumask_map(void) { } -/* - * Replace default node_to_cpumask_ptr with optimized version - * Deprecated: use "const struct cpumask *mask = cpumask_of_node(node)" - */ -#define node_to_cpumask_ptr(v, node) \ - const cpumask_t *v = cpumask_of_node(node) - -#define node_to_cpumask_ptr_next(v, node) \ - v = cpumask_of_node(node) #endif #include <asm-generic/topology.h> -extern cpumask_t cpu_coregroup_map(int cpu); extern const struct cpumask *cpu_coregroup_mask(int cpu); #ifdef ENABLE_TOPO_DEFINES #define topology_physical_package_id(cpu) (cpu_data(cpu).phys_proc_id) #define topology_core_id(cpu) (cpu_data(cpu).cpu_core_id) -#define topology_core_siblings(cpu) (per_cpu(cpu_core_map, cpu)) -#define topology_thread_siblings(cpu) (per_cpu(cpu_sibling_map, cpu)) -#define topology_core_cpumask(cpu) (&per_cpu(cpu_core_map, cpu)) -#define topology_thread_cpumask(cpu) (&per_cpu(cpu_sibling_map, cpu)) +#define topology_core_cpumask(cpu) (per_cpu(cpu_core_map, cpu)) +#define topology_thread_cpumask(cpu) (per_cpu(cpu_sibling_map, cpu)) /* indicates that pointers to the topology cpumask_t maps are valid */ #define arch_provides_topology_pointers yes @@ -256,7 +203,7 @@ struct pci_bus; void set_pci_bus_resources_arch_default(struct pci_bus *b); #ifdef CONFIG_SMP -#define mc_capable() (cpus_weight(per_cpu(cpu_core_map, 0)) != nr_cpu_ids) +#define mc_capable() (cpumask_weight(cpu_core_mask(0)) != nr_cpu_ids) #define smt_capable() (smp_num_siblings > 1) #endif diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index c611ad64137f..145cce75cda7 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -66,7 +66,8 @@ obj-$(CONFIG_X86_MPPARSE) += mpparse.o obj-y += apic/ obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups_32.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o -obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o +obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o +obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o obj-$(CONFIG_KEXEC) += machine_kexec_$(BITS).o obj-$(CONFIG_KEXEC) += relocate_kernel_$(BITS).o crash.o obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 4c80f1557433..f57658702571 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -5,6 +5,7 @@ #include <linux/kprobes.h> #include <linux/mm.h> #include <linux/vmalloc.h> +#include <linux/memory.h> #include <asm/alternative.h> #include <asm/sections.h> #include <asm/pgtable.h> @@ -12,7 +13,9 @@ #include <asm/nmi.h> #include <asm/vsyscall.h> #include <asm/cacheflush.h> +#include <asm/tlbflush.h> #include <asm/io.h> +#include <asm/fixmap.h> #define MAX_PATCH_LEN (255-1) @@ -226,6 +229,7 @@ static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end) { u8 **ptr; + mutex_lock(&text_mutex); for (ptr = start; ptr < end; ptr++) { if (*ptr < text) continue; @@ -234,6 +238,7 @@ static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end) /* turn DS segment override prefix into lock prefix */ text_poke(*ptr, ((unsigned char []){0xf0}), 1); }; + mutex_unlock(&text_mutex); } static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end) @@ -243,6 +248,7 @@ static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end if (noreplace_smp) return; + mutex_lock(&text_mutex); for (ptr = start; ptr < end; ptr++) { if (*ptr < text) continue; @@ -251,6 +257,7 @@ static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end /* turn lock prefix into DS segment override prefix */ text_poke(*ptr, ((unsigned char []){0x3E}), 1); }; + mutex_unlock(&text_mutex); } struct smp_alt_module { @@ -500,15 +507,16 @@ void *text_poke_early(void *addr, const void *opcode, size_t len) * It means the size must be writable atomically and the address must be aligned * in a way that permits an atomic write. It also makes sure we fit on a single * page. + * + * Note: Must be called under text_mutex. */ void *__kprobes text_poke(void *addr, const void *opcode, size_t len) { + unsigned long flags; char *vaddr; - int nr_pages = 2; struct page *pages[2]; int i; - might_sleep(); if (!core_kernel_text((unsigned long)addr)) { pages[0] = vmalloc_to_page(addr); pages[1] = vmalloc_to_page(addr + PAGE_SIZE); @@ -518,18 +526,21 @@ void *__kprobes text_poke(void *addr, const void *opcode, size_t len) pages[1] = virt_to_page(addr + PAGE_SIZE); } BUG_ON(!pages[0]); - if (!pages[1]) - nr_pages = 1; - vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL); - BUG_ON(!vaddr); - local_irq_disable(); + local_irq_save(flags); + set_fixmap(FIX_TEXT_POKE0, page_to_phys(pages[0])); + if (pages[1]) + set_fixmap(FIX_TEXT_POKE1, page_to_phys(pages[1])); + vaddr = (char *)fix_to_virt(FIX_TEXT_POKE0); memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len); - local_irq_enable(); - vunmap(vaddr); + clear_fixmap(FIX_TEXT_POKE0); + if (pages[1]) + clear_fixmap(FIX_TEXT_POKE1); + local_flush_tlb(); sync_core(); /* Could also do a CLFLUSH here to speed up CPU recovery; but that causes hangs on some VIA CPUs. */ for (i = 0; i < len; i++) BUG_ON(((char *)addr)[i] != ((char *)opcode)[i]); + local_irq_restore(flags); return addr; } diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c index d806ecaa948f..676cdac385c0 100644 --- a/arch/x86/kernel/apic/bigsmp_32.c +++ b/arch/x86/kernel/apic/bigsmp_32.c @@ -26,12 +26,12 @@ static int bigsmp_apic_id_registered(void) return 1; } -static const cpumask_t *bigsmp_target_cpus(void) +static const struct cpumask *bigsmp_target_cpus(void) { #ifdef CONFIG_SMP - return &cpu_online_map; + return cpu_online_mask; #else - return &cpumask_of_cpu(0); + return cpumask_of(0); #endif } @@ -118,9 +118,9 @@ static int bigsmp_check_phys_apicid_present(int boot_cpu_physical_apicid) } /* As we are using single CPU as destination, pick only one CPU here */ -static unsigned int bigsmp_cpu_mask_to_apicid(const cpumask_t *cpumask) +static unsigned int bigsmp_cpu_mask_to_apicid(const struct cpumask *cpumask) { - return bigsmp_cpu_to_logical_apicid(first_cpu(*cpumask)); + return bigsmp_cpu_to_logical_apicid(cpumask_first(cpumask)); } static unsigned int bigsmp_cpu_mask_to_apicid_and(const struct cpumask *cpumask, @@ -188,10 +188,10 @@ static const struct dmi_system_id bigsmp_dmi_table[] = { { } /* NULL entry stops DMI scanning */ }; -static void bigsmp_vector_allocation_domain(int cpu, cpumask_t *retmask) +static void bigsmp_vector_allocation_domain(int cpu, struct cpumask *retmask) { - cpus_clear(*retmask); - cpu_set(cpu, *retmask); + cpumask_clear(retmask); + cpumask_set_cpu(cpu, retmask); } static int probe_bigsmp(void) diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c index 19588f2770ee..1c11b819f245 100644 --- a/arch/x86/kernel/apic/es7000_32.c +++ b/arch/x86/kernel/apic/es7000_32.c @@ -410,7 +410,7 @@ static void es7000_enable_apic_mode(void) WARN(1, "Command failed, status = %x\n", mip_status); } -static void es7000_vector_allocation_domain(int cpu, cpumask_t *retmask) +static void es7000_vector_allocation_domain(int cpu, struct cpumask *retmask) { /* Careful. Some cpus do not strictly honor the set of cpus * specified in the interrupt destination when using lowest @@ -420,7 +420,8 @@ static void es7000_vector_allocation_domain(int cpu, cpumask_t *retmask) * deliver interrupts to the wrong hyperthread when only one * hyperthread was specified in the interrupt desitination. */ - *retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } }; + cpumask_clear(retmask); + cpumask_bits(retmask)[0] = APIC_ALL_CPUS; } @@ -455,14 +456,14 @@ static int es7000_apic_id_registered(void) return 1; } -static const cpumask_t *target_cpus_cluster(void) +static const struct cpumask *target_cpus_cluster(void) { - return &CPU_MASK_ALL; + return cpu_all_mask; } -static const cpumask_t *es7000_target_cpus(void) +static const struct cpumask *es7000_target_cpus(void) { - return &cpumask_of_cpu(smp_processor_id()); + return cpumask_of(smp_processor_id()); } static unsigned long @@ -517,7 +518,7 @@ static void es7000_setup_apic_routing(void) "Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n", (apic_version[apic] == 0x14) ? "Physical Cluster" : "Logical Cluster", - nr_ioapics, cpus_addr(*es7000_target_cpus())[0]); + nr_ioapics, cpumask_bits(es7000_target_cpus())[0]); } static int es7000_apicid_to_node(int logical_apicid) @@ -572,7 +573,7 @@ static int es7000_check_phys_apicid_present(int cpu_physical_apicid) return 1; } -static unsigned int es7000_cpu_mask_to_apicid(const cpumask_t *cpumask) +static unsigned int es7000_cpu_mask_to_apicid(const struct cpumask *cpumask) { unsigned int round = 0; int cpu, uninitialized_var(apicid); diff --git a/arch/x86/kernel/apic/nmi.c b/arch/x86/kernel/apic/nmi.c index bdfad80c3cf1..d6bd62407152 100644 --- a/arch/x86/kernel/apic/nmi.c +++ b/arch/x86/kernel/apic/nmi.c @@ -39,7 +39,7 @@ int unknown_nmi_panic; int nmi_watchdog_enabled; -static cpumask_t backtrace_mask = CPU_MASK_NONE; +static cpumask_var_t backtrace_mask; /* nmi_active: * >0: the lapic NMI watchdog is active, but can be disabled @@ -138,6 +138,7 @@ int __init check_nmi_watchdog(void) if (!prev_nmi_count) goto error; + alloc_cpumask_var(&backtrace_mask, GFP_KERNEL); printk(KERN_INFO "Testing NMI watchdog ... "); #ifdef CONFIG_SMP @@ -413,14 +414,14 @@ nmi_watchdog_tick(struct pt_regs *regs, unsigned reason) touched = 1; } - if (cpu_isset(cpu, backtrace_mask)) { + if (cpumask_test_cpu(cpu, backtrace_mask)) { static DEFINE_SPINLOCK(lock); /* Serialise the printks */ spin_lock(&lock); printk(KERN_WARNING "NMI backtrace for cpu %d\n", cpu); dump_stack(); spin_unlock(&lock); - cpu_clear(cpu, backtrace_mask); + cpumask_clear_cpu(cpu, backtrace_mask); } /* Could check oops_in_progress here too, but it's safer not to */ @@ -554,10 +555,10 @@ void __trigger_all_cpu_backtrace(void) { int i; - backtrace_mask = cpu_online_map; + cpumask_copy(backtrace_mask, cpu_online_mask); /* Wait for up to 10 seconds for all CPUs to do the backtrace */ for (i = 0; i < 10 * 1000; i++) { - if (cpus_empty(backtrace_mask)) + if (cpumask_empty(backtrace_mask)) break; mdelay(1); } diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c index ba2fc6465534..533e59c6fc82 100644 --- a/arch/x86/kernel/apic/numaq_32.c +++ b/arch/x86/kernel/apic/numaq_32.c @@ -334,9 +334,9 @@ static inline void numaq_smp_callin_clear_local_apic(void) clear_local_APIC(); } -static inline const cpumask_t *numaq_target_cpus(void) +static inline const struct cpumask *numaq_target_cpus(void) { - return &CPU_MASK_ALL; + return cpu_all_mask; } static inline unsigned long @@ -427,7 +427,7 @@ static inline int numaq_check_phys_apicid_present(int boot_cpu_physical_apicid) * We use physical apicids here, not logical, so just return the default * physical broadcast to stop people from breaking us */ -static inline unsigned int numaq_cpu_mask_to_apicid(const cpumask_t *cpumask) +static unsigned int numaq_cpu_mask_to_apicid(const struct cpumask *cpumask) { return 0x0F; } @@ -462,7 +462,7 @@ static int probe_numaq(void) return found_numaq; } -static void numaq_vector_allocation_domain(int cpu, cpumask_t *retmask) +static void numaq_vector_allocation_domain(int cpu, struct cpumask *retmask) { /* Careful. Some cpus do not strictly honor the set of cpus * specified in the interrupt destination when using lowest @@ -472,7 +472,8 @@ static void numaq_vector_allocation_domain(int cpu, cpumask_t *retmask) * deliver interrupts to the wrong hyperthread when only one * hyperthread was specified in the interrupt desitination. */ - *retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } }; + cpumask_clear(retmask); + cpumask_bits(retmask)[0] = APIC_ALL_CPUS; } static void numaq_setup_portio_remap(void) diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c index 141c99a1c264..01eda2ac65e4 100644 --- a/arch/x86/kernel/apic/probe_32.c +++ b/arch/x86/kernel/apic/probe_32.c @@ -83,7 +83,8 @@ static void default_vector_allocation_domain(int cpu, struct cpumask *retmask) * deliver interrupts to the wrong hyperthread when only one * hyperthread was specified in the interrupt desitination. */ - *retmask = (cpumask_t) { { [0] = APIC_ALL_CPUS } }; + cpumask_clear(retmask); + cpumask_bits(retmask)[0] = APIC_ALL_CPUS; } /* should be called last. */ diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c index aac52fa873ff..9cfe1f415d81 100644 --- a/arch/x86/kernel/apic/summit_32.c +++ b/arch/x86/kernel/apic/summit_32.c @@ -53,23 +53,19 @@ static unsigned summit_get_apic_id(unsigned long x) return (x >> 24) & 0xFF; } -static inline void summit_send_IPI_mask(const cpumask_t *mask, int vector) +static inline void summit_send_IPI_mask(const struct cpumask *mask, int vector) { default_send_IPI_mask_sequence_logical(mask, vector); } static void summit_send_IPI_allbutself(int vector) { - cpumask_t mask = cpu_online_map; - cpu_clear(smp_processor_id(), mask); - - if (!cpus_empty(mask)) - summit_send_IPI_mask(&mask, vector); + default_send_IPI_mask_allbutself_logical(cpu_online_mask, vector); } static void summit_send_IPI_all(int vector) { - summit_send_IPI_mask(&cpu_online_map, vector); + summit_send_IPI_mask(cpu_online_mask, vector); } #include <asm/tsc.h> @@ -186,13 +182,13 @@ static inline int is_WPEG(struct rio_detail *rio){ #define SUMMIT_APIC_DFR_VALUE (APIC_DFR_CLUSTER) -static const cpumask_t *summit_target_cpus(void) +static const struct cpumask *summit_target_cpus(void) { /* CPU_MASK_ALL (0xff) has undefined behaviour with * dest_LowestPrio mode logical clustered apic interrupt routing * Just start on cpu 0. IRQ balancing will spread load */ - return &cpumask_of_cpu(0); + return cpumask_of(0); } static unsigned long summit_check_apicid_used(physid_mask_t bitmap, int apicid) @@ -289,7 +285,7 @@ static int summit_check_phys_apicid_present(int boot_cpu_physical_apicid) return 1; } -static unsigned int summit_cpu_mask_to_apicid(const cpumask_t *cpumask) +static unsigned int summit_cpu_mask_to_apicid(const struct cpumask *cpumask) { unsigned int round = 0; int cpu, apicid = 0; @@ -346,7 +342,7 @@ static int probe_summit(void) return 0; } -static void summit_vector_allocation_domain(int cpu, cpumask_t *retmask) +static void summit_vector_allocation_domain(int cpu, struct cpumask *retmask) { /* Careful. Some cpus do not strictly honor the set of cpus * specified in the interrupt destination when using lowest @@ -356,7 +352,8 @@ static void summit_vector_allocation_domain(int cpu, cpumask_t *retmask) * deliver interrupts to the wrong hyperthread when only one * hyperthread was specified in the interrupt desitination. */ - *retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } }; + cpumask_clear(retmask); + cpumask_bits(retmask)[0] = APIC_ALL_CPUS; } #ifdef CONFIG_X86_SUMMIT_NUMA diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index ac7783a67432..49e0939bac42 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c @@ -466,7 +466,7 @@ static const lookup_t error_table[] = { * @err: APM BIOS return code * * Write a meaningful log entry to the kernel log in the event of - * an APM error. + * an APM error. Note that this also handles (negative) kernel errors. */ static void apm_error(char *str, int err) @@ -478,43 +478,14 @@ static void apm_error(char *str, int err) break; if (i < ERROR_COUNT) printk(KERN_NOTICE "apm: %s: %s\n", str, error_table[i].msg); + else if (err < 0) + printk(KERN_NOTICE "apm: %s: linux error code %i\n", str, err); else printk(KERN_NOTICE "apm: %s: unknown error code %#2.2x\n", str, err); } /* - * Lock APM functionality to physical CPU 0 - */ - -#ifdef CONFIG_SMP - -static cpumask_t apm_save_cpus(void) -{ - cpumask_t x = current->cpus_allowed; - /* Some bioses don't like being called from CPU != 0 */ - set_cpus_allowed(current, cpumask_of_cpu(0)); - BUG_ON(smp_processor_id() != 0); - return x; -} - -static inline void apm_restore_cpus(cpumask_t mask) -{ - set_cpus_allowed(current, mask); -} - -#else - -/* - * No CPU lockdown needed on a uniprocessor - */ - -#define apm_save_cpus() (current->cpus_allowed) -#define apm_restore_cpus(x) (void)(x) - -#endif - -/* * These are the actual BIOS calls. Depending on APM_ZERO_SEGS and * apm_info.allow_ints, we are being really paranoid here! Not only * are interrupts disabled, but all the segment registers (except SS) @@ -568,16 +539,23 @@ static inline void apm_irq_restore(unsigned long flags) # define APM_DO_RESTORE_SEGS #endif +struct apm_bios_call { + u32 func; + /* In and out */ + u32 ebx; + u32 ecx; + /* Out only */ + u32 eax; + u32 edx; + u32 esi; + + /* Error: -ENOMEM, or bits 8-15 of eax */ + int err; +}; + /** - * apm_bios_call - Make an APM BIOS 32bit call - * @func: APM function to execute - * @ebx_in: EBX register for call entry - * @ecx_in: ECX register for call entry - * @eax: EAX register return - * @ebx: EBX register return - * @ecx: ECX register return - * @edx: EDX register return - * @esi: ESI register return + * __apm_bios_call - Make an APM BIOS 32bit call + * @_call: pointer to struct apm_bios_call. * * Make an APM call using the 32bit protected mode interface. The * caller is responsible for knowing if APM BIOS is configured and @@ -586,80 +564,142 @@ static inline void apm_irq_restore(unsigned long flags) * flag is loaded into AL. If there is an error, then the error * code is returned in AH (bits 8-15 of eax) and this function * returns non-zero. + * + * Note: this makes the call on the current CPU. */ - -static u8 apm_bios_call(u32 func, u32 ebx_in, u32 ecx_in, - u32 *eax, u32 *ebx, u32 *ecx, u32 *edx, u32 *esi) +static long __apm_bios_call(void *_call) { APM_DECL_SEGS unsigned long flags; - cpumask_t cpus; int cpu; struct desc_struct save_desc_40; struct desc_struct *gdt; - - cpus = apm_save_cpus(); + struct apm_bios_call *call = _call; cpu = get_cpu(); + BUG_ON(cpu != 0); gdt = get_cpu_gdt_table(cpu); save_desc_40 = gdt[0x40 / 8]; gdt[0x40 / 8] = bad_bios_desc; apm_irq_save(flags); APM_DO_SAVE_SEGS; - apm_bios_call_asm(func, ebx_in, ecx_in, eax, ebx, ecx, edx, esi); + apm_bios_call_asm(call->func, call->ebx, call->ecx, + &call->eax, &call->ebx, &call->ecx, &call->edx, + &call->esi); APM_DO_RESTORE_SEGS; apm_irq_restore(flags); gdt[0x40 / 8] = save_desc_40; put_cpu(); - apm_restore_cpus(cpus); - return *eax & 0xff; + return call->eax & 0xff; +} + +/* Run __apm_bios_call or __apm_bios_call_simple on CPU 0 */ +static int on_cpu0(long (*fn)(void *), struct apm_bios_call *call) +{ + int ret; + + /* Don't bother with work_on_cpu in the common case, so we don't + * have to worry about OOM or overhead. */ + if (get_cpu() == 0) { + ret = fn(call); + put_cpu(); + } else { + put_cpu(); + ret = work_on_cpu(0, fn, call); + } + + /* work_on_cpu can fail with -ENOMEM */ + if (ret < 0) + call->err = ret; + else + call->err = (call->eax >> 8) & 0xff; + + return ret; } /** - * apm_bios_call_simple - make a simple APM BIOS 32bit call - * @func: APM function to invoke - * @ebx_in: EBX register value for BIOS call - * @ecx_in: ECX register value for BIOS call - * @eax: EAX register on return from the BIOS call + * apm_bios_call - Make an APM BIOS 32bit call (on CPU 0) + * @call: the apm_bios_call registers. + * + * If there is an error, it is returned in @call.err. + */ +static int apm_bios_call(struct apm_bios_call *call) +{ + return on_cpu0(__apm_bios_call, call); +} + +/** + * __apm_bios_call_simple - Make an APM BIOS 32bit call (on CPU 0) + * @_call: pointer to struct apm_bios_call. * * Make a BIOS call that returns one value only, or just status. * If there is an error, then the error code is returned in AH - * (bits 8-15 of eax) and this function returns non-zero. This is - * used for simpler BIOS operations. This call may hold interrupts - * off for a long time on some laptops. + * (bits 8-15 of eax) and this function returns non-zero (it can + * also return -ENOMEM). This is used for simpler BIOS operations. + * This call may hold interrupts off for a long time on some laptops. + * + * Note: this makes the call on the current CPU. */ - -static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax) +static long __apm_bios_call_simple(void *_call) { u8 error; APM_DECL_SEGS unsigned long flags; - cpumask_t cpus; int cpu; struct desc_struct save_desc_40; struct desc_struct *gdt; - - cpus = apm_save_cpus(); + struct apm_bios_call *call = _call; cpu = get_cpu(); + BUG_ON(cpu != 0); gdt = get_cpu_gdt_table(cpu); save_desc_40 = gdt[0x40 / 8]; gdt[0x40 / 8] = bad_bios_desc; apm_irq_save(flags); APM_DO_SAVE_SEGS; - error = apm_bios_call_simple_asm(func, ebx_in, ecx_in, eax); + error = apm_bios_call_simple_asm(call->func, call->ebx, call->ecx, + &call->eax); APM_DO_RESTORE_SEGS; apm_irq_restore(flags); gdt[0x40 / 8] = save_desc_40; put_cpu(); - apm_restore_cpus(cpus); return error; } /** + * apm_bios_call_simple - make a simple APM BIOS 32bit call + * @func: APM function to invoke + * @ebx_in: EBX register value for BIOS call + * @ecx_in: ECX register value for BIOS call + * @eax: EAX register on return from the BIOS call + * @err: bits + * + * Make a BIOS call that returns one value only, or just status. + * If there is an error, then the error code is returned in @err + * and this function returns non-zero. This is used for simpler + * BIOS operations. This call may hold interrupts off for a long + * time on some laptops. + */ +static int apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax, + int *err) +{ + struct apm_bios_call call; + int ret; + + call.func = func; + call.ebx = ebx_in; + call.ecx = ecx_in; + + ret = on_cpu0(__apm_bios_call_simple, &call); + *eax = call.eax; + *err = call.err; + return ret; +} + +/** * apm_driver_version - APM driver version * @val: loaded with the APM version on return * @@ -678,9 +718,10 @@ static u8 apm_bios_call_simple(u32 func, u32 ebx_in, u32 ecx_in, u32 *eax) static int apm_driver_version(u_short *val) { u32 eax; + int err; - if (apm_bios_call_simple(APM_FUNC_VERSION, 0, *val, &eax)) - return (eax >> 8) & 0xff; + if (apm_bios_call_simple(APM_FUNC_VERSION, 0, *val, &eax, &err)) + return err; *val = eax; return APM_SUCCESS; } @@ -701,22 +742,21 @@ static int apm_driver_version(u_short *val) * that APM 1.2 is in use. If no messges are pending the value 0x80 * is returned (No power management events pending). */ - static int apm_get_event(apm_event_t *event, apm_eventinfo_t *info) { - u32 eax; - u32 ebx; - u32 ecx; - u32 dummy; + struct apm_bios_call call; - if (apm_bios_call(APM_FUNC_GET_EVENT, 0, 0, &eax, &ebx, &ecx, - &dummy, &dummy)) - return (eax >> 8) & 0xff; - *event = ebx; + call.func = APM_FUNC_GET_EVENT; + call.ebx = call.ecx = 0; + + if (apm_bios_call(&call)) + return call.err; + + *event = call.ebx; if (apm_info.connection_version < 0x0102) *info = ~0; /* indicate info not valid */ else - *info = ecx; + *info = call.ecx; return APM_SUCCESS; } @@ -737,9 +777,10 @@ static int apm_get_event(apm_event_t *event, apm_eventinfo_t *info) static int set_power_state(u_short what, u_short state) { u32 eax; + int err; - if (apm_bios_call_simple(APM_FUNC_SET_STATE, what, state, &eax)) - return (eax >> 8) & 0xff; + if (apm_bios_call_simple(APM_FUNC_SET_STATE, what, state, &eax, &err)) + return err; return APM_SUCCESS; } @@ -770,6 +811,7 @@ static int apm_do_idle(void) u8 ret = 0; int idled = 0; int polling; + int err; polling = !!(current_thread_info()->status & TS_POLLING); if (polling) { @@ -782,7 +824,7 @@ static int apm_do_idle(void) } if (!need_resched()) { idled = 1; - ret = apm_bios_call_simple(APM_FUNC_IDLE, 0, 0, &eax); + ret = apm_bios_call_simple(APM_FUNC_IDLE, 0, 0, &eax, &err); } if (polling) current_thread_info()->status |= TS_POLLING; @@ -797,8 +839,7 @@ static int apm_do_idle(void) * Only report the failure the first 5 times. */ if (++t < 5) { - printk(KERN_DEBUG "apm_do_idle failed (%d)\n", - (eax >> 8) & 0xff); + printk(KERN_DEBUG "apm_do_idle failed (%d)\n", err); t = jiffies; } return -1; @@ -816,9 +857,10 @@ static int apm_do_idle(void) static void apm_do_busy(void) { u32 dummy; + int err; if (clock_slowed || ALWAYS_CALL_BUSY) { - (void)apm_bios_call_simple(APM_FUNC_BUSY, 0, 0, &dummy); + (void)apm_bios_call_simple(APM_FUNC_BUSY, 0, 0, &dummy, &err); clock_slowed = 0; } } @@ -937,7 +979,7 @@ static void apm_power_off(void) /* Some bioses don't like being called from CPU != 0 */ if (apm_info.realmode_power_off) { - (void)apm_save_cpus(); + set_cpus_allowed_ptr(current, cpumask_of(0)); machine_real_restart(po_bios_call, sizeof(po_bios_call)); } else { (void)set_system_power_state(APM_STATE_OFF); @@ -956,12 +998,13 @@ static void apm_power_off(void) static int apm_enable_power_management(int enable) { u32 eax; + int err; if ((enable == 0) && (apm_info.bios.flags & APM_BIOS_DISENGAGED)) return APM_NOT_ENGAGED; if (apm_bios_call_simple(APM_FUNC_ENABLE_PM, APM_DEVICE_BALL, - enable, &eax)) - return (eax >> 8) & 0xff; + enable, &eax, &err)) + return err; if (enable) apm_info.bios.flags &= ~APM_BIOS_DISABLED; else @@ -986,24 +1029,23 @@ static int apm_enable_power_management(int enable) static int apm_get_power_status(u_short *status, u_short *bat, u_short *life) { - u32 eax; - u32 ebx; - u32 ecx; - u32 edx; - u32 dummy; + struct apm_bios_call call; + + call.func = APM_FUNC_GET_STATUS; + call.ebx = APM_DEVICE_ALL; + call.ecx = 0; if (apm_info.get_power_status_broken) return APM_32_UNSUPPORTED; - if (apm_bios_call(APM_FUNC_GET_STATUS, APM_DEVICE_ALL, 0, - &eax, &ebx, &ecx, &edx, &dummy)) - return (eax >> 8) & 0xff; - *status = ebx; - *bat = ecx; + if (apm_bios_call(&call)) + return call.err; + *status = call.ebx; + *bat = call.ecx; if (apm_info.get_power_status_swabinminutes) { - *life = swab16((u16)edx); + *life = swab16((u16)call.edx); *life |= 0x8000; } else - *life = edx; + *life = call.edx; return APM_SUCCESS; } @@ -1048,12 +1090,14 @@ static int apm_get_battery_status(u_short which, u_short *status, static int apm_engage_power_management(u_short device, int enable) { u32 eax; + int err; if ((enable == 0) && (device == APM_DEVICE_ALL) && (apm_info.bios.flags & APM_BIOS_DISABLED)) return APM_DISABLED; - if (apm_bios_call_simple(APM_FUNC_ENGAGE_PM, device, enable, &eax)) - return (eax >> 8) & 0xff; + if (apm_bios_call_simple(APM_FUNC_ENGAGE_PM, device, enable, + &eax, &err)) + return err; if (device == APM_DEVICE_ALL) { if (enable) apm_info.bios.flags &= ~APM_BIOS_DISENGAGED; @@ -1689,16 +1733,14 @@ static int apm(void *unused) char *power_stat; char *bat_stat; -#ifdef CONFIG_SMP /* 2002/08/01 - WT * This is to avoid random crashes at boot time during initialization * on SMP systems in case of "apm=power-off" mode. Seen on ASUS A7M266D. * Some bioses don't like being called from CPU != 0. * Method suggested by Ingo Molnar. */ - set_cpus_allowed(current, cpumask_of_cpu(0)); + set_cpus_allowed_ptr(current, cpumask_of(0)); BUG_ON(smp_processor_id() != 0); -#endif if (apm_info.connection_version == 0) { apm_info.connection_version = apm_info.bios.version; diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index e2962cc1e27b..c4f667896c28 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -41,8 +41,6 @@ #include "cpu.h" -#ifdef CONFIG_X86_64 - /* all of these masks are initialized in setup_cpu_local_masks() */ cpumask_var_t cpu_initialized_mask; cpumask_var_t cpu_callout_mask; @@ -60,16 +58,6 @@ void __init setup_cpu_local_masks(void) alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask); } -#else /* CONFIG_X86_32 */ - -cpumask_t cpu_sibling_setup_map; -cpumask_t cpu_callout_map; -cpumask_t cpu_initialized; -cpumask_t cpu_callin_map; - -#endif /* CONFIG_X86_32 */ - - static const struct cpu_dev *this_cpu __cpuinitdata; DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { @@ -859,6 +847,7 @@ static void vgetcpu_set_mode(void) void __init identify_boot_cpu(void) { identify_cpu(&boot_cpu_data); + init_c1e_mask(); #ifdef CONFIG_X86_32 sysenter_setup(); enable_sep_cpu(); diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index 23da96e57b17..05209b5cc6ca 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -33,7 +33,7 @@ #include <linux/cpufreq.h> #include <linux/compiler.h> #include <linux/dmi.h> -#include <linux/ftrace.h> +#include <trace/power.h> #include <linux/acpi.h> #include <linux/io.h> @@ -72,6 +72,8 @@ struct acpi_cpufreq_data { static DEFINE_PER_CPU(struct acpi_cpufreq_data *, drv_data); +DEFINE_TRACE(power_mark); + /* acpi_perf_data is a pointer to percpu data. */ static struct acpi_processor_performance *acpi_perf_data; diff --git a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c index 41ed94915f97..6ac55bd341ae 100644 --- a/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c +++ b/arch/x86/kernel/cpu/cpufreq/p4-clockmod.c @@ -211,7 +211,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) unsigned int i; #ifdef CONFIG_SMP - cpumask_copy(policy->cpus, &per_cpu(cpu_sibling_map, policy->cpu)); + cpumask_copy(policy->cpus, cpu_sibling_mask(policy->cpu)); #endif /* Errata workaround */ diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index a15ac94e0b9b..4709ead2db52 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c @@ -54,7 +54,10 @@ static DEFINE_PER_CPU(struct powernow_k8_data *, powernow_data); static int cpu_family = CPU_OPTERON; #ifndef CONFIG_SMP -DEFINE_PER_CPU(cpumask_t, cpu_core_map); +static inline const struct cpumask *cpu_core_mask(int cpu) +{ + return cpumask_of(0); +} #endif /* Return a frequency in MHz, given an input fid */ @@ -699,7 +702,7 @@ static int fill_powernow_table(struct powernow_k8_data *data, dprintk("cfid 0x%x, cvid 0x%x\n", data->currfid, data->currvid); data->powernow_table = powernow_table; - if (first_cpu(per_cpu(cpu_core_map, data->cpu)) == data->cpu) + if (cpumask_first(cpu_core_mask(data->cpu)) == data->cpu) print_basics(data); for (j = 0; j < data->numps; j++) @@ -862,7 +865,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) /* fill in data */ data->numps = data->acpi_data.state_count; - if (first_cpu(per_cpu(cpu_core_map, data->cpu)) == data->cpu) + if (cpumask_first(cpu_core_mask(data->cpu)) == data->cpu) print_basics(data); powernow_k8_acpi_pst_values(data, 0); @@ -1300,7 +1303,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) if (cpu_family == CPU_HW_PSTATE) cpumask_copy(pol->cpus, cpumask_of(pol->cpu)); else - cpumask_copy(pol->cpus, &per_cpu(cpu_core_map, pol->cpu)); + cpumask_copy(pol->cpus, cpu_core_mask(pol->cpu)); data->available_cores = pol->cpus; if (cpu_family == CPU_HW_PSTATE) @@ -1365,7 +1368,7 @@ static unsigned int powernowk8_get(unsigned int cpu) unsigned int khz = 0; unsigned int first; - first = first_cpu(per_cpu(cpu_core_map, cpu)); + first = cpumask_first(cpu_core_mask(cpu)); data = per_cpu(powernow_data, first); if (!data) diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c index 8bbb11adb315..016c1a4fa3fc 100644 --- a/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c +++ b/arch/x86/kernel/cpu/cpufreq/speedstep-ich.c @@ -321,7 +321,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) /* only run on CPU to be set, or on its sibling */ #ifdef CONFIG_SMP - cpumask_copy(policy->cpus, &per_cpu(cpu_sibling_map, policy->cpu)); + cpumask_copy(policy->cpus, cpu_sibling_mask(policy->cpu)); #endif cpus_allowed = current->cpus_allowed; diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index c471eb1a389c..483eda96e102 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -159,7 +159,7 @@ struct _cpuid4_info_regs { unsigned long can_disable; }; -#ifdef CONFIG_PCI +#if defined(CONFIG_PCI) && defined(CONFIG_SYSFS) static struct pci_device_id k8_nb_id[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1203) }, @@ -324,15 +324,6 @@ __cpuinit cpuid4_cache_lookup_regs(int index, return 0; } -static int -__cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf) -{ - struct _cpuid4_info_regs *leaf_regs = - (struct _cpuid4_info_regs *)this_leaf; - - return cpuid4_cache_lookup_regs(index, leaf_regs); -} - static int __cpuinit find_num_cache_leaves(void) { unsigned int eax, ebx, ecx, edx; @@ -508,6 +499,8 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) return l2; } +#ifdef CONFIG_SYSFS + /* pointer to _cpuid4_info array (for each cache leaf) */ static DEFINE_PER_CPU(struct _cpuid4_info *, cpuid4_info); #define CPUID4_INFO_IDX(x, y) (&((per_cpu(cpuid4_info, x))[y])) @@ -571,6 +564,15 @@ static void __cpuinit free_cache_attributes(unsigned int cpu) per_cpu(cpuid4_info, cpu) = NULL; } +static int +__cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf) +{ + struct _cpuid4_info_regs *leaf_regs = + (struct _cpuid4_info_regs *)this_leaf; + + return cpuid4_cache_lookup_regs(index, leaf_regs); +} + static void __cpuinit get_cpu_leaves(void *_retval) { int j, *retval = _retval, cpu = smp_processor_id(); @@ -612,8 +614,6 @@ static int __cpuinit detect_cache_attributes(unsigned int cpu) return retval; } -#ifdef CONFIG_SYSFS - #include <linux/kobject.h> #include <linux/sysfs.h> diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c index ca14604611ec..863f89568b1a 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_64.c @@ -990,7 +990,7 @@ static struct sysdev_attribute *mce_attributes[] = { NULL }; -static cpumask_t mce_device_initialized = CPU_MASK_NONE; +static cpumask_var_t mce_device_initialized; /* Per cpu sysdev init. All of the cpus still share the same ctl bank */ static __cpuinit int mce_create_device(unsigned int cpu) @@ -1021,7 +1021,7 @@ static __cpuinit int mce_create_device(unsigned int cpu) if (err) goto error2; } - cpu_set(cpu, mce_device_initialized); + cpumask_set_cpu(cpu, mce_device_initialized); return 0; error2: @@ -1043,7 +1043,7 @@ static __cpuinit void mce_remove_device(unsigned int cpu) { int i; - if (!cpu_isset(cpu, mce_device_initialized)) + if (!cpumask_test_cpu(cpu, mce_device_initialized)) return; for (i = 0; mce_attributes[i]; i++) @@ -1053,7 +1053,7 @@ static __cpuinit void mce_remove_device(unsigned int cpu) sysdev_remove_file(&per_cpu(device_mce, cpu), &bank_attrs[i]); sysdev_unregister(&per_cpu(device_mce,cpu)); - cpu_clear(cpu, mce_device_initialized); + cpumask_clear_cpu(cpu, mce_device_initialized); } /* Make sure there are no machine checks on offlined CPUs. */ @@ -1162,6 +1162,8 @@ static __init int mce_init_device(void) if (!mce_available(&boot_cpu_data)) return -EIO; + alloc_cpumask_var(&mce_device_initialized, GFP_KERNEL); + err = mce_init_banks(); if (err) return err; diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c index 7d01be868870..56dde9c4bc96 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c @@ -485,7 +485,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) #ifdef CONFIG_SMP if (cpu_data(cpu).cpu_core_id && shared_bank[bank]) { /* symlink */ - i = cpumask_first(&per_cpu(cpu_core_map, cpu)); + i = cpumask_first(cpu_core_mask(cpu)); /* first core not up yet */ if (cpu_data(i).cpu_core_id) @@ -505,7 +505,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) if (err) goto out; - cpumask_copy(b->cpus, &per_cpu(cpu_core_map, cpu)); + cpumask_copy(b->cpus, cpu_core_mask(cpu)); per_cpu(threshold_banks, cpu)[bank] = b; goto out; } @@ -529,7 +529,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) #ifndef CONFIG_SMP cpumask_setall(b->cpus); #else - cpumask_copy(b->cpus, &per_cpu(cpu_core_map, cpu)); + cpumask_copy(b->cpus, cpu_core_mask(cpu)); #endif per_cpu(threshold_banks, cpu)[bank] = b; diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c index 57df3d383470..d6b72df89d69 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c @@ -249,7 +249,7 @@ void cmci_rediscover(int dying) for_each_online_cpu (cpu) { if (cpu == dying) continue; - if (set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu))) + if (set_cpus_allowed_ptr(current, cpumask_of(cpu))) continue; /* Recheck banks in case CPUs don't all have the same */ if (cmci_supported(&banks)) diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index 37f28fc7cf95..0b776c09aff3 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c @@ -462,9 +462,6 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base, *base = base_hi << (32 - PAGE_SHIFT) | base_lo >> PAGE_SHIFT; *type = base_lo & 0xff; - printk(KERN_DEBUG " get_mtrr: cpu%d reg%02d base=%010lx size=%010lx %s\n", - cpu, reg, *base, *size, - mtrr_attrib_to_str(*type & 0xff)); out_put_cpu: put_cpu(); } diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c index d67e0e48bc2d..f93047fed791 100644 --- a/arch/x86/kernel/cpu/proc.c +++ b/arch/x86/kernel/cpu/proc.c @@ -14,7 +14,7 @@ static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c, if (c->x86_max_cores * smp_num_siblings > 1) { seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); seq_printf(m, "siblings\t: %d\n", - cpus_weight(per_cpu(cpu_core_map, cpu))); + cpumask_weight(cpu_sibling_mask(cpu))); seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id); seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); seq_printf(m, "apicid\t\t: %d\n", c->apicid); @@ -143,9 +143,9 @@ static int show_cpuinfo(struct seq_file *m, void *v) static void *c_start(struct seq_file *m, loff_t *pos) { if (*pos == 0) /* just in case, cpu 0 is not the first */ - *pos = first_cpu(cpu_online_map); + *pos = cpumask_first(cpu_online_mask); else - *pos = next_cpu_nr(*pos - 1, cpu_online_map); + *pos = cpumask_next(*pos - 1, cpu_online_mask); if ((*pos) < nr_cpu_ids) return &cpu_data(*pos); return NULL; diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index dd2130b0fb3e..95ea5fa7d444 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c @@ -15,6 +15,7 @@ #include <linux/bug.h> #include <linux/nmi.h> #include <linux/sysfs.h> +#include <linux/ftrace.h> #include <asm/stacktrace.h> @@ -196,6 +197,11 @@ unsigned __kprobes long oops_begin(void) int cpu; unsigned long flags; + /* notify the hw-branch tracer so it may disable tracing and + add the last trace to the trace buffer - + the earlier this happens, the more useful the trace. */ + trace_hw_branch_oops(); + oops_enter(); /* racy, but better than risking deadlock. */ diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index 76f7141e0f91..61df77532120 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c @@ -18,6 +18,7 @@ #include <linux/init.h> #include <linux/list.h> +#include <asm/cacheflush.h> #include <asm/ftrace.h> #include <linux/ftrace.h> #include <asm/nops.h> @@ -26,6 +27,18 @@ #ifdef CONFIG_DYNAMIC_FTRACE +int ftrace_arch_code_modify_prepare(void) +{ + set_kernel_text_rw(); + return 0; +} + +int ftrace_arch_code_modify_post_process(void) +{ + set_kernel_text_ro(); + return 0; +} + union ftrace_code_union { char code[MCOUNT_INSN_SIZE]; struct { @@ -66,11 +79,11 @@ static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) * * 1) Put the instruction pointer into the IP buffer * and the new code into the "code" buffer. - * 2) Set a flag that says we are modifying code - * 3) Wait for any running NMIs to finish. - * 4) Write the code - * 5) clear the flag. - * 6) Wait for any running NMIs to finish. + * 2) Wait for any running NMIs to finish and set a flag that says + * we are modifying code, it is done in an atomic operation. + * 3) Write the code + * 4) clear the flag. + * 5) Wait for any running NMIs to finish. * * If an NMI is executed, the first thing it does is to call * "ftrace_nmi_enter". This will check if the flag is set to write @@ -82,9 +95,9 @@ static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) * are the same as what exists. */ -static atomic_t in_nmi = ATOMIC_INIT(0); +#define MOD_CODE_WRITE_FLAG (1 << 31) /* set when NMI should do the write */ +static atomic_t nmi_running = ATOMIC_INIT(0); static int mod_code_status; /* holds return value of text write */ -static int mod_code_write; /* set when NMI should do the write */ static void *mod_code_ip; /* holds the IP to write to */ static void *mod_code_newcode; /* holds the text to write to the IP */ @@ -101,6 +114,20 @@ int ftrace_arch_read_dyn_info(char *buf, int size) return r; } +static void clear_mod_flag(void) +{ + int old = atomic_read(&nmi_running); + + for (;;) { + int new = old & ~MOD_CODE_WRITE_FLAG; + + if (old == new) + break; + + old = atomic_cmpxchg(&nmi_running, old, new); + } +} + static void ftrace_mod_code(void) { /* @@ -111,37 +138,52 @@ static void ftrace_mod_code(void) */ mod_code_status = probe_kernel_write(mod_code_ip, mod_code_newcode, MCOUNT_INSN_SIZE); + + /* if we fail, then kill any new writers */ + if (mod_code_status) + clear_mod_flag(); } void ftrace_nmi_enter(void) { - atomic_inc(&in_nmi); - /* Must have in_nmi seen before reading write flag */ - smp_mb(); - if (mod_code_write) { + if (atomic_inc_return(&nmi_running) & MOD_CODE_WRITE_FLAG) { + smp_rmb(); ftrace_mod_code(); atomic_inc(&nmi_update_count); } + /* Must have previous changes seen before executions */ + smp_mb(); } void ftrace_nmi_exit(void) { - /* Finish all executions before clearing in_nmi */ - smp_wmb(); - atomic_dec(&in_nmi); + /* Finish all executions before clearing nmi_running */ + smp_mb(); + atomic_dec(&nmi_running); +} + +static void wait_for_nmi_and_set_mod_flag(void) +{ + if (!atomic_cmpxchg(&nmi_running, 0, MOD_CODE_WRITE_FLAG)) + return; + + do { + cpu_relax(); + } while (atomic_cmpxchg(&nmi_running, 0, MOD_CODE_WRITE_FLAG)); + + nmi_wait_count++; } static void wait_for_nmi(void) { - int waited = 0; + if (!atomic_read(&nmi_running)) + return; - while (atomic_read(&in_nmi)) { - waited = 1; + do { cpu_relax(); - } + } while (atomic_read(&nmi_running)); - if (waited) - nmi_wait_count++; + nmi_wait_count++; } static int @@ -151,14 +193,9 @@ do_ftrace_mod_code(unsigned long ip, void *new_code) mod_code_newcode = new_code; /* The buffers need to be visible before we let NMIs write them */ - smp_wmb(); - - mod_code_write = 1; - - /* Make sure write bit is visible before we wait on NMIs */ smp_mb(); - wait_for_nmi(); + wait_for_nmi_and_set_mod_flag(); /* Make sure all running NMIs have finished before we write the code */ smp_mb(); @@ -166,13 +203,9 @@ do_ftrace_mod_code(unsigned long ip, void *new_code) ftrace_mod_code(); /* Make sure the write happens before clearing the bit */ - smp_wmb(); - - mod_code_write = 0; - - /* make sure NMIs see the cleared bit */ smp_mb(); + clear_mod_flag(); wait_for_nmi(); return mod_code_status; @@ -368,25 +401,6 @@ int ftrace_disable_ftrace_graph_caller(void) return ftrace_mod_jmp(ip, old_offset, new_offset); } -#else /* CONFIG_DYNAMIC_FTRACE */ - -/* - * These functions are picked from those used on - * this page for dynamic ftrace. They have been - * simplified to ignore all traces in NMI context. - */ -static atomic_t in_nmi; - -void ftrace_nmi_enter(void) -{ - atomic_inc(&in_nmi); -} - -void ftrace_nmi_exit(void) -{ - atomic_dec(&in_nmi); -} - #endif /* !CONFIG_DYNAMIC_FTRACE */ /* @@ -396,14 +410,13 @@ void ftrace_nmi_exit(void) void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) { unsigned long old; - unsigned long long calltime; int faulted; struct ftrace_graph_ent trace; unsigned long return_hooker = (unsigned long) &return_to_handler; /* Nmi's are currently unsupported */ - if (unlikely(atomic_read(&in_nmi))) + if (unlikely(in_nmi())) return; if (unlikely(atomic_read(¤t->tracing_graph_pause))) @@ -439,17 +452,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) return; } - if (unlikely(!__kernel_text_address(old))) { - ftrace_graph_stop(); - *parent = old; - WARN_ON(1); - return; - } - - calltime = cpu_clock(raw_smp_processor_id()); - - if (ftrace_push_return_trace(old, calltime, - self_addr, &trace.depth) == -EBUSY) { + if (ftrace_push_return_trace(old, self_addr, &trace.depth) == -EBUSY) { *parent = old; return; } @@ -463,3 +466,66 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) } } #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ + +#ifdef CONFIG_FTRACE_SYSCALLS + +extern unsigned long __start_syscalls_metadata[]; +extern unsigned long __stop_syscalls_metadata[]; +extern unsigned long *sys_call_table; + +static struct syscall_metadata **syscalls_metadata; + +static struct syscall_metadata *find_syscall_meta(unsigned long *syscall) +{ + struct syscall_metadata *start; + struct syscall_metadata *stop; + char str[KSYM_SYMBOL_LEN]; + + + start = (struct syscall_metadata *)__start_syscalls_metadata; + stop = (struct syscall_metadata *)__stop_syscalls_metadata; + kallsyms_lookup((unsigned long) syscall, NULL, NULL, NULL, str); + + for ( ; start < stop; start++) { + if (start->name && !strcmp(start->name, str)) + return start; + } + return NULL; +} + +struct syscall_metadata *syscall_nr_to_meta(int nr) +{ + if (!syscalls_metadata || nr >= FTRACE_SYSCALL_MAX || nr < 0) + return NULL; + + return syscalls_metadata[nr]; +} + +void arch_init_ftrace_syscalls(void) +{ + int i; + struct syscall_metadata *meta; + unsigned long **psys_syscall_table = &sys_call_table; + static atomic_t refs; + + if (atomic_inc_return(&refs) != 1) + goto end; + + syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * + FTRACE_SYSCALL_MAX, GFP_KERNEL); + if (!syscalls_metadata) { + WARN_ON(1); + return; + } + + for (i = 0; i < FTRACE_SYSCALL_MAX; i++) { + meta = find_syscall_meta(psys_syscall_table[i]); + syscalls_metadata[i] = meta; + } + return; + + /* Paranoid: avoid overflow */ +end: + atomic_dec(&refs); +} +#endif diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c index 55b94614e348..7b5169d2b000 100644 --- a/arch/x86/kernel/kprobes.c +++ b/arch/x86/kernel/kprobes.c @@ -638,13 +638,13 @@ static void __used __kprobes kretprobe_trampoline_holder(void) #else " pushf\n" /* - * Skip cs, ip, orig_ax. + * Skip cs, ip, orig_ax and gs. * trampoline_handler() will plug in these values */ - " subl $12, %esp\n" + " subl $16, %esp\n" " pushl %fs\n" - " pushl %ds\n" " pushl %es\n" + " pushl %ds\n" " pushl %eax\n" " pushl %ebp\n" " pushl %edi\n" @@ -655,10 +655,10 @@ static void __used __kprobes kretprobe_trampoline_holder(void) " movl %esp, %eax\n" " call trampoline_handler\n" /* Move flags to cs */ - " movl 52(%esp), %edx\n" - " movl %edx, 48(%esp)\n" + " movl 56(%esp), %edx\n" + " movl %edx, 52(%esp)\n" /* Replace saved flags with true return address. */ - " movl %eax, 52(%esp)\n" + " movl %eax, 56(%esp)\n" " popl %ebx\n" " popl %ecx\n" " popl %edx\n" @@ -666,8 +666,8 @@ static void __used __kprobes kretprobe_trampoline_holder(void) " popl %edi\n" " popl %ebp\n" " popl %eax\n" - /* Skip ip, orig_ax, es, ds, fs */ - " addl $20, %esp\n" + /* Skip ds, es, fs, gs, orig_ax and ip */ + " addl $24, %esp\n" " popf\n" #endif " ret\n"); @@ -691,6 +691,7 @@ static __used __kprobes void *trampoline_handler(struct pt_regs *regs) regs->cs = __KERNEL_CS; #else regs->cs = __KERNEL_CS | get_kernel_rpl(); + regs->gs = 0; #endif regs->ip = trampoline_address; regs->orig_ax = ~0UL; diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index c25fdb382292..453b5795a5c6 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -12,31 +12,30 @@ * * Licensed under the terms of the GNU General Public * License version 2. See file COPYING for details. -*/ - + */ +#include <linux/platform_device.h> #include <linux/capability.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/sched.h> -#include <linux/cpumask.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/vmalloc.h> #include <linux/miscdevice.h> +#include <linux/firmware.h> #include <linux/spinlock.h> -#include <linux/mm.h> -#include <linux/fs.h> +#include <linux/cpumask.h> +#include <linux/pci_ids.h> +#include <linux/uaccess.h> +#include <linux/vmalloc.h> +#include <linux/kernel.h> +#include <linux/module.h> #include <linux/mutex.h> +#include <linux/sched.h> +#include <linux/init.h> +#include <linux/slab.h> #include <linux/cpu.h> -#include <linux/firmware.h> -#include <linux/platform_device.h> #include <linux/pci.h> -#include <linux/pci_ids.h> -#include <linux/uaccess.h> +#include <linux/fs.h> +#include <linux/mm.h> -#include <asm/msr.h> -#include <asm/processor.h> #include <asm/microcode.h> +#include <asm/processor.h> +#include <asm/msr.h> MODULE_DESCRIPTION("AMD Microcode Update Driver"); MODULE_AUTHOR("Peter Oruba"); @@ -72,8 +71,8 @@ struct microcode_header_amd { } __attribute__((packed)); struct microcode_amd { - struct microcode_header_amd hdr; - unsigned int mpb[0]; + struct microcode_header_amd hdr; + unsigned int mpb[0]; }; #define UCODE_MAX_SIZE 2048 @@ -184,8 +183,8 @@ static int get_ucode_data(void *to, const u8 *from, size_t n) return 0; } -static void *get_next_ucode(const u8 *buf, unsigned int size, - unsigned int *mc_size) +static void * +get_next_ucode(const u8 *buf, unsigned int size, unsigned int *mc_size) { unsigned int total_size; u8 section_hdr[UCODE_CONTAINER_SECTION_HDR]; @@ -223,7 +222,6 @@ static void *get_next_ucode(const u8 *buf, unsigned int size, return mc; } - static int install_equiv_cpu_table(const u8 *buf) { u8 *container_hdr[UCODE_CONTAINER_HEADER_SIZE]; @@ -372,4 +370,3 @@ struct microcode_ops * __init init_amd_microcode(void) { return µcode_amd_ops; } - diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index c9b721ba968c..a0f3851ef310 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c @@ -70,67 +70,78 @@ * Fix sigmatch() macro to handle old CPUs with pf == 0. * Thanks to Stuart Swales for pointing out this bug. */ +#include <linux/platform_device.h> #include <linux/capability.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/sched.h> +#include <linux/miscdevice.h> +#include <linux/firmware.h> #include <linux/smp_lock.h> +#include <linux/spinlock.h> #include <linux/cpumask.h> -#include <linux/module.h> -#include <linux/slab.h> +#include <linux/uaccess.h> #include <linux/vmalloc.h> -#include <linux/miscdevice.h> -#include <linux/spinlock.h> -#include <linux/mm.h> -#include <linux/fs.h> +#include <linux/kernel.h> +#include <linux/module.h> #include <linux/mutex.h> +#include <linux/sched.h> +#include <linux/init.h> +#include <linux/slab.h> #include <linux/cpu.h> -#include <linux/firmware.h> -#include <linux/platform_device.h> +#include <linux/fs.h> +#include <linux/mm.h> -#include <asm/msr.h> -#include <asm/uaccess.h> -#include <asm/processor.h> #include <asm/microcode.h> +#include <asm/processor.h> +#include <asm/msr.h> MODULE_DESCRIPTION("Microcode Update Driver"); MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>"); MODULE_LICENSE("GPL"); -#define MICROCODE_VERSION "2.00" +#define MICROCODE_VERSION "2.00" -static struct microcode_ops *microcode_ops; +static struct microcode_ops *microcode_ops; /* no concurrent ->write()s are allowed on /dev/cpu/microcode */ static DEFINE_MUTEX(microcode_mutex); -struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; +struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; EXPORT_SYMBOL_GPL(ucode_cpu_info); #ifdef CONFIG_MICROCODE_OLD_INTERFACE +struct update_for_cpu { + const void __user *buf; + size_t size; +}; + +static long update_for_cpu(void *_ufc) +{ + struct update_for_cpu *ufc = _ufc; + int error; + + error = microcode_ops->request_microcode_user(smp_processor_id(), + ufc->buf, ufc->size); + if (error < 0) + return error; + if (!error) + microcode_ops->apply_microcode(smp_processor_id()); + return error; +} + static int do_microcode_update(const void __user *buf, size_t size) { - cpumask_t old; int error = 0; int cpu; - - old = current->cpus_allowed; + struct update_for_cpu ufc = { .buf = buf, .size = size }; for_each_online_cpu(cpu) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; if (!uci->valid) continue; - - set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); - error = microcode_ops->request_microcode_user(cpu, buf, size); + error = work_on_cpu(cpu, update_for_cpu, &ufc); if (error < 0) - goto out; - if (!error) - microcode_ops->apply_microcode(cpu); + break; } -out: - set_cpus_allowed_ptr(current, &old); return error; } @@ -198,18 +209,33 @@ static void microcode_dev_exit(void) MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); #else -#define microcode_dev_init() 0 -#define microcode_dev_exit() do { } while (0) +#define microcode_dev_init() 0 +#define microcode_dev_exit() do { } while (0) #endif /* fake device for request_firmware */ -static struct platform_device *microcode_pdev; +static struct platform_device *microcode_pdev; + +static long reload_for_cpu(void *unused) +{ + struct ucode_cpu_info *uci = ucode_cpu_info + smp_processor_id(); + int err = 0; + + mutex_lock(µcode_mutex); + if (uci->valid) { + err = microcode_ops->request_microcode_fw(smp_processor_id(), + µcode_pdev->dev); + if (!err) + microcode_ops->apply_microcode(smp_processor_id()); + } + mutex_unlock(µcode_mutex); + return err; +} static ssize_t reload_store(struct sys_device *dev, struct sysdev_attribute *attr, const char *buf, size_t sz) { - struct ucode_cpu_info *uci = ucode_cpu_info + dev->id; char *end; unsigned long val = simple_strtoul(buf, &end, 0); int err = 0; @@ -218,21 +244,9 @@ static ssize_t reload_store(struct sys_device *dev, if (end == buf) return -EINVAL; if (val == 1) { - cpumask_t old = current->cpus_allowed; - get_online_cpus(); - if (cpu_online(cpu)) { - set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); - mutex_lock(µcode_mutex); - if (uci->valid) { - err = microcode_ops->request_microcode_fw(cpu, - µcode_pdev->dev); - if (!err) - microcode_ops->apply_microcode(cpu); - } - mutex_unlock(µcode_mutex); - set_cpus_allowed_ptr(current, &old); - } + if (cpu_online(cpu)) + err = work_on_cpu(cpu, reload_for_cpu, NULL); put_online_cpus(); } if (err) @@ -268,8 +282,8 @@ static struct attribute *mc_default_attrs[] = { }; static struct attribute_group mc_attr_group = { - .attrs = mc_default_attrs, - .name = "microcode", + .attrs = mc_default_attrs, + .name = "microcode", }; static void __microcode_fini_cpu(int cpu) @@ -328,9 +342,9 @@ static int microcode_resume_cpu(int cpu) return 0; } -static void microcode_update_cpu(int cpu) +static long microcode_update_cpu(void *unused) { - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; + struct ucode_cpu_info *uci = ucode_cpu_info + smp_processor_id(); int err = 0; /* @@ -338,30 +352,27 @@ static void microcode_update_cpu(int cpu) * otherwise just request a firmware: */ if (uci->valid) { - err = microcode_resume_cpu(cpu); - } else { - collect_cpu_info(cpu); + err = microcode_resume_cpu(smp_processor_id()); + } else { + collect_cpu_info(smp_processor_id()); if (uci->valid && system_state == SYSTEM_RUNNING) - err = microcode_ops->request_microcode_fw(cpu, + err = microcode_ops->request_microcode_fw( + smp_processor_id(), µcode_pdev->dev); } if (!err) - microcode_ops->apply_microcode(cpu); + microcode_ops->apply_microcode(smp_processor_id()); + return err; } -static void microcode_init_cpu(int cpu) +static int microcode_init_cpu(int cpu) { - cpumask_t old = current->cpus_allowed; - - set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); - /* We should bind the task to the CPU */ - BUG_ON(raw_smp_processor_id() != cpu); - + int err; mutex_lock(µcode_mutex); - microcode_update_cpu(cpu); + err = work_on_cpu(cpu, microcode_update_cpu, NULL); mutex_unlock(µcode_mutex); - set_cpus_allowed_ptr(current, &old); + return err; } static int mc_sysdev_add(struct sys_device *sys_dev) @@ -379,8 +390,11 @@ static int mc_sysdev_add(struct sys_device *sys_dev) if (err) return err; - microcode_init_cpu(cpu); - return 0; + err = microcode_init_cpu(cpu); + if (err) + sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); + + return err; } static int mc_sysdev_remove(struct sys_device *sys_dev) @@ -404,14 +418,14 @@ static int mc_sysdev_resume(struct sys_device *dev) return 0; /* only CPU 0 will apply ucode here */ - microcode_update_cpu(0); + microcode_update_cpu(NULL); return 0; } static struct sysdev_driver mc_sysdev_driver = { - .add = mc_sysdev_add, - .remove = mc_sysdev_remove, - .resume = mc_sysdev_resume, + .add = mc_sysdev_add, + .remove = mc_sysdev_remove, + .resume = mc_sysdev_resume, }; static __cpuinit int @@ -424,7 +438,9 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) switch (action) { case CPU_ONLINE: case CPU_ONLINE_FROZEN: - microcode_init_cpu(cpu); + if (microcode_init_cpu(cpu)) + printk(KERN_ERR "microcode: failed to init CPU%d\n", + cpu); case CPU_DOWN_FAILED: case CPU_DOWN_FAILED_FROZEN: pr_debug("microcode: CPU%d added\n", cpu); @@ -448,7 +464,7 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) } static struct notifier_block __refdata mc_cpu_notifier = { - .notifier_call = mc_cpu_callback, + .notifier_call = mc_cpu_callback, }; static int __init microcode_init(void) diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index 5e9f4fc51385..149b9ec7c1ab 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -70,28 +70,28 @@ * Fix sigmatch() macro to handle old CPUs with pf == 0. * Thanks to Stuart Swales for pointing out this bug. */ +#include <linux/platform_device.h> #include <linux/capability.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/sched.h> +#include <linux/miscdevice.h> +#include <linux/firmware.h> #include <linux/smp_lock.h> +#include <linux/spinlock.h> #include <linux/cpumask.h> -#include <linux/module.h> -#include <linux/slab.h> +#include <linux/uaccess.h> #include <linux/vmalloc.h> -#include <linux/miscdevice.h> -#include <linux/spinlock.h> -#include <linux/mm.h> -#include <linux/fs.h> +#include <linux/kernel.h> +#include <linux/module.h> #include <linux/mutex.h> +#include <linux/sched.h> +#include <linux/init.h> +#include <linux/slab.h> #include <linux/cpu.h> -#include <linux/firmware.h> -#include <linux/platform_device.h> -#include <linux/uaccess.h> +#include <linux/fs.h> +#include <linux/mm.h> -#include <asm/msr.h> -#include <asm/processor.h> #include <asm/microcode.h> +#include <asm/processor.h> +#include <asm/msr.h> MODULE_DESCRIPTION("Microcode Update Driver"); MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>"); @@ -129,12 +129,13 @@ struct extended_sigtable { struct extended_signature sigs[0]; }; -#define DEFAULT_UCODE_DATASIZE (2000) +#define DEFAULT_UCODE_DATASIZE (2000) #define MC_HEADER_SIZE (sizeof(struct microcode_header_intel)) #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) #define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) #define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) #define DWSIZE (sizeof(u32)) + #define get_totalsize(mc) \ (((struct microcode_intel *)mc)->hdr.totalsize ? \ ((struct microcode_intel *)mc)->hdr.totalsize : \ @@ -197,30 +198,31 @@ static inline int update_match_cpu(struct cpu_signature *csig, int sig, int pf) } static inline int -update_match_revision(struct microcode_header_intel *mc_header, int rev) +update_match_revision(struct microcode_header_intel *mc_header, int rev) { return (mc_header->rev <= rev) ? 0 : 1; } static int microcode_sanity_check(void *mc) { + unsigned long total_size, data_size, ext_table_size; struct microcode_header_intel *mc_header = mc; struct extended_sigtable *ext_header = NULL; - struct extended_signature *ext_sig; - unsigned long total_size, data_size, ext_table_size; int sum, orig_sum, ext_sigcount = 0, i; + struct extended_signature *ext_sig; total_size = get_totalsize(mc_header); data_size = get_datasize(mc_header); + if (data_size + MC_HEADER_SIZE > total_size) { printk(KERN_ERR "microcode: error! " - "Bad data size in microcode data file\n"); + "Bad data size in microcode data file\n"); return -EINVAL; } if (mc_header->ldrver != 1 || mc_header->hdrver != 1) { printk(KERN_ERR "microcode: error! " - "Unknown microcode update format\n"); + "Unknown microcode update format\n"); return -EINVAL; } ext_table_size = total_size - (MC_HEADER_SIZE + data_size); @@ -318,11 +320,15 @@ get_matching_microcode(struct cpu_signature *cpu_sig, void *mc, int rev) static void apply_microcode(int cpu) { + struct microcode_intel *mc_intel; + struct ucode_cpu_info *uci; unsigned long flags; unsigned int val[2]; - int cpu_num = raw_smp_processor_id(); - struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - struct microcode_intel *mc_intel = uci->mc; + int cpu_num; + + cpu_num = raw_smp_processor_id(); + uci = ucode_cpu_info + cpu; + mc_intel = uci->mc; /* We should bind the task to the CPU */ BUG_ON(cpu_num != cpu); @@ -348,15 +354,17 @@ static void apply_microcode(int cpu) spin_unlock_irqrestore(µcode_update_lock, flags); if (val[1] != mc_intel->hdr.rev) { printk(KERN_ERR "microcode: CPU%d update from revision " - "0x%x to 0x%x failed\n", cpu_num, uci->cpu_sig.rev, val[1]); + "0x%x to 0x%x failed\n", + cpu_num, uci->cpu_sig.rev, val[1]); return; } printk(KERN_INFO "microcode: CPU%d updated from revision " - "0x%x to 0x%x, date = %04x-%02x-%02x \n", + "0x%x to 0x%x, date = %04x-%02x-%02x \n", cpu_num, uci->cpu_sig.rev, val[1], mc_intel->hdr.date & 0xffff, mc_intel->hdr.date >> 24, (mc_intel->hdr.date >> 16) & 0xff); + uci->cpu_sig.rev = val[1]; } @@ -404,18 +412,23 @@ static int generic_load_microcode(int cpu, void *data, size_t size, leftover -= mc_size; } - if (new_mc) { - if (!leftover) { - if (uci->mc) - vfree(uci->mc); - uci->mc = (struct microcode_intel *)new_mc; - pr_debug("microcode: CPU%d found a matching microcode update with" - " version 0x%x (current=0x%x)\n", - cpu, new_rev, uci->cpu_sig.rev); - } else - vfree(new_mc); + if (!new_mc) + goto out; + + if (leftover) { + vfree(new_mc); + goto out; } + if (uci->mc) + vfree(uci->mc); + uci->mc = (struct microcode_intel *)new_mc; + + pr_debug("microcode: CPU%d found a matching microcode update with" + " version 0x%x (current=0x%x)\n", + cpu, new_rev, uci->cpu_sig.rev); + + out: return (int)leftover; } diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 156f87582c6c..ca989158e847 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -8,7 +8,7 @@ #include <linux/module.h> #include <linux/pm.h> #include <linux/clockchips.h> -#include <linux/ftrace.h> +#include <trace/power.h> #include <asm/system.h> #include <asm/apic.h> #include <asm/idle.h> @@ -22,6 +22,9 @@ EXPORT_SYMBOL(idle_nomwait); struct kmem_cache *task_xstate_cachep; +DEFINE_TRACE(power_start); +DEFINE_TRACE(power_end); + int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) { *dst = *src; @@ -325,7 +328,7 @@ void stop_this_cpu(void *dummy) /* * Remove this CPU: */ - cpu_clear(smp_processor_id(), cpu_online_map); + set_cpu_online(smp_processor_id(), false); disable_local_APIC(); for (;;) { @@ -475,12 +478,13 @@ static int __cpuinit check_c1e_idle(const struct cpuinfo_x86 *c) return 1; } -static cpumask_t c1e_mask = CPU_MASK_NONE; +static cpumask_var_t c1e_mask; static int c1e_detected; void c1e_remove_cpu(int cpu) { - cpu_clear(cpu, c1e_mask); + if (c1e_mask != NULL) + cpumask_clear_cpu(cpu, c1e_mask); } /* @@ -509,8 +513,8 @@ static void c1e_idle(void) if (c1e_detected) { int cpu = smp_processor_id(); - if (!cpu_isset(cpu, c1e_mask)) { - cpu_set(cpu, c1e_mask); + if (!cpumask_test_cpu(cpu, c1e_mask)) { + cpumask_set_cpu(cpu, c1e_mask); /* * Force broadcast so ACPI can not interfere. Needs * to run with interrupts enabled as it uses @@ -562,6 +566,15 @@ void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) pm_idle = default_idle; } +void __init init_c1e_mask(void) +{ + /* If we're using c1e_idle, we need to allocate c1e_mask. */ + if (pm_idle == c1e_idle) { + alloc_cpumask_var(&c1e_mask, GFP_KERNEL); + cpumask_clear(c1e_mask); + } +} + static int __init idle_setup(char *str) { if (!str) diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index b7cc21bc6ae0..fe9345c967de 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -21,6 +21,7 @@ #include <linux/audit.h> #include <linux/seccomp.h> #include <linux/signal.h> +#include <linux/ftrace.h> #include <asm/uaccess.h> #include <asm/pgtable.h> @@ -1415,6 +1416,9 @@ asmregparm long syscall_trace_enter(struct pt_regs *regs) tracehook_report_syscall_entry(regs)) ret = -1L; + if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE))) + ftrace_syscall_enter(regs); + if (unlikely(current->audit_context)) { if (IS_IA32) audit_syscall_entry(AUDIT_ARCH_I386, @@ -1438,6 +1442,9 @@ asmregparm void syscall_trace_leave(struct pt_regs *regs) if (unlikely(current->audit_context)) audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax); + if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE))) + ftrace_syscall_exit(regs); + if (test_thread_flag(TIF_SYSCALL_TRACE)) tracehook_report_syscall_exit(regs, 0); diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 400331b50a53..3a97a4cf1872 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c @@ -153,7 +153,6 @@ static struct page * __init pcpur_get_page(unsigned int cpu, int pageno) static ssize_t __init setup_pcpu_remap(size_t static_size) { static struct vm_struct vm; - pg_data_t *last; size_t ptrs_size, dyn_size; unsigned int cpu; ssize_t ret; @@ -162,22 +161,9 @@ static ssize_t __init setup_pcpu_remap(size_t static_size) * If large page isn't supported, there's no benefit in doing * this. Also, on non-NUMA, embedding is better. */ - if (!cpu_has_pse || pcpu_need_numa()) + if (!cpu_has_pse || !pcpu_need_numa()) return -EINVAL; - last = NULL; - for_each_possible_cpu(cpu) { - int node = early_cpu_to_node(cpu); - - if (node_online(node) && NODE_DATA(node) && - last && last != NODE_DATA(node)) - goto proceed; - - last = NODE_DATA(node); - } - return -EINVAL; - -proceed: /* * Currently supports only single page. Supporting multiple * pages won't be too difficult if it ever becomes necessary. diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index dfcc74ab0ab6..14425166b8e3 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -221,7 +221,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, if (!onsigstack) { /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { - if (sas_ss_flags(sp) == 0) + if (current->sas_ss_size) sp = current->sas_ss_sp + current->sas_ss_size; } else { #ifdef CONFIG_X86_32 diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index ef7d10170c30..58d24ef917d8 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -101,11 +101,11 @@ EXPORT_SYMBOL(smp_num_siblings); DEFINE_PER_CPU(u16, cpu_llc_id) = BAD_APICID; /* representing HT siblings of each logical CPU */ -DEFINE_PER_CPU(cpumask_t, cpu_sibling_map); +DEFINE_PER_CPU(cpumask_var_t, cpu_sibling_map); EXPORT_PER_CPU_SYMBOL(cpu_sibling_map); /* representing HT and core siblings of each logical CPU */ -DEFINE_PER_CPU(cpumask_t, cpu_core_map); +DEFINE_PER_CPU(cpumask_var_t, cpu_core_map); EXPORT_PER_CPU_SYMBOL(cpu_core_map); /* Per CPU bogomips and other parameters */ @@ -115,11 +115,6 @@ EXPORT_PER_CPU_SYMBOL(cpu_info); atomic_t init_deasserted; #if defined(CONFIG_NUMA) && defined(CONFIG_X86_32) - -/* which logical CPUs are on which nodes */ -cpumask_t node_to_cpumask_map[MAX_NUMNODES] __read_mostly = - { [0 ... MAX_NUMNODES-1] = CPU_MASK_NONE }; -EXPORT_SYMBOL(node_to_cpumask_map); /* which node each logical CPU is on */ int cpu_to_node_map[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = 0 }; EXPORT_SYMBOL(cpu_to_node_map); @@ -128,7 +123,7 @@ EXPORT_SYMBOL(cpu_to_node_map); static void map_cpu_to_node(int cpu, int node) { printk(KERN_INFO "Mapping cpu %d to node %d\n", cpu, node); - cpumask_set_cpu(cpu, &node_to_cpumask_map[node]); + cpumask_set_cpu(cpu, node_to_cpumask_map[node]); cpu_to_node_map[cpu] = node; } @@ -139,7 +134,7 @@ static void unmap_cpu_to_node(int cpu) printk(KERN_INFO "Unmapping cpu %d from all nodes\n", cpu); for (node = 0; node < MAX_NUMNODES; node++) - cpumask_clear_cpu(cpu, &node_to_cpumask_map[node]); + cpumask_clear_cpu(cpu, node_to_cpumask_map[node]); cpu_to_node_map[cpu] = 0; } #else /* !(CONFIG_NUMA && CONFIG_X86_32) */ @@ -301,7 +296,7 @@ notrace static void __cpuinit start_secondary(void *unused) __flush_tlb_all(); #endif - /* This must be done before setting cpu_online_map */ + /* This must be done before setting cpu_online_mask */ set_cpu_sibling_map(raw_smp_processor_id()); wmb(); @@ -334,6 +329,23 @@ notrace static void __cpuinit start_secondary(void *unused) cpu_idle(); } +#ifdef CONFIG_CPUMASK_OFFSTACK +/* In this case, llc_shared_map is a pointer to a cpumask. */ +static inline void copy_cpuinfo_x86(struct cpuinfo_x86 *dst, + const struct cpuinfo_x86 *src) +{ + struct cpumask *llc = dst->llc_shared_map; + *dst = *src; + dst->llc_shared_map = llc; +} +#else +static inline void copy_cpuinfo_x86(struct cpuinfo_x86 *dst, + const struct cpuinfo_x86 *src) +{ + *dst = *src; +} +#endif /* CONFIG_CPUMASK_OFFSTACK */ + /* * The bootstrap kernel entry code has set these up. Save them for * a given CPU @@ -343,7 +355,7 @@ void __cpuinit smp_store_cpu_info(int id) { struct cpuinfo_x86 *c = &cpu_data(id); - *c = boot_cpu_data; + copy_cpuinfo_x86(c, &boot_cpu_data); c->cpu_index = id; if (id != 0) identify_secondary_cpu(c); @@ -367,15 +379,15 @@ void __cpuinit set_cpu_sibling_map(int cpu) cpumask_set_cpu(cpu, cpu_sibling_mask(i)); cpumask_set_cpu(i, cpu_core_mask(cpu)); cpumask_set_cpu(cpu, cpu_core_mask(i)); - cpumask_set_cpu(i, &c->llc_shared_map); - cpumask_set_cpu(cpu, &o->llc_shared_map); + cpumask_set_cpu(i, c->llc_shared_map); + cpumask_set_cpu(cpu, o->llc_shared_map); } } } else { cpumask_set_cpu(cpu, cpu_sibling_mask(cpu)); } - cpumask_set_cpu(cpu, &c->llc_shared_map); + cpumask_set_cpu(cpu, c->llc_shared_map); if (current_cpu_data.x86_max_cores == 1) { cpumask_copy(cpu_core_mask(cpu), cpu_sibling_mask(cpu)); @@ -386,8 +398,8 @@ void __cpuinit set_cpu_sibling_map(int cpu) for_each_cpu(i, cpu_sibling_setup_mask) { if (per_cpu(cpu_llc_id, cpu) != BAD_APICID && per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) { - cpumask_set_cpu(i, &c->llc_shared_map); - cpumask_set_cpu(cpu, &cpu_data(i).llc_shared_map); + cpumask_set_cpu(i, c->llc_shared_map); + cpumask_set_cpu(cpu, cpu_data(i).llc_shared_map); } if (c->phys_proc_id == cpu_data(i).phys_proc_id) { cpumask_set_cpu(i, cpu_core_mask(cpu)); @@ -425,12 +437,7 @@ const struct cpumask *cpu_coregroup_mask(int cpu) if (sched_mc_power_savings || sched_smt_power_savings) return cpu_core_mask(cpu); else - return &c->llc_shared_map; -} - -cpumask_t cpu_coregroup_map(int cpu) -{ - return *cpu_coregroup_mask(cpu); + return c->llc_shared_map; } static void impress_friends(void) @@ -897,9 +904,8 @@ int __cpuinit native_cpu_up(unsigned int cpu) */ static __init void disable_smp(void) { - /* use the read/write pointers to the present and possible maps */ - cpumask_copy(&cpu_present_map, cpumask_of(0)); - cpumask_copy(&cpu_possible_map, cpumask_of(0)); + init_cpu_present(cpumask_of(0)); + init_cpu_possible(cpumask_of(0)); smpboot_clear_io_apic_irqs(); if (smp_found_config) @@ -1031,6 +1037,8 @@ static void __init smp_cpu_index_default(void) */ void __init native_smp_prepare_cpus(unsigned int max_cpus) { + unsigned int i; + preempt_disable(); smp_cpu_index_default(); current_cpu_data = boot_cpu_data; @@ -1044,6 +1052,14 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) boot_cpu_logical_apicid = logical_smp_processor_id(); #endif current_thread_info()->cpu = 0; /* needed? */ + for_each_possible_cpu(i) { + alloc_cpumask_var(&per_cpu(cpu_sibling_map, i), GFP_KERNEL); + alloc_cpumask_var(&per_cpu(cpu_core_map, i), GFP_KERNEL); + alloc_cpumask_var(&cpu_data(i).llc_shared_map, GFP_KERNEL); + cpumask_clear(per_cpu(cpu_core_map, i)); + cpumask_clear(per_cpu(cpu_sibling_map, i)); + cpumask_clear(cpu_data(i).llc_shared_map); + } set_cpu_sibling_map(0); enable_IR_x2apic(); @@ -1132,11 +1148,11 @@ early_param("possible_cpus", _setup_possible_cpus); /* - * cpu_possible_map should be static, it cannot change as cpu's + * cpu_possible_mask should be static, it cannot change as cpu's * are onlined, or offlined. The reason is per-cpu data-structures * are allocated by some modules at init time, and dont expect to * do this dynamically on cpu arrival/departure. - * cpu_present_map on the other hand can change dynamically. + * cpu_present_mask on the other hand can change dynamically. * In case when cpu_hotplug is not compiled, then we resort to current * behaviour, which is cpu_possible == cpu_present. * - Ashok Raj diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c index 79c073247284..deb5ebb32c3b 100644 --- a/arch/x86/kernel/tlb_uv.c +++ b/arch/x86/kernel/tlb_uv.c @@ -275,6 +275,8 @@ const struct cpumask *uv_flush_send_and_wait(int cpu, int this_blade, return NULL; } +static DEFINE_PER_CPU(cpumask_var_t, uv_flush_tlb_mask); + /** * uv_flush_tlb_others - globally purge translation cache of a virtual * address or all TLB's @@ -304,8 +306,7 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, unsigned long va, unsigned int cpu) { - static DEFINE_PER_CPU(cpumask_t, flush_tlb_mask); - struct cpumask *flush_mask = &__get_cpu_var(flush_tlb_mask); + struct cpumask *flush_mask = __get_cpu_var(uv_flush_tlb_mask); int i; int bit; int blade; @@ -755,6 +756,10 @@ static int __init uv_bau_init(void) if (!is_uv_system()) return 0; + for_each_possible_cpu(cur_cpu) + alloc_cpumask_var_node(&per_cpu(uv_flush_tlb_mask, cur_cpu), + GFP_KERNEL, cpu_to_node(cur_cpu)); + uv_bau_retry_limit = 1; uv_nshift = uv_hub_info->n_val; uv_mmask = (1UL << uv_hub_info->n_val) - 1; diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index 0a303c3ed11f..a58504ea78cc 100644 --- a/arch/x86/kvm/Kconfig +++ b/arch/x86/kvm/Kconfig @@ -59,7 +59,8 @@ config KVM_AMD config KVM_TRACE bool "KVM trace support" - depends on KVM && MARKERS && SYSFS + depends on KVM && SYSFS + select MARKERS select RELAY select DEBUG_FS default n diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile index 08537747cb58..fdd30d08ab52 100644 --- a/arch/x86/mm/Makefile +++ b/arch/x86/mm/Makefile @@ -14,7 +14,7 @@ obj-$(CONFIG_MMIOTRACE) += mmiotrace.o mmiotrace-y := kmmio.o pf_in.o mmio-mod.o obj-$(CONFIG_MMIOTRACE_TEST) += testmmiotrace.o -obj-$(CONFIG_NUMA) += numa_$(BITS).o +obj-$(CONFIG_NUMA) += numa.o numa_$(BITS).o obj-$(CONFIG_K8_NUMA) += k8topology_64.o obj-$(CONFIG_ACPI_NUMA) += srat_$(BITS).o diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index db81e9a8556b..749559ed80f5 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -1054,17 +1054,47 @@ static noinline int do_test_wp_bit(void) const int rodata_test_data = 0xC3; EXPORT_SYMBOL_GPL(rodata_test_data); +static int kernel_set_to_readonly; + +void set_kernel_text_rw(void) +{ + unsigned long start = PFN_ALIGN(_text); + unsigned long size = PFN_ALIGN(_etext) - start; + + if (!kernel_set_to_readonly) + return; + + pr_debug("Set kernel text: %lx - %lx for read write\n", + start, start+size); + + set_pages_rw(virt_to_page(start), size >> PAGE_SHIFT); +} + +void set_kernel_text_ro(void) +{ + unsigned long start = PFN_ALIGN(_text); + unsigned long size = PFN_ALIGN(_etext) - start; + + if (!kernel_set_to_readonly) + return; + + pr_debug("Set kernel text: %lx - %lx for read only\n", + start, start+size); + + set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); +} + void mark_rodata_ro(void) { unsigned long start = PFN_ALIGN(_text); unsigned long size = PFN_ALIGN(_etext) - start; -#ifndef CONFIG_DYNAMIC_FTRACE - /* Dynamic tracing modifies the kernel text section */ set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); printk(KERN_INFO "Write protecting the kernel text: %luk\n", size >> 10); + kernel_set_to_readonly = 1; + #ifdef CONFIG_CPA_DEBUG printk(KERN_INFO "Testing CPA: Reverting %lx-%lx\n", start, start+size); @@ -1073,7 +1103,6 @@ void mark_rodata_ro(void) printk(KERN_INFO "Testing CPA: write protecting again\n"); set_pages_ro(virt_to_page(start), size>>PAGE_SHIFT); #endif -#endif /* CONFIG_DYNAMIC_FTRACE */ start += size; size = (unsigned long)__end_rodata - start; diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 54efa57d1c03..1753e8020df6 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -734,21 +734,48 @@ void __init mem_init(void) const int rodata_test_data = 0xC3; EXPORT_SYMBOL_GPL(rodata_test_data); +static int kernel_set_to_readonly; + +void set_kernel_text_rw(void) +{ + unsigned long start = PFN_ALIGN(_stext); + unsigned long end = PFN_ALIGN(__start_rodata); + + if (!kernel_set_to_readonly) + return; + + pr_debug("Set kernel text: %lx - %lx for read write\n", + start, end); + + set_memory_rw(start, (end - start) >> PAGE_SHIFT); +} + +void set_kernel_text_ro(void) +{ + unsigned long start = PFN_ALIGN(_stext); + unsigned long end = PFN_ALIGN(__start_rodata); + + if (!kernel_set_to_readonly) + return; + + pr_debug("Set kernel text: %lx - %lx for read only\n", + start, end); + + set_memory_ro(start, (end - start) >> PAGE_SHIFT); +} + void mark_rodata_ro(void) { unsigned long start = PFN_ALIGN(_stext), end = PFN_ALIGN(__end_rodata); unsigned long rodata_start = ((unsigned long)__start_rodata + PAGE_SIZE - 1) & PAGE_MASK; -#ifdef CONFIG_DYNAMIC_FTRACE - /* Dynamic tracing modifies the kernel text section */ - start = rodata_start; -#endif - printk(KERN_INFO "Write protecting the kernel read-only data: %luk\n", (end - start) >> 10); set_memory_ro(start, (end - start) >> PAGE_SHIFT); + kernel_set_to_readonly = 1; + /* * The rodata section (but not the kernel text!) should also be * not-executable. diff --git a/arch/x86/mm/iomap_32.c b/arch/x86/mm/iomap_32.c index e331f77348a7..8056545e2d39 100644 --- a/arch/x86/mm/iomap_32.c +++ b/arch/x86/mm/iomap_32.c @@ -23,7 +23,7 @@ int is_io_mapping_possible(resource_size_t base, unsigned long size) { -#ifndef CONFIG_X86_PAE +#if !defined(CONFIG_X86_PAE) && defined(CONFIG_PHYS_ADDR_T_64BIT) /* There is no way to map greater than 1 << 32 address without PAE */ if (base + size > 0x100000000ULL) return 0; diff --git a/arch/x86/mm/mmio-mod.c b/arch/x86/mm/mmio-mod.c index 2c4baa88f2cb..c9342ed8b402 100644 --- a/arch/x86/mm/mmio-mod.c +++ b/arch/x86/mm/mmio-mod.c @@ -378,27 +378,34 @@ static void clear_trace_list(void) } #ifdef CONFIG_HOTPLUG_CPU -static cpumask_t downed_cpus; +static cpumask_var_t downed_cpus; static void enter_uniprocessor(void) { int cpu; int err; + if (downed_cpus == NULL && + !alloc_cpumask_var(&downed_cpus, GFP_KERNEL)) { + pr_notice(NAME "Failed to allocate mask\n"); + goto out; + } + get_online_cpus(); - downed_cpus = cpu_online_map; - cpu_clear(first_cpu(cpu_online_map), downed_cpus); + cpumask_copy(downed_cpus, cpu_online_mask); + cpumask_clear_cpu(cpumask_first(cpu_online_mask), downed_cpus); if (num_online_cpus() > 1) pr_notice(NAME "Disabling non-boot CPUs...\n"); put_online_cpus(); - for_each_cpu_mask(cpu, downed_cpus) { + for_each_cpu(cpu, downed_cpus) { err = cpu_down(cpu); if (!err) pr_info(NAME "CPU%d is down.\n", cpu); else pr_err(NAME "Error taking CPU%d down: %d\n", cpu, err); } +out: if (num_online_cpus() > 1) pr_warning(NAME "multiple CPUs still online, " "may miss events.\n"); @@ -411,10 +418,10 @@ static void __ref leave_uniprocessor(void) int cpu; int err; - if (cpus_weight(downed_cpus) == 0) + if (downed_cpus == NULL || cpumask_weight(downed_cpus) == 0) return; pr_notice(NAME "Re-enabling CPUs...\n"); - for_each_cpu_mask(cpu, downed_cpus) { + for_each_cpu(cpu, downed_cpus) { err = cpu_up(cpu); if (!err) pr_info(NAME "enabled CPU%d.\n", cpu); diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c new file mode 100644 index 000000000000..550df481accd --- /dev/null +++ b/arch/x86/mm/numa.c @@ -0,0 +1,67 @@ +/* Common code for 32 and 64-bit NUMA */ +#include <linux/topology.h> +#include <linux/module.h> +#include <linux/bootmem.h> + +#ifdef CONFIG_DEBUG_PER_CPU_MAPS +# define DBG(x...) printk(KERN_DEBUG x) +#else +# define DBG(x...) +#endif + +/* + * Which logical CPUs are on which nodes + */ +cpumask_var_t node_to_cpumask_map[MAX_NUMNODES]; +EXPORT_SYMBOL(node_to_cpumask_map); + +/* + * Allocate node_to_cpumask_map based on number of available nodes + * Requires node_possible_map to be valid. + * + * Note: node_to_cpumask() is not valid until after this is done. + * (Use CONFIG_DEBUG_PER_CPU_MAPS to check this.) + */ +void __init setup_node_to_cpumask_map(void) +{ + unsigned int node, num = 0; + + /* setup nr_node_ids if not done yet */ + if (nr_node_ids == MAX_NUMNODES) { + for_each_node_mask(node, node_possible_map) + num = node; + nr_node_ids = num + 1; + } + + /* allocate the map */ + for (node = 0; node < nr_node_ids; node++) + alloc_bootmem_cpumask_var(&node_to_cpumask_map[node]); + + /* cpumask_of_node() will now work */ + pr_debug("Node to cpumask map for %d nodes\n", nr_node_ids); +} + +#ifdef CONFIG_DEBUG_PER_CPU_MAPS +/* + * Returns a pointer to the bitmask of CPUs on Node 'node'. + */ +const struct cpumask *cpumask_of_node(int node) +{ + if (node >= nr_node_ids) { + printk(KERN_WARNING + "cpumask_of_node(%d): node > nr_node_ids(%d)\n", + node, nr_node_ids); + dump_stack(); + return cpu_none_mask; + } + if (node_to_cpumask_map[node] == NULL) { + printk(KERN_WARNING + "cpumask_of_node(%d): no node_to_cpumask_map!\n", + node); + dump_stack(); + return cpu_online_mask; + } + return node_to_cpumask_map[node]; +} +EXPORT_SYMBOL(cpumask_of_node); +#endif diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c index 64c9cf043cdd..d73aaa892371 100644 --- a/arch/x86/mm/numa_64.c +++ b/arch/x86/mm/numa_64.c @@ -20,12 +20,6 @@ #include <asm/acpi.h> #include <asm/k8.h> -#ifdef CONFIG_DEBUG_PER_CPU_MAPS -# define DBG(x...) printk(KERN_DEBUG x) -#else -# define DBG(x...) -#endif - struct pglist_data *node_data[MAX_NUMNODES] __read_mostly; EXPORT_SYMBOL(node_data); @@ -49,12 +43,6 @@ DEFINE_EARLY_PER_CPU(int, x86_cpu_to_node_map, NUMA_NO_NODE); EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_node_map); /* - * Which logical CPUs are on which nodes - */ -cpumask_t *node_to_cpumask_map; -EXPORT_SYMBOL(node_to_cpumask_map); - -/* * Given a shift value, try to populate memnodemap[] * Returns : * 1 if OK @@ -661,36 +649,6 @@ void __init init_cpu_to_node(void) #endif -/* - * Allocate node_to_cpumask_map based on number of available nodes - * Requires node_possible_map to be valid. - * - * Note: node_to_cpumask() is not valid until after this is done. - * (Use CONFIG_DEBUG_PER_CPU_MAPS to check this.) - */ -void __init setup_node_to_cpumask_map(void) -{ - unsigned int node, num = 0; - cpumask_t *map; - - /* setup nr_node_ids if not done yet */ - if (nr_node_ids == MAX_NUMNODES) { - for_each_node_mask(node, node_possible_map) - num = node; - nr_node_ids = num + 1; - } - - /* allocate the map */ - map = alloc_bootmem_low(nr_node_ids * sizeof(cpumask_t)); - DBG("node_to_cpumask_map at %p for %d nodes\n", map, nr_node_ids); - - pr_debug("Node to cpumask map at %p for %d nodes\n", - map, nr_node_ids); - - /* node_to_cpumask() will now work */ - node_to_cpumask_map = map; -} - void __cpuinit numa_set_node(int cpu, int node) { int *cpu_to_node_map = early_per_cpu_ptr(x86_cpu_to_node_map); @@ -723,12 +681,12 @@ void __cpuinit numa_clear_node(int cpu) void __cpuinit numa_add_cpu(int cpu) { - cpu_set(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); + cpumask_set_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); } void __cpuinit numa_remove_cpu(int cpu) { - cpu_clear(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); + cpumask_clear_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); } #else /* CONFIG_DEBUG_PER_CPU_MAPS */ @@ -739,20 +697,20 @@ void __cpuinit numa_remove_cpu(int cpu) static void __cpuinit numa_set_cpumask(int cpu, int enable) { int node = early_cpu_to_node(cpu); - cpumask_t *mask; + struct cpumask *mask; char buf[64]; - if (node_to_cpumask_map == NULL) { - printk(KERN_ERR "node_to_cpumask_map NULL\n"); + mask = node_to_cpumask_map[node]; + if (mask == NULL) { + printk(KERN_ERR "node_to_cpumask_map[%i] NULL\n", node); dump_stack(); return; } - mask = &node_to_cpumask_map[node]; if (enable) - cpu_set(cpu, *mask); + cpumask_set_cpu(cpu, mask); else - cpu_clear(cpu, *mask); + cpumask_clear_cpu(cpu, mask); cpulist_scnprintf(buf, sizeof(buf), mask); printk(KERN_DEBUG "%s cpu %d node %d: mask now %s\n", @@ -799,59 +757,6 @@ int early_cpu_to_node(int cpu) return per_cpu(x86_cpu_to_node_map, cpu); } - -/* empty cpumask */ -static const cpumask_t cpu_mask_none; - -/* - * Returns a pointer to the bitmask of CPUs on Node 'node'. - */ -const cpumask_t *cpumask_of_node(int node) -{ - if (node_to_cpumask_map == NULL) { - printk(KERN_WARNING - "cpumask_of_node(%d): no node_to_cpumask_map!\n", - node); - dump_stack(); - return (const cpumask_t *)&cpu_online_map; - } - if (node >= nr_node_ids) { - printk(KERN_WARNING - "cpumask_of_node(%d): node > nr_node_ids(%d)\n", - node, nr_node_ids); - dump_stack(); - return &cpu_mask_none; - } - return &node_to_cpumask_map[node]; -} -EXPORT_SYMBOL(cpumask_of_node); - -/* - * Returns a bitmask of CPUs on Node 'node'. - * - * Side note: this function creates the returned cpumask on the stack - * so with a high NR_CPUS count, excessive stack space is used. The - * node_to_cpumask_ptr function should be used whenever possible. - */ -cpumask_t node_to_cpumask(int node) -{ - if (node_to_cpumask_map == NULL) { - printk(KERN_WARNING - "node_to_cpumask(%d): no node_to_cpumask_map!\n", node); - dump_stack(); - return cpu_online_map; - } - if (node >= nr_node_ids) { - printk(KERN_WARNING - "node_to_cpumask(%d): node > nr_node_ids(%d)\n", - node, nr_node_ids); - dump_stack(); - return cpu_mask_none; - } - return node_to_cpumask_map[node]; -} -EXPORT_SYMBOL(node_to_cpumask); - /* * --------- end of debug versions of the numa functions --------- */ diff --git a/arch/x86/oprofile/op_model_p4.c b/arch/x86/oprofile/op_model_p4.c index 4c4a51c90bc2..819b131fd752 100644 --- a/arch/x86/oprofile/op_model_p4.c +++ b/arch/x86/oprofile/op_model_p4.c @@ -380,7 +380,7 @@ static unsigned int get_stagger(void) { #ifdef CONFIG_SMP int cpu = smp_processor_id(); - return (cpu != first_cpu(per_cpu(cpu_sibling_map, cpu))); + return cpu != cpumask_first(__get_cpu_var(cpu_sibling_map)); #endif return 0; } diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index f234a37bd428..f1817f71e009 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -258,24 +258,7 @@ void pcibios_set_master(struct pci_dev *dev) pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); } -static void pci_unmap_page_range(struct vm_area_struct *vma) -{ - u64 addr = (u64)vma->vm_pgoff << PAGE_SHIFT; - free_memtype(addr, addr + vma->vm_end - vma->vm_start); -} - -static void pci_track_mmap_page_range(struct vm_area_struct *vma) -{ - u64 addr = (u64)vma->vm_pgoff << PAGE_SHIFT; - unsigned long flags = pgprot_val(vma->vm_page_prot) - & _PAGE_CACHE_MASK; - - reserve_memtype(addr, addr + vma->vm_end - vma->vm_start, flags, NULL); -} - static struct vm_operations_struct pci_mmap_ops = { - .open = pci_track_mmap_page_range, - .close = pci_unmap_page_range, .access = generic_access_phys, }; @@ -283,11 +266,6 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine) { unsigned long prot; - u64 addr = vma->vm_pgoff << PAGE_SHIFT; - unsigned long len = vma->vm_end - vma->vm_start; - unsigned long flags; - unsigned long new_flags; - int retval; /* I/O space cannot be accessed via normal processor loads and * stores on this platform. @@ -308,30 +286,6 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, vma->vm_page_prot = __pgprot(prot); - flags = pgprot_val(vma->vm_page_prot) & _PAGE_CACHE_MASK; - retval = reserve_memtype(addr, addr + len, flags, &new_flags); - if (retval) - return retval; - - if (flags != new_flags) { - if (!is_new_memtype_allowed(flags, new_flags)) { - free_memtype(addr, addr+len); - return -EINVAL; - } - flags = new_flags; - vma->vm_page_prot = __pgprot( - (pgprot_val(vma->vm_page_prot) & ~_PAGE_CACHE_MASK) | - flags); - } - - if (((vma->vm_pgoff < max_low_pfn_mapped) || - (vma->vm_pgoff >= (1UL<<(32 - PAGE_SHIFT)) && - vma->vm_pgoff < max_pfn_mapped)) && - ioremap_change_attr((unsigned long)__va(addr), len, flags)) { - free_memtype(addr, addr + len); - return -EINVAL; - } - if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot)) diff --git a/arch/x86/power/Makefile b/arch/x86/power/Makefile index 9ff4d5b55ad1..58b32db33125 100644 --- a/arch/x86/power/Makefile +++ b/arch/x86/power/Makefile @@ -1,2 +1,7 @@ +# __restore_processor_state() restores %gs after S3 resume and so should not +# itself be stack-protected +nostackp := $(call cc-option, -fno-stack-protector) +CFLAGS_cpu_$(BITS).o := $(nostackp) + obj-$(CONFIG_PM_SLEEP) += cpu_$(BITS).o obj-$(CONFIG_HIBERNATION) += hibernate_$(BITS).o hibernate_asm_$(BITS).o diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 8d470562ffc9..585a6e330837 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -158,7 +158,7 @@ static void __init xen_fill_possible_map(void) rc = HYPERVISOR_vcpu_op(VCPUOP_is_up, i, NULL); if (rc >= 0) { num_processors++; - cpu_set(i, cpu_possible_map); + set_cpu_possible(i, true); } } } @@ -197,7 +197,7 @@ static void __init xen_smp_prepare_cpus(unsigned int max_cpus) while ((num_possible_cpus() > 1) && (num_possible_cpus() > max_cpus)) { for (cpu = nr_cpu_ids - 1; !cpu_possible(cpu); cpu--) continue; - cpu_clear(cpu, cpu_possible_map); + set_cpu_possible(cpu, false); } for_each_possible_cpu (cpu) { @@ -210,7 +210,7 @@ static void __init xen_smp_prepare_cpus(unsigned int max_cpus) if (IS_ERR(idle)) panic("failed fork for CPU %d", cpu); - cpu_set(cpu, cpu_present_map); + set_cpu_present(cpu, true); } } diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 981200830432..fa6dc4dd3b19 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -4,16 +4,13 @@ mainmenu "Linux/Xtensa Kernel Configuration" config FRAME_POINTER - bool - default n + def_bool n config ZONE_DMA - bool - default y + def_bool y config XTENSA - bool - default y + def_bool y select HAVE_IDE help Xtensa processors are 32-bit RISC machines designed by Tensilica @@ -24,28 +21,25 @@ config XTENSA a home page at <http://xtensa.sourceforge.net/>. config RWSEM_XCHGADD_ALGORITHM - bool - default y + def_bool y config GENERIC_FIND_NEXT_BIT - bool - default y + def_bool y config GENERIC_HWEIGHT - bool - default y + def_bool y config GENERIC_HARDIRQS - bool - default y + def_bool y + +config GENERIC_GPIO + def_bool y config ARCH_HAS_ILOG2_U32 - bool - default n + def_bool n config ARCH_HAS_ILOG2_U64 - bool - default n + def_bool n config NO_IOPORT def_bool y @@ -54,9 +48,18 @@ config HZ int default 100 +config GENERIC_TIME + def_bool y + source "init/Kconfig" source "kernel/Kconfig.freezer" +config MMU + def_bool n + +config VARIANT_IRQ_SWITCH + def_bool n + menu "Processor type and features" choice @@ -65,38 +68,41 @@ choice config XTENSA_VARIANT_FSF bool "fsf - default (not generic) configuration" + select MMU config XTENSA_VARIANT_DC232B bool "dc232b - Diamond 232L Standard Core Rev.B (LE)" + select MMU help - This variant refers to Tensilica's Diamond 232L Standard core Rev.B (LE). -endchoice + This variant refers to Tensilica's Diamond 232L Standard core Rev.B (LE). -config MMU - bool - default y +config XTENSA_VARIANT_S6000 + bool "s6000 - Stretch software configurable processor" + select VARIANT_IRQ_SWITCH + select ARCH_REQUIRE_GPIOLIB +endchoice config XTENSA_UNALIGNED_USER bool "Unaligned memory access in use space" - ---help--- - The Xtensa architecture currently does not handle unaligned - memory accesses in hardware but through an exception handler. - Per default, unaligned memory accesses are disabled in user space. + help + The Xtensa architecture currently does not handle unaligned + memory accesses in hardware but through an exception handler. + Per default, unaligned memory accesses are disabled in user space. - Say Y here to enable unaligned memory access in user space. + Say Y here to enable unaligned memory access in user space. config PREEMPT bool "Preemptible Kernel" - ---help--- - This option reduces the latency of the kernel when reacting to - real-time or interactive events by allowing a low priority process to - be preempted even if it is in kernel mode executing a system call. - Unfortunately the kernel code has some race conditions if both - CONFIG_SMP and CONFIG_PREEMPT are enabled, so this option is - currently disabled if you are building an SMP kernel. + help + This option reduces the latency of the kernel when reacting to + real-time or interactive events by allowing a low priority process to + be preempted even if it is in kernel mode executing a system call. + Unfortunately the kernel code has some race conditions if both + CONFIG_SMP and CONFIG_PREEMPT are enabled, so this option is + currently disabled if you are building an SMP kernel. - Say Y here if you are building a kernel for a desktop, embedded - or real-time system. Say N if you are unsure. + Say Y here if you are building a kernel for a desktop, embedded + or real-time system. Say N if you are unsure. config MATH_EMULATION bool "Math emulation" @@ -105,6 +111,32 @@ config MATH_EMULATION endmenu +config XTENSA_CALIBRATE_CCOUNT + def_bool n + help + On some platforms (XT2000, for example), the CPU clock rate can + vary. The frequency can be determined, however, by measuring + against a well known, fixed frequency, such as an UART oscillator. + +config SERIAL_CONSOLE + def_bool n + +config XTENSA_ISS_NETWORK + def_bool n + +menu "Bus options" + +config PCI + bool "PCI support" + default y + help + Find out whether you have a PCI motherboard. PCI is the name of a + bus system, i.e. the way the CPU talks to the other stuff inside + your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or + VESA. If you have PCI, say Y, otherwise N. + +source "drivers/pci/Kconfig" + menu "Platform options" choice @@ -113,33 +145,35 @@ choice config XTENSA_PLATFORM_ISS bool "ISS" + select XTENSA_CALIBRATE_CCOUNT + select SERIAL_CONSOLE + select XTENSA_ISS_NETWORK help ISS is an acronym for Tensilica's Instruction Set Simulator. config XTENSA_PLATFORM_XT2000 bool "XT2000" + select XTENSA_CALIBRATE_CCOUNT + select PCI help XT2000 is the name of Tensilica's feature-rich emulation platform. This hardware is capable of running a full Linux distribution. -endchoice +config XTENSA_PLATFORM_S6105 + bool "S6105" + select SERIAL_CONSOLE +endchoice -config XTENSA_CALIBRATE_CCOUNT - bool "Auto calibration of the CPU clock rate" - ---help--- - On some platforms (XT2000, for example), the CPU clock rate can - vary. The frequency can be determined, however, by measuring - against a well known, fixed frequency, such as an UART oscillator. config XTENSA_CPU_CLOCK int "CPU clock rate [MHz]" depends on !XTENSA_CALIBRATE_CCOUNT - default "16" + default 16 config GENERIC_CALIBRATE_DELAY bool "Auto calibration of the BogoMIPS value" - ---help--- + help The BogoMIPS value can easily be derived from the CPU frequency. config CMDLINE_BOOL @@ -156,52 +190,27 @@ config CMDLINE time by entering them here. As a minimum, you should specify the memory size and the root device (e.g., mem=64M root=/dev/nfs). -config SERIAL_CONSOLE - bool - depends on XTENSA_PLATFORM_ISS - default y - -config XTENSA_ISS_NETWORK - bool - depends on XTENSA_PLATFORM_ISS - default y - source "mm/Kconfig" endmenu -menu "Bus options" - -config PCI - bool "PCI support" if !XTENSA_PLATFORM_ISS - depends on !XTENSA_PLATFORM_ISS - default y +config HOTPLUG + bool "Support for hot-pluggable devices" help - Find out whether you have a PCI motherboard. PCI is the name of a - bus system, i.e. the way the CPU talks to the other stuff inside - your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or - VESA. If you have PCI, say Y, otherwise N. + Say Y here if you want to plug devices into your computer while + the system is running, and be able to use them quickly. In many + cases, the devices can likewise be unplugged at any time too. -source "drivers/pci/Kconfig" + One well known example of this is PCMCIA- or PC-cards, credit-card + size devices such as network cards, modems or hard drives which are + plugged into slots found on all modern laptop computers. Another + example, used on modern desktops as well as laptops, is USB. -config HOTPLUG - - bool "Support for hot-pluggable devices" - ---help--- - Say Y here if you want to plug devices into your computer while - the system is running, and be able to use them quickly. In many - cases, the devices can likewise be unplugged at any time too. - - One well known example of this is PCMCIA- or PC-cards, credit-card - size devices such as network cards, modems or hard drives which are - plugged into slots found on all modern laptop computers. Another - example, used on modern desktops as well as laptops, is USB. - - Enable HOTPLUG and build a modular kernel. Get agent software - (from <http://linux-hotplug.sourceforge.net/>) and install it. - Then your kernel will automatically call out to a user mode "policy - agent" (/sbin/hotplug) to load modules and set up software needed - to use devices as you hotplug them. + Enable HOTPLUG and build a modular kernel. Get agent software + (from <http://linux-hotplug.sourceforge.net/>) and install it. + Then your kernel will automatically call out to a user mode "policy + agent" (/sbin/hotplug) to load modules and set up software needed + to use devices as you hotplug them. source "drivers/pcmcia/Kconfig" @@ -213,9 +222,8 @@ menu "Executable file formats" # only elf supported config KCORE_ELF - bool + def_bool y depends on PROC_FS - default y help If you enabled support for /proc file system then the file /proc/kcore will contain the kernel core image in ELF format. This @@ -240,7 +248,7 @@ source "fs/Kconfig" menu "Xtensa initrd options" depends on BLK_DEV_INITRD - config EMBEDDED_RAMDISK +config EMBEDDED_RAMDISK bool "Embed root filesystem ramdisk into the kernel" config EMBEDDED_RAMDISK_IMAGE diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile index 1da55fe4beff..4caffac3ca2e 100644 --- a/arch/xtensa/Makefile +++ b/arch/xtensa/Makefile @@ -15,6 +15,7 @@ variant-$(CONFIG_XTENSA_VARIANT_FSF) := fsf variant-$(CONFIG_XTENSA_VARIANT_DC232B) := dc232b +variant-$(CONFIG_XTENSA_VARIANT_S6000) := s6000 variant-$(CONFIG_XTENSA_VARIANT_LINUX_CUSTOM) := custom VARIANT = $(variant-y) @@ -24,6 +25,7 @@ export VARIANT platform-$(CONFIG_XTENSA_PLATFORM_XT2000) := xt2000 platform-$(CONFIG_XTENSA_PLATFORM_ISS) := iss +platform-$(CONFIG_XTENSA_PLATFORM_S6105) := s6105 PLATFORM = $(platform-y) export PLATFORM @@ -62,20 +64,23 @@ ifneq ($(VARIANT),) endif endif -# +# Only build variant and/or platform if it includes a Makefile + +buildvar := $(shell test -a $(srctree)/arch/xtensa/variants/$(VARIANT)/Makefile && echo arch/xtensa/variants/$(VARIANT)/) +buildplf := $(shell test -a $(srctree)/arch/xtensa/platforms/$(PLATFORM)/Makefile && echo arch/xtensa/platforms/$(PLATFORM)/) + +# Find libgcc.a LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) head-y := arch/xtensa/kernel/head.o core-y += arch/xtensa/kernel/ arch/xtensa/mm/ -ifneq ($(PLATFORM),) -core-y += arch/xtensa/platforms/$(PLATFORM)/ -endif +core-y += $(buildvar) $(buildplf) + libs-y += arch/xtensa/lib/ $(LIBGCC) boot := arch/xtensa/boot - all: zImage bzImage : zImage diff --git a/arch/xtensa/configs/s6105_defconfig b/arch/xtensa/configs/s6105_defconfig new file mode 100644 index 000000000000..6e1deff41590 --- /dev/null +++ b/arch/xtensa/configs/s6105_defconfig @@ -0,0 +1,530 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.29-rc7-s6 +# Tue Mar 10 11:09:26 2009 +# +# CONFIG_FRAME_POINTER is not set +CONFIG_ZONE_DMA=y +CONFIG_XTENSA=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_GPIO=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_NO_IOPORT=y +CONFIG_HZ=100 +CONFIG_GENERIC_TIME=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +# CONFIG_CLASSIC_RCU is not set +# CONFIG_TREE_RCU is not set +CONFIG_PREEMPT_RCU=y +# CONFIG_RCU_TRACE is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=16 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +# CONFIG_HOTPLUG is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +# CONFIG_COMPAT_BRK is not set +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +# CONFIG_MODULES is not set +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_FREEZER is not set +# CONFIG_MMU is not set +CONFIG_VARIANT_IRQ_SWITCH=y + +# +# Processor type and features +# +# CONFIG_XTENSA_VARIANT_FSF is not set +# CONFIG_XTENSA_VARIANT_DC232B is not set +CONFIG_XTENSA_VARIANT_S6000=y +# CONFIG_XTENSA_UNALIGNED_USER is not set +CONFIG_PREEMPT=y +# CONFIG_MATH_EMULATION is not set +# CONFIG_HIGHMEM is not set +# CONFIG_XTENSA_CALIBRATE_CCOUNT is not set +CONFIG_SERIAL_CONSOLE=y +# CONFIG_XTENSA_ISS_NETWORK is not set + +# +# Bus options +# +# CONFIG_PCI is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set + +# +# Platform options +# +# CONFIG_XTENSA_PLATFORM_ISS is not set +# CONFIG_XTENSA_PLATFORM_XT2000 is not set +CONFIG_XTENSA_PLATFORM_S6105=y +CONFIG_XTENSA_CPU_CLOCK=300 +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttyS1,38400 debug bootmem_debug loglevel=7" +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_VIRT_TO_BUS=y + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_FLAT=y +# CONFIG_BINFMT_ZFLAT is not set +# CONFIG_BINFMT_SHARED_FLAT is not set +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_COMPAT_NET_DEV_OPS=y +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_PHONET is not set +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_HD is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_NETDEVICES is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_DEVKMEM is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_GPIO_SYSFS is not set + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_REGULATOR is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_SOUND is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_DNOTIFY is not set +# CONFIG_INOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +# CONFIG_MISC_FILESYSTEMS is not set +# CONFIG_NETWORK_FILESYSTEMS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set +# CONFIG_DLM is not set + +# +# Xtensa initrd options +# +# CONFIG_EMBEDDED_RAMDISK is not set + +# +# Kernel hacking +# +CONFIG_PRINTK_TIME=y +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_SHIRQ=y +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_NOMMU_REGIONS=y +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set + +# +# Tracers +# +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_GENERIC_FIND_LAST_BIT=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +# CONFIG_CRC32 is not set +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_DMA=y diff --git a/arch/xtensa/include/asm/cacheflush.h b/arch/xtensa/include/asm/cacheflush.h index 94c4c53a099e..8fc1c0c8de07 100644 --- a/arch/xtensa/include/asm/cacheflush.h +++ b/arch/xtensa/include/asm/cacheflush.h @@ -65,13 +65,17 @@ extern void __flush_invalidate_dcache_range(unsigned long, unsigned long); # define __flush_invalidate_dcache_range(p,s) __invalidate_dcache_range(p,s) #endif -#if (DCACHE_WAY_SIZE > PAGE_SIZE) +#if defined(CONFIG_MMU) && (DCACHE_WAY_SIZE > PAGE_SIZE) extern void __flush_invalidate_dcache_page_alias(unsigned long, unsigned long); +#else +static inline void __flush_invalidate_dcache_page_alias(unsigned long virt, + unsigned long phys) { } #endif -#if (ICACHE_WAY_SIZE > PAGE_SIZE) +#if defined(CONFIG_MMU) && (ICACHE_WAY_SIZE > PAGE_SIZE) extern void __invalidate_icache_page_alias(unsigned long, unsigned long); #else -# define __invalidate_icache_page_alias(v,p) do { } while(0) +static inline void __invalidate_icache_page_alias(unsigned long virt, + unsigned long phys) { } #endif /* diff --git a/arch/xtensa/include/asm/dma.h b/arch/xtensa/include/asm/dma.h index e30f3abf48f0..137ca3945b07 100644 --- a/arch/xtensa/include/asm/dma.h +++ b/arch/xtensa/include/asm/dma.h @@ -44,8 +44,9 @@ * the value desired). */ +#ifndef MAX_DMA_ADDRESS #define MAX_DMA_ADDRESS (PAGE_OFFSET + XCHAL_KIO_SIZE - 1) - +#endif /* Reserve and release a DMA channel */ extern int request_dma(unsigned int dmanr, const char * device_id); diff --git a/arch/xtensa/include/asm/flat.h b/arch/xtensa/include/asm/flat.h new file mode 100644 index 000000000000..94c44abf15e4 --- /dev/null +++ b/arch/xtensa/include/asm/flat.h @@ -0,0 +1,12 @@ +#ifndef __ASM_XTENSA_FLAT_H +#define __ASM_XTENSA_FLAT_H + +#define flat_argvp_envp_on_stack() 0 +#define flat_old_ram_flag(flags) (flags) +#define flat_reloc_valid(reloc, size) ((reloc) <= (size)) +#define flat_get_addr_from_rp(rp, relval, flags, p) get_unaligned(rp) +#define flat_put_addr_at_rp(rp, val, relval ) put_unaligned(val, rp) +#define flat_get_relocate_addr(rel) (rel) +#define flat_set_persistent(relval, p) 0 + +#endif /* __ASM_XTENSA_FLAT_H */ diff --git a/arch/xtensa/include/asm/ftrace.h b/arch/xtensa/include/asm/ftrace.h new file mode 100644 index 000000000000..40a8c178f10d --- /dev/null +++ b/arch/xtensa/include/asm/ftrace.h @@ -0,0 +1 @@ +/* empty */ diff --git a/arch/xtensa/include/asm/gpio.h b/arch/xtensa/include/asm/gpio.h new file mode 100644 index 000000000000..0763b0763960 --- /dev/null +++ b/arch/xtensa/include/asm/gpio.h @@ -0,0 +1,56 @@ +/* + * Generic GPIO API implementation for xtensa. + * + * Stolen from x86, which is derived from the generic GPIO API for powerpc: + * + * Copyright (c) 2007-2008 MontaVista Software, Inc. + * + * Author: Anton Vorontsov <avorontsov@ru.mvista.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. + */ + +#ifndef _ASM_XTENSA_GPIO_H +#define _ASM_XTENSA_GPIO_H + +#include <asm-generic/gpio.h> + +#ifdef CONFIG_GPIOLIB + +/* + * Just call gpiolib. + */ +static inline int gpio_get_value(unsigned int gpio) +{ + return __gpio_get_value(gpio); +} + +static inline void gpio_set_value(unsigned int gpio, int value) +{ + __gpio_set_value(gpio, value); +} + +static inline int gpio_cansleep(unsigned int gpio) +{ + return __gpio_cansleep(gpio); +} + +/* + * Not implemented, yet. + */ +static inline int gpio_to_irq(unsigned int gpio) +{ + return -ENOSYS; +} + +static inline int irq_to_gpio(unsigned int irq) +{ + return -EINVAL; +} + +#endif /* CONFIG_GPIOLIB */ + +#endif /* _ASM_XTENSA_GPIO_H */ diff --git a/arch/xtensa/include/asm/io.h b/arch/xtensa/include/asm/io.h index 07b7299dab20..d04cd3a625fa 100644 --- a/arch/xtensa/include/asm/io.h +++ b/arch/xtensa/include/asm/io.h @@ -69,21 +69,28 @@ static inline void * phys_to_virt(unsigned long address) static inline void *ioremap(unsigned long offset, unsigned long size) { +#ifdef CONFIG_MMU if (offset >= XCHAL_KIO_PADDR && offset < XCHAL_KIO_PADDR + XCHAL_KIO_SIZE) return (void*)(offset-XCHAL_KIO_PADDR+XCHAL_KIO_BYPASS_VADDR); - else BUG(); +#else + return (void *)offset; +#endif } static inline void *ioremap_nocache(unsigned long offset, unsigned long size) { +#ifdef CONFIG_MMU if (offset >= XCHAL_KIO_PADDR && offset < XCHAL_KIO_PADDR + XCHAL_KIO_SIZE) return (void*)(offset-XCHAL_KIO_PADDR+XCHAL_KIO_CACHED_VADDR); else BUG(); +#else + return (void *)offset; +#endif } static inline void iounmap(void *addr) diff --git a/arch/xtensa/include/asm/irq.h b/arch/xtensa/include/asm/irq.h index 1620d1e0e695..dfac82dc52ad 100644 --- a/arch/xtensa/include/asm/irq.h +++ b/arch/xtensa/include/asm/irq.h @@ -14,6 +14,13 @@ #include <platform/hardware.h> #include <variant/core.h> +#ifdef CONFIG_VARIANT_IRQ_SWITCH +#include <variant/irq.h> +#else +static inline void variant_irq_enable(unsigned int irq) { } +static inline void variant_irq_disable(unsigned int irq) { } +#endif + #ifndef PLATFORM_NR_IRQS # define PLATFORM_NR_IRQS 0 #endif diff --git a/arch/xtensa/include/asm/mmu.h b/arch/xtensa/include/asm/mmu.h index 44c5bb04c55c..04890d6e2335 100644 --- a/arch/xtensa/include/asm/mmu.h +++ b/arch/xtensa/include/asm/mmu.h @@ -11,7 +11,12 @@ #ifndef _XTENSA_MMU_H #define _XTENSA_MMU_H +#ifndef CONFIG_MMU +#include <asm/nommu.h> +#else + /* Default "unsigned long" context */ typedef unsigned long mm_context_t; +#endif /* CONFIG_MMU */ #endif /* _XTENSA_MMU_H */ diff --git a/arch/xtensa/include/asm/mmu_context.h b/arch/xtensa/include/asm/mmu_context.h index c0fd8e5b4513..dbd8731a876a 100644 --- a/arch/xtensa/include/asm/mmu_context.h +++ b/arch/xtensa/include/asm/mmu_context.h @@ -13,16 +13,20 @@ #ifndef _XTENSA_MMU_CONTEXT_H #define _XTENSA_MMU_CONTEXT_H +#ifndef CONFIG_MMU +#include <asm/nommu_context.h> +#else + #include <linux/stringify.h> #include <linux/sched.h> +#include <variant/core.h> + #include <asm/pgtable.h> #include <asm/cacheflush.h> #include <asm/tlbflush.h> #include <asm-generic/mm_hooks.h> -#define XCHAL_MMU_ASID_BITS 8 - #if (XCHAL_HAVE_TLBS != 1) # error "Linux must have an MMU!" #endif @@ -133,4 +137,5 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) } +#endif /* CONFIG_MMU */ #endif /* _XTENSA_MMU_CONTEXT_H */ diff --git a/arch/xtensa/include/asm/nommu.h b/arch/xtensa/include/asm/nommu.h new file mode 100644 index 000000000000..dce2c438c5ba --- /dev/null +++ b/arch/xtensa/include/asm/nommu.h @@ -0,0 +1,3 @@ +typedef struct { + unsigned long end_brk; +} mm_context_t; diff --git a/arch/xtensa/include/asm/nommu_context.h b/arch/xtensa/include/asm/nommu_context.h new file mode 100644 index 000000000000..599e7a2e729d --- /dev/null +++ b/arch/xtensa/include/asm/nommu_context.h @@ -0,0 +1,25 @@ +static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) +{ +} + +static inline int init_new_context(struct task_struct *tsk, struct mm_struct *mm) +{ + return 0; +} + +static inline void destroy_context(struct mm_struct *mm) +{ +} + +static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next) +{ +} + +static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, + struct task_struct *tsk) +{ +} + +static inline void deactivate_mm(struct task_struct *tsk, struct mm_struct *mm) +{ +} diff --git a/arch/xtensa/include/asm/page.h b/arch/xtensa/include/asm/page.h index 11f7dc2dbec7..17e0c5383b10 100644 --- a/arch/xtensa/include/asm/page.h +++ b/arch/xtensa/include/asm/page.h @@ -14,6 +14,7 @@ #include <asm/processor.h> #include <asm/types.h> #include <asm/cache.h> +#include <platform/hardware.h> /* * Fixed TLB translations in the processor. @@ -32,8 +33,14 @@ #define PAGE_SIZE (__XTENSA_UL_CONST(1) << PAGE_SHIFT) #define PAGE_MASK (~(PAGE_SIZE-1)) +#ifdef CONFIG_MMU #define PAGE_OFFSET XCHAL_KSEG_CACHED_VADDR #define MAX_MEM_PFN XCHAL_KSEG_SIZE +#else +#define PAGE_OFFSET 0 +#define MAX_MEM_PFN (PLATFORM_DEFAULT_MEM_START + PLATFORM_DEFAULT_MEM_SIZE) +#endif + #define PGTABLE_START 0x80000000 /* @@ -150,9 +157,11 @@ extern void copy_user_page(void*, void*, unsigned long, struct page*); * addresses. */ +#define ARCH_PFN_OFFSET (PLATFORM_DEFAULT_MEM_START >> PAGE_SHIFT) + #define __pa(x) ((unsigned long) (x) - PAGE_OFFSET) #define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET)) -#define pfn_valid(pfn) ((unsigned long)pfn < max_mapnr) +#define pfn_valid(pfn) ((pfn) >= ARCH_PFN_OFFSET && ((pfn) - ARCH_PFN_OFFSET) < max_mapnr) #ifdef CONFIG_DISCONTIGMEM # error CONFIG_DISCONTIGMEM not supported #endif @@ -162,8 +171,9 @@ extern void copy_user_page(void*, void*, unsigned long, struct page*); #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) +#ifdef CONFIG_MMU #define WANT_PAGE_VIRTUAL - +#endif #endif /* __ASSEMBLY__ */ diff --git a/arch/xtensa/include/asm/pgtable.h b/arch/xtensa/include/asm/pgtable.h index 8014d96b21f1..a138770c358e 100644 --- a/arch/xtensa/include/asm/pgtable.h +++ b/arch/xtensa/include/asm/pgtable.h @@ -183,7 +183,15 @@ extern unsigned long empty_zero_page[1024]; #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) +#ifdef CONFIG_MMU extern pgd_t swapper_pg_dir[PAGE_SIZE/sizeof(pgd_t)]; +extern void paging_init(void); +extern void pgtable_cache_init(void); +#else +# define swapper_pg_dir NULL +static inline void paging_init(void) { } +static inline void pgtable_cache_init(void) { } +#endif /* * The pmd contains the kernel virtual address of the pte page. @@ -383,8 +391,6 @@ ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) #else -extern void paging_init(void); - #define kern_addr_valid(addr) (1) extern void update_mmu_cache(struct vm_area_struct * vma, @@ -398,9 +404,6 @@ extern void update_mmu_cache(struct vm_area_struct * vma, #define io_remap_pfn_range(vma,from,pfn,size,prot) \ remap_pfn_range(vma, from, pfn, size, prot) - -extern void pgtable_cache_init(void); - typedef pte_t *pte_addr_t; #endif /* !defined (__ASSEMBLY__) */ diff --git a/arch/xtensa/include/asm/platform.h b/arch/xtensa/include/asm/platform.h index e3d5a48ad495..7d936e58e9be 100644 --- a/arch/xtensa/include/asm/platform.h +++ b/arch/xtensa/include/asm/platform.h @@ -74,16 +74,5 @@ extern int platform_pcibios_fixup (void); */ extern void platform_calibrate_ccount (void); -/* - * platform_get_rtc_time returns RTC seconds (returns 0 for no error) - */ -extern int platform_get_rtc_time(time_t*); - -/* - * platform_set_rtc_time set RTC seconds (returns 0 for no error) - */ -extern int platform_set_rtc_time(time_t); - - #endif /* _XTENSA_PLATFORM_H */ diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h index 07387d3b99f4..0ea4937c0b61 100644 --- a/arch/xtensa/include/asm/processor.h +++ b/arch/xtensa/include/asm/processor.h @@ -13,6 +13,7 @@ #include <variant/core.h> #include <asm/coprocessor.h> +#include <platform/hardware.h> #include <linux/compiler.h> #include <asm/ptrace.h> @@ -25,6 +26,8 @@ # error Linux requires the Xtensa Windowed Registers Option. #endif +#define ARCH_SLAB_MINALIGN XCHAL_DATA_WIDTH + /* * User space process size: 1 GB. * Windowed call ABI requires caller and callee to be located within the same @@ -33,7 +36,12 @@ * the 1 GB requirement applies to the stack as well. */ +#ifdef CONFIG_MMU #define TASK_SIZE __XTENSA_UL_CONST(0x40000000) +#else +#define TASK_SIZE (PLATFORM_DEFAULT_MEM_START + PLATFORM_DEFAULT_MEM_SIZE) +#endif + #define STACK_TOP TASK_SIZE #define STACK_TOP_MAX STACK_TOP diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index a51d36a27389..80d24c485fd3 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -1463,6 +1463,7 @@ ENTRY(_spill_registers) callx0 a0 # should not return 1: j 1b +#ifdef CONFIG_MMU /* * We should never get here. Bail out! */ @@ -1775,7 +1776,7 @@ ENTRY(fast_store_prohibited) bbsi.l a2, PS_UM_BIT, 1f j _kernel_exception 1: j _user_exception - +#endif /* CONFIG_MMU */ /* * System Calls. diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S index 67e69139520b..0817f9db836e 100644 --- a/arch/xtensa/kernel/head.S +++ b/arch/xtensa/kernel/head.S @@ -53,7 +53,7 @@ _start: _j 2f 2: l32r a0, 1b jx a0 - .text + .section .init.text, "ax" .align 4 _startup: @@ -235,8 +235,9 @@ should_never_return: */ .section ".bss.page_aligned", "w" +#ifdef CONFIG_MMU ENTRY(swapper_pg_dir) .fill PAGE_SIZE, 1, 0 +#endif ENTRY(empty_zero_page) .fill PAGE_SIZE, 1, 0 - diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c index f3b66fba5b8f..a36c85edd045 100644 --- a/arch/xtensa/kernel/irq.c +++ b/arch/xtensa/kernel/irq.c @@ -132,6 +132,18 @@ static void xtensa_irq_unmask(unsigned int irq) set_sr (cached_irq_mask, INTENABLE); } +static void xtensa_irq_enable(unsigned int irq) +{ + variant_irq_enable(irq); + xtensa_irq_unmask(irq); +} + +static void xtensa_irq_disable(unsigned int irq) +{ + xtensa_irq_mask(irq); + variant_irq_disable(irq); +} + static void xtensa_irq_ack(unsigned int irq) { set_sr(1 << irq, INTCLEAR); @@ -146,6 +158,8 @@ static int xtensa_irq_retrigger(unsigned int irq) static struct irq_chip xtensa_irq_chip = { .name = "xtensa", + .enable = xtensa_irq_enable, + .disable = xtensa_irq_disable, .mask = xtensa_irq_mask, .unmask = xtensa_irq_unmask, .ack = xtensa_irq_ack, diff --git a/arch/xtensa/kernel/platform.c b/arch/xtensa/kernel/platform.c index 69675f216062..1b91a97f1d84 100644 --- a/arch/xtensa/kernel/platform.c +++ b/arch/xtensa/kernel/platform.c @@ -36,8 +36,6 @@ _F(void, power_off, (void), { while(1); }); _F(void, idle, (void), { __asm__ __volatile__ ("waiti 0" ::: "memory"); }); _F(void, heartbeat, (void), { }); _F(int, pcibios_fixup, (void), { return 0; }); -_F(int, get_rtc_time, (time_t* t), { return 0; }); -_F(int, set_rtc_time, (time_t t), { return 0; }); #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT _F(void, calibrate_ccount, (void), diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 4ec1633c2941..1e5a034fe011 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c @@ -84,7 +84,13 @@ sysmem_info_t __initdata sysmem; int initrd_is_mapped; #endif +#ifdef CONFIG_MMU extern void init_mmu(void); +#else +static inline void init_mmu(void) { } +#endif + +extern void zones_init(void); /* * Boot parameter parsing. @@ -286,6 +292,7 @@ void __init setup_arch(char **cmdline_p) paging_init(); + zones_init(); #ifdef CONFIG_VT # if defined(CONFIG_VGA_CONSOLE) diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index 8df1e842f6d4..8848120d291b 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -14,7 +14,7 @@ #include <linux/errno.h> #include <linux/time.h> -#include <linux/timex.h> +#include <linux/clocksource.h> #include <linux/interrupt.h> #include <linux/module.h> #include <linux/init.h> @@ -25,27 +25,31 @@ #include <asm/timex.h> #include <asm/platform.h> - -DEFINE_SPINLOCK(rtc_lock); -EXPORT_SYMBOL(rtc_lock); - - #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT unsigned long ccount_per_jiffy; /* per 1/HZ */ unsigned long nsec_per_ccount; /* nsec per ccount increment */ #endif -static long last_rtc_update = 0; - -/* - * Scheduler clock - returns current tim in nanosec units. - */ - -unsigned long long sched_clock(void) +static cycle_t ccount_read(void) { - return (unsigned long long)jiffies * (1000000000 / HZ); + return (cycle_t)get_ccount(); } +static struct clocksource ccount_clocksource = { + .name = "ccount", + .rating = 200, + .read = ccount_read, + .mask = CLOCKSOURCE_MASK(32), + /* + * With a shift of 22 the lower limit of the cpu clock is + * 1MHz, where NSEC_PER_CCOUNT is 1000 or a bit less than + * 2^10: Since we have 32 bits and the multiplicator can + * already take up as much as 10 bits, this leaves us with + * remaining upper 22 bits. + */ + .shift = 22, +}; + static irqreturn_t timer_interrupt(int irq, void *dev_id); static struct irqaction timer_irqaction = { .handler = timer_interrupt, @@ -55,11 +59,11 @@ static struct irqaction timer_irqaction = { void __init time_init(void) { - time_t sec_o, sec_n = 0; + xtime.tv_nsec = 0; + xtime.tv_sec = read_persistent_clock(); - /* The platform must provide a function to calibrate the processor - * speed for the CALIBRATE. - */ + set_normalized_timespec(&wall_to_monotonic, + -xtime.tv_sec, -xtime.tv_nsec); #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT printk("Calibrating CPU frequency "); @@ -67,19 +71,10 @@ void __init time_init(void) printk("%d.%02d MHz\n", (int)ccount_per_jiffy/(1000000/HZ), (int)(ccount_per_jiffy/(10000/HZ))%100); #endif - - /* Set time from RTC (if provided) */ - - if (platform_get_rtc_time(&sec_o) == 0) - while (platform_get_rtc_time(&sec_n)) - if (sec_o != sec_n) - break; - - xtime.tv_nsec = 0; - last_rtc_update = xtime.tv_sec = sec_n; - - set_normalized_timespec(&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); + ccount_clocksource.mult = + clocksource_hz2mult(CCOUNT_PER_JIFFY * HZ, + ccount_clocksource.shift); + clocksource_register(&ccount_clocksource); /* Initialize the linux timer interrupt. */ @@ -87,69 +82,6 @@ void __init time_init(void) set_linux_timer(get_ccount() + CCOUNT_PER_JIFFY); } - -int do_settimeofday(struct timespec *tv) -{ - time_t wtm_sec, sec = tv->tv_sec; - long wtm_nsec, nsec = tv->tv_nsec; - unsigned long delta; - - if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) - return -EINVAL; - - write_seqlock_irq(&xtime_lock); - - /* This is revolting. We need to set "xtime" correctly. However, the - * value in this location is the value at the most recent update of - * wall time. Discover what correction gettimeofday() would have - * made, and then undo it! - */ - - delta = CCOUNT_PER_JIFFY; - delta += get_ccount() - get_linux_timer(); - nsec -= delta * NSEC_PER_CCOUNT; - - wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); - wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); - - set_normalized_timespec(&xtime, sec, nsec); - set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); - - ntp_clear(); - write_sequnlock_irq(&xtime_lock); - return 0; -} - -EXPORT_SYMBOL(do_settimeofday); - - -void do_gettimeofday(struct timeval *tv) -{ - unsigned long flags; - unsigned long volatile sec, usec, delta, seq; - - do { - seq = read_seqbegin_irqsave(&xtime_lock, flags); - - sec = xtime.tv_sec; - usec = (xtime.tv_nsec / NSEC_PER_USEC); - - delta = get_linux_timer() - get_ccount(); - - } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - - usec += (((unsigned long) CCOUNT_PER_JIFFY - delta) - * (unsigned long) NSEC_PER_CCOUNT) / NSEC_PER_USEC; - - for (; usec >= 1000000; sec++, usec -= 1000000) - ; - - tv->tv_sec = sec; - tv->tv_usec = usec; -} - -EXPORT_SYMBOL(do_gettimeofday); - /* * The timer interrupt is called HZ times per second. */ @@ -178,16 +110,6 @@ again: next += CCOUNT_PER_JIFFY; set_linux_timer(next); - if (ntp_synced() && - xtime.tv_sec - last_rtc_update >= 659 && - abs((xtime.tv_nsec/1000)-(1000000-1000000/HZ))<5000000/HZ) { - - if (platform_set_rtc_time(xtime.tv_sec+1) == 0) - last_rtc_update = xtime.tv_sec+1; - else - /* Do it again in 60 s */ - last_rtc_update += 60; - } write_sequnlock(&xtime_lock); } @@ -213,4 +135,3 @@ void __cpuinit calibrate_delay(void) (loops_per_jiffy/(10000/HZ)) % 100); } #endif - diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index c44f830b6c7a..9f0b71189e94 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c @@ -104,6 +104,7 @@ static dispatch_init_table_t __initdata dispatch_init_table[] = { #endif { EXCCAUSE_UNALIGNED, KRNL, fast_unaligned }, #endif +#ifdef CONFIG_MMU { EXCCAUSE_ITLB_MISS, 0, do_page_fault }, { EXCCAUSE_ITLB_MISS, USER|KRNL, fast_second_level_miss}, { EXCCAUSE_ITLB_MULTIHIT, 0, do_multihit }, @@ -118,6 +119,7 @@ static dispatch_init_table_t __initdata dispatch_init_table[] = { { EXCCAUSE_STORE_CACHE_ATTRIBUTE, USER|KRNL, fast_store_prohibited }, { EXCCAUSE_STORE_CACHE_ATTRIBUTE, 0, do_page_fault }, { EXCCAUSE_LOAD_CACHE_ATTRIBUTE, 0, do_page_fault }, +#endif /* CONFIG_MMU */ /* XCCHAL_EXCCAUSE_FLOATING_POINT unhandled */ #if XTENSA_HAVE_COPROCESSOR(0) COPROCESSOR(0), @@ -372,11 +374,10 @@ void show_trace(struct task_struct *task, unsigned long *sp) unsigned long a0, a1, pc; unsigned long sp_start, sp_end; - a1 = (unsigned long)sp; - - if (a1 == 0) - __asm__ __volatile__ ("mov %0, a1\n" : "=a"(a1)); - + if (sp) + a1 = (unsigned long)sp; + else + a1 = task->thread.sp; sp_start = a1 & ~(THREAD_SIZE-1); sp_end = sp_start + THREAD_SIZE; @@ -418,9 +419,8 @@ void show_stack(struct task_struct *task, unsigned long *sp) int i = 0; unsigned long *stack; - if (sp == 0) - __asm__ __volatile__ ("mov %0, a1\n" : "=a"(sp)); - + if (!sp) + sp = (unsigned long *)task->thread.sp; stack = sp; printk("\nStack: "); diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S index eb2d7bb69ee0..74a7518faf16 100644 --- a/arch/xtensa/kernel/vectors.S +++ b/arch/xtensa/kernel/vectors.S @@ -309,6 +309,7 @@ ENTRY(_DoubleExceptionVector) * All other exceptions are unexpected and thus unrecoverable! */ +#ifdef CONFIG_MMU .extern fast_second_level_miss_double_kernel .Lksp: /* a0: a0, a1: a1, a2: a2, a3: trashed, depc: depc, excsave: a3 */ @@ -319,6 +320,9 @@ ENTRY(_DoubleExceptionVector) bnez a3, .Lunrecoverable 1: movi a3, fast_second_level_miss_double_kernel jx a3 +#else +.equ .Lksp, .Lunrecoverable +#endif /* Critical! We can't handle this situation. PANIC! */ diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S index d506774f4b05..c1be9a4a740c 100644 --- a/arch/xtensa/kernel/vmlinux.lds.S +++ b/arch/xtensa/kernel/vmlinux.lds.S @@ -17,6 +17,7 @@ #include <asm-generic/vmlinux.lds.h> #include <variant/core.h> +#include <platform/hardware.h> OUTPUT_ARCH(xtensa) ENTRY(_start) @@ -26,7 +27,9 @@ jiffies = jiffies_64 + 4; jiffies = jiffies_64; #endif +#ifndef KERNELOFFSET #define KERNELOFFSET 0xd0001000 +#endif /* Note: In the following macros, it would be nice to specify only the vector name and section kind and construct "sym" and "section" using diff --git a/arch/xtensa/mm/Makefile b/arch/xtensa/mm/Makefile index 64e304a2f884..f0b646d2f843 100644 --- a/arch/xtensa/mm/Makefile +++ b/arch/xtensa/mm/Makefile @@ -2,4 +2,5 @@ # Makefile for the Linux/Xtensa-specific parts of the memory manager. # -obj-y := init.o fault.o tlb.o misc.o cache.o +obj-y := init.o cache.o misc.o +obj-$(CONFIG_MMU) += fault.o mmu.o tlb.o diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c index 34163cfaaffc..427e14fa43c5 100644 --- a/arch/xtensa/mm/init.c +++ b/arch/xtensa/mm/init.c @@ -24,15 +24,8 @@ #include <linux/mm.h> #include <linux/slab.h> -#include <asm/pgtable.h> #include <asm/bootparam.h> -#include <asm/mmu_context.h> -#include <asm/tlb.h> #include <asm/page.h> -#include <asm/pgalloc.h> - - -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); /* References to section boundaries */ @@ -130,7 +123,8 @@ void __init bootmem_init(void) /* Find an area to use for the bootmem bitmap. */ - bootmap_size = bootmem_bootmap_pages(max_low_pfn) << PAGE_SHIFT; + bootmap_size = bootmem_bootmap_pages(max_low_pfn - min_low_pfn); + bootmap_size <<= PAGE_SHIFT; bootmap_start = ~0; for (i=0; i<sysmem.nr_banks; i++) @@ -145,8 +139,9 @@ void __init bootmem_init(void) /* Reserve the bootmem bitmap area */ mem_reserve(bootmap_start, bootmap_start + bootmap_size, 1); - bootmap_size = init_bootmem_node(NODE_DATA(0), min_low_pfn, + bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_start >> PAGE_SHIFT, + min_low_pfn, max_low_pfn); /* Add all remaining memory pieces into the bootmem map */ @@ -158,14 +153,14 @@ void __init bootmem_init(void) } -void __init paging_init(void) +void __init zones_init(void) { unsigned long zones_size[MAX_NR_ZONES]; int i; /* All pages are DMA-able, so we put them all in the DMA zone. */ - zones_size[ZONE_DMA] = max_low_pfn; + zones_size[ZONE_DMA] = max_low_pfn - ARCH_PFN_OFFSET; for (i = 1; i < MAX_NR_ZONES; i++) zones_size[i] = 0; @@ -173,40 +168,7 @@ void __init paging_init(void) zones_size[ZONE_HIGHMEM] = max_pfn - max_low_pfn; #endif - /* Initialize the kernel's page tables. */ - - memset(swapper_pg_dir, 0, PAGE_SIZE); - - free_area_init(zones_size); -} - -/* - * Flush the mmu and reset associated register to default values. - */ - -void __init init_mmu (void) -{ - /* Writing zeros to the <t>TLBCFG special registers ensure - * that valid values exist in the register. For existing - * PGSZID<w> fields, zero selects the first element of the - * page-size array. For nonexistent PGSZID<w> fields, zero is - * the best value to write. Also, when changing PGSZID<w> - * fields, the corresponding TLB must be flushed. - */ - set_itlbcfg_register (0); - set_dtlbcfg_register (0); - flush_tlb_all (); - - /* Set rasid register to a known value. */ - - set_rasid_register (ASID_USER_FIRST); - - /* Set PTEVADDR special register to the start of the page - * table, which is in kernel mappable space (ie. not - * statically mapped). This register's value is undefined on - * reset. - */ - set_ptevaddr_register (PGTABLE_START); + free_area_init_node(0, zones_size, ARCH_PFN_OFFSET, NULL); } /* @@ -218,8 +180,8 @@ void __init mem_init(void) unsigned long codesize, reservedpages, datasize, initsize; unsigned long highmemsize, tmp, ram; - max_mapnr = num_physpages = max_low_pfn; - high_memory = (void *) __va(max_mapnr << PAGE_SHIFT); + max_mapnr = num_physpages = max_low_pfn - ARCH_PFN_OFFSET; + high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT); highmemsize = 0; #ifdef CONFIG_HIGHMEM @@ -229,7 +191,7 @@ void __init mem_init(void) totalram_pages += free_all_bootmem(); reservedpages = ram = 0; - for (tmp = 0; tmp < max_low_pfn; tmp++) { + for (tmp = 0; tmp < max_mapnr; tmp++) { ram++; if (PageReserved(mem_map+tmp)) reservedpages++; @@ -279,23 +241,3 @@ void free_initmem(void) printk("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10); } - -struct kmem_cache *pgtable_cache __read_mostly; - -static void pgd_ctor(void* addr) -{ - pte_t* ptep = (pte_t*)addr; - int i; - - for (i = 0; i < 1024; i++, ptep++) - pte_clear(NULL, 0, ptep); - -} - -void __init pgtable_cache_init(void) -{ - pgtable_cache = kmem_cache_create("pgd", - PAGE_SIZE, PAGE_SIZE, - SLAB_HWCACHE_ALIGN, - pgd_ctor); -} diff --git a/arch/xtensa/mm/misc.S b/arch/xtensa/mm/misc.S index c885664211d1..b048406d8756 100644 --- a/arch/xtensa/mm/misc.S +++ b/arch/xtensa/mm/misc.S @@ -84,6 +84,7 @@ ENTRY(copy_page) retw +#ifdef CONFIG_MMU /* * If we have to deal with cache aliasing, we use temporary memory mappings * to ensure that the source and destination pages have the same color as @@ -311,6 +312,7 @@ ENTRY(__invalidate_icache_page_alias) /* End of special treatment in tlb miss exception */ ENTRY(__tlbtemp_mapping_end) +#endif /* CONFIG_MMU /* * void __invalidate_icache_page(ulong start) diff --git a/arch/xtensa/mm/mmu.c b/arch/xtensa/mm/mmu.c new file mode 100644 index 000000000000..4bb91a970f1f --- /dev/null +++ b/arch/xtensa/mm/mmu.c @@ -0,0 +1,70 @@ +/* + * xtensa mmu stuff + * + * Extracted from init.c + */ +#include <linux/percpu.h> +#include <linux/init.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <linux/cache.h> + +#include <asm/tlb.h> +#include <asm/tlbflush.h> +#include <asm/mmu_context.h> +#include <asm/page.h> + +DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); + +void __init paging_init(void) +{ + memset(swapper_pg_dir, 0, PAGE_SIZE); +} + +/* + * Flush the mmu and reset associated register to default values. + */ +void __init init_mmu(void) +{ + /* Writing zeros to the <t>TLBCFG special registers ensure + * that valid values exist in the register. For existing + * PGSZID<w> fields, zero selects the first element of the + * page-size array. For nonexistent PGSZID<w> fields, zero is + * the best value to write. Also, when changing PGSZID<w> + * fields, the corresponding TLB must be flushed. + */ + set_itlbcfg_register(0); + set_dtlbcfg_register(0); + flush_tlb_all(); + + /* Set rasid register to a known value. */ + + set_rasid_register(ASID_USER_FIRST); + + /* Set PTEVADDR special register to the start of the page + * table, which is in kernel mappable space (ie. not + * statically mapped). This register's value is undefined on + * reset. + */ + set_ptevaddr_register(PGTABLE_START); +} + +struct kmem_cache *pgtable_cache __read_mostly; + +static void pgd_ctor(void *addr) +{ + pte_t *ptep = (pte_t *)addr; + int i; + + for (i = 0; i < 1024; i++, ptep++) + pte_clear(NULL, 0, ptep); + +} + +void __init pgtable_cache_init(void) +{ + pgtable_cache = kmem_cache_create("pgd", + PAGE_SIZE, PAGE_SIZE, + SLAB_HWCACHE_ALIGN, + pgd_ctor); +} diff --git a/arch/xtensa/platforms/s6105/Makefile b/arch/xtensa/platforms/s6105/Makefile new file mode 100644 index 000000000000..0be6194bcb72 --- /dev/null +++ b/arch/xtensa/platforms/s6105/Makefile @@ -0,0 +1,3 @@ +# Makefile for the Stretch S6105 eval board + +obj-y := setup.o device.o diff --git a/arch/xtensa/platforms/s6105/device.c b/arch/xtensa/platforms/s6105/device.c new file mode 100644 index 000000000000..78b08be5a92d --- /dev/null +++ b/arch/xtensa/platforms/s6105/device.c @@ -0,0 +1,67 @@ +/* + * s6105 platform devices + * + * Copyright (c) 2009 emlix GmbH + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/serial.h> +#include <linux/serial_8250.h> + +#include <variant/hardware.h> + +#define UART_INTNUM 4 + +static const signed char uart_irq_mappings[] = { + S6_INTC_UART(0), + S6_INTC_UART(1), + -1, +}; + +const signed char *platform_irq_mappings[NR_IRQS] = { + [UART_INTNUM] = uart_irq_mappings, +}; + +static struct plat_serial8250_port serial_platform_data[] = { + { + .membase = (void *)S6_REG_UART + 0x0000, + .mapbase = S6_REG_UART + 0x0000, + .irq = UART_INTNUM, + .uartclk = S6_SCLK, + .regshift = 2, + .iotype = SERIAL_IO_MEM, + .flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST, + }, + { + .membase = (void *)S6_REG_UART + 0x1000, + .mapbase = S6_REG_UART + 0x1000, + .irq = UART_INTNUM, + .uartclk = S6_SCLK, + .regshift = 2, + .iotype = SERIAL_IO_MEM, + .flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST, + }, + { }, +}; + +static struct platform_device platform_devices[] = { + { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev = { + .platform_data = serial_platform_data, + }, + }, +}; + +static int __init device_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(platform_devices); i++) + platform_device_register(&platform_devices[i]); + return 0; +} +arch_initcall_sync(device_init); diff --git a/arch/xtensa/platforms/s6105/include/platform/gpio.h b/arch/xtensa/platforms/s6105/include/platform/gpio.h new file mode 100644 index 000000000000..fa11aa4b61e9 --- /dev/null +++ b/arch/xtensa/platforms/s6105/include/platform/gpio.h @@ -0,0 +1,27 @@ +#ifndef __ASM_XTENSA_S6105_GPIO_H +#define __ASM_XTENSA_S6105_GPIO_H + +#define GPIO_BP_TEMP_ALARM 0 +#define GPIO_PB_RESET_IN 1 +#define GPIO_EXP_IRQ 2 +#define GPIO_TRIGGER_IRQ 3 +#define GPIO_RTC_IRQ 4 +#define GPIO_PHY_IRQ 5 +#define GPIO_IMAGER_RESET 6 +#define GPIO_SD_IRQ 7 +#define GPIO_MINI_BOOT_INH 8 +#define GPIO_BOARD_RESET 9 +#define GPIO_EXP_PRESENT 10 +#define GPIO_LED1_NGREEN 12 +#define GPIO_LED1_RED 13 +#define GPIO_LED0_NGREEN 14 +#define GPIO_LED0_NRED 15 +#define GPIO_SPI_CS0 16 +#define GPIO_SPI_CS1 17 +#define GPIO_SPI_CS3 19 +#define GPIO_SPI_CS4 20 +#define GPIO_SD_WP 21 +#define GPIO_BP_RESET 22 +#define GPIO_ALARM_OUT 23 + +#endif /* __ASM_XTENSA_S6105_GPIO_H */ diff --git a/arch/xtensa/platforms/s6105/include/platform/hardware.h b/arch/xtensa/platforms/s6105/include/platform/hardware.h new file mode 100644 index 000000000000..d628efac7089 --- /dev/null +++ b/arch/xtensa/platforms/s6105/include/platform/hardware.h @@ -0,0 +1,11 @@ +#ifndef __XTENSA_S6105_HARDWARE_H +#define __XTENSA_S6105_HARDWARE_H + +#define PLATFORM_DEFAULT_MEM_START 0x40000000 +#define PLATFORM_DEFAULT_MEM_SIZE 0x08000000 + +#define MAX_DMA_ADDRESS 0 + +#define KERNELOFFSET (PLATFORM_DEFAULT_MEM_START + 0x1000) + +#endif /* __XTENSA_S6105_HARDWARE_H */ diff --git a/arch/xtensa/platforms/s6105/include/platform/serial.h b/arch/xtensa/platforms/s6105/include/platform/serial.h new file mode 100644 index 000000000000..c8a771e5981b --- /dev/null +++ b/arch/xtensa/platforms/s6105/include/platform/serial.h @@ -0,0 +1,8 @@ +#ifndef __ASM_XTENSA_S6105_SERIAL_H +#define __ASM_XTENSA_S6105_SERIAL_H + +#include <variant/hardware.h> + +#define BASE_BAUD (S6_SCLK / 16) + +#endif /* __ASM_XTENSA_S6105_SERIAL_H */ diff --git a/arch/xtensa/platforms/s6105/setup.c b/arch/xtensa/platforms/s6105/setup.c new file mode 100644 index 000000000000..ae041d5027a2 --- /dev/null +++ b/arch/xtensa/platforms/s6105/setup.c @@ -0,0 +1,61 @@ +/* + * s6105 control routines + * + * Copyright (c) 2009 emlix GmbH + */ +#include <linux/irq.h> +#include <linux/io.h> +#include <linux/gpio.h> + +#include <asm/bootparam.h> + +#include <variant/hardware.h> +#include <platform/gpio.h> + +void platform_halt(void) +{ + local_irq_disable(); + while (1) + ; +} + +void platform_power_off(void) +{ + platform_halt(); +} + +void platform_restart(void) +{ + platform_halt(); +} + +void __init platform_setup(char **cmdline) +{ + unsigned long reg; + + reg = readl(S6_REG_GREG1 + S6_GREG1_CLKGATE); + reg &= ~(1 << S6_GREG1_BLOCK_SB); + writel(reg, S6_REG_GREG1 + S6_GREG1_CLKGATE); + + reg = readl(S6_REG_GREG1 + S6_GREG1_BLOCKENA); + reg |= 1 << S6_GREG1_BLOCK_SB; + writel(reg, S6_REG_GREG1 + S6_GREG1_BLOCKENA); + + printk(KERN_NOTICE "S6105 on Stretch S6000 - " + "Copyright (C) 2009 emlix GmbH <info@emlix.com>\n"); +} + +void __init platform_init(bp_tag_t *first) +{ + gpio_request(GPIO_LED1_NGREEN, "led1_green"); + gpio_request(GPIO_LED1_RED, "led1_red"); + gpio_direction_output(GPIO_LED1_NGREEN, 1); +} + +void platform_heartbeat(void) +{ + static unsigned int c; + + if (!(++c & 0x4F)) + gpio_direction_output(GPIO_LED1_RED, !(c & 0x10)); +} diff --git a/arch/xtensa/platforms/xt2000/include/platform/hardware.h b/arch/xtensa/platforms/xt2000/include/platform/hardware.h index 41459ad07766..886ef156ded3 100644 --- a/arch/xtensa/platforms/xt2000/include/platform/hardware.h +++ b/arch/xtensa/platforms/xt2000/include/platform/hardware.h @@ -16,7 +16,6 @@ #define _XTENSA_XT2000_HARDWARE_H #include <variant/core.h> -#include <asm/io.h> /* * Memory configuration. diff --git a/arch/xtensa/variants/s6000/Makefile b/arch/xtensa/variants/s6000/Makefile new file mode 100644 index 000000000000..03b3975468bd --- /dev/null +++ b/arch/xtensa/variants/s6000/Makefile @@ -0,0 +1,3 @@ +# s6000 Makefile + +obj-y += irq.o gpio.o diff --git a/arch/xtensa/variants/s6000/gpio.c b/arch/xtensa/variants/s6000/gpio.c new file mode 100644 index 000000000000..33a8d952934c --- /dev/null +++ b/arch/xtensa/variants/s6000/gpio.c @@ -0,0 +1,71 @@ +/* + * s6000 gpio driver + * + * Copyright (c) 2009 emlix GmbH + * Authors: Oskar Schirmer <os@emlix.com> + * Johannes Weiner <jw@emlix.com> + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/gpio.h> + +#include <variant/hardware.h> + +#define S6_GPIO_DATA 0x000 +#define S6_GPIO_IS 0x404 +#define S6_GPIO_IBE 0x408 +#define S6_GPIO_IEV 0x40C +#define S6_GPIO_IE 0x410 +#define S6_GPIO_RIS 0x414 +#define S6_GPIO_MIS 0x418 +#define S6_GPIO_IC 0x41C +#define S6_GPIO_AFSEL 0x420 +#define S6_GPIO_DIR 0x800 +#define S6_GPIO_BANK(nr) ((nr) * 0x1000) +#define S6_GPIO_MASK(nr) (4 << (nr)) +#define S6_GPIO_OFFSET(nr) \ + (S6_GPIO_BANK((nr) >> 3) + S6_GPIO_MASK((nr) & 7)) + +static int direction_input(struct gpio_chip *chip, unsigned int off) +{ + writeb(0, S6_REG_GPIO + S6_GPIO_DIR + S6_GPIO_OFFSET(off)); + return 0; +} + +static int get(struct gpio_chip *chip, unsigned int off) +{ + return readb(S6_REG_GPIO + S6_GPIO_DATA + S6_GPIO_OFFSET(off)); +} + +static int direction_output(struct gpio_chip *chip, unsigned int off, int val) +{ + unsigned rel = S6_GPIO_OFFSET(off); + writeb(~0, S6_REG_GPIO + S6_GPIO_DIR + rel); + writeb(val ? ~0 : 0, S6_REG_GPIO + S6_GPIO_DATA + rel); + return 0; +} + +static void set(struct gpio_chip *chip, unsigned int off, int val) +{ + writeb(val ? ~0 : 0, S6_REG_GPIO + S6_GPIO_DATA + S6_GPIO_OFFSET(off)); +} + +static struct gpio_chip gpiochip = { + .owner = THIS_MODULE, + .direction_input = direction_input, + .get = get, + .direction_output = direction_output, + .set = set, + .base = 0, + .ngpio = 24, + .can_sleep = 0, /* no blocking io needed */ + .exported = 0, /* no exporting to userspace */ +}; + +static int gpio_init(void) +{ + return gpiochip_add(&gpiochip); +} +device_initcall(gpio_init); diff --git a/arch/xtensa/variants/s6000/include/variant/core.h b/arch/xtensa/variants/s6000/include/variant/core.h new file mode 100644 index 000000000000..af007953027e --- /dev/null +++ b/arch/xtensa/variants/s6000/include/variant/core.h @@ -0,0 +1,431 @@ +/* + * Xtensa processor core configuration information. + * + * 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. + * + * Copyright (c) 1999-2008 Tensilica Inc. + */ + +#ifndef _XTENSA_CORE_CONFIGURATION_H +#define _XTENSA_CORE_CONFIGURATION_H + + +/**************************************************************************** + Parameters Useful for Any Code, USER or PRIVILEGED + ****************************************************************************/ + +/* + * Note: Macros of the form XCHAL_HAVE_*** have a value of 1 if the option is + * configured, and a value of 0 otherwise. These macros are always defined. + */ + + +/*---------------------------------------------------------------------- + ISA + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_BE 0 /* big-endian byte ordering */ +#define XCHAL_HAVE_WINDOWED 1 /* windowed registers option */ +#define XCHAL_NUM_AREGS 64 /* num of physical addr regs */ +#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */ +#define XCHAL_MAX_INSTRUCTION_SIZE 8 /* max instr bytes (3..8) */ +#define XCHAL_HAVE_DEBUG 1 /* debug option */ +#define XCHAL_HAVE_DENSITY 1 /* 16-bit instructions */ +#define XCHAL_HAVE_LOOPS 1 /* zero-overhead loops */ +#define XCHAL_HAVE_NSA 1 /* NSA/NSAU instructions */ +#define XCHAL_HAVE_MINMAX 1 /* MIN/MAX instructions */ +#define XCHAL_HAVE_SEXT 1 /* SEXT instruction */ +#define XCHAL_HAVE_CLAMPS 1 /* CLAMPS instruction */ +#define XCHAL_HAVE_MUL16 1 /* MUL16S/MUL16U instructions */ +#define XCHAL_HAVE_MUL32 1 /* MULL instruction */ +#define XCHAL_HAVE_MUL32_HIGH 1 /* MULUH/MULSH instructions */ +#define XCHAL_HAVE_DIV32 0 /* QUOS/QUOU/REMS/REMU instructions */ +#define XCHAL_HAVE_L32R 1 /* L32R instruction */ +#define XCHAL_HAVE_ABSOLUTE_LITERALS 1 /* non-PC-rel (extended) L32R */ +#define XCHAL_HAVE_CONST16 0 /* CONST16 instruction */ +#define XCHAL_HAVE_ADDX 1 /* ADDX#/SUBX# instructions */ +#define XCHAL_HAVE_WIDE_BRANCHES 0 /* B*.W18 or B*.W15 instr's */ +#define XCHAL_HAVE_PREDICTED_BRANCHES 0 /* B[EQ/EQZ/NE/NEZ]T instr's */ +#define XCHAL_HAVE_CALL4AND12 1 /* (obsolete option) */ +#define XCHAL_HAVE_ABS 1 /* ABS instruction */ +/*#define XCHAL_HAVE_POPC 0*/ /* POPC instruction */ +/*#define XCHAL_HAVE_CRC 0*/ /* CRC instruction */ +#define XCHAL_HAVE_RELEASE_SYNC 0 /* L32AI/S32RI instructions */ +#define XCHAL_HAVE_S32C1I 0 /* S32C1I instruction */ +#define XCHAL_HAVE_SPECULATION 0 /* speculation */ +#define XCHAL_HAVE_FULL_RESET 0 /* all regs/state reset */ +#define XCHAL_NUM_CONTEXTS 1 /* */ +#define XCHAL_NUM_MISC_REGS 4 /* num of scratch regs (0..4) */ +#define XCHAL_HAVE_TAP_MASTER 0 /* JTAG TAP control instr's */ +#define XCHAL_HAVE_PRID 0 /* processor ID register */ +#define XCHAL_HAVE_THREADPTR 0 /* THREADPTR register */ +#define XCHAL_HAVE_BOOLEANS 1 /* boolean registers */ +#define XCHAL_HAVE_CP 1 /* CPENABLE reg (coprocessor) */ +#define XCHAL_CP_MAXCFG 8 /* max allowed cp id plus one */ +#define XCHAL_HAVE_MAC16 0 /* MAC16 package */ +#define XCHAL_HAVE_VECTORFPU2005 0 /* vector floating-point pkg */ +#define XCHAL_HAVE_FP 1 /* floating point pkg */ +#define XCHAL_HAVE_VECTRA1 0 /* Vectra I pkg */ +#define XCHAL_HAVE_VECTRALX 0 /* Vectra LX pkg */ +#define XCHAL_HAVE_HIFI2 0 /* HiFi2 Audio Engine pkg */ + + +/*---------------------------------------------------------------------- + MISC + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_WRITEBUFFER_ENTRIES 8 /* size of write buffer */ +#define XCHAL_INST_FETCH_WIDTH 8 /* instr-fetch width in bytes */ +#define XCHAL_DATA_WIDTH 16 /* data width in bytes */ +/* In T1050, applies to selected core load and store instructions (see ISA): */ +#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* unaligned loads cause exc. */ +#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* unaligned stores cause exc.*/ + +#define XCHAL_SW_VERSION 701001 /* sw version of this header */ + +#define XCHAL_CORE_ID "stretch_bali" /* alphanum core name + (CoreID) set in the Xtensa + Processor Generator */ + +#define XCHAL_BUILD_UNIQUE_ID 0x000104B9 /* 22-bit sw build ID */ + +/* + * These definitions describe the hardware targeted by this software. + */ +#define XCHAL_HW_CONFIGID0 0xC2F3F9FE /* ConfigID hi 32 bits*/ +#define XCHAL_HW_CONFIGID1 0x054104B9 /* ConfigID lo 32 bits*/ +#define XCHAL_HW_VERSION_NAME "LX1.0.2" /* full version name */ +#define XCHAL_HW_VERSION_MAJOR 2100 /* major ver# of targeted hw */ +#define XCHAL_HW_VERSION_MINOR 2 /* minor ver# of targeted hw */ +#define XCHAL_HW_VERSION 210002 /* major*100+minor */ +#define XCHAL_HW_REL_LX1 1 +#define XCHAL_HW_REL_LX1_0 1 +#define XCHAL_HW_REL_LX1_0_2 1 +#define XCHAL_HW_CONFIGID_RELIABLE 1 +/* If software targets a *range* of hardware versions, these are the bounds: */ +#define XCHAL_HW_MIN_VERSION_MAJOR 2100 /* major v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION_MINOR 2 /* minor v of earliest tgt hw */ +#define XCHAL_HW_MIN_VERSION 210002 /* earliest targeted hw */ +#define XCHAL_HW_MAX_VERSION_MAJOR 2100 /* major v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION_MINOR 2 /* minor v of latest tgt hw */ +#define XCHAL_HW_MAX_VERSION 210002 /* latest targeted hw */ + + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_ICACHE_LINESIZE 16 /* I-cache line size in bytes */ +#define XCHAL_DCACHE_LINESIZE 16 /* D-cache line size in bytes */ +#define XCHAL_ICACHE_LINEWIDTH 4 /* log2(I line size in bytes) */ +#define XCHAL_DCACHE_LINEWIDTH 4 /* log2(D line size in bytes) */ + +#define XCHAL_ICACHE_SIZE 32768 /* I-cache size in bytes or 0 */ +#define XCHAL_DCACHE_SIZE 32768 /* D-cache size in bytes or 0 */ + +#define XCHAL_DCACHE_IS_WRITEBACK 1 /* writeback feature */ + + + + +/**************************************************************************** + Parameters Useful for PRIVILEGED (Supervisory or Non-Virtualized) Code + ****************************************************************************/ + + +#ifndef XTENSA_HAL_NON_PRIVILEGED_ONLY + +/*---------------------------------------------------------------------- + CACHE + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_PIF 1 /* any outbound PIF present */ + +/* If present, cache size in bytes == (ways * 2^(linewidth + setwidth)). */ + +/* Number of cache sets in log2(lines per way): */ +#define XCHAL_ICACHE_SETWIDTH 9 +#define XCHAL_DCACHE_SETWIDTH 10 + +/* Cache set associativity (number of ways): */ +#define XCHAL_ICACHE_WAYS 4 +#define XCHAL_DCACHE_WAYS 2 + +/* Cache features: */ +#define XCHAL_ICACHE_LINE_LOCKABLE 1 +#define XCHAL_DCACHE_LINE_LOCKABLE 0 +#define XCHAL_ICACHE_ECC_PARITY 0 +#define XCHAL_DCACHE_ECC_PARITY 0 + +/* Number of encoded cache attr bits (see <xtensa/hal.h> for decoded bits): */ +#define XCHAL_CA_BITS 4 + + +/*---------------------------------------------------------------------- + INTERNAL I/D RAM/ROMs and XLMI + ----------------------------------------------------------------------*/ + +#define XCHAL_NUM_INSTROM 0 /* number of core instr. ROMs */ +#define XCHAL_NUM_INSTRAM 0 /* number of core instr. RAMs */ +#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs */ +#define XCHAL_NUM_DATARAM 1 /* number of core data RAMs */ +#define XCHAL_NUM_URAM 0 /* number of core unified RAMs*/ +#define XCHAL_NUM_XLMI 1 /* number of core XLMI ports */ + +/* Data RAM 0: */ +#define XCHAL_DATARAM0_VADDR 0x3FFF0000 +#define XCHAL_DATARAM0_PADDR 0x3FFF0000 +#define XCHAL_DATARAM0_SIZE 65536 +#define XCHAL_DATARAM0_ECC_PARITY 0 + +/* XLMI Port 0: */ +#define XCHAL_XLMI0_VADDR 0x37F80000 +#define XCHAL_XLMI0_PADDR 0x37F80000 +#define XCHAL_XLMI0_SIZE 262144 +#define XCHAL_XLMI0_ECC_PARITY 0 + + +/*---------------------------------------------------------------------- + INTERRUPTS and TIMERS + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_INTERRUPTS 1 /* interrupt option */ +#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* med/high-pri. interrupts */ +#define XCHAL_HAVE_NMI 1 /* non-maskable interrupt */ +#define XCHAL_HAVE_CCOUNT 1 /* CCOUNT reg. (timer option) */ +#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */ +#define XCHAL_NUM_INTERRUPTS 27 /* number of interrupts */ +#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* ceil(log2(NUM_INTERRUPTS)) */ +#define XCHAL_NUM_EXTINTERRUPTS 20 /* num of external interrupts */ +#define XCHAL_NUM_INTLEVELS 4 /* number of interrupt levels + (not including level zero) */ +#define XCHAL_EXCM_LEVEL 1 /* level masked by PS.EXCM */ + /* (always 1 in XEA1; levels 2 .. EXCM_LEVEL are "medium priority") */ + +/* Masks of interrupts at each interrupt level: */ +#define XCHAL_INTLEVEL1_MASK 0x01F07FFF +#define XCHAL_INTLEVEL2_MASK 0x02018000 +#define XCHAL_INTLEVEL3_MASK 0x04060000 +#define XCHAL_INTLEVEL4_MASK 0x00000000 +#define XCHAL_INTLEVEL5_MASK 0x00080000 +#define XCHAL_INTLEVEL6_MASK 0x00000000 +#define XCHAL_INTLEVEL7_MASK 0x00000000 + +/* Masks of interrupts at each range 1..n of interrupt levels: */ +#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x01F07FFF +#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x03F1FFFF +#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x07F7FFFF +#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x07F7FFFF +#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x07FFFFFF +#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x07FFFFFF +#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x07FFFFFF + +/* Level of each interrupt: */ +#define XCHAL_INT0_LEVEL 1 +#define XCHAL_INT1_LEVEL 1 +#define XCHAL_INT2_LEVEL 1 +#define XCHAL_INT3_LEVEL 1 +#define XCHAL_INT4_LEVEL 1 +#define XCHAL_INT5_LEVEL 1 +#define XCHAL_INT6_LEVEL 1 +#define XCHAL_INT7_LEVEL 1 +#define XCHAL_INT8_LEVEL 1 +#define XCHAL_INT9_LEVEL 1 +#define XCHAL_INT10_LEVEL 1 +#define XCHAL_INT11_LEVEL 1 +#define XCHAL_INT12_LEVEL 1 +#define XCHAL_INT13_LEVEL 1 +#define XCHAL_INT14_LEVEL 1 +#define XCHAL_INT15_LEVEL 2 +#define XCHAL_INT16_LEVEL 2 +#define XCHAL_INT17_LEVEL 3 +#define XCHAL_INT18_LEVEL 3 +#define XCHAL_INT19_LEVEL 5 +#define XCHAL_INT20_LEVEL 1 +#define XCHAL_INT21_LEVEL 1 +#define XCHAL_INT22_LEVEL 1 +#define XCHAL_INT23_LEVEL 1 +#define XCHAL_INT24_LEVEL 1 +#define XCHAL_INT25_LEVEL 2 +#define XCHAL_INT26_LEVEL 3 +#define XCHAL_DEBUGLEVEL 4 /* debug interrupt level */ +#define XCHAL_HAVE_DEBUG_EXTERN_INT 1 /* OCD external db interrupt */ +#define XCHAL_NMILEVEL 5 /* NMI "level" (for use with + EXCSAVE/EPS/EPC_n, RFI n) */ + +/* Type of each interrupt: */ +#define XCHAL_INT0_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT1_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT6_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT7_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT9_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT10_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT11_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT12_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT13_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT14_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT15_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT16_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT17_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT18_TYPE XTHAL_INTTYPE_EXTERN_LEVEL +#define XCHAL_INT19_TYPE XTHAL_INTTYPE_NMI +#define XCHAL_INT20_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT21_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT22_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT23_TYPE XTHAL_INTTYPE_SOFTWARE +#define XCHAL_INT24_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT25_TYPE XTHAL_INTTYPE_TIMER +#define XCHAL_INT26_TYPE XTHAL_INTTYPE_TIMER + +/* Masks of interrupts for each type of interrupt: */ +#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xF8000000 +#define XCHAL_INTTYPE_MASK_SOFTWARE 0x00F00000 +#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000000 +#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x0007FFFF +#define XCHAL_INTTYPE_MASK_TIMER 0x07000000 +#define XCHAL_INTTYPE_MASK_NMI 0x00080000 +#define XCHAL_INTTYPE_MASK_WRITE_ERROR 0x00000000 + +/* Interrupt numbers assigned to specific interrupt sources: */ +#define XCHAL_TIMER0_INTERRUPT 24 /* CCOMPARE0 */ +#define XCHAL_TIMER1_INTERRUPT 25 /* CCOMPARE1 */ +#define XCHAL_TIMER2_INTERRUPT 26 /* CCOMPARE2 */ +#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED +#define XCHAL_NMI_INTERRUPT 19 /* non-maskable interrupt */ + +/* Interrupt numbers for levels at which only one interrupt is configured: */ +#define XCHAL_INTLEVEL5_NUM 19 +/* (There are many interrupts each at level(s) 1, 2, 3.) */ + + +/* + * External interrupt vectors/levels. + * These macros describe how Xtensa processor interrupt numbers + * (as numbered internally, eg. in INTERRUPT and INTENABLE registers) + * map to external BInterrupt<n> pins, for those interrupts + * configured as external (level-triggered, edge-triggered, or NMI). + * See the Xtensa processor databook for more details. + */ + +/* Core interrupt numbers mapped to each EXTERNAL interrupt number: */ +#define XCHAL_EXTINT0_NUM 0 /* (intlevel 1) */ +#define XCHAL_EXTINT1_NUM 1 /* (intlevel 1) */ +#define XCHAL_EXTINT2_NUM 2 /* (intlevel 1) */ +#define XCHAL_EXTINT3_NUM 3 /* (intlevel 1) */ +#define XCHAL_EXTINT4_NUM 4 /* (intlevel 1) */ +#define XCHAL_EXTINT5_NUM 5 /* (intlevel 1) */ +#define XCHAL_EXTINT6_NUM 6 /* (intlevel 1) */ +#define XCHAL_EXTINT7_NUM 7 /* (intlevel 1) */ +#define XCHAL_EXTINT8_NUM 8 /* (intlevel 1) */ +#define XCHAL_EXTINT9_NUM 9 /* (intlevel 1) */ +#define XCHAL_EXTINT10_NUM 10 /* (intlevel 1) */ +#define XCHAL_EXTINT11_NUM 11 /* (intlevel 1) */ +#define XCHAL_EXTINT12_NUM 12 /* (intlevel 1) */ +#define XCHAL_EXTINT13_NUM 13 /* (intlevel 1) */ +#define XCHAL_EXTINT14_NUM 14 /* (intlevel 1) */ +#define XCHAL_EXTINT15_NUM 15 /* (intlevel 2) */ +#define XCHAL_EXTINT16_NUM 16 /* (intlevel 2) */ +#define XCHAL_EXTINT17_NUM 17 /* (intlevel 3) */ +#define XCHAL_EXTINT18_NUM 18 /* (intlevel 3) */ +#define XCHAL_EXTINT19_NUM 19 /* (intlevel 5) */ + + +/*---------------------------------------------------------------------- + EXCEPTIONS and VECTORS + ----------------------------------------------------------------------*/ + +#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture + number: 1 == XEA1 (old) + 2 == XEA2 (new) + 0 == XEAX (extern) */ +#define XCHAL_HAVE_XEA1 0 /* Exception Architecture 1 */ +#define XCHAL_HAVE_XEA2 1 /* Exception Architecture 2 */ +#define XCHAL_HAVE_XEAX 0 /* External Exception Arch. */ +#define XCHAL_HAVE_EXCEPTIONS 1 /* exception option */ +#define XCHAL_HAVE_MEM_ECC_PARITY 0 /* local memory ECC/parity */ +#define XCHAL_HAVE_VECTOR_SELECT 0 /* relocatable vectors */ +#define XCHAL_HAVE_VECBASE 0 /* relocatable vectors */ + +#define XCHAL_RESET_VECOFS 0x00000000 +#define XCHAL_RESET_VECTOR_VADDR 0x3FFE03D0 +#define XCHAL_RESET_VECTOR_PADDR 0x3FFE03D0 +#define XCHAL_USER_VECOFS 0x00000000 +#define XCHAL_USER_VECTOR_VADDR 0x40000220 +#define XCHAL_USER_VECTOR_PADDR 0x40000220 +#define XCHAL_KERNEL_VECOFS 0x00000000 +#define XCHAL_KERNEL_VECTOR_VADDR 0x40000200 +#define XCHAL_KERNEL_VECTOR_PADDR 0x40000200 +#define XCHAL_DOUBLEEXC_VECOFS 0x00000000 +#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0x400002A0 +#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x400002A0 +#define XCHAL_WINDOW_OF4_VECOFS 0x00000000 +#define XCHAL_WINDOW_UF4_VECOFS 0x00000040 +#define XCHAL_WINDOW_OF8_VECOFS 0x00000080 +#define XCHAL_WINDOW_UF8_VECOFS 0x000000C0 +#define XCHAL_WINDOW_OF12_VECOFS 0x00000100 +#define XCHAL_WINDOW_UF12_VECOFS 0x00000140 +#define XCHAL_WINDOW_VECTORS_VADDR 0x40000000 +#define XCHAL_WINDOW_VECTORS_PADDR 0x40000000 +#define XCHAL_INTLEVEL2_VECOFS 0x00000000 +#define XCHAL_INTLEVEL2_VECTOR_VADDR 0x40000240 +#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x40000240 +#define XCHAL_INTLEVEL3_VECOFS 0x00000000 +#define XCHAL_INTLEVEL3_VECTOR_VADDR 0x40000260 +#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x40000260 +#define XCHAL_INTLEVEL4_VECOFS 0x00000000 +#define XCHAL_INTLEVEL4_VECTOR_VADDR 0x40000390 +#define XCHAL_INTLEVEL4_VECTOR_PADDR 0x40000390 +#define XCHAL_DEBUG_VECOFS XCHAL_INTLEVEL4_VECOFS +#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL4_VECTOR_VADDR +#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL4_VECTOR_PADDR +#define XCHAL_NMI_VECOFS 0x00000000 +#define XCHAL_NMI_VECTOR_VADDR 0x400003B0 +#define XCHAL_NMI_VECTOR_PADDR 0x400003B0 +#define XCHAL_INTLEVEL5_VECOFS XCHAL_NMI_VECOFS +#define XCHAL_INTLEVEL5_VECTOR_VADDR XCHAL_NMI_VECTOR_VADDR +#define XCHAL_INTLEVEL5_VECTOR_PADDR XCHAL_NMI_VECTOR_PADDR + + +/*---------------------------------------------------------------------- + DEBUG + ----------------------------------------------------------------------*/ + +#define XCHAL_HAVE_OCD 1 /* OnChipDebug option */ +#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */ +#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */ +#define XCHAL_HAVE_OCD_DIR_ARRAY 1 /* faster OCD option */ + + +/*---------------------------------------------------------------------- + MMU + ----------------------------------------------------------------------*/ + +/* See core-matmap.h header file for more details. */ + +#define XCHAL_HAVE_TLBS 1 /* inverse of HAVE_CACHEATTR */ +#define XCHAL_HAVE_SPANNING_WAY 1 /* one way maps I+D 4GB vaddr */ +#define XCHAL_HAVE_IDENTITY_MAP 1 /* vaddr == paddr always */ +#define XCHAL_HAVE_CACHEATTR 0 /* CACHEATTR register present */ +#define XCHAL_HAVE_MIMIC_CACHEATTR 1 /* region protection */ +#define XCHAL_HAVE_XLT_CACHEATTR 0 /* region prot. w/translation */ +#define XCHAL_HAVE_PTP_MMU 0 /* full MMU (with page table + [autorefill] and protection) + usable for an MMU-based OS */ +/* If none of the above last 4 are set, it's a custom TLB configuration. */ + +#define XCHAL_MMU_ASID_BITS 0 /* number of bits in ASIDs */ +#define XCHAL_MMU_RINGS 1 /* number of rings (1..4) */ +#define XCHAL_MMU_RING_BITS 0 /* num of bits in RING field */ + +#endif /* !XTENSA_HAL_NON_PRIVILEGED_ONLY */ + + +#endif /* _XTENSA_CORE_CONFIGURATION_H */ + diff --git a/arch/xtensa/variants/s6000/include/variant/hardware.h b/arch/xtensa/variants/s6000/include/variant/hardware.h new file mode 100644 index 000000000000..5d9ba098d84a --- /dev/null +++ b/arch/xtensa/variants/s6000/include/variant/hardware.h @@ -0,0 +1,259 @@ +#ifndef __XTENSA_S6000_HARDWARE_H +#define __XTENSA_S6000_HARDWARE_H + +#define S6_SCLK 1843200 + +#define S6_MEM_REG 0x20000000 +#define S6_MEM_EFI 0x33F00000 +#define S6_MEM_PCIE_DATARAM1 0x34000000 +#define S6_MEM_XLMI 0x37F80000 +#define S6_MEM_PIF_DATARAM1 0x37FFC000 +#define S6_MEM_GMAC 0x38000000 +#define S6_MEM_I2S 0x3A000000 +#define S6_MEM_EGIB 0x3C000000 +#define S6_MEM_PCIE_CFG 0x3E000000 +#define S6_MEM_PIF_DATARAM 0x3FFE0000 +#define S6_MEM_XLMI_DATARAM 0x3FFF0000 +#define S6_MEM_DDR 0x40000000 +#define S6_MEM_PCIE_APER 0xC0000000 +#define S6_MEM_AUX 0xF0000000 + +/* Device addresses */ + +#define S6_REG_SCB S6_MEM_REG +#define S6_REG_NB (S6_REG_SCB + 0x10000) +#define S6_REG_LMSDMA (S6_REG_SCB + 0x20000) +#define S6_REG_NI (S6_REG_SCB + 0x30000) +#define S6_REG_NIDMA (S6_REG_SCB + 0x40000) +#define S6_REG_NS (S6_REG_SCB + 0x50000) +#define S6_REG_DDR (S6_REG_SCB + 0x60000) +#define S6_REG_GREG1 (S6_REG_SCB + 0x70000) +#define S6_REG_DP (S6_REG_SCB + 0x80000) +#define S6_REG_DPDMA (S6_REG_SCB + 0x90000) +#define S6_REG_EGIB (S6_REG_SCB + 0xA0000) +#define S6_REG_PCIE (S6_REG_SCB + 0xB0000) +#define S6_REG_I2S (S6_REG_SCB + 0xC0000) +#define S6_REG_GMAC (S6_REG_SCB + 0xD0000) +#define S6_REG_HIFDMA (S6_REG_SCB + 0xE0000) +#define S6_REG_GREG2 (S6_REG_SCB + 0xF0000) + +#define S6_REG_APB S6_REG_SCB +#define S6_REG_UART (S6_REG_APB + 0x0000) +#define S6_REG_INTC (S6_REG_APB + 0x2000) +#define S6_REG_SPI (S6_REG_APB + 0x3000) +#define S6_REG_I2C (S6_REG_APB + 0x4000) +#define S6_REG_GPIO (S6_REG_APB + 0x8000) + +/* Global register block */ + +#define S6_GREG1_PLL_LOCKCLEAR 0x000 +#define S6_GREG1_PLL_LOCK_SYS 0 +#define S6_GREG1_PLL_LOCK_IO 1 +#define S6_GREG1_PLL_LOCK_AIM 2 +#define S6_GREG1_PLL_LOCK_DP0 3 +#define S6_GREG1_PLL_LOCK_DP2 4 +#define S6_GREG1_PLL_LOCK_DDR 5 +#define S6_GREG1_PLL_LOCKSTAT 0x004 +#define S6_GREG1_PLL_LOCKSTAT_CURLOCK 0 +#define S6_GREG1_PLL_LOCKSTAT_EVERUNLCK 8 +#define S6_GREG1_PLLSEL 0x010 +#define S6_GREG1_PLLSEL_AIM 0 +#define S6_GREG1_PLLSEL_AIM_DDR2 0 +#define S6_GREG1_PLLSEL_AIM_300MHZ 1 +#define S6_GREG1_PLLSEL_AIM_240MHZ 2 +#define S6_GREG1_PLLSEL_AIM_200MHZ 3 +#define S6_GREG1_PLLSEL_AIM_150MHZ 4 +#define S6_GREG1_PLLSEL_AIM_120MHZ 5 +#define S6_GREG1_PLLSEL_AIM_40MHZ 6 +#define S6_GREG1_PLLSEL_AIM_PLLAIMREF 7 +#define S6_GREG1_PLLSEL_AIM_MASK 7 +#define S6_GREG1_PLLSEL_DDR 8 +#define S6_GREG1_PLLSEL_DDR_HS 0 +#define S6_GREG1_PLLSEL_DDR_333MHZ 1 +#define S6_GREG1_PLLSEL_DDR_250MHZ 2 +#define S6_GREG1_PLLSEL_DDR_200MHZ 3 +#define S6_GREG1_PLLSEL_DDR_167MHZ 4 +#define S6_GREG1_PLLSEL_DDR_100MHZ 5 +#define S6_GREG1_PLLSEL_DDR_33MHZ 6 +#define S6_GREG1_PLLSEL_DDR_PLLIOREF 7 +#define S6_GREG1_PLLSEL_DDR_MASK 7 +#define S6_GREG1_PLLSEL_GMAC 16 +#define S6_GREG1_PLLSEL_GMAC_125MHZ 0 +#define S6_GREG1_PLLSEL_GMAC_25MHZ 1 +#define S6_GREG1_PLLSEL_GMAC_2500KHZ 2 +#define S6_GREG1_PLLSEL_GMAC_EXTERN 3 +#define S6_GREG1_PLLSEL_GMAC_MASK 3 +#define S6_GREG1_PLLSEL_GMII 18 +#define S6_GREG1_PLLSEL_GMII_111MHZ 0 +#define S6_GREG1_PLLSEL_GMII_IOREF 1 +#define S6_GREG1_PLLSEL_GMII_NONE 2 +#define S6_GREG1_PLLSEL_GMII_125MHZ 3 +#define S6_GREG1_PLLSEL_GMII_MASK 3 +#define S6_GREG1_SYSUNLOCKCNT 0x020 +#define S6_GREG1_IOUNLOCKCNT 0x024 +#define S6_GREG1_AIMUNLOCKCNT 0x028 +#define S6_GREG1_DP0UNLOCKCNT 0x02C +#define S6_GREG1_DP2UNLOCKCNT 0x030 +#define S6_GREG1_DDRUNLOCKCNT 0x034 +#define S6_GREG1_CLKBAL0 0x040 +#define S6_GREG1_CLKBAL0_LSGB 0 +#define S6_GREG1_CLKBAL0_LSPX 8 +#define S6_GREG1_CLKBAL0_MEMDO 16 +#define S6_GREG1_CLKBAL0_HSXT1 24 +#define S6_GREG1_CLKBAL1 0x044 +#define S6_GREG1_CLKBAL1_HSISEF 0 +#define S6_GREG1_CLKBAL1_HSNI 8 +#define S6_GREG1_CLKBAL1_HSNS 16 +#define S6_GREG1_CLKBAL1_HSISEFCFG 24 +#define S6_GREG1_CLKBAL2 0x048 +#define S6_GREG1_CLKBAL2_LSNB 0 +#define S6_GREG1_CLKBAL2_LSSB 8 +#define S6_GREG1_CLKBAL2_LSREST 24 +#define S6_GREG1_CLKBAL3 0x04C +#define S6_GREG1_CLKBAL3_ISEFXAD 0 +#define S6_GREG1_CLKBAL3_ISEFLMS 8 +#define S6_GREG1_CLKBAL3_ISEFISEF 16 +#define S6_GREG1_CLKBAL3_DDRDD 24 +#define S6_GREG1_CLKBAL4 0x050 +#define S6_GREG1_CLKBAL4_DDRDP 0 +#define S6_GREG1_CLKBAL4_DDRDO 8 +#define S6_GREG1_CLKBAL4_DDRNB 16 +#define S6_GREG1_CLKBAL4_DDRLMS 24 +#define S6_GREG1_BLOCKENA 0x100 +#define S6_GREG1_BLOCK_DDR 0 +#define S6_GREG1_BLOCK_DP 1 +#define S6_GREG1_BLOCK_NSNI 2 +#define S6_GREG1_BLOCK_PCIE 3 +#define S6_GREG1_BLOCK_GMAC 4 +#define S6_GREG1_BLOCK_I2S 5 +#define S6_GREG1_BLOCK_EGIB 6 +#define S6_GREG1_BLOCK_SB 7 +#define S6_GREG1_BLOCK_XT1 8 +#define S6_GREG1_CLKGATE 0x104 +#define S6_GREG1_BGATE_AIMNORTH 9 +#define S6_GREG1_BGATE_AIMEAST 10 +#define S6_GREG1_BGATE_AIMWEST 11 +#define S6_GREG1_BGATE_AIMSOUTH 12 +#define S6_GREG1_CHIPRES 0x108 +#define S6_GREG1_CHIPRES_SOFTRES 0 +#define S6_GREG1_CHIPRES_LOSTLOCK 1 +#define S6_GREG1_RESETCAUSE 0x10C +#define S6_GREG1_RESETCAUSE_RESETN 0 +#define S6_GREG1_RESETCAUSE_GLOBAL 1 +#define S6_GREG1_RESETCAUSE_WDOGTIMER 2 +#define S6_GREG1_RESETCAUSE_SWCHIP 3 +#define S6_GREG1_RESETCAUSE_PLLSYSLOSS 4 +#define S6_GREG1_RESETCAUSE_PCIE 5 +#define S6_GREG1_RESETCAUSE_CREATEDGLOB 6 +#define S6_GREG1_REFCLOCKCNT 0x110 +#define S6_GREG1_RESETTIMER 0x114 +#define S6_GREG1_NMITIMER 0x118 +#define S6_GREG1_GLOBAL_TIMER 0x11C +#define S6_GREG1_TIMER0 0x180 +#define S6_GREG1_TIMER1 0x184 +#define S6_GREG1_UARTCLOCKSEL 0x204 +#define S6_GREG1_CHIPVERSPACKG 0x208 +#define S6_GREG1_CHIPVERSPACKG_CHIPVID 0 +#define S6_GREG1_CHIPVERSPACKG_PACKSEL 8 +#define S6_GREG1_ONDIETERMCTRL 0x20C +#define S6_GREG1_ONDIETERMCTRL_WEST 0 +#define S6_GREG1_ONDIETERMCTRL_NORTH 2 +#define S6_GREG1_ONDIETERMCTRL_EAST 4 +#define S6_GREG1_ONDIETERMCTRL_SOUTH 6 +#define S6_GREG1_ONDIETERMCTRL_NONE 0 +#define S6_GREG1_ONDIETERMCTRL_75OHM 2 +#define S6_GREG1_ONDIETERMCTRL_MASK 3 +#define S6_GREG1_BOOT_CFG0 0x210 +#define S6_GREG1_BOOT_CFG0_AIMSTRONG 1 +#define S6_GREG1_BOOT_CFG0_MINIBOOTDL 2 +#define S6_GREG1_BOOT_CFG0_OCDGPIO8SET 5 +#define S6_GREG1_BOOT_CFG0_OCDGPIOENA 6 +#define S6_GREG1_BOOT_CFG0_DOWNSTREAM 7 +#define S6_GREG1_BOOT_CFG0_PLLSYSDIV 8 +#define S6_GREG1_BOOT_CFG0_PLLSYSDIV_300MHZ 1 +#define S6_GREG1_BOOT_CFG0_PLLSYSDIV_240MHZ 2 +#define S6_GREG1_BOOT_CFG0_PLLSYSDIV_200MHZ 3 +#define S6_GREG1_BOOT_CFG0_PLLSYSDIV_150MHZ 4 +#define S6_GREG1_BOOT_CFG0_PLLSYSDIV_120MHZ 5 +#define S6_GREG1_BOOT_CFG0_PLLSYSDIV_40MHZ 6 +#define S6_GREG1_BOOT_CFG0_PLLSYSDIV_MASK 7 +#define S6_GREG1_BOOT_CFG0_BALHSLMS 12 +#define S6_GREG1_BOOT_CFG0_BALHSNB 18 +#define S6_GREG1_BOOT_CFG0_BALHSXAD 24 +#define S6_GREG1_BOOT_CFG1 0x214 +#define S6_GREG1_BOOT_CFG1_PCIE1LANE 1 +#define S6_GREG1_BOOT_CFG1_MPLLPRESCALE 2 +#define S6_GREG1_BOOT_CFG1_MPLLNCY 4 +#define S6_GREG1_BOOT_CFG1_MPLLNCY5 9 +#define S6_GREG1_BOOT_CFG1_BALHSREST 14 +#define S6_GREG1_BOOT_CFG1_BALHSPSMEMS 20 +#define S6_GREG1_BOOT_CFG1_BALLSGI 26 +#define S6_GREG1_BOOT_CFG2 0x218 +#define S6_GREG1_BOOT_CFG2_PEID 0 +#define S6_GREG1_BOOT_CFG3 0x21C +#define S6_GREG1_DRAMBUSYHOLDOF 0x220 +#define S6_GREG1_DRAMBUSYHOLDOF_XT0 0 +#define S6_GREG1_DRAMBUSYHOLDOF_XT1 4 +#define S6_GREG1_DRAMBUSYHOLDOF_XT_MASK 7 +#define S6_GREG1_PCIEBAR1SIZE 0x224 +#define S6_GREG1_PCIEBAR2SIZE 0x228 +#define S6_GREG1_PCIEVENDOR 0x22C +#define S6_GREG1_PCIEDEVICE 0x230 +#define S6_GREG1_PCIEREV 0x234 +#define S6_GREG1_PCIECLASS 0x238 +#define S6_GREG1_XT1DCACHEMISS 0x240 +#define S6_GREG1_XT1ICACHEMISS 0x244 +#define S6_GREG1_HWSEMAPHORE(n) (0x400 + 4 * (n)) +#define S6_GREG1_HWSEMAPHORE_NB 16 + +/* peripheral interrupt numbers */ + +#define S6_INTC_GPIO(n) (n) /* 0..3 */ +#define S6_INTC_I2C 4 +#define S6_INTC_SPI 5 +#define S6_INTC_NB_ERR 6 +#define S6_INTC_DMA_LMSERR 7 +#define S6_INTC_DMA_LMSLOWWMRK(n) (8 + (n)) /* 0..11 */ +#define S6_INTC_DMA_LMSPENDCNT(n) (20 + (n)) /* 0..11 */ +#define S6_INTC_DMA HOSTLOWWMRK(n) (32 + (n)) /* 0..6 */ +#define S6_INTC_DMA_HOSTPENDCNT(n) (39 + (n)) /* 0..6 */ +#define S6_INTC_DMA_HOSTERR 46 +#define S6_INTC_UART(n) (47 + (n)) /* 0..1 */ +#define S6_INTC_XAD 49 +#define S6_INTC_NI_ERR 50 +#define S6_INTC_NI_INFIFOFULL 51 +#define S6_INTC_DMA_NIERR 52 +#define S6_INTC_DMA_NILOWWMRK(n) (53 + (n)) /* 0..3 */ +#define S6_INTC_DMA_NIPENDCNT(n) (57 + (n)) /* 0..3 */ +#define S6_INTC_DDR 61 +#define S6_INTC_NS_ERR 62 +#define S6_INTC_EFI_CFGERR 63 +#define S6_INTC_EFI_ISEFTEST 64 +#define S6_INTC_EFI_WRITEERR 65 +#define S6_INTC_NMI_TIMER 66 +#define S6_INTC_PLLLOCK_SYS 67 +#define S6_INTC_PLLLOCK_IO 68 +#define S6_INTC_PLLLOCK_AIM 69 +#define S6_INTC_PLLLOCK_DP0 70 +#define S6_INTC_PLLLOCK_DP2 71 +#define S6_INTC_I2S_ERR 72 +#define S6_INTC_GMAC_STAT 73 +#define S6_INTC_GMAC_ERR 74 +#define S6_INTC_GIB_ERR 75 +#define S6_INTC_PCIE_ERR 76 +#define S6_INTC_PCIE_MSI(n) (77 + (n)) /* 0..3 */ +#define S6_INTC_PCIE_INTA 81 +#define S6_INTC_PCIE_INTB 82 +#define S6_INTC_PCIE_INTC 83 +#define S6_INTC_PCIE_INTD 84 +#define S6_INTC_SW(n) (85 + (n)) /* 0..9 */ +#define S6_INTC_SW_ENABLE(n) (85 + 256 + (n)) +#define S6_INTC_DMA_DP_ERR 95 +#define S6_INTC_DMA_DPLOWWMRK(n) (96 + (n)) /* 0..3 */ +#define S6_INTC_DMA_DPPENDCNT(n) (100 + (n)) /* 0..3 */ +#define S6_INTC_DMA_DPTERMCNT(n) (104 + (n)) /* 0..3 */ +#define S6_INTC_TIMER0 108 +#define S6_INTC_TIMER1 109 +#define S6_INTC_DMA_HOSTTERMCNT(n) (110 + (n)) /* 0..6 */ + +#endif /* __XTENSA_S6000_HARDWARE_H */ diff --git a/arch/xtensa/variants/s6000/include/variant/irq.h b/arch/xtensa/variants/s6000/include/variant/irq.h new file mode 100644 index 000000000000..fa031cb0acc4 --- /dev/null +++ b/arch/xtensa/variants/s6000/include/variant/irq.h @@ -0,0 +1,9 @@ +#ifndef __XTENSA_S6000_IRQ_H +#define __XTENSA_S6000_IRQ_H + +#define NO_IRQ (-1) + +extern void variant_irq_enable(unsigned int irq); +extern void variant_irq_disable(unsigned int irq); + +#endif /* __XTENSA_S6000_IRQ_H */ diff --git a/arch/xtensa/variants/s6000/include/variant/tie-asm.h b/arch/xtensa/variants/s6000/include/variant/tie-asm.h new file mode 100644 index 000000000000..f02d0a3a2e20 --- /dev/null +++ b/arch/xtensa/variants/s6000/include/variant/tie-asm.h @@ -0,0 +1,304 @@ +/* + * This header file contains assembly-language definitions (assembly + * macros, etc.) for this specific Xtensa processor's TIE extensions + * and options. It is customized to this Xtensa processor configuration. + * + * 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. + * + * Copyright (C) 1999-2008 Tensilica Inc. + */ + +#ifndef _XTENSA_CORE_TIE_ASM_H +#define _XTENSA_CORE_TIE_ASM_H + +/* Selection parameter values for save-area save/restore macros: */ +/* Option vs. TIE: */ +#define XTHAL_SAS_TIE 0x0001 /* custom extension or coprocessor */ +#define XTHAL_SAS_OPT 0x0002 /* optional (and not a coprocessor) */ +/* Whether used automatically by compiler: */ +#define XTHAL_SAS_NOCC 0x0004 /* not used by compiler w/o special opts/code */ +#define XTHAL_SAS_CC 0x0008 /* used by compiler without special opts/code */ +/* ABI handling across function calls: */ +#define XTHAL_SAS_CALR 0x0010 /* caller-saved */ +#define XTHAL_SAS_CALE 0x0020 /* callee-saved */ +#define XTHAL_SAS_GLOB 0x0040 /* global across function calls (in thread) */ +/* Misc */ +#define XTHAL_SAS_ALL 0xFFFF /* include all default NCP contents */ + + + +/* Macro to save all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Save area ptr (clobbered): ptr (16 byte aligned) + * Scratch regs (clobbered): at1..at4 (only first XCHAL_NCP_NUM_ATMPS needed) + */ + .macro xchal_ncp_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL + xchal_sa_start \continue, \ofs + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~\select + xchal_sa_align \ptr, 0, 1024-4, 4, 4 + rsr \at1, BR // boolean option + s32i \at1, \ptr, .Lxchal_ofs_ + 0 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + .endm // xchal_ncp_store + +/* Macro to save all non-coprocessor (extra) custom TIE and optional state + * (not including zero-overhead loop registers). + * Save area ptr (clobbered): ptr (16 byte aligned) + * Scratch regs (clobbered): at1..at4 (only first XCHAL_NCP_NUM_ATMPS needed) + */ + .macro xchal_ncp_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL + xchal_sa_start \continue, \ofs + .ifeq (XTHAL_SAS_OPT | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~\select + xchal_sa_align \ptr, 0, 1024-4, 4, 4 + l32i \at1, \ptr, .Lxchal_ofs_ + 0 + wsr \at1, BR // boolean option + .set .Lxchal_ofs_, .Lxchal_ofs_ + 4 + .endif + .endm // xchal_ncp_load + + + +#define XCHAL_NCP_NUM_ATMPS 1 + + + +/* Macro to save the state of TIE coprocessor FPU. + * Save area ptr (clobbered): ptr (16 byte aligned) + * Scratch regs (clobbered): at1..at4 (only first XCHAL_CP0_NUM_ATMPS needed) + */ +#define xchal_cp_FPU_store xchal_cp0_store +/* #define xchal_cp_FPU_store_a2 xchal_cp0_store a2 a3 a4 a5 a6 */ + .macro xchal_cp0_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL + xchal_sa_start \continue, \ofs + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~\select + xchal_sa_align \ptr, 0, 0, 1, 16 + rur232 \at1 // FCR + s32i \at1, \ptr, 0 + rur233 \at1 // FSR + s32i \at1, \ptr, 4 + SSI f0, \ptr, 8 + SSI f1, \ptr, 12 + SSI f2, \ptr, 16 + SSI f3, \ptr, 20 + SSI f4, \ptr, 24 + SSI f5, \ptr, 28 + SSI f6, \ptr, 32 + SSI f7, \ptr, 36 + SSI f8, \ptr, 40 + SSI f9, \ptr, 44 + SSI f10, \ptr, 48 + SSI f11, \ptr, 52 + SSI f12, \ptr, 56 + SSI f13, \ptr, 60 + SSI f14, \ptr, 64 + SSI f15, \ptr, 68 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 + .endif + .endm // xchal_cp0_store + +/* Macro to restore the state of TIE coprocessor FPU. + * Save area ptr (clobbered): ptr (16 byte aligned) + * Scratch regs (clobbered): at1..at4 (only first XCHAL_CP0_NUM_ATMPS needed) + */ +#define xchal_cp_FPU_load xchal_cp0_load +/* #define xchal_cp_FPU_load_a2 xchal_cp0_load a2 a3 a4 a5 a6 */ + .macro xchal_cp0_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL + xchal_sa_start \continue, \ofs + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~\select + xchal_sa_align \ptr, 0, 0, 1, 16 + l32i \at1, \ptr, 0 + wur232 \at1 // FCR + l32i \at1, \ptr, 4 + wur233 \at1 // FSR + LSI f0, \ptr, 8 + LSI f1, \ptr, 12 + LSI f2, \ptr, 16 + LSI f3, \ptr, 20 + LSI f4, \ptr, 24 + LSI f5, \ptr, 28 + LSI f6, \ptr, 32 + LSI f7, \ptr, 36 + LSI f8, \ptr, 40 + LSI f9, \ptr, 44 + LSI f10, \ptr, 48 + LSI f11, \ptr, 52 + LSI f12, \ptr, 56 + LSI f13, \ptr, 60 + LSI f14, \ptr, 64 + LSI f15, \ptr, 68 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 72 + .endif + .endm // xchal_cp0_load + +#define XCHAL_CP0_NUM_ATMPS 1 + +/* Macro to save the state of TIE coprocessor XAD. + * Save area ptr (clobbered): ptr (16 byte aligned) + * Scratch regs (clobbered): at1..at4 (only first XCHAL_CP6_NUM_ATMPS needed) + */ +#define xchal_cp_XAD_store xchal_cp6_store +/* #define xchal_cp_XAD_store_a2 xchal_cp6_store a2 a3 a4 a5 a6 */ + .macro xchal_cp6_store ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL + xchal_sa_start \continue, \ofs + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~\select + xchal_sa_align \ptr, 0, 0, 1, 16 + rur0 \at1 // LDCBHI + s32i \at1, \ptr, 0 + rur1 \at1 // LDCBLO + s32i \at1, \ptr, 4 + rur2 \at1 // STCBHI + s32i \at1, \ptr, 8 + rur3 \at1 // STCBLO + s32i \at1, \ptr, 12 + rur8 \at1 // LDBRBASE + s32i \at1, \ptr, 16 + rur9 \at1 // LDBROFF + s32i \at1, \ptr, 20 + rur10 \at1 // LDBRINC + s32i \at1, \ptr, 24 + rur11 \at1 // STBRBASE + s32i \at1, \ptr, 28 + rur12 \at1 // STBROFF + s32i \at1, \ptr, 32 + rur13 \at1 // STBRINC + s32i \at1, \ptr, 36 + rur24 \at1 // SCRATCH0 + s32i \at1, \ptr, 40 + rur25 \at1 // SCRATCH1 + s32i \at1, \ptr, 44 + rur26 \at1 // SCRATCH2 + s32i \at1, \ptr, 48 + rur27 \at1 // SCRATCH3 + s32i \at1, \ptr, 52 + WRAS128I wra0, \ptr, 64 + WRAS128I wra1, \ptr, 80 + WRAS128I wra2, \ptr, 96 + WRAS128I wra3, \ptr, 112 + WRAS128I wra4, \ptr, 128 + WRAS128I wra5, \ptr, 144 + WRAS128I wra6, \ptr, 160 + WRAS128I wra7, \ptr, 176 + WRAS128I wra8, \ptr, 192 + WRAS128I wra9, \ptr, 208 + WRAS128I wra10, \ptr, 224 + WRAS128I wra11, \ptr, 240 + WRAS128I wra12, \ptr, 256 + WRAS128I wra13, \ptr, 272 + WRAS128I wra14, \ptr, 288 + WRAS128I wra15, \ptr, 304 + WRBS128I wrb0, \ptr, 320 + WRBS128I wrb1, \ptr, 336 + WRBS128I wrb2, \ptr, 352 + WRBS128I wrb3, \ptr, 368 + WRBS128I wrb4, \ptr, 384 + WRBS128I wrb5, \ptr, 400 + WRBS128I wrb6, \ptr, 416 + WRBS128I wrb7, \ptr, 432 + WRBS128I wrb8, \ptr, 448 + WRBS128I wrb9, \ptr, 464 + WRBS128I wrb10, \ptr, 480 + WRBS128I wrb11, \ptr, 496 + WRBS128I wrb12, \ptr, 512 + WRBS128I wrb13, \ptr, 528 + WRBS128I wrb14, \ptr, 544 + WRBS128I wrb15, \ptr, 560 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 576 + .endif + .endm // xchal_cp6_store + +/* Macro to restore the state of TIE coprocessor XAD. + * Save area ptr (clobbered): ptr (16 byte aligned) + * Scratch regs (clobbered): at1..at4 (only first XCHAL_CP6_NUM_ATMPS needed) + */ +#define xchal_cp_XAD_load xchal_cp6_load +/* #define xchal_cp_XAD_load_a2 xchal_cp6_load a2 a3 a4 a5 a6 */ + .macro xchal_cp6_load ptr at1 at2 at3 at4 continue=0 ofs=-1 select=XTHAL_SAS_ALL + xchal_sa_start \continue, \ofs + .ifeq (XTHAL_SAS_TIE | XTHAL_SAS_NOCC | XTHAL_SAS_CALR) & ~\select + xchal_sa_align \ptr, 0, 0, 1, 16 + l32i \at1, \ptr, 0 + wur0 \at1 // LDCBHI + l32i \at1, \ptr, 4 + wur1 \at1 // LDCBLO + l32i \at1, \ptr, 8 + wur2 \at1 // STCBHI + l32i \at1, \ptr, 12 + wur3 \at1 // STCBLO + l32i \at1, \ptr, 16 + wur8 \at1 // LDBRBASE + l32i \at1, \ptr, 20 + wur9 \at1 // LDBROFF + l32i \at1, \ptr, 24 + wur10 \at1 // LDBRINC + l32i \at1, \ptr, 28 + wur11 \at1 // STBRBASE + l32i \at1, \ptr, 32 + wur12 \at1 // STBROFF + l32i \at1, \ptr, 36 + wur13 \at1 // STBRINC + l32i \at1, \ptr, 40 + wur24 \at1 // SCRATCH0 + l32i \at1, \ptr, 44 + wur25 \at1 // SCRATCH1 + l32i \at1, \ptr, 48 + wur26 \at1 // SCRATCH2 + l32i \at1, \ptr, 52 + wur27 \at1 // SCRATCH3 + WRBL128I wrb0, \ptr, 320 + WRBL128I wrb1, \ptr, 336 + WRBL128I wrb2, \ptr, 352 + WRBL128I wrb3, \ptr, 368 + WRBL128I wrb4, \ptr, 384 + WRBL128I wrb5, \ptr, 400 + WRBL128I wrb6, \ptr, 416 + WRBL128I wrb7, \ptr, 432 + WRBL128I wrb8, \ptr, 448 + WRBL128I wrb9, \ptr, 464 + WRBL128I wrb10, \ptr, 480 + WRBL128I wrb11, \ptr, 496 + WRBL128I wrb12, \ptr, 512 + WRBL128I wrb13, \ptr, 528 + WRBL128I wrb14, \ptr, 544 + WRBL128I wrb15, \ptr, 560 + WRAL128I wra0, \ptr, 64 + WRAL128I wra1, \ptr, 80 + WRAL128I wra2, \ptr, 96 + WRAL128I wra3, \ptr, 112 + WRAL128I wra4, \ptr, 128 + WRAL128I wra5, \ptr, 144 + WRAL128I wra6, \ptr, 160 + WRAL128I wra7, \ptr, 176 + WRAL128I wra8, \ptr, 192 + WRAL128I wra9, \ptr, 208 + WRAL128I wra10, \ptr, 224 + WRAL128I wra11, \ptr, 240 + WRAL128I wra12, \ptr, 256 + WRAL128I wra13, \ptr, 272 + WRAL128I wra14, \ptr, 288 + WRAL128I wra15, \ptr, 304 + .set .Lxchal_ofs_, .Lxchal_ofs_ + 576 + .endif + .endm // xchal_cp6_load + +#define XCHAL_CP6_NUM_ATMPS 1 +#define XCHAL_SA_NUM_ATMPS 1 + + /* Empty macros for unconfigured coprocessors: */ + .macro xchal_cp1_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp1_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp2_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp3_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp4_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp5_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_store p a b c d continue=0 ofs=-1 select=-1 ; .endm + .macro xchal_cp7_load p a b c d continue=0 ofs=-1 select=-1 ; .endm + +#endif /*_XTENSA_CORE_TIE_ASM_H*/ + diff --git a/arch/xtensa/variants/s6000/include/variant/tie.h b/arch/xtensa/variants/s6000/include/variant/tie.h new file mode 100644 index 000000000000..be7ea843d5df --- /dev/null +++ b/arch/xtensa/variants/s6000/include/variant/tie.h @@ -0,0 +1,191 @@ +/* + * This header file describes this specific Xtensa processor's TIE extensions + * that extend basic Xtensa core functionality. It is customized to this + * Xtensa processor configuration. + * + * 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. + * + * Copyright (C) 1999-2008 Tensilica Inc. + */ + +#ifndef _XTENSA_CORE_TIE_H +#define _XTENSA_CORE_TIE_H + +#define XCHAL_CP_NUM 2 /* number of coprocessors */ +#define XCHAL_CP_MAX 7 /* max CP ID + 1 (0 if none) */ +#define XCHAL_CP_MASK 0x41 /* bitmask of all CPs by ID */ +#define XCHAL_CP_PORT_MASK 0x00 /* bitmask of only port CPs */ + +/* Basic parameters of each coprocessor: */ +#define XCHAL_CP0_NAME "FPU" +#define XCHAL_CP0_IDENT FPU +#define XCHAL_CP0_SA_SIZE 72 /* size of state save area */ +#define XCHAL_CP0_SA_ALIGN 4 /* min alignment of save area */ +#define XCHAL_CP_ID_FPU 0 /* coprocessor ID (0..7) */ +#define XCHAL_CP6_NAME "XAD" +#define XCHAL_CP6_IDENT XAD +#define XCHAL_CP6_SA_SIZE 576 /* size of state save area */ +#define XCHAL_CP6_SA_ALIGN 16 /* min alignment of save area */ +#define XCHAL_CP_ID_XAD 6 /* coprocessor ID (0..7) */ + +/* Filler info for unassigned coprocessors, to simplify arrays etc: */ +#define XCHAL_CP1_SA_SIZE 0 +#define XCHAL_CP1_SA_ALIGN 1 +#define XCHAL_CP2_SA_SIZE 0 +#define XCHAL_CP2_SA_ALIGN 1 +#define XCHAL_CP3_SA_SIZE 0 +#define XCHAL_CP3_SA_ALIGN 1 +#define XCHAL_CP4_SA_SIZE 0 +#define XCHAL_CP4_SA_ALIGN 1 +#define XCHAL_CP5_SA_SIZE 0 +#define XCHAL_CP5_SA_ALIGN 1 +#define XCHAL_CP7_SA_SIZE 0 +#define XCHAL_CP7_SA_ALIGN 1 + +/* Save area for non-coprocessor optional and custom (TIE) state: */ +#define XCHAL_NCP_SA_SIZE 4 +#define XCHAL_NCP_SA_ALIGN 4 + +/* Total save area for optional and custom state (NCP + CPn): */ +#define XCHAL_TOTAL_SA_SIZE 672 /* with 16-byte align padding */ +#define XCHAL_TOTAL_SA_ALIGN 16 /* actual minimum alignment */ + +/* + * Detailed contents of save areas. + * NOTE: caller must define the XCHAL_SA_REG macro (not defined here) + * before expanding the XCHAL_xxx_SA_LIST() macros. + * + * XCHAL_SA_REG(s,ccused,abikind,kind,opt,name,galign,align,asize, + * dbnum,base,regnum,bitsz,gapsz,reset,x...) + * + * s = passed from XCHAL_*_LIST(s), eg. to select how to expand + * ccused = set if used by compiler without special options or code + * abikind = 0 (caller-saved), 1 (callee-saved), or 2 (thread-global) + * kind = 0 (special reg), 1 (TIE user reg), or 2 (TIE regfile reg) + * opt = 0 (custom TIE extension or coprocessor), or 1 (optional reg) + * name = lowercase reg name (no quotes) + * galign = group byte alignment (power of 2) (galign >= align) + * align = register byte alignment (power of 2) + * asize = allocated size in bytes (asize*8 == bitsz + gapsz + padsz) + * (not including any pad bytes required to galign this or next reg) + * dbnum = unique target number f/debug (see <xtensa-libdb-macros.h>) + * base = reg shortname w/o index (or sr=special, ur=TIE user reg) + * regnum = reg index in regfile, or special/TIE-user reg number + * bitsz = number of significant bits (regfile width, or ur/sr mask bits) + * gapsz = intervening bits, if bitsz bits not stored contiguously + * (padsz = pad bits at end [TIE regfile] or at msbits [ur,sr] of asize) + * reset = register reset value (or 0 if undefined at reset) + * x = reserved for future use (0 until then) + * + * To filter out certain registers, e.g. to expand only the non-global + * registers used by the compiler, you can do something like this: + * + * #define XCHAL_SA_REG(s,ccused,p...) SELCC##ccused(p) + * #define SELCC0(p...) + * #define SELCC1(abikind,p...) SELAK##abikind(p) + * #define SELAK0(p...) REG(p) + * #define SELAK1(p...) REG(p) + * #define SELAK2(p...) + * #define REG(kind,tie,name,galn,aln,asz,csz,dbnum,base,rnum,bsz,rst,x...) \ + * ...what you want to expand... + */ + +#define XCHAL_NCP_SA_NUM 1 +#define XCHAL_NCP_SA_LIST(s) \ + XCHAL_SA_REG(s,0,0,0,1, br, 4, 4, 4,0x0204, sr,4 , 16,0,0,0) + +#define XCHAL_CP0_SA_NUM 18 +#define XCHAL_CP0_SA_LIST(s) \ + XCHAL_SA_REG(s,0,0,1,0, fcr, 4, 4, 4,0x03E8, ur,232, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, fsr, 4, 4, 4,0x03E9, ur,233, 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f0, 4, 4, 4,0x0030, f,0 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f1, 4, 4, 4,0x0031, f,1 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f2, 4, 4, 4,0x0032, f,2 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f3, 4, 4, 4,0x0033, f,3 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f4, 4, 4, 4,0x0034, f,4 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f5, 4, 4, 4,0x0035, f,5 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f6, 4, 4, 4,0x0036, f,6 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f7, 4, 4, 4,0x0037, f,7 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f8, 4, 4, 4,0x0038, f,8 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f9, 4, 4, 4,0x0039, f,9 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f10, 4, 4, 4,0x003A, f,10 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f11, 4, 4, 4,0x003B, f,11 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f12, 4, 4, 4,0x003C, f,12 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f13, 4, 4, 4,0x003D, f,13 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f14, 4, 4, 4,0x003E, f,14 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, f15, 4, 4, 4,0x003F, f,15 , 32,0,0,0) + +#define XCHAL_CP1_SA_NUM 0 +#define XCHAL_CP1_SA_LIST(s) /* empty */ + +#define XCHAL_CP2_SA_NUM 0 +#define XCHAL_CP2_SA_LIST(s) /* empty */ + +#define XCHAL_CP3_SA_NUM 0 +#define XCHAL_CP3_SA_LIST(s) /* empty */ + +#define XCHAL_CP4_SA_NUM 0 +#define XCHAL_CP4_SA_LIST(s) /* empty */ + +#define XCHAL_CP5_SA_NUM 0 +#define XCHAL_CP5_SA_LIST(s) /* empty */ + +#define XCHAL_CP6_SA_NUM 46 +#define XCHAL_CP6_SA_LIST(s) \ + XCHAL_SA_REG(s,0,0,1,0, ldcbhi,16, 4, 4,0x0300, ur,0 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ldcblo, 4, 4, 4,0x0301, ur,1 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, stcbhi, 4, 4, 4,0x0302, ur,2 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, stcblo, 4, 4, 4,0x0303, ur,3 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ldbrbase, 4, 4, 4,0x0308, ur,8 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ldbroff, 4, 4, 4,0x0309, ur,9 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, ldbrinc, 4, 4, 4,0x030A, ur,10 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, stbrbase, 4, 4, 4,0x030B, ur,11 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, stbroff, 4, 4, 4,0x030C, ur,12 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, stbrinc, 4, 4, 4,0x030D, ur,13 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, scratch0, 4, 4, 4,0x0318, ur,24 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, scratch1, 4, 4, 4,0x0319, ur,25 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, scratch2, 4, 4, 4,0x031A, ur,26 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,1,0, scratch3, 4, 4, 4,0x031B, ur,27 , 32,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wra0,16,16,16,0x1010, wra,0 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wra1,16,16,16,0x1011, wra,1 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wra2,16,16,16,0x1012, wra,2 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wra3,16,16,16,0x1013, wra,3 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wra4,16,16,16,0x1014, wra,4 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wra5,16,16,16,0x1015, wra,5 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wra6,16,16,16,0x1016, wra,6 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wra7,16,16,16,0x1017, wra,7 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wra8,16,16,16,0x1018, wra,8 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wra9,16,16,16,0x1019, wra,9 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wra10,16,16,16,0x101A, wra,10 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wra11,16,16,16,0x101B, wra,11 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wra12,16,16,16,0x101C, wra,12 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wra13,16,16,16,0x101D, wra,13 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wra14,16,16,16,0x101E, wra,14 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wra15,16,16,16,0x101F, wra,15 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wrb0,16,16,16,0x1020, wrb,0 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wrb1,16,16,16,0x1021, wrb,1 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wrb2,16,16,16,0x1022, wrb,2 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wrb3,16,16,16,0x1023, wrb,3 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wrb4,16,16,16,0x1024, wrb,4 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wrb5,16,16,16,0x1025, wrb,5 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wrb6,16,16,16,0x1026, wrb,6 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wrb7,16,16,16,0x1027, wrb,7 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wrb8,16,16,16,0x1028, wrb,8 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wrb9,16,16,16,0x1029, wrb,9 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wrb10,16,16,16,0x102A, wrb,10 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wrb11,16,16,16,0x102B, wrb,11 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wrb12,16,16,16,0x102C, wrb,12 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wrb13,16,16,16,0x102D, wrb,13 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wrb14,16,16,16,0x102E, wrb,14 ,128,0,0,0) \ + XCHAL_SA_REG(s,0,0,2,0, wrb15,16,16,16,0x102F, wrb,15 ,128,0,0,0) + +#define XCHAL_CP7_SA_NUM 0 +#define XCHAL_CP7_SA_LIST(s) /* empty */ + +/* Byte length of instruction from its first nibble (op0 field), per FLIX. */ +#define XCHAL_OP0_FORMAT_LENGTHS 3,3,3,3,3,3,3,3,2,2,2,2,2,2,8,8 + +#endif /*_XTENSA_CORE_TIE_H*/ + diff --git a/arch/xtensa/variants/s6000/irq.c b/arch/xtensa/variants/s6000/irq.c new file mode 100644 index 000000000000..6651e3285fcf --- /dev/null +++ b/arch/xtensa/variants/s6000/irq.c @@ -0,0 +1,74 @@ +/* + * s6000 irq crossbar + * + * Copyright (c) 2009 emlix GmbH + * Authors: Johannes Weiner <jw@emlix.com> + * Oskar Schirmer <os@emlix.com> + */ +#include <linux/io.h> +#include <asm/irq.h> +#include <variant/hardware.h> + +/* S6_REG_INTC */ +#define INTC_STATUS 0x000 +#define INTC_RAW 0x010 +#define INTC_STATUS_AG 0x100 +#define INTC_CFG(n) (0x200 + 4 * (n)) + +/* + * The s6000 has a crossbar that multiplexes interrupt output lines + * from the peripherals to input lines on the xtensa core. + * + * We leave the mapping decisions to the platform as it depends on the + * actually connected peripherals which distribution makes sense. + */ +extern const signed char *platform_irq_mappings[NR_IRQS]; + +static unsigned long scp_to_intc_enable[] = { +#define TO_INTC_ENABLE(n) (((n) << 1) + 1) + TO_INTC_ENABLE(0), + TO_INTC_ENABLE(1), + TO_INTC_ENABLE(2), + TO_INTC_ENABLE(3), + TO_INTC_ENABLE(4), + TO_INTC_ENABLE(5), + TO_INTC_ENABLE(6), + TO_INTC_ENABLE(7), + TO_INTC_ENABLE(8), + TO_INTC_ENABLE(9), + TO_INTC_ENABLE(10), + TO_INTC_ENABLE(11), + TO_INTC_ENABLE(12), + -1, + -1, + TO_INTC_ENABLE(13), + -1, + TO_INTC_ENABLE(14), + -1, + TO_INTC_ENABLE(15), +#undef TO_INTC_ENABLE +}; + +static void irq_set(unsigned int irq, int enable) +{ + unsigned long en; + const signed char *m = platform_irq_mappings[irq]; + + if (!m) + return; + en = enable ? scp_to_intc_enable[irq] : 0; + while (*m >= 0) { + writel(en, S6_REG_INTC + INTC_CFG(*m)); + m++; + } +} + +void variant_irq_enable(unsigned int irq) +{ + irq_set(irq, 1); +} + +void variant_irq_disable(unsigned int irq) +{ + irq_set(irq, 0); +} |