Merge branch 'for-linus' of git://git.linaro.org/people/rmk/linux-arm
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 29 Mar 2012 23:53:48 +0000 (16:53 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 29 Mar 2012 23:53:48 +0000 (16:53 -0700)
Pull more ARM updates from Russell King.

This got a fair number of conflicts with the <asm/system.h> split, but
also with some other sparse-irq and header file include cleanups.  They
all looked pretty trivial, though.

* 'for-linus' of git://git.linaro.org/people/rmk/linux-arm: (59 commits)
  ARM: fix Kconfig warning for HAVE_BPF_JIT
  ARM: 7361/1: provide XIP_VIRT_ADDR for no-MMU builds
  ARM: 7349/1: integrator: convert to sparse irqs
  ARM: 7259/3: net: JIT compiler for packet filters
  ARM: 7334/1: add jump label support
  ARM: 7333/2: jump label: detect %c support for ARM
  ARM: 7338/1: add support for early console output via semihosting
  ARM: use set_current_blocked() and block_sigmask()
  ARM: exec: remove redundant set_fs(USER_DS)
  ARM: 7332/1: extract out code patch function from kprobes
  ARM: 7331/1: extract out insn generation code from ftrace
  ARM: 7330/1: ftrace: use canonical Thumb-2 wide instruction format
  ARM: 7351/1: ftrace: remove useless memory checks
  ARM: 7316/1: kexec: EOI active and mask all interrupts in kexec crash path
  ARM: Versatile Express: add NO_IOPORT
  ARM: get rid of asm/irq.h in asm/prom.h
  ARM: 7319/1: Print debug info for SIGBUS in user faults
  ARM: 7318/1: gic: refactor irq_start assignment
  ARM: 7317/1: irq: avoid NULL check in for_each_irq_desc loop
  ARM: 7315/1: perf: add support for the Cortex-A7 PMU
  ...

159 files changed:
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/Makefile
arch/arm/boot/compressed/.gitignore
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/decompress.c
arch/arm/boot/compressed/piggy.xzkern.S [new file with mode: 0644]
arch/arm/common/gic.c
arch/arm/configs/integrator_defconfig
arch/arm/include/asm/elf.h
arch/arm/include/asm/hardware/cache-l2x0.h
arch/arm/include/asm/hardware/it8152.h
arch/arm/include/asm/irq.h
arch/arm/include/asm/jump_label.h [new file with mode: 0644]
arch/arm/include/asm/mc146818rtc.h
arch/arm/include/asm/memory.h
arch/arm/include/asm/mmu_context.h
arch/arm/include/asm/opcodes.h
arch/arm/include/asm/page.h
arch/arm/include/asm/perf_event.h
arch/arm/include/asm/processor.h
arch/arm/include/asm/prom.h
arch/arm/include/asm/tlbflush.h
arch/arm/include/asm/traps.h
arch/arm/kernel/Makefile
arch/arm/kernel/debug.S
arch/arm/kernel/ftrace.c
arch/arm/kernel/head.S
arch/arm/kernel/insn.c [new file with mode: 0644]
arch/arm/kernel/insn.h [new file with mode: 0644]
arch/arm/kernel/irq.c
arch/arm/kernel/jump_label.c [new file with mode: 0644]
arch/arm/kernel/kprobes.c
arch/arm/kernel/machine_kexec.c
arch/arm/kernel/patch.c [new file with mode: 0644]
arch/arm/kernel/patch.h [new file with mode: 0644]
arch/arm/kernel/perf_event.c
arch/arm/kernel/perf_event_v7.c
arch/arm/kernel/process.c
arch/arm/kernel/sched_clock.c
arch/arm/kernel/setup.c
arch/arm/kernel/signal.c
arch/arm/kernel/smp.c
arch/arm/kernel/time.c
arch/arm/kernel/traps.c
arch/arm/mach-davinci/time.c
arch/arm/mach-highbank/highbank.c
arch/arm/mach-highbank/include/mach/irqs.h [deleted file]
arch/arm/mach-integrator/core.c
arch/arm/mach-integrator/include/mach/irqs.h
arch/arm/mach-integrator/integrator_ap.c
arch/arm/mach-integrator/integrator_cp.c
arch/arm/mach-integrator/pci.c
arch/arm/mach-integrator/pci_v3.c
arch/arm/mach-mmp/aspenite.c
arch/arm/mach-mmp/avengers_lite.c
arch/arm/mach-mmp/brownstone.c
arch/arm/mach-mmp/flint.c
arch/arm/mach-mmp/gplugd.c
arch/arm/mach-mmp/include/mach/irqs.h
arch/arm/mach-mmp/irq-mmp2.c
arch/arm/mach-mmp/jasper.c
arch/arm/mach-mmp/tavorevb.c
arch/arm/mach-mmp/teton_bga.c
arch/arm/mach-mmp/ttc_dkb.c
arch/arm/mach-msm/timer.c
arch/arm/mach-picoxcell/include/mach/irqs.h [deleted file]
arch/arm/mach-prima2/timer.c
arch/arm/mach-pxa/capc7117.c
arch/arm/mach-pxa/cm-x300.c
arch/arm/mach-pxa/colibri-pxa270.c
arch/arm/mach-pxa/colibri-pxa300.c
arch/arm/mach-pxa/colibri-pxa320.c
arch/arm/mach-pxa/corgi.c
arch/arm/mach-pxa/csb726.c
arch/arm/mach-pxa/devices.c
arch/arm/mach-pxa/em-x270.c
arch/arm/mach-pxa/gumstix.c
arch/arm/mach-pxa/h5000.c
arch/arm/mach-pxa/himalaya.c
arch/arm/mach-pxa/icontrol.c
arch/arm/mach-pxa/idp.c
arch/arm/mach-pxa/include/mach/irqs.h
arch/arm/mach-pxa/include/mach/mainstone.h
arch/arm/mach-pxa/mioa701.c
arch/arm/mach-pxa/mp900.c
arch/arm/mach-pxa/palmld.c
arch/arm/mach-pxa/palmt5.c
arch/arm/mach-pxa/palmtc.c
arch/arm/mach-pxa/palmte2.c
arch/arm/mach-pxa/palmtreo.c
arch/arm/mach-pxa/palmtx.c
arch/arm/mach-pxa/palmz72.c
arch/arm/mach-pxa/pxa3xx.c
arch/arm/mach-pxa/raumfeld.c
arch/arm/mach-pxa/saar.c
arch/arm/mach-pxa/spitz.c
arch/arm/mach-pxa/stargate2.c
arch/arm/mach-pxa/tavorevb.c
arch/arm/mach-pxa/time.c
arch/arm/mach-pxa/trizeps4.c
arch/arm/mach-pxa/viper.c
arch/arm/mach-pxa/vpac270.c
arch/arm/mach-pxa/xcep.c
arch/arm/mach-pxa/z2.c
arch/arm/mach-shmobile/Kconfig
arch/arm/mach-shmobile/board-ag5evm.c
arch/arm/mach-shmobile/board-bonito.c
arch/arm/mach-shmobile/board-g3evm.c
arch/arm/mach-shmobile/board-g4evm.c
arch/arm/mach-shmobile/board-kota2.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-shmobile/board-marzen.c
arch/arm/mach-shmobile/include/mach/irqs.h
arch/arm/mach-shmobile/intc-r8a7740.c
arch/arm/mach-shmobile/intc-sh7367.c
arch/arm/mach-shmobile/intc-sh7372.c
arch/arm/mach-shmobile/intc-sh7377.c
arch/arm/mach-shmobile/intc-sh73a0.c
arch/arm/mach-shmobile/setup-r8a7740.c
arch/arm/mach-shmobile/setup-r8a7779.c
arch/arm/mach-shmobile/setup-sh7367.c
arch/arm/mach-shmobile/setup-sh7372.c
arch/arm/mach-shmobile/setup-sh7377.c
arch/arm/mach-shmobile/setup-sh73a0.c
arch/arm/mach-vexpress/include/mach/io.h
arch/arm/mm/cache-l2x0.c
arch/arm/mm/copypage-v4mc.c
arch/arm/mm/copypage-v6.c
arch/arm/mm/copypage-xscale.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/fault.c
arch/arm/mm/flush.c
arch/arm/mm/highmem.c
arch/arm/mm/init.c
arch/arm/mm/mm.h
arch/arm/mm/mmu.c
arch/arm/mm/vmregion.c
arch/arm/mm/vmregion.h
arch/arm/net/Makefile [new file with mode: 0644]
arch/arm/net/bpf_jit_32.c [new file with mode: 0644]
arch/arm/net/bpf_jit_32.h [new file with mode: 0644]
arch/arm/plat-nomadik/Kconfig
arch/arm/plat-versatile/Kconfig
arch/c6x/Kconfig
arch/powerpc/Kconfig
arch/sh/Kconfig
arch/sh/include/asm/irq.h
arch/x86/Kconfig
drivers/clocksource/Kconfig
drivers/gpio/gpio-pxa.c
drivers/sh/intc/balancing.c
drivers/sh/intc/core.c
drivers/sh/intc/handle.c
drivers/sh/intc/virq.c
include/linux/sh_intc.h
kernel/irq/Kconfig
scripts/gcc-goto.sh
sound/arm/pxa2xx-ac97-lib.c

index 5098564d58799cc8c63e222003a6881a44c509af..242f3a33d741378ef4687128779853fbf4385a36 100644 (file)
@@ -9,6 +9,7 @@ config ARM
        select SYS_SUPPORTS_APM_EMULATION
        select GENERIC_ATOMIC64 if (CPU_V6 || !CPU_32v6K || !AEABI)
        select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
+       select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
        select HAVE_ARCH_KGDB
        select HAVE_KPROBES if !XIP_KERNEL
        select HAVE_KRETPROBES if (HAVE_KPROBES)
@@ -21,6 +22,7 @@ config ARM
        select HAVE_KERNEL_GZIP
        select HAVE_KERNEL_LZO
        select HAVE_KERNEL_LZMA
+       select HAVE_KERNEL_XZ
        select HAVE_IRQ_WORK
        select HAVE_PERF_EVENTS
        select PERF_USE_VMALLOC
@@ -28,10 +30,10 @@ config ARM
        select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7))
        select HAVE_C_RECORDMCOUNT
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_SPARSE_IRQ
        select GENERIC_IRQ_SHOW
        select CPU_PM if (SUSPEND || CPU_IDLE)
        select GENERIC_PCI_IOMAP
+       select HAVE_BPF_JIT if NET
        help
          The ARM series is a line of low-power-consumption RISC chip designs
          licensed by ARM Ltd and targeted at embedded applications and
@@ -52,9 +54,6 @@ config MIGHT_HAVE_PCI
 config SYS_SUPPORTS_APM_EMULATION
        bool
 
-config HAVE_SCHED_CLOCK
-       bool
-
 config GENERIC_GPIO
        bool
 
@@ -269,6 +268,7 @@ config ARCH_INTEGRATOR
        select PLAT_VERSATILE
        select PLAT_VERSATILE_FPGA_IRQ
        select NEED_MACH_MEMORY_H
+       select SPARSE_IRQ
        help
          Support for ARM's Integrator platform.
 
@@ -315,6 +315,7 @@ config ARCH_VEXPRESS
        select HAVE_CLK
        select HAVE_PATA_PLATFORM
        select ICST
+       select NO_IOPORT
        select PLAT_VERSATILE
        select PLAT_VERSATILE_CLCD
        help
@@ -354,6 +355,7 @@ config ARCH_HIGHBANK
        select GENERIC_CLOCKEVENTS
        select HAVE_ARM_SCU
        select HAVE_SMP
+       select SPARSE_IRQ
        select USE_OF
        help
          Support for the Calxeda Highbank SoC based boards.
@@ -442,7 +444,6 @@ config ARCH_MXC
        select CLKDEV_LOOKUP
        select CLKSRC_MMIO
        select GENERIC_IRQ_CHIP
-       select HAVE_SCHED_CLOCK
        select MULTI_IRQ_HANDLER
        help
          Support for Freescale MXC/iMX-based family of processors
@@ -537,7 +538,6 @@ config ARCH_IXP4XX
        select CPU_XSCALE
        select GENERIC_GPIO
        select GENERIC_CLOCKEVENTS
-       select HAVE_SCHED_CLOCK
        select MIGHT_HAVE_PCI
        select DMABOUNCE if PCI
        help
@@ -608,7 +608,6 @@ config ARCH_MMP
        select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
        select GPIO_PXA
-       select HAVE_SCHED_CLOCK
        select TICK_ONESHOT
        select PLAT_PXA
        select SPARSE_IRQ
@@ -649,7 +648,6 @@ config ARCH_TEGRA
        select GENERIC_CLOCKEVENTS
        select GENERIC_GPIO
        select HAVE_CLK
-       select HAVE_SCHED_CLOCK
        select HAVE_SMP
        select MIGHT_HAVE_CACHE_L2X0
        select ARCH_HAS_CPUFREQ
@@ -666,7 +664,6 @@ config ARCH_PICOXCELL
        select DW_APB_TIMER
        select GENERIC_CLOCKEVENTS
        select GENERIC_GPIO
-       select HAVE_SCHED_CLOCK
        select HAVE_TCM
        select NO_IOPORT
        select SPARSE_IRQ
@@ -694,7 +691,6 @@ config ARCH_PXA
        select ARCH_REQUIRE_GPIOLIB
        select GENERIC_CLOCKEVENTS
        select GPIO_PXA
-       select HAVE_SCHED_CLOCK
        select TICK_ONESHOT
        select PLAT_PXA
        select SPARSE_IRQ
@@ -761,7 +757,6 @@ config ARCH_SA1100
        select CPU_FREQ
        select GENERIC_CLOCKEVENTS
        select CLKDEV_LOOKUP
-       select HAVE_SCHED_CLOCK
        select TICK_ONESHOT
        select ARCH_REQUIRE_GPIOLIB
        select HAVE_IDE
@@ -818,7 +813,6 @@ config ARCH_S5P64X0
        select CLKSRC_MMIO
        select HAVE_S3C2410_WATCHDOG if WATCHDOG
        select GENERIC_CLOCKEVENTS
-       select HAVE_SCHED_CLOCK
        select HAVE_S3C2410_I2C if I2C
        select HAVE_S3C_RTC if RTC_CLASS
        help
@@ -849,7 +843,6 @@ config ARCH_S5PV210
        select CLKSRC_MMIO
        select ARCH_HAS_CPUFREQ
        select GENERIC_CLOCKEVENTS
-       select HAVE_SCHED_CLOCK
        select HAVE_S3C2410_I2C if I2C
        select HAVE_S3C_RTC if RTC_CLASS
        select HAVE_S3C2410_WATCHDOG if WATCHDOG
@@ -892,7 +885,6 @@ config ARCH_U300
        depends on MMU
        select CLKSRC_MMIO
        select CPU_ARM926T
-       select HAVE_SCHED_CLOCK
        select HAVE_TCM
        select ARM_AMBA
        select ARM_PATCH_PHYS_VIRT
@@ -951,7 +943,6 @@ config ARCH_OMAP
        select ARCH_HAS_CPUFREQ
        select CLKSRC_MMIO
        select GENERIC_CLOCKEVENTS
-       select HAVE_SCHED_CLOCK
        select ARCH_HAS_HOLES_MEMORYMODEL
        help
          Support for TI's OMAP platform (OMAP1/2/3/4).
@@ -1115,13 +1106,11 @@ config ARCH_ACORN
 config PLAT_IOP
        bool
        select GENERIC_CLOCKEVENTS
-       select HAVE_SCHED_CLOCK
 
 config PLAT_ORION
        bool
        select CLKSRC_MMIO
        select GENERIC_IRQ_CHIP
-       select HAVE_SCHED_CLOCK
 
 config PLAT_PXA
        bool
index 66ca8014ff3e6648fcb353923e39ee4663d3edc4..85348a09d655afc220fc55f71810b07830ea8936 100644 (file)
@@ -292,6 +292,22 @@ choice
                  Note that the system will appear to hang during boot if there
                  is nothing connected to read from the DCC.
 
+       config DEBUG_SEMIHOSTING
+               bool "Kernel low-level debug output via semihosting I"
+               help
+                 Semihosting enables code running on an ARM target to use
+                 the I/O facilities on a host debugger/emulator through a
+                 simple SVC calls. The host debugger or emulator must have
+                 semihosting enabled for the special svc call to be trapped
+                 otherwise the kernel will crash.
+
+                 This is known to work with OpenOCD, as wellas
+                 ARM's Fast Models, or any other controlling environment
+                 that implements semihosting.
+
+                 For more details about semihosting, please see
+                 chapter 8 of DUI0203I_rvct_developer_guide.pdf from ARM Ltd.
+
 endchoice
 
 config EARLY_PRINTK
index dcb088e868feaa02eb039947cf658b692a7ed0bc..047a20780fc15a5b753c3ea80c2178efed29c18c 100644 (file)
@@ -253,6 +253,7 @@ core-$(CONFIG_VFP)          += arch/arm/vfp/
 
 # If we have a machine-specific directory, then include it in the build.
 core-y                         += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
+core-y                         += arch/arm/net/
 core-y                         += $(machdirs) $(platdirs)
 
 drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/
index e0936a148516e2c5005d3620065938b4acec8b11..d0d441c429ae3e4e6c438fad1c51c7079c6eda5b 100644 (file)
@@ -1,8 +1,10 @@
+ashldi3.S
 font.c
 lib1funcs.S
 piggy.gzip
 piggy.lzo
 piggy.lzma
+piggy.xzkern
 vmlinux
 vmlinux.lds
 
index cf0a64ce4b83ad73b21b5cd6d59ab4c96fc5f2f3..bb267562e7ed9a763218c83eaeb2c5c8645debb9 100644 (file)
@@ -92,6 +92,7 @@ SEDFLAGS      = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
 suffix_$(CONFIG_KERNEL_GZIP) = gzip
 suffix_$(CONFIG_KERNEL_LZO)  = lzo
 suffix_$(CONFIG_KERNEL_LZMA) = lzma
+suffix_$(CONFIG_KERNEL_XZ)   = xzkern
 
 # Borrowed libfdt files for the ATAG compatibility mode
 
@@ -112,10 +113,12 @@ endif
 
 targets       := vmlinux vmlinux.lds \
                 piggy.$(suffix_y) piggy.$(suffix_y).o \
-                lib1funcs.o lib1funcs.S font.o font.c head.o misc.o $(OBJS)
+                lib1funcs.o lib1funcs.S ashldi3.o ashldi3.S \
+                font.o font.c head.o misc.o $(OBJS)
 
 # Make sure files are removed during clean
-extra-y       += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S $(libfdt) $(libfdt_hdrs)
+extra-y       += piggy.gzip piggy.lzo piggy.lzma piggy.xzkern \
+                lib1funcs.S ashldi3.S $(libfdt) $(libfdt_hdrs)
 
 ifeq ($(CONFIG_FUNCTION_TRACER),y)
 ORIG_CFLAGS := $(KBUILD_CFLAGS)
@@ -151,6 +154,12 @@ lib1funcs = $(obj)/lib1funcs.o
 $(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S
        $(call cmd,shipped)
 
+# For __aeabi_llsl
+ashldi3 = $(obj)/ashldi3.o
+
+$(obj)/ashldi3.S: $(srctree)/arch/$(SRCARCH)/lib/ashldi3.S
+       $(call cmd,shipped)
+
 # We need to prevent any GOTOFF relocs being used with references
 # to symbols in the .bss section since we cannot relocate them
 # independently from the rest at run time.  This can be achieved by
@@ -172,7 +181,7 @@ if [ $(words $(ZRELADDR)) -gt 1 -a "$(CONFIG_AUTO_ZRELADDR)" = "" ]; then \
 fi
 
 $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
-               $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE
+               $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) FORCE
        @$(check_for_multiple_zreladdr)
        $(call if_changed,ld)
        @$(check_for_bad_syms)
index 07be5a2f830236736b15022da52fa0362ff5c16f..f41b38cafce80b046217364df5947926dfccf46b 100644 (file)
@@ -44,6 +44,12 @@ extern void error(char *);
 #include "../../../../lib/decompress_unlzma.c"
 #endif
 
+#ifdef CONFIG_KERNEL_XZ
+#define memmove memmove
+#define memcpy memcpy
+#include "../../../../lib/decompress_unxz.c"
+#endif
+
 int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x))
 {
        return decompress(input, len, NULL, NULL, output, NULL, error);
diff --git a/arch/arm/boot/compressed/piggy.xzkern.S b/arch/arm/boot/compressed/piggy.xzkern.S
new file mode 100644 (file)
index 0000000..5703f30
--- /dev/null
@@ -0,0 +1,6 @@
+       .section .piggydata,#alloc
+       .globl  input_data
+input_data:
+       .incbin "arch/arm/boot/compressed/piggy.xzkern"
+       .globl  input_data_end
+input_data_end:
index f0783be1735202cafb9dfe715da353f24c0076bb..aa52699841879a36347ec8feafc76b289232739f 100644 (file)
@@ -686,13 +686,12 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
         * For primary GICs, skip over SGIs.
         * For secondary GICs, skip over PPIs, too.
         */
-       hwirq_base = 32;
-       if (gic_nr == 0) {
-               if ((irq_start & 31) > 0) {
-                       hwirq_base = 16;
-                       if (irq_start != -1)
-                               irq_start = (irq_start & ~31) + 16;
-               }
+       if (gic_nr == 0 && (irq_start & 31) > 0) {
+               hwirq_base = 16;
+               if (irq_start != -1)
+                       irq_start = (irq_start & ~31) + 16;
+       } else {
+               hwirq_base = 32;
        }
 
        /*
index 1103f62a1964e86b799534af2ebd0c535bc64854..a8314c3ee84d554b3cbecb3fbb9b1cc4dd450c9a 100644 (file)
@@ -57,18 +57,24 @@ CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_NET_PCI=y
 CONFIG_E100=y
+CONFIG_SMC91X=y
 # CONFIG_KEYBOARD_ATKBD is not set
 # CONFIG_SERIO_SERPORT is not set
 CONFIG_SERIAL_AMBA_PL010=y
 CONFIG_SERIAL_AMBA_PL010_CONSOLE=y
 CONFIG_FB=y
 CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_ARMCLCD=y
 CONFIG_FB_MATROX=y
 CONFIG_FB_MATROX_MILLENIUM=y
 CONFIG_FB_MATROX_MYSTIQUE=y
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_MMC=y
+CONFIG_MMC_ARMMMCI=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_PL030=y
 CONFIG_EXT2_FS=y
+CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_CRAMFS=y
@@ -78,5 +84,7 @@ CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
 CONFIG_PARTITION_ADVANCED=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
index 0e9ce8d9686ee916af2263a42e0ddcd5926cbe53..38050b1c4800b90b190a415b7d173e9948e20b97 100644 (file)
@@ -130,8 +130,4 @@ struct mm_struct;
 extern unsigned long arch_randomize_brk(struct mm_struct *mm);
 #define arch_randomize_brk arch_randomize_brk
 
-extern int vectors_user_mapping(void);
-#define arch_setup_additional_pages(bprm, uses_interp) vectors_user_mapping()
-#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
-
 #endif
index 7df239bcdf2745b6a3d20e5a90ed3bac27d73ecc..c4c87bc1223195478a76547d0e756ddec961eb70 100644 (file)
 #define L2X0_ADDR_FILTER_EN            1
 
 #ifndef __ASSEMBLY__
-extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask);
+extern void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask);
 #if defined(CONFIG_CACHE_L2X0) && defined(CONFIG_OF)
-extern int l2x0_of_init(__u32 aux_val, __u32 aux_mask);
+extern int l2x0_of_init(u32 aux_val, u32 aux_mask);
 #else
-static inline int l2x0_of_init(__u32 aux_val, __u32 aux_mask)
+static inline int l2x0_of_init(u32 aux_val, u32 aux_mask)
 {
        return -ENODEV;
 }
index 43cab498bc279c1e6f6078c03717e1c497384680..73f84fa4f366d0b1c4978414a42209e86cc27ab0 100644 (file)
@@ -9,6 +9,9 @@
 
 #ifndef __ASM_HARDWARE_IT8152_H
 #define __ASM_HARDWARE_IT8152_H
+
+#include <mach/irqs.h>
+
 extern void __iomem *it8152_base_address;
 
 #define IT8152_IO_BASE                 (it8152_base_address + 0x03e00000)
index 5a526afb5f1858615ec02928f2e2010b3a25982d..35c21c375d81c19121495c66114ead04044f0fa3 100644 (file)
@@ -1,14 +1,18 @@
 #ifndef __ASM_ARM_IRQ_H
 #define __ASM_ARM_IRQ_H
 
+#define NR_IRQS_LEGACY 16
+
+#ifndef CONFIG_SPARSE_IRQ
 #include <mach/irqs.h>
+#else
+#define NR_IRQS NR_IRQS_LEGACY
+#endif
 
 #ifndef irq_canonicalize
 #define irq_canonicalize(i)    (i)
 #endif
 
-#define NR_IRQS_LEGACY 16
-
 /*
  * Use this value to indicate lack of interrupt
  * capability
diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h
new file mode 100644 (file)
index 0000000..5c5ca2e
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef _ASM_ARM_JUMP_LABEL_H
+#define _ASM_ARM_JUMP_LABEL_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <asm/system.h>
+
+#define JUMP_LABEL_NOP_SIZE 4
+
+#ifdef CONFIG_THUMB2_KERNEL
+#define JUMP_LABEL_NOP "nop.w"
+#else
+#define JUMP_LABEL_NOP "nop"
+#endif
+
+static __always_inline bool arch_static_branch(struct jump_label_key *key)
+{
+       asm goto("1:\n\t"
+                JUMP_LABEL_NOP "\n\t"
+                ".pushsection __jump_table,  \"aw\"\n\t"
+                ".word 1b, %l[l_yes], %c0\n\t"
+                ".popsection\n\t"
+                : :  "i" (key) :  : l_yes);
+
+       return false;
+l_yes:
+       return true;
+}
+
+#endif /* __KERNEL__ */
+
+typedef u32 jump_label_t;
+
+struct jump_entry {
+       jump_label_t code;
+       jump_label_t target;
+       jump_label_t key;
+};
+
+#endif
index 6b884d2b0b69eaf0395040d9d440b93cf0f274d1..e8567bb99dfc5531012c14976f3f93f57615cf58 100644 (file)
@@ -5,7 +5,9 @@
 #define _ASM_MC146818RTC_H
 
 #include <linux/io.h>
-#include <mach/irqs.h>
+#include <linux/kernel.h>
+
+#define RTC_IRQ BUILD_BUG_ON(1)
 
 #ifndef RTC_PORT
 #define RTC_PORT(x)    (0x70 + (x))
index a8997d71084e23b9343b27b650166ba715b96db1..fcb575747e5eb66082a9a7c96bbc6391a767faf5 100644 (file)
 #define MODULES_END            (END_MEM)
 #define MODULES_VADDR          (PHYS_OFFSET)
 
+#define XIP_VIRT_ADDR(physaddr)  (physaddr)
+
 #endif /* !CONFIG_MMU */
 
 /*
index 71605d9f8e421ad36a058992c032ad5459114929..a0b3cac0547c0a9949c30cc919adcf5e08fcf500 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/cacheflush.h>
 #include <asm/cachetype.h>
 #include <asm/proc-fns.h>
+#include <asm-generic/mm_hooks.h>
 
 void __check_kvm_seq(struct mm_struct *mm);
 
@@ -133,32 +134,4 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
 #define deactivate_mm(tsk,mm)  do { } while (0)
 #define activate_mm(prev,next) switch_mm(prev, next, NULL)
 
-/*
- * We are inserting a "fake" vma for the user-accessible vector page so
- * gdb and friends can get to it through ptrace and /proc/<pid>/mem.
- * But we also want to remove it before the generic code gets to see it
- * during process exit or the unmapping of it would  cause total havoc.
- * (the macro is used as remove_vma() is static to mm/mmap.c)
- */
-#define arch_exit_mmap(mm) \
-do { \
-       struct vm_area_struct *high_vma = find_vma(mm, 0xffff0000); \
-       if (high_vma) { \
-               BUG_ON(high_vma->vm_next);  /* it should be last */ \
-               if (high_vma->vm_prev) \
-                       high_vma->vm_prev->vm_next = NULL; \
-               else \
-                       mm->mmap = NULL; \
-               rb_erase(&high_vma->vm_rb, &mm->mm_rb); \
-               mm->mmap_cache = NULL; \
-               mm->map_count--; \
-               remove_vma(high_vma); \
-       } \
-} while (0)
-
-static inline void arch_dup_mmap(struct mm_struct *oldmm,
-                                struct mm_struct *mm)
-{
-}
-
 #endif
index c0efdd60966f11fc38d6d16ebf829ee2354ef279..19c48deda70f1b759b94b3a852dc0b4f207adfd8 100644 (file)
@@ -17,4 +17,63 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
 #define ARM_OPCODE_CONDTEST_PASS   1
 #define ARM_OPCODE_CONDTEST_UNCOND 2
 
+
+/*
+ * Opcode byteswap helpers
+ *
+ * These macros help with converting instructions between a canonical integer
+ * format and in-memory representation, in an endianness-agnostic manner.
+ *
+ * __mem_to_opcode_*() convert from in-memory representation to canonical form.
+ * __opcode_to_mem_*() convert from canonical form to in-memory representation.
+ *
+ *
+ * Canonical instruction representation:
+ *
+ *     ARM:            0xKKLLMMNN
+ *     Thumb 16-bit:   0x0000KKLL, where KK < 0xE8
+ *     Thumb 32-bit:   0xKKLLMMNN, where KK >= 0xE8
+ *
+ * There is no way to distinguish an ARM instruction in canonical representation
+ * from a Thumb instruction (just as these cannot be distinguished in memory).
+ * Where this distinction is important, it needs to be tracked separately.
+ *
+ * Note that values in the range 0x0000E800..0xE7FFFFFF intentionally do not
+ * represent any valid Thumb-2 instruction.  For this range,
+ * __opcode_is_thumb32() and __opcode_is_thumb16() will both be false.
+ */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+#include <linux/swab.h>
+
+#ifdef CONFIG_CPU_ENDIAN_BE8
+#define __opcode_to_mem_arm(x) swab32(x)
+#define __opcode_to_mem_thumb16(x) swab16(x)
+#define __opcode_to_mem_thumb32(x) swahb32(x)
+#else
+#define __opcode_to_mem_arm(x) ((u32)(x))
+#define __opcode_to_mem_thumb16(x) ((u16)(x))
+#define __opcode_to_mem_thumb32(x) swahw32(x)
+#endif
+
+#define __mem_to_opcode_arm(x) __opcode_to_mem_arm(x)
+#define __mem_to_opcode_thumb16(x) __opcode_to_mem_thumb16(x)
+#define __mem_to_opcode_thumb32(x) __opcode_to_mem_thumb32(x)
+
+/* Operations specific to Thumb opcodes */
+
+/* Instruction size checks: */
+#define __opcode_is_thumb32(x) ((u32)(x) >= 0xE8000000UL)
+#define __opcode_is_thumb16(x) ((u32)(x) < 0xE800UL)
+
+/* Operations to construct or split 32-bit Thumb instructions: */
+#define __opcode_thumb32_first(x) ((u16)((x) >> 16))
+#define __opcode_thumb32_second(x) ((u16)(x))
+#define __opcode_thumb32_compose(first, second) \
+       (((u32)(u16)(first) << 16) | (u32)(u16)(second))
+
+#endif /* __ASSEMBLY__ */
+
 #endif /* __ASM_ARM_OPCODES_H */
index 97b440c25c5855977481a40ba18977f1f988dd09..5838361c48b335040c892233da299605ce9e089f 100644 (file)
@@ -151,6 +151,8 @@ extern void __cpu_copy_user_highpage(struct page *to, struct page *from,
 #define clear_page(page)       memset((void *)(page), 0, PAGE_SIZE)
 extern void copy_page(void *to, const void *from);
 
+#define __HAVE_ARCH_GATE_AREA 1
+
 #ifdef CONFIG_ARM_LPAE
 #include <asm/pgtable-3level-types.h>
 #else
index 7523340afb8a13a15f389537d0f3d432e257cf7d..00cbe10a50e3693b32afe48d0d20e3787e9183d0 100644 (file)
@@ -22,6 +22,7 @@ enum arm_perf_pmu_ids {
        ARM_PERF_PMU_ID_CA9,
        ARM_PERF_PMU_ID_CA5,
        ARM_PERF_PMU_ID_CA15,
+       ARM_PERF_PMU_ID_CA7,
        ARM_NUM_PMU_IDS,
 };
 
index f4d7f56ee51f867539b1bcf618c923fd9f63fb0a..5ac8d3d3e0259cc8ceaa16b7ac7caa6facf177f7 100644 (file)
@@ -55,7 +55,6 @@ struct thread_struct {
 #define start_thread(regs,pc,sp)                                       \
 ({                                                                     \
        unsigned long *stack = (unsigned long *)sp;                     \
-       set_fs(USER_DS);                                                \
        memset(regs->uregs, 0, sizeof(regs->uregs));                    \
        if (current->personality & ADDR_LIMIT_32BIT)                    \
                regs->ARM_cpsr = USR_MODE;                              \
index ee0363307918b1d889897553f0283e0848307b15..aeae9c609df4885570646d076741cef0565328da 100644 (file)
@@ -13,8 +13,6 @@
 
 #ifdef CONFIG_OF
 
-#include <asm/irq.h>
-
 extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
 extern void arm_dt_memblock_reserve(void);
 
index 02b2f82039828bb0d4b016e41882c3071b686b93..85fe61e7320265e6932e8659d95c57c7712ad04d 100644 (file)
@@ -318,6 +318,21 @@ extern struct cpu_tlb_fns cpu_tlb;
 
 #define tlb_flag(f)    ((always_tlb_flags & (f)) || (__tlb_flag & possible_tlb_flags & (f)))
 
+#define __tlb_op(f, insnarg, arg)                                      \
+       do {                                                            \
+               if (always_tlb_flags & (f))                             \
+                       asm("mcr " insnarg                              \
+                           : : "r" (arg) : "cc");                      \
+               else if (possible_tlb_flags & (f))                      \
+                       asm("tst %1, %2\n\t"                            \
+                           "mcrne " insnarg                            \
+                           : : "r" (arg), "r" (__tlb_flag), "Ir" (f)   \
+                           : "cc");                                    \
+       } while (0)
+
+#define tlb_op(f, regs, arg)   __tlb_op(f, "p15, 0, %0, " regs, arg)
+#define tlb_l2_op(f, regs, arg)        __tlb_op(f, "p15, 1, %0, " regs, arg)
+
 static inline void local_flush_tlb_all(void)
 {
        const int zero = 0;
@@ -326,16 +341,11 @@ static inline void local_flush_tlb_all(void)
        if (tlb_flag(TLB_WB))
                dsb();
 
-       if (tlb_flag(TLB_V3_FULL))
-               asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (zero) : "cc");
-       if (tlb_flag(TLB_V4_U_FULL | TLB_V6_U_FULL))
-               asm("mcr p15, 0, %0, c8, c7, 0" : : "r" (zero) : "cc");
-       if (tlb_flag(TLB_V4_D_FULL | TLB_V6_D_FULL))
-               asm("mcr p15, 0, %0, c8, c6, 0" : : "r" (zero) : "cc");
-       if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL))
-               asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
-       if (tlb_flag(TLB_V7_UIS_FULL))
-               asm("mcr p15, 0, %0, c8, c3, 0" : : "r" (zero) : "cc");
+       tlb_op(TLB_V3_FULL, "c6, c0, 0", zero);
+       tlb_op(TLB_V4_U_FULL | TLB_V6_U_FULL, "c8, c7, 0", zero);
+       tlb_op(TLB_V4_D_FULL | TLB_V6_D_FULL, "c8, c6, 0", zero);
+       tlb_op(TLB_V4_I_FULL | TLB_V6_I_FULL, "c8, c5, 0", zero);
+       tlb_op(TLB_V7_UIS_FULL, "c8, c3, 0", zero);
 
        if (tlb_flag(TLB_BARRIER)) {
                dsb();
@@ -352,29 +362,23 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm)
        if (tlb_flag(TLB_WB))
                dsb();
 
-       if (cpumask_test_cpu(get_cpu(), mm_cpumask(mm))) {
-               if (tlb_flag(TLB_V3_FULL))
-                       asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (zero) : "cc");
-               if (tlb_flag(TLB_V4_U_FULL))
-                       asm("mcr p15, 0, %0, c8, c7, 0" : : "r" (zero) : "cc");
-               if (tlb_flag(TLB_V4_D_FULL))
-                       asm("mcr p15, 0, %0, c8, c6, 0" : : "r" (zero) : "cc");
-               if (tlb_flag(TLB_V4_I_FULL))
-                       asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
+       if (possible_tlb_flags & (TLB_V3_FULL|TLB_V4_U_FULL|TLB_V4_D_FULL|TLB_V4_I_FULL)) {
+               if (cpumask_test_cpu(get_cpu(), mm_cpumask(mm))) {
+                       tlb_op(TLB_V3_FULL, "c6, c0, 0", zero);
+                       tlb_op(TLB_V4_U_FULL, "c8, c7, 0", zero);
+                       tlb_op(TLB_V4_D_FULL, "c8, c6, 0", zero);
+                       tlb_op(TLB_V4_I_FULL, "c8, c5, 0", zero);
+               }
+               put_cpu();
        }
-       put_cpu();
-
-       if (tlb_flag(TLB_V6_U_ASID))
-               asm("mcr p15, 0, %0, c8, c7, 2" : : "r" (asid) : "cc");
-       if (tlb_flag(TLB_V6_D_ASID))
-               asm("mcr p15, 0, %0, c8, c6, 2" : : "r" (asid) : "cc");
-       if (tlb_flag(TLB_V6_I_ASID))
-               asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc");
-       if (tlb_flag(TLB_V7_UIS_ASID))
+
+       tlb_op(TLB_V6_U_ASID, "c8, c7, 2", asid);
+       tlb_op(TLB_V6_D_ASID, "c8, c6, 2", asid);
+       tlb_op(TLB_V6_I_ASID, "c8, c5, 2", asid);
 #ifdef CONFIG_ARM_ERRATA_720789
-               asm("mcr p15, 0, %0, c8, c3, 0" : : "r" (zero) : "cc");
+       tlb_op(TLB_V7_UIS_ASID, "c8, c3, 0", zero);
 #else
-               asm("mcr p15, 0, %0, c8, c3, 2" : : "r" (asid) : "cc");
+       tlb_op(TLB_V7_UIS_ASID, "c8, c3, 2", asid);
 #endif
 
        if (tlb_flag(TLB_BARRIER))
@@ -392,30 +396,23 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
        if (tlb_flag(TLB_WB))
                dsb();
 
-       if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) {
-               if (tlb_flag(TLB_V3_PAGE))
-                       asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (uaddr) : "cc");
-               if (tlb_flag(TLB_V4_U_PAGE))
-                       asm("mcr p15, 0, %0, c8, c7, 1" : : "r" (uaddr) : "cc");
-               if (tlb_flag(TLB_V4_D_PAGE))
-                       asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (uaddr) : "cc");
-               if (tlb_flag(TLB_V4_I_PAGE))
-                       asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
+       if (possible_tlb_flags & (TLB_V3_PAGE|TLB_V4_U_PAGE|TLB_V4_D_PAGE|TLB_V4_I_PAGE|TLB_V4_I_FULL) &&
+           cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) {
+               tlb_op(TLB_V3_PAGE, "c6, c0, 0", uaddr);
+               tlb_op(TLB_V4_U_PAGE, "c8, c7, 1", uaddr);
+               tlb_op(TLB_V4_D_PAGE, "c8, c6, 1", uaddr);
+               tlb_op(TLB_V4_I_PAGE, "c8, c5, 1", uaddr);
                if (!tlb_flag(TLB_V4_I_PAGE) && tlb_flag(TLB_V4_I_FULL))
                        asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
        }
 
-       if (tlb_flag(TLB_V6_U_PAGE))
-               asm("mcr p15, 0, %0, c8, c7, 1" : : "r" (uaddr) : "cc");
-       if (tlb_flag(TLB_V6_D_PAGE))
-               asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (uaddr) : "cc");
-       if (tlb_flag(TLB_V6_I_PAGE))
-               asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
-       if (tlb_flag(TLB_V7_UIS_PAGE))
+       tlb_op(TLB_V6_U_PAGE, "c8, c7, 1", uaddr);
+       tlb_op(TLB_V6_D_PAGE, "c8, c6, 1", uaddr);
+       tlb_op(TLB_V6_I_PAGE, "c8, c5, 1", uaddr);
 #ifdef CONFIG_ARM_ERRATA_720789
-               asm("mcr p15, 0, %0, c8, c3, 3" : : "r" (uaddr & PAGE_MASK) : "cc");
+       tlb_op(TLB_V7_UIS_PAGE, "c8, c3, 3", uaddr & PAGE_MASK);
 #else
-               asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (uaddr) : "cc");
+       tlb_op(TLB_V7_UIS_PAGE, "c8, c3, 1", uaddr);
 #endif
 
        if (tlb_flag(TLB_BARRIER))
@@ -432,25 +429,17 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
        if (tlb_flag(TLB_WB))
                dsb();
 
-       if (tlb_flag(TLB_V3_PAGE))
-               asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (kaddr) : "cc");
-       if (tlb_flag(TLB_V4_U_PAGE))
-               asm("mcr p15, 0, %0, c8, c7, 1" : : "r" (kaddr) : "cc");
-       if (tlb_flag(TLB_V4_D_PAGE))
-               asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (kaddr) : "cc");
-       if (tlb_flag(TLB_V4_I_PAGE))
-               asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
+       tlb_op(TLB_V3_PAGE, "c6, c0, 0", kaddr);
+       tlb_op(TLB_V4_U_PAGE, "c8, c7, 1", kaddr);
+       tlb_op(TLB_V4_D_PAGE, "c8, c6, 1", kaddr);
+       tlb_op(TLB_V4_I_PAGE, "c8, c5, 1", kaddr);
        if (!tlb_flag(TLB_V4_I_PAGE) && tlb_flag(TLB_V4_I_FULL))
                asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
 
-       if (tlb_flag(TLB_V6_U_PAGE))
-               asm("mcr p15, 0, %0, c8, c7, 1" : : "r" (kaddr) : "cc");
-       if (tlb_flag(TLB_V6_D_PAGE))
-               asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (kaddr) : "cc");
-       if (tlb_flag(TLB_V6_I_PAGE))
-               asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
-       if (tlb_flag(TLB_V7_UIS_PAGE))
-               asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (kaddr) : "cc");
+       tlb_op(TLB_V6_U_PAGE, "c8, c7, 1", kaddr);
+       tlb_op(TLB_V6_D_PAGE, "c8, c6, 1", kaddr);
+       tlb_op(TLB_V6_I_PAGE, "c8, c5, 1", kaddr);
+       tlb_op(TLB_V7_UIS_PAGE, "c8, c3, 1", kaddr);
 
        if (tlb_flag(TLB_BARRIER)) {
                dsb();
@@ -475,13 +464,8 @@ static inline void flush_pmd_entry(void *pmd)
 {
        const unsigned int __tlb_flag = __cpu_tlb_flags;
 
-       if (tlb_flag(TLB_DCLEAN))
-               asm("mcr        p15, 0, %0, c7, c10, 1  @ flush_pmd"
-                       : : "r" (pmd) : "cc");
-
-       if (tlb_flag(TLB_L2CLEAN_FR))
-               asm("mcr        p15, 1, %0, c15, c9, 1  @ L2 flush_pmd"
-                       : : "r" (pmd) : "cc");
+       tlb_op(TLB_DCLEAN, "c7, c10, 1  @ flush_pmd", pmd);
+       tlb_l2_op(TLB_L2CLEAN_FR, "c15, c9, 1  @ L2 flush_pmd", pmd);
 
        if (tlb_flag(TLB_WB))
                dsb();
@@ -491,15 +475,11 @@ static inline void clean_pmd_entry(void *pmd)
 {
        const unsigned int __tlb_flag = __cpu_tlb_flags;
 
-       if (tlb_flag(TLB_DCLEAN))
-               asm("mcr        p15, 0, %0, c7, c10, 1  @ flush_pmd"
-                       : : "r" (pmd) : "cc");
-
-       if (tlb_flag(TLB_L2CLEAN_FR))
-               asm("mcr        p15, 1, %0, c15, c9, 1  @ L2 flush_pmd"
-                       : : "r" (pmd) : "cc");
+       tlb_op(TLB_DCLEAN, "c7, c10, 1  @ flush_pmd", pmd);
+       tlb_l2_op(TLB_L2CLEAN_FR, "c15, c9, 1  @ L2 flush_pmd", pmd);
 }
 
+#undef tlb_op
 #undef tlb_flag
 #undef always_tlb_flags
 #undef possible_tlb_flags
index 5b29a66736250e71d9a4ee24cfb9e0cd341ea14f..f555bb3664dcaa2dbee6ab4e1f486d24e360ba8f 100644 (file)
@@ -46,7 +46,7 @@ static inline int in_exception_text(unsigned long ptr)
        return in ? : __in_irqentry_text(ptr);
 }
 
-extern void __init early_trap_init(void);
+extern void __init early_trap_init(void *);
 extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame);
 extern void ptrace_break(struct task_struct *tsk, struct pt_regs *regs);
 
index 3a274878412ec7b1728de840469cd1ffc68e3a38..8269d892874232f59f6e49537dc6df49e8c0927b 100644 (file)
@@ -7,6 +7,8 @@ AFLAGS_head.o        := -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 ifdef CONFIG_FUNCTION_TRACER
 CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_insn.o = -pg
+CFLAGS_REMOVE_patch.o = -pg
 endif
 
 CFLAGS_REMOVE_return_address.o = -pg
@@ -14,8 +16,8 @@ CFLAGS_REMOVE_return_address.o = -pg
 # Object file lists.
 
 obj-y          := elf.o entry-armv.o entry-common.o irq.o opcodes.o \
-                  process.o ptrace.o return_address.o setup.o signal.o \
-                  sys_arm.o stacktrace.o time.o traps.o
+                  process.o ptrace.o return_address.o sched_clock.o \
+                  setup.o signal.o stacktrace.o sys_arm.o time.o traps.o
 
 obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += compat.o
 
@@ -29,14 +31,14 @@ obj-$(CONFIG_ARTHUR)                += arthur.o
 obj-$(CONFIG_ISA_DMA)          += dma-isa.o
 obj-$(CONFIG_PCI)              += bios32.o isa.o
 obj-$(CONFIG_ARM_CPU_SUSPEND)  += sleep.o suspend.o
-obj-$(CONFIG_HAVE_SCHED_CLOCK) += sched_clock.o
 obj-$(CONFIG_SMP)              += smp.o smp_tlb.o
 obj-$(CONFIG_HAVE_ARM_SCU)     += smp_scu.o
 obj-$(CONFIG_HAVE_ARM_TWD)     += smp_twd.o
-obj-$(CONFIG_DYNAMIC_FTRACE)   += ftrace.o
-obj-$(CONFIG_FUNCTION_GRAPH_TRACER)    += ftrace.o
+obj-$(CONFIG_DYNAMIC_FTRACE)   += ftrace.o insn.o
+obj-$(CONFIG_FUNCTION_GRAPH_TRACER)    += ftrace.o insn.o
+obj-$(CONFIG_JUMP_LABEL)       += jump_label.o insn.o patch.o
 obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o
-obj-$(CONFIG_KPROBES)          += kprobes.o kprobes-common.o
+obj-$(CONFIG_KPROBES)          += kprobes.o kprobes-common.o patch.o
 ifdef CONFIG_THUMB2_KERNEL
 obj-$(CONFIG_KPROBES)          += kprobes-thumb.o
 else
index 204e2160cfccbdd5fa88a00285086d73a522ebcb..e5a765c5f06ae5ff5f0d0b1871340e68faf72000 100644 (file)
 
 #endif /* CONFIG_CPU_V6 */
 
-#else
+#elif !defined(CONFIG_DEBUG_SEMIHOSTING)
 #include <mach/debug-macro.S>
 #endif /* CONFIG_DEBUG_ICEDCC */
 
@@ -155,6 +155,8 @@ hexbuf:             .space 16
 
                .ltorg
 
+#ifndef CONFIG_DEBUG_SEMIHOSTING
+
 ENTRY(printascii)
                addruart_current r3, r1, r2
                b       2f
@@ -177,3 +179,24 @@ ENTRY(printch)
                mov     r0, #0
                b       1b
 ENDPROC(printch)
+
+#else
+
+ENTRY(printascii)
+               mov     r1, r0
+               mov     r0, #0x04               @ SYS_WRITE0
+       ARM(    svc     #0x123456       )
+       THUMB(  svc     #0xab           )
+               mov     pc, lr
+ENDPROC(printascii)
+
+ENTRY(printch)
+               adr     r1, hexbuf
+               strb    r0, [r1]
+               mov     r0, #0x03               @ SYS_WRITEC
+       ARM(    svc     #0x123456       )
+       THUMB(  svc     #0xab           )
+               mov     pc, lr
+ENDPROC(printch)
+
+#endif
index c0062ad1e847b5a1ab68a21a8ed3f4d37eb9ce2a..df0bf0c8cb790a5ee501c55a204a45ddbcb48aab 100644 (file)
 #include <linux/uaccess.h>
 
 #include <asm/cacheflush.h>
+#include <asm/opcodes.h>
 #include <asm/ftrace.h>
 
+#include "insn.h"
+
 #ifdef CONFIG_THUMB2_KERNEL
-#define        NOP             0xeb04f85d      /* pop.w {lr} */
+#define        NOP             0xf85deb04      /* pop.w {lr} */
 #else
 #define        NOP             0xe8bd4000      /* pop {lr} */
 #endif
@@ -60,76 +63,31 @@ static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr)
 }
 #endif
 
-#ifdef CONFIG_THUMB2_KERNEL
-static unsigned long ftrace_gen_branch(unsigned long pc, unsigned long addr,
-                                      bool link)
-{
-       unsigned long s, j1, j2, i1, i2, imm10, imm11;
-       unsigned long first, second;
-       long offset;
-
-       offset = (long)addr - (long)(pc + 4);
-       if (offset < -16777216 || offset > 16777214) {
-               WARN_ON_ONCE(1);
-               return 0;
-       }
-
-       s       = (offset >> 24) & 0x1;
-       i1      = (offset >> 23) & 0x1;
-       i2      = (offset >> 22) & 0x1;
-       imm10   = (offset >> 12) & 0x3ff;
-       imm11   = (offset >>  1) & 0x7ff;
-
-       j1 = (!i1) ^ s;
-       j2 = (!i2) ^ s;
-
-       first = 0xf000 | (s << 10) | imm10;
-       second = 0x9000 | (j1 << 13) | (j2 << 11) | imm11;
-       if (link)
-               second |= 1 << 14;
-
-       return (second << 16) | first;
-}
-#else
-static unsigned long ftrace_gen_branch(unsigned long pc, unsigned long addr,
-                                      bool link)
-{
-       unsigned long opcode = 0xea000000;
-       long offset;
-
-       if (link)
-               opcode |= 1 << 24;
-
-       offset = (long)addr - (long)(pc + 8);
-       if (unlikely(offset < -33554432 || offset > 33554428)) {
-               /* Can't generate branches that far (from ARM ARM). Ftrace
-                * doesn't generate branches outside of kernel text.
-                */
-               WARN_ON_ONCE(1);
-               return 0;
-       }
-
-       offset = (offset >> 2) & 0x00ffffff;
-
-       return opcode | offset;
-}
-#endif
-
 static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
 {
-       return ftrace_gen_branch(pc, addr, true);
+       return arm_gen_branch_link(pc, addr);
 }
 
 static int ftrace_modify_code(unsigned long pc, unsigned long old,
-                             unsigned long new)
+                             unsigned long new, bool validate)
 {
        unsigned long replaced;
 
-       if (probe_kernel_read(&replaced, (void *)pc, MCOUNT_INSN_SIZE))
-               return -EFAULT;
+       if (IS_ENABLED(CONFIG_THUMB2_KERNEL)) {
+               old = __opcode_to_mem_thumb32(old);
+               new = __opcode_to_mem_thumb32(new);
+       } else {
+               old = __opcode_to_mem_arm(old);
+               new = __opcode_to_mem_arm(new);
+       }
 
-       if (replaced != old)
-               return -EINVAL;
+       if (validate) {
+               if (probe_kernel_read(&replaced, (void *)pc, MCOUNT_INSN_SIZE))
+                       return -EFAULT;
+
+               if (replaced != old)
+                       return -EINVAL;
+       }
 
        if (probe_kernel_write((void *)pc, &new, MCOUNT_INSN_SIZE))
                return -EPERM;
@@ -141,23 +99,21 @@ static int ftrace_modify_code(unsigned long pc, unsigned long old,
 
 int ftrace_update_ftrace_func(ftrace_func_t func)
 {
-       unsigned long pc, old;
+       unsigned long pc;
        unsigned long new;
        int ret;
 
        pc = (unsigned long)&ftrace_call;
-       memcpy(&old, &ftrace_call, MCOUNT_INSN_SIZE);
        new = ftrace_call_replace(pc, (unsigned long)func);
 
-       ret = ftrace_modify_code(pc, old, new);
+       ret = ftrace_modify_code(pc, 0, new, false);
 
 #ifdef CONFIG_OLD_MCOUNT
        if (!ret) {
                pc = (unsigned long)&ftrace_call_old;
-               memcpy(&old, &ftrace_call_old, MCOUNT_INSN_SIZE);
                new = ftrace_call_replace(pc, (unsigned long)func);
 
-               ret = ftrace_modify_code(pc, old, new);
+               ret = ftrace_modify_code(pc, 0, new, false);
        }
 #endif
 
@@ -172,7 +128,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
        old = ftrace_nop_replace(rec);
        new = ftrace_call_replace(ip, adjust_address(rec, addr));
 
-       return ftrace_modify_code(rec->ip, old, new);
+       return ftrace_modify_code(rec->ip, old, new, true);
 }
 
 int ftrace_make_nop(struct module *mod,
@@ -185,7 +141,7 @@ int ftrace_make_nop(struct module *mod,
 
        old = ftrace_call_replace(ip, adjust_address(rec, addr));
        new = ftrace_nop_replace(rec);
-       ret = ftrace_modify_code(ip, old, new);
+       ret = ftrace_modify_code(ip, old, new, true);
 
 #ifdef CONFIG_OLD_MCOUNT
        if (ret == -EINVAL && addr == MCOUNT_ADDR) {
@@ -193,7 +149,7 @@ int ftrace_make_nop(struct module *mod,
 
                old = ftrace_call_replace(ip, adjust_address(rec, addr));
                new = ftrace_nop_replace(rec);
-               ret = ftrace_modify_code(ip, old, new);
+               ret = ftrace_modify_code(ip, old, new, true);
        }
 #endif
 
@@ -249,12 +205,12 @@ static int __ftrace_modify_caller(unsigned long *callsite,
 {
        unsigned long caller_fn = (unsigned long) func;
        unsigned long pc = (unsigned long) callsite;
-       unsigned long branch = ftrace_gen_branch(pc, caller_fn, false);
+       unsigned long branch = arm_gen_branch(pc, caller_fn);
        unsigned long nop = 0xe1a00000; /* mov r0, r0 */
        unsigned long old = enable ? nop : branch;
        unsigned long new = enable ? branch : nop;
 
-       return ftrace_modify_code(pc, old, new);
+       return ftrace_modify_code(pc, old, new, true);
 }
 
 static int ftrace_modify_graph_caller(bool enable)
index a2e9694a68eec8693ac1597da2827ad4edfec9b6..3bf0c7f8b043c52b4e616397cc768541a6009a89 100644 (file)
@@ -265,7 +265,7 @@ __create_page_tables:
        str     r6, [r3]
 
 #ifdef CONFIG_DEBUG_LL
-#ifndef CONFIG_DEBUG_ICEDCC
+#if !defined(CONFIG_DEBUG_ICEDCC) && !defined(CONFIG_DEBUG_SEMIHOSTING)
        /*
         * Map in IO space for serial debugging.
         * This allows debug messages to be output
@@ -297,10 +297,10 @@ __create_page_tables:
        cmp     r0, r6
        blo     1b
 
-#else /* CONFIG_DEBUG_ICEDCC */
-       /* we don't need any serial debugging mappings for ICEDCC */
+#else /* CONFIG_DEBUG_ICEDCC || CONFIG_DEBUG_SEMIHOSTING */
+       /* we don't need any serial debugging mappings */
        ldr     r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
-#endif /* !CONFIG_DEBUG_ICEDCC */
+#endif
 
 #if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS)
        /*
diff --git a/arch/arm/kernel/insn.c b/arch/arm/kernel/insn.c
new file mode 100644 (file)
index 0000000..ab312e5
--- /dev/null
@@ -0,0 +1,61 @@
+#include <linux/kernel.h>
+#include <asm/opcodes.h>
+
+static unsigned long
+__arm_gen_branch_thumb2(unsigned long pc, unsigned long addr, bool link)
+{
+       unsigned long s, j1, j2, i1, i2, imm10, imm11;
+       unsigned long first, second;
+       long offset;
+
+       offset = (long)addr - (long)(pc + 4);
+       if (offset < -16777216 || offset > 16777214) {
+               WARN_ON_ONCE(1);
+               return 0;
+       }
+
+       s       = (offset >> 24) & 0x1;
+       i1      = (offset >> 23) & 0x1;
+       i2      = (offset >> 22) & 0x1;
+       imm10   = (offset >> 12) & 0x3ff;
+       imm11   = (offset >>  1) & 0x7ff;
+
+       j1 = (!i1) ^ s;
+       j2 = (!i2) ^ s;
+
+       first = 0xf000 | (s << 10) | imm10;
+       second = 0x9000 | (j1 << 13) | (j2 << 11) | imm11;
+       if (link)
+               second |= 1 << 14;
+
+       return __opcode_thumb32_compose(first, second);
+}
+
+static unsigned long
+__arm_gen_branch_arm(unsigned long pc, unsigned long addr, bool link)
+{
+       unsigned long opcode = 0xea000000;
+       long offset;
+
+       if (link)
+               opcode |= 1 << 24;
+
+       offset = (long)addr - (long)(pc + 8);
+       if (unlikely(offset < -33554432 || offset > 33554428)) {
+               WARN_ON_ONCE(1);
+               return 0;
+       }
+
+       offset = (offset >> 2) & 0x00ffffff;
+
+       return opcode | offset;
+}
+
+unsigned long
+__arm_gen_branch(unsigned long pc, unsigned long addr, bool link)
+{
+       if (IS_ENABLED(CONFIG_THUMB2_KERNEL))
+               return __arm_gen_branch_thumb2(pc, addr, link);
+       else
+               return __arm_gen_branch_arm(pc, addr, link);
+}
diff --git a/arch/arm/kernel/insn.h b/arch/arm/kernel/insn.h
new file mode 100644 (file)
index 0000000..e96065d
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __ASM_ARM_INSN_H
+#define __ASM_ARM_INSN_H
+
+static inline unsigned long
+arm_gen_nop(void)
+{
+#ifdef CONFIG_THUMB2_KERNEL
+       return 0xf3af8000; /* nop.w */
+#else
+       return 0xe1a00000; /* mov r0, r0 */
+#endif
+}
+
+unsigned long
+__arm_gen_branch(unsigned long pc, unsigned long addr, bool link);
+
+static inline unsigned long
+arm_gen_branch(unsigned long pc, unsigned long addr)
+{
+       return __arm_gen_branch(pc, addr, false);
+}
+
+static inline unsigned long
+arm_gen_branch_link(unsigned long pc, unsigned long addr)
+{
+       return __arm_gen_branch(pc, addr, true);
+}
+
+#endif
index 6a6a097edd614d82bfe1855d31e03dca344c3d79..71ccdbfed66276f2c76db1b683da17cab392f0ad 100644 (file)
@@ -180,10 +180,7 @@ void migrate_irqs(void)
        local_irq_save(flags);
 
        for_each_irq_desc(i, desc) {
-               bool affinity_broken = false;
-
-               if (!desc)
-                       continue;
+               bool affinity_broken;
 
                raw_spin_lock(&desc->lock);
                affinity_broken = migrate_one_irq(desc);
diff --git a/arch/arm/kernel/jump_label.c b/arch/arm/kernel/jump_label.c
new file mode 100644 (file)
index 0000000..4ce4f78
--- /dev/null
@@ -0,0 +1,39 @@
+#include <linux/kernel.h>
+#include <linux/jump_label.h>
+
+#include "insn.h"
+#include "patch.h"
+
+#ifdef HAVE_JUMP_LABEL
+
+static void __arch_jump_label_transform(struct jump_entry *entry,
+                                       enum jump_label_type type,
+                                       bool is_static)
+{
+       void *addr = (void *)entry->code;
+       unsigned int insn;
+
+       if (type == JUMP_LABEL_ENABLE)
+               insn = arm_gen_branch(entry->code, entry->target);
+       else
+               insn = arm_gen_nop();
+
+       if (is_static)
+               __patch_text(addr, insn);
+       else
+               patch_text(addr, insn);
+}
+
+void arch_jump_label_transform(struct jump_entry *entry,
+                              enum jump_label_type type)
+{
+       __arch_jump_label_transform(entry, type, false);
+}
+
+void arch_jump_label_transform_static(struct jump_entry *entry,
+                                     enum jump_label_type type)
+{
+       __arch_jump_label_transform(entry, type, true);
+}
+
+#endif
index 129c1163248bf2acf11133713ec755d7075abea6..ab1869dac97a96a6399964e088f1dc58ff6191e2 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/cacheflush.h>
 
 #include "kprobes.h"
+#include "patch.h"
 
 #define MIN_STACK_SIZE(addr)                           \
        min((unsigned long)MAX_STACK_SIZE,              \
@@ -103,57 +104,33 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
        return 0;
 }
 
-#ifdef CONFIG_THUMB2_KERNEL
-
-/*
- * For a 32-bit Thumb breakpoint spanning two memory words we need to take
- * special precautions to insert the breakpoint atomically, especially on SMP
- * systems. This is achieved by calling this arming function using stop_machine.
- */
-static int __kprobes set_t32_breakpoint(void *addr)
-{
-       ((u16 *)addr)[0] = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION >> 16;
-       ((u16 *)addr)[1] = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION & 0xffff;
-       flush_insns(addr, 2*sizeof(u16));
-       return 0;
-}
-
 void __kprobes arch_arm_kprobe(struct kprobe *p)
 {
-       uintptr_t addr = (uintptr_t)p->addr & ~1; /* Remove any Thumb flag */
-
-       if (!is_wide_instruction(p->opcode)) {
-               *(u16 *)addr = KPROBE_THUMB16_BREAKPOINT_INSTRUCTION;
-               flush_insns(addr, sizeof(u16));
-       } else if (addr & 2) {
-               /* A 32-bit instruction spanning two words needs special care */
-               stop_machine(set_t32_breakpoint, (void *)addr, &cpu_online_map);
+       unsigned int brkp;
+       void *addr;
+
+       if (IS_ENABLED(CONFIG_THUMB2_KERNEL)) {
+               /* Remove any Thumb flag */
+               addr = (void *)((uintptr_t)p->addr & ~1);
+
+               if (is_wide_instruction(p->opcode))
+                       brkp = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION;
+               else
+                       brkp = KPROBE_THUMB16_BREAKPOINT_INSTRUCTION;
        } else {
-               /* Word aligned 32-bit instruction can be written atomically */
-               u32 bkp = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION;
-#ifndef __ARMEB__ /* Swap halfwords for little-endian */
-               bkp = (bkp >> 16) | (bkp << 16);
-#endif
-               *(u32 *)addr = bkp;
-               flush_insns(addr, sizeof(u32));
-       }
-}
+               kprobe_opcode_t insn = p->opcode;
 
-#else /* !CONFIG_THUMB2_KERNEL */
+               addr = p->addr;
+               brkp = KPROBE_ARM_BREAKPOINT_INSTRUCTION;
 
-void __kprobes arch_arm_kprobe(struct kprobe *p)
-{
-       kprobe_opcode_t insn = p->opcode;
-       kprobe_opcode_t brkp = KPROBE_ARM_BREAKPOINT_INSTRUCTION;
-       if (insn >= 0xe0000000)
-               brkp |= 0xe0000000;  /* Unconditional instruction */
-       else
-               brkp |= insn & 0xf0000000;  /* Copy condition from insn */
-       *p->addr = brkp;
-       flush_insns(p->addr, sizeof(p->addr[0]));
-}
+               if (insn >= 0xe0000000)
+                       brkp |= 0xe0000000;  /* Unconditional instruction */
+               else
+                       brkp |= insn & 0xf0000000;  /* Copy condition from insn */
+       }
 
-#endif /* !CONFIG_THUMB2_KERNEL */
+       patch_text(addr, brkp);
+}
 
 /*
  * The actual disarming is done here on each CPU and synchronized using
@@ -166,25 +143,10 @@ void __kprobes arch_arm_kprobe(struct kprobe *p)
 int __kprobes __arch_disarm_kprobe(void *p)
 {
        struct kprobe *kp = p;
-#ifdef CONFIG_THUMB2_KERNEL
-       u16 *addr = (u16 *)((uintptr_t)kp->addr & ~1);
-       kprobe_opcode_t insn = kp->opcode;
-       unsigned int len;
+       void *addr = (void *)((uintptr_t)kp->addr & ~1);
 
-       if (is_wide_instruction(insn)) {
-               ((u16 *)addr)[0] = insn>>16;
-               ((u16 *)addr)[1] = insn;
-               len = 2*sizeof(u16);
-       } else {
-               ((u16 *)addr)[0] = insn;
-               len = sizeof(u16);
-       }
-       flush_insns(addr, len);
+       __patch_text(addr, kp->opcode);
 
-#else /* !CONFIG_THUMB2_KERNEL */
-       *kp->addr = kp->opcode;
-       flush_insns(kp->addr, sizeof(kp->addr[0]));
-#endif
        return 0;
 }
 
index 56995983eed8baf3e4c04e0c67874572b8fa2585..dfcdb9f7c1261143f93c31846ed372269a4b4783 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/delay.h>
 #include <linux/reboot.h>
 #include <linux/io.h>
+#include <linux/irq.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
@@ -53,6 +54,29 @@ void machine_crash_nonpanic_core(void *unused)
                cpu_relax();
 }
 
+static void machine_kexec_mask_interrupts(void)
+{
+       unsigned int i;
+       struct irq_desc *desc;
+
+       for_each_irq_desc(i, desc) {
+               struct irq_chip *chip;
+
+               chip = irq_desc_get_chip(desc);
+               if (!chip)
+                       continue;
+
+               if (chip->irq_eoi && irqd_irq_inprogress(&desc->irq_data))
+                       chip->irq_eoi(&desc->irq_data);
+
+               if (chip->irq_mask)
+                       chip->irq_mask(&desc->irq_data);
+
+               if (chip->irq_disable && !irqd_irq_disabled(&desc->irq_data))
+                       chip->irq_disable(&desc->irq_data);
+       }
+}
+
 void machine_crash_shutdown(struct pt_regs *regs)
 {
        unsigned long msecs;
@@ -70,6 +94,7 @@ void machine_crash_shutdown(struct pt_regs *regs)
                printk(KERN_WARNING "Non-crashing CPUs did not react to IPI\n");
 
        crash_save_cpu(regs, smp_processor_id());
+       machine_kexec_mask_interrupts();
 
        printk(KERN_INFO "Loading crashdump kernel...\n");
 }
diff --git a/arch/arm/kernel/patch.c b/arch/arm/kernel/patch.c
new file mode 100644 (file)
index 0000000..07314af
--- /dev/null
@@ -0,0 +1,75 @@
+#include <linux/kernel.h>
+#include <linux/kprobes.h>
+#include <linux/stop_machine.h>
+
+#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
+#include <asm/opcodes.h>
+
+#include "patch.h"
+
+struct patch {
+       void *addr;
+       unsigned int insn;
+};
+
+void __kprobes __patch_text(void *addr, unsigned int insn)
+{
+       bool thumb2 = IS_ENABLED(CONFIG_THUMB2_KERNEL);
+       int size;
+
+       if (thumb2 && __opcode_is_thumb16(insn)) {
+               *(u16 *)addr = __opcode_to_mem_thumb16(insn);
+               size = sizeof(u16);
+       } else if (thumb2 && ((uintptr_t)addr & 2)) {
+               u16 first = __opcode_thumb32_first(insn);
+               u16 second = __opcode_thumb32_second(insn);
+               u16 *addrh = addr;
+
+               addrh[0] = __opcode_to_mem_thumb16(first);
+               addrh[1] = __opcode_to_mem_thumb16(second);
+
+               size = sizeof(u32);
+       } else {
+               if (thumb2)
+                       insn = __opcode_to_mem_thumb32(insn);
+               else
+                       insn = __opcode_to_mem_arm(insn);
+
+               *(u32 *)addr = insn;
+               size = sizeof(u32);
+       }
+
+       flush_icache_range((uintptr_t)(addr),
+                          (uintptr_t)(addr) + size);
+}
+
+static int __kprobes patch_text_stop_machine(void *data)
+{
+       struct patch *patch = data;
+
+       __patch_text(patch->addr, patch->insn);
+
+       return 0;
+}
+
+void __kprobes patch_text(void *addr, unsigned int insn)
+{
+       struct patch patch = {
+               .addr = addr,
+               .insn = insn,
+       };
+
+       if (cache_ops_need_broadcast()) {
+               stop_machine(patch_text_stop_machine, &patch, cpu_online_mask);
+       } else {
+               bool straddles_word = IS_ENABLED(CONFIG_THUMB2_KERNEL)
+                                     && __opcode_is_thumb32(insn)
+                                     && ((uintptr_t)addr & 2);
+
+               if (straddles_word)
+                       stop_machine(patch_text_stop_machine, &patch, NULL);
+               else
+                       __patch_text(addr, insn);
+       }
+}
diff --git a/arch/arm/kernel/patch.h b/arch/arm/kernel/patch.h
new file mode 100644 (file)
index 0000000..b4731f2
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _ARM_KERNEL_PATCH_H
+#define _ARM_KERNEL_PATCH_H
+
+void patch_text(void *addr, unsigned int insn);
+void __patch_text(void *addr, unsigned int insn);
+
+#endif
index 8a89d3b7626b2fd6e7e984f6561ca113b12d1081..186c8cb982c543a2cc1631796b34376151b33702 100644 (file)
@@ -738,6 +738,9 @@ init_hw_perf_events(void)
                case 0xC0F0:    /* Cortex-A15 */
                        cpu_pmu = armv7_a15_pmu_init();
                        break;
+               case 0xC070:    /* Cortex-A7 */
+                       cpu_pmu = armv7_a7_pmu_init();
+                       break;
                }
        /* Intel CPUs [xscale]. */
        } else if (0x69 == implementor) {
index 4d7095af2ab3a55075f080b3d4fee66b84d39f17..00755d82e2f2cbe06cda363c53ff115397d94d59 100644 (file)
@@ -609,6 +609,130 @@ static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
        },
 };
 
+/*
+ * Cortex-A7 HW events mapping
+ */
+static const unsigned armv7_a7_perf_map[PERF_COUNT_HW_MAX] = {
+       [PERF_COUNT_HW_CPU_CYCLES]              = ARMV7_PERFCTR_CPU_CYCLES,
+       [PERF_COUNT_HW_INSTRUCTIONS]            = ARMV7_PERFCTR_INSTR_EXECUTED,
+       [PERF_COUNT_HW_CACHE_REFERENCES]        = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+       [PERF_COUNT_HW_CACHE_MISSES]            = ARMV7_PERFCTR_L1_DCACHE_REFILL,
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]     = ARMV7_PERFCTR_PC_WRITE,
+       [PERF_COUNT_HW_BRANCH_MISSES]           = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+       [PERF_COUNT_HW_BUS_CYCLES]              = ARMV7_PERFCTR_BUS_CYCLES,
+       [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = HW_OP_UNSUPPORTED,
+       [PERF_COUNT_HW_STALLED_CYCLES_BACKEND]  = HW_OP_UNSUPPORTED,
+};
+
+static const unsigned armv7_a7_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+                                       [PERF_COUNT_HW_CACHE_OP_MAX]
+                                       [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+       [C(L1D)] = {
+               /*
+                * The performance counters don't differentiate between read
+                * and write accesses/misses so this isn't strictly correct,
+                * but it's the best we can do. Writes and reads get
+                * combined.
+                */
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_DCACHE_REFILL,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_DCACHE_REFILL,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(L1I)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_ICACHE_REFILL,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L1_ICACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L1_ICACHE_REFILL,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(LL)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L2_CACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L2_CACHE_REFILL,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_L2_CACHE_ACCESS,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_L2_CACHE_REFILL,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(DTLB)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_DTLB_REFILL,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(ITLB)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_REFILL,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_ITLB_REFILL,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(BPU)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_BRANCH_PRED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = ARMV7_PERFCTR_PC_BRANCH_PRED,
+                       [C(RESULT_MISS)]        = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+       [C(NODE)] = {
+               [C(OP_READ)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_WRITE)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+               [C(OP_PREFETCH)] = {
+                       [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
+                       [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
+               },
+       },
+};
+
 /*
  * Perf Events' indices
  */
@@ -1104,6 +1228,12 @@ static int armv7_a15_map_event(struct perf_event *event)
                                &armv7_a15_perf_cache_map, 0xFF);
 }
 
+static int armv7_a7_map_event(struct perf_event *event)
+{
+       return map_cpu_event(event, &armv7_a7_perf_map,
+                               &armv7_a7_perf_cache_map, 0xFF);
+}
+
 static struct arm_pmu armv7pmu = {
        .handle_irq             = armv7pmu_handle_irq,
        .enable                 = armv7pmu_enable_event,
@@ -1164,6 +1294,16 @@ static struct arm_pmu *__init armv7_a15_pmu_init(void)
        armv7pmu.set_event_filter = armv7pmu_set_event_filter;
        return &armv7pmu;
 }
+
+static struct arm_pmu *__init armv7_a7_pmu_init(void)
+{
+       armv7pmu.id             = ARM_PERF_PMU_ID_CA7;
+       armv7pmu.name           = "ARMv7 Cortex-A7";
+       armv7pmu.map_event      = armv7_a7_map_event;
+       armv7pmu.num_events     = armv7_read_num_pmnc_events();
+       armv7pmu.set_event_filter = armv7pmu_set_event_filter;
+       return &armv7pmu;
+}
 #else
 static struct arm_pmu *__init armv7_a8_pmu_init(void)
 {
@@ -1184,4 +1324,9 @@ static struct arm_pmu *__init armv7_a15_pmu_init(void)
 {
        return NULL;
 }
+
+static struct arm_pmu *__init armv7_a7_pmu_init(void)
+{
+       return NULL;
+}
 #endif /* CONFIG_CPU_V7 */
index 7b9cddef6e53f5949abb280079f0d135906f9454..2b7b017a20cd6fe9e1644e61ab1f5fe03f7d1be0 100644 (file)
@@ -528,21 +528,39 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
 #ifdef CONFIG_MMU
 /*
  * The vectors page is always readable from user space for the
- * atomic helpers and the signal restart code.  Let's declare a mapping
- * for it so it is visible through ptrace and /proc/<pid>/mem.
+ * atomic helpers and the signal restart code. Insert it into the
+ * gate_vma so that it is visible through ptrace and /proc/<pid>/mem.
  */
+static struct vm_area_struct gate_vma;
 
-int vectors_user_mapping(void)
+static int __init gate_vma_init(void)
 {
-       struct mm_struct *mm = current->mm;
-       return install_special_mapping(mm, 0xffff0000, PAGE_SIZE,
-                                      VM_READ | VM_EXEC |
-                                      VM_MAYREAD | VM_MAYEXEC | VM_RESERVED,
-                                      NULL);
+       gate_vma.vm_start       = 0xffff0000;
+       gate_vma.vm_end         = 0xffff0000 + PAGE_SIZE;
+       gate_vma.vm_page_prot   = PAGE_READONLY_EXEC;
+       gate_vma.vm_flags       = VM_READ | VM_EXEC |
+                                 VM_MAYREAD | VM_MAYEXEC;
+       return 0;
+}
+arch_initcall(gate_vma_init);
+
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
+{
+       return &gate_vma;
+}
+
+int in_gate_area(struct mm_struct *mm, unsigned long addr)
+{
+       return (addr >= gate_vma.vm_start) && (addr < gate_vma.vm_end);
+}
+
+int in_gate_area_no_mm(unsigned long addr)
+{
+       return in_gate_area(NULL, addr);
 }
 
 const char *arch_vma_name(struct vm_area_struct *vma)
 {
-       return (vma->vm_start == 0xffff0000) ? "[vectors]" : NULL;
+       return (vma == &gate_vma) ? "[vectors]" : NULL;
 }
 #endif
index 5416c7c125289b201cb5c8db3c27b9bf8eeea298..27d186abbc06f8aa3aa6310faa5b67039d447f03 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/jiffies.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/syscore_ops.h>
 #include <linux/timer.h>
 
 #include <asm/sched_clock.h>
@@ -164,3 +165,20 @@ void __init sched_clock_postinit(void)
 
        sched_clock_poll(sched_clock_timer.data);
 }
+
+static int sched_clock_suspend(void)
+{
+       sched_clock_poll(sched_clock_timer.data);
+       return 0;
+}
+
+static struct syscore_ops sched_clock_ops = {
+       .suspend = sched_clock_suspend,
+};
+
+static int __init sched_clock_syscore_init(void)
+{
+       register_syscore_ops(&sched_clock_ops);
+       return 0;
+}
+device_initcall(sched_clock_syscore_init);
index 9e0fdb3a1988ea549442f5c1369e209ab3f44164..b91411371ae19b1ae75c2184b4b26ec6c9b06193 100644 (file)
@@ -976,7 +976,6 @@ void __init setup_arch(char **cmdline_p)
        conswitchp = &dummy_con;
 #endif
 #endif
-       early_trap_init();
 
        if (mdesc->init_early)
                mdesc->init_early();
index 9e617bd4a146250d7d3f453d50a45431fa261e08..7cb532fc8aa4e3a9dc1e9d63d4cb887a08b1fad1 100644 (file)
@@ -66,12 +66,13 @@ const unsigned long syscall_restart_code[2] = {
  */
 asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
 {
-       mask &= _BLOCKABLE;
-       spin_lock_irq(&current->sighand->siglock);
+       sigset_t blocked;
+
        current->saved_sigmask = current->blocked;
-       siginitset(&current->blocked, mask);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+
+       mask &= _BLOCKABLE;
+       siginitset(&blocked, mask);
+       set_current_blocked(&blocked);
 
        current->state = TASK_INTERRUPTIBLE;
        schedule();
@@ -280,10 +281,7 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
        err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
        if (err == 0) {
                sigdelsetmask(&set, ~_BLOCKABLE);
-               spin_lock_irq(&current->sighand->siglock);
-               current->blocked = set;
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
+               set_current_blocked(&set);
        }
 
        __get_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err);
@@ -636,13 +634,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
        /*
         * Block the signal if we were successful.
         */
-       spin_lock_irq(&tsk->sighand->siglock);
-       sigorsets(&tsk->blocked, &tsk->blocked,
-                 &ka->sa.sa_mask);
-       if (!(ka->sa.sa_flags & SA_NODEFER))
-               sigaddset(&tsk->blocked, sig);
-       recalc_sigpending();
-       spin_unlock_irq(&tsk->sighand->siglock);
+       block_sigmask(ka, sig);
 
        return 0;
 }
index 8f8cce2c46c42d8a10427b77014abb5008a2530c..2cee7d1eb958bc39b19b31f18447fe4c6119419a 100644 (file)
@@ -58,6 +58,8 @@ enum ipi_msg_type {
        IPI_CPU_STOP,
 };
 
+static DECLARE_COMPLETION(cpu_running);
+
 int __cpuinit __cpu_up(unsigned int cpu)
 {
        struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu);
@@ -98,20 +100,12 @@ int __cpuinit __cpu_up(unsigned int cpu)
         */
        ret = boot_secondary(cpu, idle);
        if (ret == 0) {
-               unsigned long timeout;
-
                /*
                 * CPU was successfully started, wait for it
                 * to come online or time out.
                 */
-               timeout = jiffies + HZ;
-               while (time_before(jiffies, timeout)) {
-                       if (cpu_online(cpu))
-                               break;
-
-                       udelay(10);
-                       barrier();
-               }
+               wait_for_completion_timeout(&cpu_running,
+                                                msecs_to_jiffies(1000));
 
                if (!cpu_online(cpu)) {
                        pr_crit("CPU%u: failed to come online\n", cpu);
@@ -288,9 +282,10 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
        /*
         * OK, now it's safe to let the boot CPU continue.  Wait for
         * the CPU migration code to notice that the CPU is online
-        * before we continue.
+        * before we continue - which happens after __cpu_up returns.
         */
        set_cpu_online(cpu, true);
+       complete(&cpu_running);
 
        /*
         * Setup the percpu timer for this CPU.
index 8c57dd3680e9eeee46f5476d10c4c295c8796568..fe31b22f18fdd8a2bc3a8553626ba0903c4d8d13 100644 (file)
@@ -25,8 +25,6 @@
 #include <linux/timer.h>
 #include <linux/irq.h>
 
-#include <linux/mc146818rtc.h>
-
 #include <asm/leds.h>
 #include <asm/thread_info.h>
 #include <asm/sched_clock.h>
@@ -149,8 +147,6 @@ void __init time_init(void)
 {
        system_timer = machine_desc->timer;
        system_timer->init();
-#ifdef CONFIG_HAVE_SCHED_CLOCK
        sched_clock_postinit();
-#endif
 }
 
index cd77743472a209bd65592dd0ec5eb9c7da6f3045..778454750a6c323037e382ce8353443e63da36d3 100644 (file)
@@ -227,6 +227,11 @@ void show_stack(struct task_struct *tsk, unsigned long *sp)
 #else
 #define S_SMP ""
 #endif
+#ifdef CONFIG_THUMB2_KERNEL
+#define S_ISA " THUMB2"
+#else
+#define S_ISA " ARM"
+#endif
 
 static int __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs)
 {
@@ -234,8 +239,8 @@ static int __die(const char *str, int err, struct thread_info *thread, struct pt
        static int die_counter;
        int ret;
 
-       printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n",
-              str, err, ++die_counter);
+       printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP
+              S_ISA "\n", str, err, ++die_counter);
 
        /* trap and error numbers are mostly meaningless on ARM */
        ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV);
@@ -784,18 +789,16 @@ static void __init kuser_get_tls_init(unsigned long vectors)
                memcpy((void *)vectors + 0xfe0, (void *)vectors + 0xfe8, 4);
 }
 
-void __init early_trap_init(void)
+void __init early_trap_init(void *vectors_base)
 {
-#if defined(CONFIG_CPU_USE_DOMAINS)
-       unsigned long vectors = CONFIG_VECTORS_BASE;
-#else
-       unsigned long vectors = (unsigned long)vectors_page;
-#endif
+       unsigned long vectors = (unsigned long)vectors_base;
        extern char __stubs_start[], __stubs_end[];
        extern char __vectors_start[], __vectors_end[];
        extern char __kuser_helper_start[], __kuser_helper_end[];
        int kuser_sz = __kuser_helper_end - __kuser_helper_start;
 
+       vectors_page = vectors_base;
+
        /*
         * Copy the vectors, stubs and kuser helpers (in entry-armv.S)
         * into the vector page, mapped at 0xffff0000, and ensure these
index e1969ce904dc5b4de9ff8f0d44442175c7c2497f..75da315b658724fabe134cb40fef3015b2df9697 100644 (file)
 #include <linux/err.h>
 #include <linux/platform_device.h>
 
-#include <mach/hardware.h>
+#include <asm/sched_clock.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
+
 #include <mach/cputype.h>
+#include <mach/hardware.h>
 #include <mach/time.h>
+
 #include "clock.h"
 
 static struct clock_event_device clockevent_davinci;
@@ -272,19 +275,9 @@ static cycle_t read_cycles(struct clocksource *cs)
        return (cycles_t)timer32_read(t);
 }
 
-/*
- * Kernel assumes that sched_clock can be called early but may not have
- * things ready yet.
- */
-static cycle_t read_dummy(struct clocksource *cs)
-{
-       return 0;
-}
-
-
 static struct clocksource clocksource_davinci = {
        .rating         = 300,
-       .read           = read_dummy,
+       .read           = read_cycles,
        .mask           = CLOCKSOURCE_MASK(32),
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
@@ -292,12 +285,9 @@ static struct clocksource clocksource_davinci = {
 /*
  * Overwrite weak default sched_clock with something more precise
  */
-unsigned long long notrace sched_clock(void)
+static u32 notrace davinci_read_sched_clock(void)
 {
-       const cycle_t cyc = clocksource_davinci.read(&clocksource_davinci);
-
-       return clocksource_cyc2ns(cyc, clocksource_davinci.mult,
-                               clocksource_davinci.shift);
+       return timer32_read(&timers[TID_CLOCKSOURCE]);
 }
 
 /*
@@ -397,12 +387,14 @@ static void __init davinci_timer_init(void)
        davinci_clock_tick_rate = clk_get_rate(timer_clk);
 
        /* setup clocksource */
-       clocksource_davinci.read = read_cycles;
        clocksource_davinci.name = id_to_name[clocksource_id];
        if (clocksource_register_hz(&clocksource_davinci,
                                    davinci_clock_tick_rate))
                printk(err, clocksource_davinci.name);
 
+       setup_sched_clock(davinci_read_sched_clock, 32,
+                         davinci_clock_tick_rate);
+
        /* setup clockevent */
        clockevent_davinci.name = id_to_name[timers[TID_CLOCKEVENT].id];
        clockevent_davinci.mult = div_sc(davinci_clock_tick_rate, NSEC_PER_SEC,
index 808b055289b2b0443cf5f197e47f3eac11aa6679..410a112bb52e29036d22c1de07ffed1965011389 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
-#include <mach/irqs.h>
 
 #include "core.h"
 #include "sysregs.h"
diff --git a/arch/arm/mach-highbank/include/mach/irqs.h b/arch/arm/mach-highbank/include/mach/irqs.h
deleted file mode 100644 (file)
index 9746aab..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __MACH_IRQS_H
-#define __MACH_IRQS_H
-
-#define NR_IRQS                        192
-
-#endif
index 1a65d77bd55d774bd1ac59f6434479c147ab8510..eaf6c6366ffa0c7cac50a5c4e33715c8a2626afa 100644 (file)
@@ -25,8 +25,9 @@
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
-#include <asm/irq.h>
 #include <mach/cm.h>
+#include <mach/irqs.h>
+
 #include <asm/leds.h>
 #include <asm/mach-types.h>
 #include <asm/mach/time.h>
index 1fbe6d1902226a0d19bc796ef9048720a2853c9b..a19a1a2fcf6bece62d342599548286dae08aace4 100644 (file)
@@ -78,5 +78,6 @@
 #define IRQ_SIC_CP_LMINT7              46
 #define IRQ_SIC_END                    46
 
-#define NR_IRQS                         47
+#define NR_IRQS_INTEGRATOR_AP          34
+#define NR_IRQS_INTEGRATOR_CP          47
 
index 21a1d6cbef40c43dad90ff3fc9da70d550f78fe9..871f148ffd723fdb4389e7fff95f7b0d47494cea 100644 (file)
 #include <mach/hardware.h>
 #include <mach/platform.h>
 #include <asm/hardware/arm_timer.h>
-#include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/param.h>         /* HZ */
 #include <asm/mach-types.h>
+#include <asm/sched_clock.h>
 
 #include <mach/lm.h>
+#include <mach/irqs.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
@@ -325,6 +326,11 @@ static void __init ap_init(void)
 
 static unsigned long timer_reload;
 
+static u32 notrace integrator_read_sched_clock(void)
+{
+       return -readl((void __iomem *) TIMER2_VA_BASE + TIMER_VALUE);
+}
+
 static void integrator_clocksource_init(unsigned long inrate)
 {
        void __iomem *base = (void __iomem *)TIMER2_VA_BASE;
@@ -341,6 +347,7 @@ static void integrator_clocksource_init(unsigned long inrate)
 
        clocksource_mmio_init(base + TIMER_VALUE, "timer2",
                        rate, 200, 16, clocksource_mmio_readl_down);
+       setup_sched_clock(integrator_read_sched_clock, 16, rate);
 }
 
 static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE;
@@ -468,6 +475,7 @@ MACHINE_START(INTEGRATOR, "ARM-Integrator")
        .atag_offset    = 0x100,
        .reserve        = integrator_reserve,
        .map_io         = ap_map_io,
+       .nr_irqs        = NR_IRQS_INTEGRATOR_AP,
        .init_early     = integrator_init_early,
        .init_irq       = ap_init_irq,
        .timer          = &ap_timer,
index be9ead4a3bcc3b55a44634fbdc6eabcb37733a32..48a115a91d9d1c3a2bb479dc00bedefe257ceb5c 100644 (file)
@@ -26,7 +26,6 @@
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
-#include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/hardware/arm_timer.h>
@@ -34,6 +33,7 @@
 
 #include <mach/cm.h>
 #include <mach/lm.h>
+#include <mach/irqs.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
@@ -464,6 +464,7 @@ MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
        .atag_offset    = 0x100,
        .reserve        = integrator_reserve,
        .map_io         = intcp_map_io,
+       .nr_irqs        = NR_IRQS_INTEGRATOR_CP,
        .init_early     = intcp_init_early,
        .init_irq       = intcp_init_irq,
        .timer          = &cp_timer,
index 36068f438f2bd7d2590c3e64feb1e0b79bb57ddc..f1ca9c122861ba468ec2bc507a2e7a48050d15aa 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/init.h>
 
-#include <asm/irq.h>
 #include <asm/mach/pci.h>
 #include <asm/mach-types.h>
 
+#include <mach/irqs.h>
+
 /* 
  * A small note about bridges and interrupts.  The DECchip 21050 (and
  * later) adheres to the PCI-PCI bridge specification.  This says that
index 4be172c3cbe0d2478270be0479d5dd34184aa090..67e6f9a9d1a0962e8f64f4b09e1582a35d6bcad2 100644 (file)
@@ -30,7 +30,8 @@
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
-#include <asm/irq.h>
+#include <mach/irqs.h>
+
 #include <asm/signal.h>
 #include <asm/mach/pci.h>
 #include <asm/irq_regs.h>
index 3588a55841532f4dc0c6c5268ec87b0e0c40319a..bf5d8e195c3efb03849660ffac3d923897e88b33 100644 (file)
@@ -23,6 +23,7 @@
 #include <mach/addr-map.h>
 #include <mach/mfp-pxa168.h>
 #include <mach/pxa168.h>
+#include <mach/irqs.h>
 #include <video/pxa168fb.h>
 #include <linux/input.h>
 #include <plat/pxa27x_keypad.h>
@@ -239,7 +240,7 @@ static void __init common_init(void)
 
 MACHINE_START(ASPENITE, "PXA168-based Aspenite Development Platform")
        .map_io         = mmp_map_io,
-       .nr_irqs        = IRQ_BOARD_START,
+       .nr_irqs        = MMP_NR_IRQS,
        .init_irq       = pxa168_init_irq,
        .timer          = &pxa168_timer,
        .init_machine   = common_init,
@@ -248,7 +249,7 @@ MACHINE_END
 
 MACHINE_START(ZYLONITE2, "PXA168-based Zylonite2 Development Platform")
        .map_io         = mmp_map_io,
-       .nr_irqs        = IRQ_BOARD_START,
+       .nr_irqs        = MMP_NR_IRQS,
        .init_irq       = pxa168_init_irq,
        .timer          = &pxa168_timer,
        .init_machine   = common_init,
index b148a9dc5a443a5e19987ba9a46b66c4fe043d71..603542ae6fbd61e6696cad9eef7424f82fb90cca 100644 (file)
@@ -43,6 +43,7 @@ static void __init avengers_lite_init(void)
 
 MACHINE_START(AVENGERS_LITE, "PXA168 Avengers lite Development Platform")
        .map_io         = mmp_map_io,
+       .nr_irqs        = MMP_NR_IRQS,
        .init_irq       = pxa168_init_irq,
        .timer          = &pxa168_timer,
        .init_machine   = avengers_lite_init,
index d839fe6421e69654468a3e3aaa22002cdb142076..5cb769cd26d9a470a62fca737dc6dffe0afa80ee 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "common.h"
 
-#define BROWNSTONE_NR_IRQS     (IRQ_BOARD_START + 40)
+#define BROWNSTONE_NR_IRQS     (MMP_NR_IRQS + 40)
 
 #define GPIO_5V_ENABLE         (89)
 
@@ -158,7 +158,7 @@ static struct platform_device brownstone_v_5vp_device = {
 };
 
 static struct max8925_platform_data brownstone_max8925_info = {
-       .irq_base               = IRQ_BOARD_START,
+       .irq_base               = MMP_NR_IRQS,
 };
 
 static struct i2c_board_info brownstone_twsi1_info[] = {
index 2ee8cd7829dd862ff0d062b52f56baeab12a1c7a..8059cc0905c6063e5dc079f9b03545d28d90bb5d 100644 (file)
 #include <mach/addr-map.h>
 #include <mach/mfp-mmp2.h>
 #include <mach/mmp2.h>
+#include <mach/irqs.h>
 
 #include "common.h"
 
-#define FLINT_NR_IRQS  (IRQ_BOARD_START + 48)
+#define FLINT_NR_IRQS  (MMP_NR_IRQS + 48)
 
 static unsigned long flint_pin_config[] __initdata = {
        /* UART1 */
index 87765467de633c896c00188906bb289c966dda68..f516e74ce0d5bf1ecc2b20fc874fae1c822c185e 100644 (file)
@@ -191,7 +191,7 @@ static void __init gplugd_init(void)
 
 MACHINE_START(GPLUGD, "PXA168-based GuruPlug Display (gplugD) Platform")
        .map_io         = mmp_map_io,
-       .nr_irqs        = IRQ_BOARD_START,
+       .nr_irqs        = MMP_NR_IRQS,
        .init_irq       = pxa168_init_irq,
        .timer          = &pxa168_timer,
        .init_machine   = gplugd_init,
index 34635a0bbb5924be0db26ffa8a1ddfd12d65da71..d0e746626a3d895250268c301eaa6d2372c946be 100644 (file)
 #define MMP_GPIO_TO_IRQ(gpio)          (IRQ_GPIO_START + (gpio))
 
 #define IRQ_BOARD_START                        (IRQ_GPIO_START + MMP_NR_BUILTIN_GPIO)
-
-#define NR_IRQS                                (IRQ_BOARD_START)
+#define MMP_NR_IRQS                    IRQ_BOARD_START
 
 #endif /* __ASM_MACH_IRQS_H */
index d21c5441a3d0c7c8e0649376b4556d29b6e44cd5..7895d277421e74c225bfddcb76b19a8a7bd72e24 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 
+#include <mach/irqs.h>
 #include <mach/regs-icu.h>
 #include <mach/mmp2.h>
 
index 96cf5c8fe47dcb3b0529ead1538281d584f47e13..ff73249884d031bb165b89d905411ffb65cd067c 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/mfd/max8925.h>
 #include <linux/interrupt.h>
 
+#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/addr-map.h>
@@ -27,7 +28,7 @@
 
 #include "common.h"
 
-#define JASPER_NR_IRQS         (IRQ_BOARD_START + 48)
+#define JASPER_NR_IRQS         (MMP_NR_IRQS + 48)
 
 static unsigned long jasper_pin_config[] __initdata = {
        /* UART1 */
@@ -135,7 +136,7 @@ static struct max8925_power_pdata jasper_power_data = {
 static struct max8925_platform_data jasper_max8925_info = {
        .backlight              = &jasper_backlight_data,
        .power                  = &jasper_power_data,
-       .irq_base               = IRQ_BOARD_START,
+       .irq_base               = MMP_NR_IRQS,
 };
 
 static struct i2c_board_info jasper_twsi1_info[] = {
index bc97170125bf6b410d04af230c2961d9739d2714..b28f9084dfff2e62bd57f6c0518c6320091d03ce 100644 (file)
@@ -101,6 +101,7 @@ static void __init tavorevb_init(void)
 
 MACHINE_START(TAVOREVB, "PXA910 Evaluation Board (aka TavorEVB)")
        .map_io         = mmp_map_io,
+       .nr_irqs        = MMP_NR_IRQS,
        .init_irq       = pxa910_init_irq,
        .timer          = &pxa910_timer,
        .init_machine   = tavorevb_init,
index 0523e422990eeb3f3e6cb98afab1a4d6ea62f049..42bef6674ecfdb2eb601553ff2267e7ad77a17fe 100644 (file)
@@ -26,6 +26,7 @@
 #include <mach/mfp-pxa168.h>
 #include <mach/pxa168.h>
 #include <mach/teton_bga.h>
+#include <mach/irqs.h>
 
 #include "common.h"
 
@@ -83,7 +84,7 @@ static void __init teton_bga_init(void)
 
 MACHINE_START(TETON_BGA, "PXA168-based Teton BGA Development Platform")
        .map_io         = mmp_map_io,
-       .nr_irqs        = IRQ_BOARD_START,
+       .nr_irqs        = MMP_NR_IRQS,
        .init_irq       = pxa168_init_irq,
        .timer          = &pxa168_timer,
        .init_machine   = teton_bga_init,
index e72c709da44f3e2461e6817c504ed571b909fecd..3fc9ed21f97d20d8c5a63a79b5dce8f0be05c1a9 100644 (file)
@@ -38,7 +38,7 @@
  * 16 board interrupts -- PCA9575 GPIO expander
  * 24 board interrupts -- 88PM860x PMIC
  */
-#define TTCDKB_NR_IRQS         (IRQ_BOARD_START + 16 + 16 + 24)
+#define TTCDKB_NR_IRQS         (MMP_NR_IRQS + 16 + 16 + 24)
 
 static unsigned long ttc_dkb_pin_config[] __initdata = {
        /* UART2 */
@@ -131,7 +131,7 @@ static struct platform_device *ttc_dkb_devices[] = {
 static struct pca953x_platform_data max7312_data[] = {
        {
                .gpio_base      = TTCDKB_GPIO_EXT0(0),
-               .irq_base       = IRQ_BOARD_START,
+               .irq_base       = MMP_NR_IRQS,
        },
 };
 
index 75f4be40b3e5d8f8ed98ab87e33282b685009999..812808254936575efb06902de9b4bbe7d4941084 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/mach/time.h>
 #include <asm/hardware/gic.h>
 #include <asm/localtimer.h>
+#include <asm/sched_clock.h>
 
 #include <mach/msm_iomap.h>
 #include <mach/cpu.h>
@@ -105,12 +106,12 @@ static union {
 
 static void __iomem *source_base;
 
-static cycle_t msm_read_timer_count(struct clocksource *cs)
+static notrace cycle_t msm_read_timer_count(struct clocksource *cs)
 {
        return readl_relaxed(source_base + TIMER_COUNT_VAL);
 }
 
-static cycle_t msm_read_timer_count_shift(struct clocksource *cs)
+static notrace cycle_t msm_read_timer_count_shift(struct clocksource *cs)
 {
        /*
         * Shift timer count down by a constant due to unreliable lower bits
@@ -166,6 +167,11 @@ static struct local_timer_ops msm_local_timer_ops __cpuinitdata = {
 };
 #endif /* CONFIG_LOCAL_TIMERS */
 
+static notrace u32 msm_sched_clock_read(void)
+{
+       return msm_clocksource.read(&msm_clocksource);
+}
+
 static void __init msm_timer_init(void)
 {
        struct clock_event_device *ce = &msm_clockevent;
@@ -232,6 +238,8 @@ err:
        res = clocksource_register_hz(cs, dgt_hz);
        if (res)
                pr_err("clocksource_register failed\n");
+       setup_sched_clock(msm_sched_clock_read,
+                       cpu_is_msm7x01() ? 32 - MSM_DGT_SHIFT : 32, dgt_hz);
 }
 
 struct sys_timer msm_timer = {
diff --git a/arch/arm/mach-picoxcell/include/mach/irqs.h b/arch/arm/mach-picoxcell/include/mach/irqs.h
deleted file mode 100644 (file)
index 59eac1e..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2011 Picochip Ltd., Jamie Iles
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#ifndef __MACH_IRQS_H
-#define __MACH_IRQS_H
-
-/* We dynamically allocate our irq_desc's. */
-#define NR_IRQS                                0
-
-#endif /* __MACH_IRQS_H */
index b7a6091ce7914a819f1f902de3d32bce8391211d..0d024b1e916d417a67516101a54a409c36840d38 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <mach/map.h>
+#include <asm/sched_clock.h>
 #include <asm/mach/time.h>
 
 #define SIRFSOC_TIMER_COUNTER_LO       0x0000
@@ -165,21 +166,9 @@ static struct irqaction sirfsoc_timer_irq = {
 };
 
 /* Overwrite weak default sched_clock with more precise one */
-unsigned long long notrace sched_clock(void)
+static u32 notrace sirfsoc_read_sched_clock(void)
 {
-       static int is_mapped;
-
-       /*
-        * sched_clock is called earlier than .init of sys_timer
-        * if we map timer memory in .init of sys_timer, system
-        * will panic due to illegal memory access
-        */
-       if (!is_mapped) {
-               sirfsoc_of_timer_map();
-               is_mapped = 1;
-       }
-
-       return sirfsoc_timer_read(NULL) * (NSEC_PER_SEC / CLOCK_TICK_RATE);
+       return (u32)(sirfsoc_timer_read(NULL) & 0xffffffff);
 }
 
 static void __init sirfsoc_clockevent_init(void)
@@ -210,6 +199,8 @@ static void __init sirfsoc_timer_init(void)
        BUG_ON(rate < CLOCK_TICK_RATE);
        BUG_ON(rate % CLOCK_TICK_RATE);
 
+       sirfsoc_of_timer_map();
+
        writel_relaxed(rate / CLOCK_TICK_RATE / 2 - 1, sirfsoc_timer_base + SIRFSOC_TIMER_DIV);
        writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
        writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
@@ -217,6 +208,8 @@ static void __init sirfsoc_timer_init(void)
 
        BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE));
 
+       setup_sched_clock(sirfsoc_read_sched_clock, 32, CLOCK_TICK_RATE);
+
        BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq));
 
        sirfsoc_clockevent_init();
index c91727d1fe097ab5bf01d0dbf261afefc7748775..9a8760b729132a5055880858d1aab1b0cdc90eda 100644 (file)
@@ -150,6 +150,7 @@ MACHINE_START(CAPC7117,
              "Embedian CAPC-7117 evaluation kit based on the MXM-8x10 CoM")
        .atag_offset = 0x100,
        .map_io = pxa3xx_map_io,
+       .nr_irqs = PXA_NR_IRQS,
        .init_irq = pxa3xx_init_irq,
        .handle_irq = pxa3xx_handle_irq,
        .timer = &pxa_timer,
index 895ee8c45009ff1388ebdbfaf3fb8a2b60ab0887..638eebedc883529a8be95937f542af38f919b4b7 100644 (file)
@@ -854,6 +854,7 @@ static void __init cm_x300_fixup(struct tag *tags, char **cmdline,
 MACHINE_START(CM_X300, "CM-X300 module")
        .atag_offset    = 0x100,
        .map_io         = pxa3xx_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
index 29d5d541f602f081b17b26acce6ef8f7bc148772..b2f227d361250e738c1f0b5a1d685b1ae9e44271 100644 (file)
@@ -310,6 +310,7 @@ MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
        .atag_offset    = 0x100,
        .init_machine   = colibri_pxa270_init,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
@@ -320,6 +321,7 @@ MACHINE_START(INCOME, "Income s.r.o. SH-Dmaster PXA270 SBC")
        .atag_offset    = 0x100,
        .init_machine   = colibri_pxa270_income_init,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index 0846d210cb05401be28b4b22840c683bcb09f6f8..bb6def8ec979d280ebf866c927612b5445424919 100644 (file)
@@ -186,6 +186,7 @@ MACHINE_START(COLIBRI300, "Toradex Colibri PXA300")
        .atag_offset    = 0x100,
        .init_machine   = colibri_pxa300_init,
        .map_io         = pxa3xx_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
index 6ad3359063af4fe49727c0645367050b2a9adf36..d88e7b37f1dacfdc99a2991c5eab1d6d74d999bd 100644 (file)
@@ -256,6 +256,7 @@ MACHINE_START(COLIBRI320, "Toradex Colibri PXA320")
        .atag_offset    = 0x100,
        .init_machine   = colibri_pxa320_init,
        .map_io         = pxa3xx_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
index de9d45e673fd25a57b269ac984e339b7afe16f28..c1fe32db47552b7f0d73d5133675fab340791f18 100644 (file)
@@ -729,6 +729,7 @@ static void __init fixup_corgi(struct tag *tags, char **cmdline,
 MACHINE_START(CORGI, "SHARP Corgi")
        .fixup          = fixup_corgi,
        .map_io         = pxa25x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .init_machine   = corgi_init,
@@ -741,6 +742,7 @@ MACHINE_END
 MACHINE_START(SHEPHERD, "SHARP Shepherd")
        .fixup          = fixup_corgi,
        .map_io         = pxa25x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .init_machine   = corgi_init,
@@ -753,6 +755,7 @@ MACHINE_END
 MACHINE_START(HUSKY, "SHARP Husky")
        .fixup          = fixup_corgi,
        .map_io         = pxa25x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .init_machine   = corgi_init,
index fb5a51d834e5391c4cb407b4270009dcaf68b33c..67f0de37f46ebf1fb3308bd86d0d7ce6ed38fe71 100644 (file)
@@ -274,6 +274,7 @@ static void __init csb726_init(void)
 MACHINE_START(CSB726, "Cogent CSB726")
        .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq       = pxa27x_handle_irq,
        .init_machine   = csb726_init,
index 84f2d7015cfeced0850588ba7572968f1943f630..166eee5b8a70fe8f4bc555543ea8027564ee0392 100644 (file)
@@ -12,6 +12,7 @@
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <mach/irda.h>
+#include <mach/irqs.h>
 #include <mach/ohci.h>
 #include <plat/pxa27x_keypad.h>
 #include <mach/camera.h>
index d80c0ba9a0955613a2f393f5fefd1d882483ad52..c1b65da263358b6cf554728cb23b51e0631ec94c 100644 (file)
@@ -1301,6 +1301,7 @@ static void __init em_x270_init(void)
 MACHINE_START(EM_X270, "Compulab EM-X270")
        .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
@@ -1311,6 +1312,7 @@ MACHINE_END
 MACHINE_START(EXEDA, "Compulab eXeda")
        .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index ac3b1cef47519ed4c431cc2b576bfc76ebcda792..e529a35a44cee06a4a24fe39290a0fda172e505c 100644 (file)
@@ -235,6 +235,7 @@ static void __init gumstix_init(void)
 MACHINE_START(GUMSTIX, "Gumstix")
        .atag_offset    = 0x100, /* match u-boot bi_boot_params */
        .map_io         = pxa25x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .timer          = &pxa_timer,
index fde6b4c873c40fba6fe1c0aad5d85d1f03272c8f..e7dec589f0141704587051c16e3cdbb65388de5b 100644 (file)
@@ -205,6 +205,7 @@ static void __init h5000_init(void)
 MACHINE_START(H5400, "HP iPAQ H5000")
        .atag_offset = 0x100,
        .map_io = pxa25x_map_io,
+       .nr_irqs = PXA_NR_IRQS,
        .init_irq = pxa25x_init_irq,
        .handle_irq = pxa25x_handle_irq,
        .timer = &pxa_timer,
index 26d069a9f900117269936685f86a504fdb55f672..2962de898da9eefb0c1e35649e18468642b2abe4 100644 (file)
@@ -160,6 +160,7 @@ static void __init himalaya_init(void)
 MACHINE_START(HIMALAYA, "HTC Himalaya")
        .atag_offset = 0x100,
        .map_io = pxa25x_map_io,
+       .nr_irqs = PXA_NR_IRQS,
        .init_irq = pxa25x_init_irq,
        .handle_irq = pxa25x_handle_irq,
        .init_machine = himalaya_init,
index 67400192ed3b9d6532792e967a207f25a933c89a..1d02eabc9c654bb18751a9b802c2f3cdbc8c83a5 100644 (file)
@@ -193,6 +193,7 @@ static void __init icontrol_init(void)
 MACHINE_START(ICONTROL, "iControl/SafeTcam boards using Embedian MXM-8x10 CoM")
        .atag_offset    = 0x100,
        .map_io         = pxa3xx_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
index 8af1840e12cc4d8cdb6b24dd2f9e46110c59139d..6ff466bd43e8840b76bc71b6f1bcebc97d2092bb 100644 (file)
@@ -195,6 +195,7 @@ static void __init idp_map_io(void)
 MACHINE_START(PXA_IDP, "Vibren PXA255 IDP")
        /* Maintainer: Vibren Technologies */
        .map_io         = idp_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .timer          = &pxa_timer,
index 32975adf3ca4927a2d77eba14efb1ad7bddd0638..8765782dd955f129a9e510f749de6fabee5a9e92 100644 (file)
  */
 #define IRQ_BOARD_START                (PXA_GPIO_IRQ_BASE + PXA_NR_BUILTIN_GPIO)
 
-#define NR_IRQS                        (IRQ_BOARD_START)
+#define PXA_NR_IRQS            (IRQ_BOARD_START)
 
 #ifndef __ASSEMBLY__
 struct irq_data;
index 4c2d11cd824dda4415d1ad74af1a368ffdd9b439..1bfc4e822a4152439a1cd0220ee614147472edc6 100644 (file)
@@ -13,6 +13,8 @@
 #ifndef ASM_ARCH_MAINSTONE_H
 #define ASM_ARCH_MAINSTONE_H
 
+#include <mach/irqs.h>
+
 #define MST_ETH_PHYS           PXA_CS4_PHYS
 
 #define MST_FPGA_PHYS          PXA_CS2_PHYS
index e80a3db735c26e6e9c32ffd34ef435246b2949c8..061d57009cee98aec4335c745d3a7a51cfd975ea 100644 (file)
@@ -758,6 +758,7 @@ MACHINE_START(MIOA701, "MIO A701")
        .atag_offset    = 0x100,
        .restart_mode   = 's',
        .map_io         = &pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = &pxa27x_init_irq,
        .handle_irq     = &pxa27x_handle_irq,
        .init_machine   = mioa701_machine_init,
index 169bf8f97af00028a76d314b2bb8efa2d6b19e93..152efbf093f6b1f08eb2f18a2e2707688bb2a475 100644 (file)
@@ -95,6 +95,7 @@ MACHINE_START(NEC_MP900, "MobilePro900/C")
        .atag_offset    = 0x220100,
        .timer          = &pxa_timer,
        .map_io         = pxa25x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .init_machine   = mp900c_init,
index 1fa80f4f80c8484595c4f4a5a17cdaf931a9cc33..31e0433d83ba2ffee4e1ddd24460f360ea940446 100644 (file)
@@ -344,6 +344,7 @@ static void __init palmld_init(void)
 MACHINE_START(PALMLD, "Palm LifeDrive")
        .atag_offset    = 0x100,
        .map_io         = palmld_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index 5ba14316bd9c273b386e6267582dc93aa1131463..0f6bd4fcfa3b1f311cde34c6a540c852e24efc20 100644 (file)
@@ -205,6 +205,7 @@ MACHINE_START(PALMT5, "Palm Tungsten|T5")
        .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
        .reserve        = palmt5_reserve,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index 29b51b40f09df49a60a2ab07d91122f0f840ed74..e2d97eed07a7603224945b547d32cb0c1cd8ef40 100644 (file)
@@ -539,6 +539,7 @@ static void __init palmtc_init(void)
 MACHINE_START(PALMTC, "Palm Tungsten|C")
        .atag_offset    = 0x100,
        .map_io         = pxa25x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .timer          = &pxa_timer,
index 5ebf49acb8279d321a61596718980dc45dadfa11..c054827c567f81805771e7a9160748dcb8124b68 100644 (file)
@@ -358,6 +358,7 @@ static void __init palmte2_init(void)
 MACHINE_START(PALMTE2, "Palm Tungsten|E2")
        .atag_offset    = 0x100,
        .map_io         = pxa25x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .timer          = &pxa_timer,
index ec8249156c0846b1d6129b6c55ab7a431d23d2a4..fbdebee39a53dbbe57b6cfa8f2324b785d4429f5 100644 (file)
@@ -448,6 +448,7 @@ MACHINE_START(TREO680, "Palm Treo 680")
        .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
        .reserve        = treo_reserve,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq       = pxa27x_handle_irq,
        .timer          = &pxa_timer,
@@ -461,6 +462,7 @@ MACHINE_START(CENTRO, "Palm Centro 685")
        .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
        .reserve        = treo_reserve,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq       = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index 6170d76dfba8f395a41ff16c6c16ac28d1760970..9507605ed547a5366abf75cb704ee7c23a50ee62 100644 (file)
@@ -366,6 +366,7 @@ static void __init palmtx_init(void)
 MACHINE_START(PALMTX, "Palm T|X")
        .atag_offset    = 0x100,
        .map_io         = palmtx_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index b2dff9d415ebf69eedba22393913e74075bb75ac..a97b59965bb917a542ed252446cefd7cf3e037c0 100644 (file)
@@ -401,6 +401,7 @@ static void __init palmz72_init(void)
 MACHINE_START(PALMZ72, "Palm Zire72")
        .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index 1570d457fea3b87f52629ce2b1982c27229c3d40..dffb7e813d98743e3330db699770f5862eca6d49 100644 (file)
@@ -31,6 +31,7 @@
 #include <mach/pm.h>
 #include <mach/dma.h>
 #include <mach/smemc.h>
+#include <mach/irqs.h>
 
 #include "generic.h"
 #include "devices.h"
index 22818c7694a8fdb142b619f32c801e3cc9424386..7d691e51cb54048d679440b766dba67a7b3c9f4c 100644 (file)
@@ -1090,6 +1090,7 @@ MACHINE_START(RAUMFELD_RC, "Raumfeld Controller")
        .atag_offset    = 0x100,
        .init_machine   = raumfeld_controller_init,
        .map_io         = pxa3xx_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
@@ -1102,6 +1103,7 @@ MACHINE_START(RAUMFELD_CONNECTOR, "Raumfeld Connector")
        .atag_offset    = 0x100,
        .init_machine   = raumfeld_connector_init,
        .map_io         = pxa3xx_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
@@ -1114,6 +1116,7 @@ MACHINE_START(RAUMFELD_SPEAKER, "Raumfeld Speaker")
        .atag_offset    = 0x100,
        .init_machine   = raumfeld_speaker_init,
        .map_io         = pxa3xx_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq     = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
index 0fe354efb9317a8d183b76ef23a5e1a056982c58..86c95a5d8533a2e6db55116afa13d26925f2232d 100644 (file)
@@ -598,6 +598,7 @@ MACHINE_START(SAAR, "PXA930 Handheld Platform (aka SAAR)")
        /* Maintainer: Eric Miao <eric.miao@marvell.com> */
        .atag_offset    = 0x100,
        .map_io         = pxa3xx_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq       = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
index abf355d0c92f4fda72ea75cdfeb146cfa32d4c48..df2ab0fb2aced7c34736019f123c9e8cdfe38a2f 100644 (file)
@@ -984,6 +984,7 @@ MACHINE_START(SPITZ, "SHARP Spitz")
        .restart_mode   = 'g',
        .fixup          = spitz_fixup,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .init_machine   = spitz_init,
@@ -997,6 +998,7 @@ MACHINE_START(BORZOI, "SHARP Borzoi")
        .restart_mode   = 'g',
        .fixup          = spitz_fixup,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .init_machine   = spitz_init,
@@ -1010,6 +1012,7 @@ MACHINE_START(AKITA, "SHARP Akita")
        .restart_mode   = 'g',
        .fixup          = spitz_fixup,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .init_machine   = spitz_init,
index b0656e158d90409f249cc4a6965483bb68e1dc52..adb601a3762fb6e2612339fb306b959cd27a722d 100644 (file)
@@ -1006,6 +1006,7 @@ static void __init stargate2_init(void)
 #ifdef CONFIG_MACH_INTELMOTE2
 MACHINE_START(INTELMOTE2, "IMOTE 2")
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index 9fb38e80e076ca984056031cadae43ba306060c5..736bfdc50ee61dedf68da32b8475c9283a500af0 100644 (file)
@@ -491,6 +491,7 @@ MACHINE_START(TAVOREVB, "PXA930 Evaluation Board (aka TavorEVB)")
        /* Maintainer: Eric Miao <eric.miao@marvell.com> */
        .atag_offset    = 0x100,
        .map_io         = pxa3xx_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa3xx_init_irq,
        .handle_irq       = pxa3xx_handle_irq,
        .timer          = &pxa_timer,
index b503049d6d2657f6147b0bc82929426e2fe9f463..3d6c9bd90de6b183cd741e891c926a4bcb841c7e 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/mach/time.h>
 #include <asm/sched_clock.h>
 #include <mach/regs-ost.h>
+#include <mach/irqs.h>
 
 /*
  * This is PXA's sched_clock implementation. This has a resolution
index 0f30af617d8f47924eb1591928aa9a87627f3405..2b6ac00b2cd98ce24e3e5e34bf56d36698d54c87 100644 (file)
@@ -558,6 +558,7 @@ MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module")
        .atag_offset    = 0x100,
        .init_machine   = trizeps4_init,
        .map_io         = trizeps4_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
@@ -569,6 +570,7 @@ MACHINE_START(TRIZEPS4WL, "Keith und Koep Trizeps IV-WL module")
        .atag_offset    = 0x100,
        .init_machine   = trizeps4_init,
        .map_io         = trizeps4_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index 7a3d342a773230df12c0800102cb41d66b4f7b89..130379fb9d0fbbd405c0df4a36aee790ea1244ec 100644 (file)
@@ -995,6 +995,7 @@ MACHINE_START(VIPER, "Arcom/Eurotech VIPER SBC")
        /* Maintainer: Marc Zyngier <maz@misterjones.org> */
        .atag_offset    = 0x100,
        .map_io         = viper_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = viper_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .timer          = &pxa_timer,
index 1f5cfa96f6d6a244da2d43f867d666b8b9232138..c57ab636ea9c85f5f459c48c422ca6fb680e35f4 100644 (file)
@@ -718,6 +718,7 @@ static void __init vpac270_init(void)
 MACHINE_START(VPAC270, "Voipac PXA270")
        .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index 4bbe9a36fe74df730ca419f4bfeeb6c3be6516dc..4275713ccd1045e4410c9efb0ac10323e0ed9f79 100644 (file)
@@ -182,6 +182,7 @@ MACHINE_START(XCEP, "Iskratel XCEP")
        .atag_offset    = 0x100,
        .init_machine   = xcep_init,
        .map_io         = pxa25x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa25x_init_irq,
        .handle_irq     = pxa25x_handle_irq,
        .timer          = &pxa_timer,
index b6476848b5618dfc72f68f3f76dfdd1bee2d3533..fa8619970841b8e12a7b1b8a14e1844952e660a7 100644 (file)
@@ -721,6 +721,7 @@ static void __init z2_init(void)
 MACHINE_START(ZIPIT2, "Zipit Z2")
        .atag_offset    = 0x100,
        .map_io         = pxa27x_map_io,
+       .nr_irqs        = PXA_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .handle_irq     = pxa27x_handle_irq,
        .timer          = &pxa_timer,
index 060e5644c49c4711668835d451885f552a63a210..34560cab45d916729ccf03733ca88aaa8f7c9023 100644 (file)
@@ -100,6 +100,10 @@ config MACH_MARZEN
 
 comment "SH-Mobile System Configuration"
 
+config CPU_HAS_INTEVT
+        bool
+       default y
+
 menu "Memory configuration"
 
 config MEMORY_START
index f50d7c8b1221bc2f9b32b6b3a0414d43a485c2ce..f9153294e928d8370052adecc32ab6741a5dfbdd 100644 (file)
@@ -43,6 +43,7 @@
 #include <video/sh_mipi_dsi.h>
 #include <sound/sh_fsi.h>
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 #include <mach/sh73a0.h>
 #include <mach/common.h>
 #include <asm/mach-types.h>
index 8b2124da245d46ad2aca08c63e7431ce97e962a2..a71ae802cc49e83ff44b33e2366a2d6cfd7698b5 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/mach/time.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <mach/r8a7740.h>
+#include <mach/irqs.h>
 #include <video/sh_mobile_lcdc.h>
 
 /*
index b627e89037f5e567d15101b1e3fe3051bbfa94c0..39b6cf85ced6cc2d98d3132c56629ff0a7398874 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
 #include <linux/dma-mapping.h>
+#include <mach/irqs.h>
 #include <mach/sh7367.h>
 #include <mach/common.h>
 #include <asm/mach-types.h>
index 46d757d2759d0120c37db14f79ce1d55b5015b11..0e5a39c670bc259731790e7f275bcfeb47ead4c9 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/gpio.h>
 #include <linux/dma-mapping.h>
+#include <mach/irqs.h>
 #include <mach/sh7377.h>
 #include <mach/common.h>
 #include <asm/mach-types.h>
index 61c067294660f41d36dad57557459f30471a1701..10e9e6967903f85b46da85e73919cdc014c2e03e 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/mfd/tmio.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 #include <mach/sh73a0.h>
 #include <mach/common.h>
 #include <asm/mach-types.h>
index ca609502d6cdda92dda69a3cc421e58d25e9b4c7..a125d4e114ec53db0500632fa7d8addaa5d99bee 100644 (file)
@@ -54,6 +54,7 @@
 #include <sound/sh_fsi.h>
 
 #include <mach/common.h>
+#include <mach/irqs.h>
 #include <mach/sh7372.h>
 
 #include <asm/mach/arch.h>
index cbd5e4cd06d2b241a5d24ee67d578943234d4cf5..ef0e13bf0b3a46911564e1ef7515740a77028574 100644 (file)
@@ -31,6 +31,7 @@
 #include <mach/hardware.h>
 #include <mach/r8a7779.h>
 #include <mach/common.h>
+#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
index dcb714f4d75ab15c2dca37bc0843ad1de73872d6..4e686cc201fc8bacab46ad6aed6c01aac653c42c 100644 (file)
@@ -1,15 +1,11 @@
 #ifndef __ASM_MACH_IRQS_H
 #define __ASM_MACH_IRQS_H
 
-#define NR_IRQS         1024
+#include <linux/sh_intc.h>
 
 /* GIC */
 #define gic_spi(nr)            ((nr) + 32)
 
-/* INTCA */
-#define evt2irq(evt)           (((evt) >> 5) - 16)
-#define irq2evt(irq)           (((irq) + 16) << 5)
-
 /* INTCS */
 #define INTCS_VECT_BASE                0x2200
 #define INTCS_VECT(n, vect)    INTC_VECT((n), INTCS_VECT_BASE + (vect))
index 272c84c20c839d5415bc9953c7b234a4f053e676..09c42afcb22dae848551c1306b922866fc78a957 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/io.h>
 #include <linux/sh_intc.h>
 #include <mach/intc.h>
+#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
index cfde9bfc36699dec881fa738f2d19aec58075955..5bf776495b7521f43a4cfb71c8021485cda891ff 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/io.h>
 #include <linux/sh_intc.h>
 #include <mach/intc.h>
+#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
index 89afcaba99a1a74e132dc1264d249e0099d21944..6447e0af52d412123b222ea94978cc84969c4778 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/io.h>
 #include <linux/sh_intc.h>
 #include <mach/intc.h>
+#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
index 2af4e6e9bc5b3a852070367d80ba9e3b3e27c370..b84a460a340577f005d552099b00f4902d6e4a82 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/io.h>
 #include <linux/sh_intc.h>
 #include <mach/intc.h>
+#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
index 9857595eaa7925186f73664277c0ddf9a57a481b..15b408f58272bcf36a7bdf1e76a15ccb4470c3a9 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/io.h>
 #include <linux/sh_intc.h>
 #include <mach/intc.h>
+#include <mach/irqs.h>
 #include <mach/sh73a0.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
index 74e52341dd1bda1352e70de479c75fa53a99356b..14edb5cffa7f23023d8224d055af3e7974a6807d 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/sh_timer.h>
 #include <mach/r8a7740.h>
 #include <mach/common.h>
+#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
 #include <asm/mach/arch.h>
index 6820d785493db3a2c1516cb4f1fc01461dae6579..12c6f529ab891eac5b4482930e7156adfa842ce6 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/sh_intc.h>
 #include <linux/sh_timer.h>
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 #include <mach/r8a7779.h>
 #include <mach/common.h>
 #include <asm/mach-types.h>
index a51e1a1e6996ddf7a3bd097a23fdbc3071261ae0..2e3074ab75b3189cc239a8c06bdb51a31fce1391 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/sh_timer.h>
 #include <mach/hardware.h>
 #include <mach/common.h>
+#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
index 4e818b7de7815fb466f0b4c5451fad7225859628..2fe8f83ca12492363821fd6462073783b21e9e2d 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/pm_domain.h>
 #include <linux/dma-mapping.h>
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 #include <mach/sh7372.h>
 #include <mach/common.h>
 #include <asm/mach/map.h>
index 9f146095098b258766bebe319b47adc225ec00ce..d576a6abbade8338a33eb8e39d290e29d57e302d 100644 (file)
@@ -32,6 +32,7 @@
 #include <mach/hardware.h>
 #include <mach/common.h>
 #include <asm/mach/map.h>
+#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
index b6a0734a738e472c684b949ce9029a095c03eed2..5bebffc10455ec88132dab1742da1f86b610bda8 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/sh_intc.h>
 #include <linux/sh_timer.h>
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 #include <mach/sh73a0.h>
 #include <mach/common.h>
 #include <asm/mach-types.h>
index 13522d86685e2daa5f77bbe2d37c12d30e8e0ddc..0088cd388a84573ecaff73a1b52b3a137cbfc8d6 100644 (file)
@@ -20,7 +20,6 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
-#define __io(a)                __typesafe_io(a)
 #define __mem_pci(a)   (a)
 
 #endif
index b1e192ba8c2450cb75a8118f86f8b650be284c82..a53fd2aaa2f4b59397bfa01847b22cd991bcdd8b 100644 (file)
 
 static void __iomem *l2x0_base;
 static DEFINE_RAW_SPINLOCK(l2x0_lock);
-static uint32_t l2x0_way_mask; /* Bitmask of active ways */
-static uint32_t l2x0_size;
+static u32 l2x0_way_mask;      /* Bitmask of active ways */
+static u32 l2x0_size;
 
 struct l2x0_regs l2x0_saved_regs;
 
 struct l2x0_of_data {
-       void (*setup)(const struct device_node *, __u32 *, __u32 *);
+       void (*setup)(const struct device_node *, u32 *, u32 *);
        void (*save)(void);
        void (*resume)(void);
 };
@@ -288,7 +288,7 @@ static void l2x0_disable(void)
        raw_spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
-static void l2x0_unlock(__u32 cache_id)
+static void l2x0_unlock(u32 cache_id)
 {
        int lockregs;
        int i;
@@ -307,11 +307,11 @@ static void l2x0_unlock(__u32 cache_id)
        }
 }
 
-void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
+void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
 {
-       __u32 aux;
-       __u32 cache_id;
-       __u32 way_size = 0;
+       u32 aux;
+       u32 cache_id;
+       u32 way_size = 0;
        int ways;
        const char *type;
 
@@ -388,7 +388,7 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
 
 #ifdef CONFIG_OF
 static void __init l2x0_of_setup(const struct device_node *np,
-                                __u32 *aux_val, __u32 *aux_mask)
+                                u32 *aux_val, u32 *aux_mask)
 {
        u32 data[2] = { 0, 0 };
        u32 tag = 0;
@@ -422,7 +422,7 @@ static void __init l2x0_of_setup(const struct device_node *np,
 }
 
 static void __init pl310_of_setup(const struct device_node *np,
-                                 __u32 *aux_val, __u32 *aux_mask)
+                                 u32 *aux_val, u32 *aux_mask)
 {
        u32 data[3] = { 0, 0, 0 };
        u32 tag[3] = { 0, 0, 0 };
@@ -548,7 +548,7 @@ static const struct of_device_id l2x0_ids[] __initconst = {
        {}
 };
 
-int __init l2x0_of_init(__u32 aux_val, __u32 aux_mask)
+int __init l2x0_of_init(u32 aux_val, u32 aux_mask)
 {
        struct device_node *np;
        struct l2x0_of_data *data;
index ec8c3befb9c8d857f8db99c33ee6a9cecf75ff1a..1267e64133b9251feea121d1170ed095b7734944 100644 (file)
 
 #include "mm.h"
 
-/*
- * 0xffff8000 to 0xffffffff is reserved for any ARM architecture
- * specific hacks for copying pages efficiently.
- */
 #define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
                                  L_PTE_MT_MINICACHE)
 
@@ -78,10 +74,9 @@ void v4_mc_copy_user_highpage(struct page *to, struct page *from,
 
        raw_spin_lock(&minicache_lock);
 
-       set_pte_ext(TOP_PTE(0xffff8000), pfn_pte(page_to_pfn(from), minicache_pgprot), 0);
-       flush_tlb_kernel_page(0xffff8000);
+       set_top_pte(COPYPAGE_MINICACHE, mk_pte(from, minicache_pgprot));
 
-       mc_copy_user_page((void *)0xffff8000, kto);
+       mc_copy_user_page((void *)COPYPAGE_MINICACHE, kto);
 
        raw_spin_unlock(&minicache_lock);
 
index 8b03a5814d005e0591e79885f562c401c23a6379..b9bcc9d79176a43c464ef562b2118a119d14a825 100644 (file)
@@ -24,9 +24,6 @@
 #error FIX ME
 #endif
 
-#define from_address   (0xffff8000)
-#define to_address     (0xffffc000)
-
 static DEFINE_RAW_SPINLOCK(v6_lock);
 
 /*
@@ -90,14 +87,11 @@ static void v6_copy_user_highpage_aliasing(struct page *to,
         */
        raw_spin_lock(&v6_lock);
 
-       set_pte_ext(TOP_PTE(from_address) + offset, pfn_pte(page_to_pfn(from), PAGE_KERNEL), 0);
-       set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(page_to_pfn(to), PAGE_KERNEL), 0);
-
-       kfrom = from_address + (offset << PAGE_SHIFT);
-       kto   = to_address + (offset << PAGE_SHIFT);
+       kfrom = COPYPAGE_V6_FROM + (offset << PAGE_SHIFT);
+       kto   = COPYPAGE_V6_TO + (offset << PAGE_SHIFT);
 
-       flush_tlb_kernel_page(kfrom);
-       flush_tlb_kernel_page(kto);
+       set_top_pte(kfrom, mk_pte(from, PAGE_KERNEL));
+       set_top_pte(kto, mk_pte(to, PAGE_KERNEL));
 
        copy_page((void *)kto, (void *)kfrom);
 
@@ -111,8 +105,7 @@ static void v6_copy_user_highpage_aliasing(struct page *to,
  */
 static void v6_clear_user_highpage_aliasing(struct page *page, unsigned long vaddr)
 {
-       unsigned int offset = CACHE_COLOUR(vaddr);
-       unsigned long to = to_address + (offset << PAGE_SHIFT);
+       unsigned long to = COPYPAGE_V6_TO + (CACHE_COLOUR(vaddr) << PAGE_SHIFT);
 
        /* FIXME: not highmem safe */
        discard_old_kernel_data(page_address(page));
@@ -123,8 +116,7 @@ static void v6_clear_user_highpage_aliasing(struct page *page, unsigned long vad
         */
        raw_spin_lock(&v6_lock);
 
-       set_pte_ext(TOP_PTE(to_address) + offset, pfn_pte(page_to_pfn(page), PAGE_KERNEL), 0);
-       flush_tlb_kernel_page(to);
+       set_top_pte(to, mk_pte(page, PAGE_KERNEL));
        clear_page((void *)to);
 
        raw_spin_unlock(&v6_lock);
index 439d106ae63804461d9b4f4149ad310a604e2379..0fb85025344d936734f0ff695ed21c2626414560 100644 (file)
 
 #include "mm.h"
 
-/*
- * 0xffff8000 to 0xffffffff is reserved for any ARM architecture
- * specific hacks for copying pages efficiently.
- */
-#define COPYPAGE_MINICACHE     0xffff8000
-
 #define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
                                  L_PTE_MT_MINICACHE)
 
@@ -100,8 +94,7 @@ void xscale_mc_copy_user_highpage(struct page *to, struct page *from,
 
        raw_spin_lock(&minicache_lock);
 
-       set_pte_ext(TOP_PTE(COPYPAGE_MINICACHE), pfn_pte(page_to_pfn(from), minicache_pgprot), 0);
-       flush_tlb_kernel_page(COPYPAGE_MINICACHE);
+       set_top_pte(COPYPAGE_MINICACHE, mk_pte(from, minicache_pgprot));
 
        mc_copy_user_page((void *)COPYPAGE_MINICACHE, kto);
 
index 1aa664a1999fce45c2548726b50b6fa924608ec2..db23ae4aaaaba3384d000181e4dfb1c9ac476e60 100644 (file)
@@ -214,7 +214,8 @@ static int __init consistent_init(void)
 core_initcall(consistent_init);
 
 static void *
-__dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot)
+__dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot,
+       const void *caller)
 {
        struct arm_vmregion *c;
        size_t align;
@@ -241,7 +242,7 @@ __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot)
         * Allocate a virtual address in the consistent mapping region.
         */
        c = arm_vmregion_alloc(&consistent_head, align, size,
-                           gfp & ~(__GFP_DMA | __GFP_HIGHMEM));
+                           gfp & ~(__GFP_DMA | __GFP_HIGHMEM), caller);
        if (c) {
                pte_t *pte;
                int idx = CONSISTENT_PTE_INDEX(c->vm_start);
@@ -320,14 +321,14 @@ static void __dma_free_remap(void *cpu_addr, size_t size)
 
 #else  /* !CONFIG_MMU */
 
-#define __dma_alloc_remap(page, size, gfp, prot)       page_address(page)
+#define __dma_alloc_remap(page, size, gfp, prot, c)    page_address(page)
 #define __dma_free_remap(addr, size)                   do { } while (0)
 
 #endif /* CONFIG_MMU */
 
 static void *
 __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
-           pgprot_t prot)
+           pgprot_t prot, const void *caller)
 {
        struct page *page;
        void *addr;
@@ -349,7 +350,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
                return NULL;
 
        if (!arch_is_coherent())
-               addr = __dma_alloc_remap(page, size, gfp, prot);
+               addr = __dma_alloc_remap(page, size, gfp, prot, caller);
        else
                addr = page_address(page);
 
@@ -374,7 +375,8 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gf
                return memory;
 
        return __dma_alloc(dev, size, handle, gfp,
-                          pgprot_dmacoherent(pgprot_kernel));
+                          pgprot_dmacoherent(pgprot_kernel),
+                          __builtin_return_address(0));
 }
 EXPORT_SYMBOL(dma_alloc_coherent);
 
@@ -386,7 +388,8 @@ void *
 dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
 {
        return __dma_alloc(dev, size, handle, gfp,
-                          pgprot_writecombine(pgprot_kernel));
+                          pgprot_writecombine(pgprot_kernel),
+                          __builtin_return_address(0));
 }
 EXPORT_SYMBOL(dma_alloc_writecombine);
 
@@ -723,6 +726,9 @@ EXPORT_SYMBOL(dma_set_mask);
 
 static int __init dma_debug_do_init(void)
 {
+#ifdef CONFIG_MMU
+       arm_vmregion_create_proc("dma-mappings", &consistent_head);
+#endif
        dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
        return 0;
 }
index 5bdff5c3e6cb807d1ff0e2f4a5346fee5443c2ac..9055b5a84ec5614914ab19dc5ed54004a821370f 100644 (file)
@@ -165,7 +165,8 @@ __do_user_fault(struct task_struct *tsk, unsigned long addr,
        struct siginfo si;
 
 #ifdef CONFIG_DEBUG_USER
-       if (user_debug & UDBG_SEGV) {
+       if (((user_debug & UDBG_SEGV) && (sig == SIGSEGV)) ||
+           ((user_debug & UDBG_BUS)  && (sig == SIGBUS))) {
                printk(KERN_DEBUG "%s: unhandled page fault (%d) at 0x%08lx, code 0x%03x\n",
                       tsk->comm, sig, addr, fsr);
                show_pte(tsk->mm, addr);
index 062d61a1f87d02b7b2d4c2c2161324b41f40b967..77458548e031fe73d75a5a79ea36f923c95cc88a 100644 (file)
 
 #ifdef CONFIG_CPU_CACHE_VIPT
 
-#define ALIAS_FLUSH_START      0xffff4000
-
 static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
 {
-       unsigned long to = ALIAS_FLUSH_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT);
+       unsigned long to = FLUSH_ALIAS_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT);
        const int zero = 0;
 
-       set_pte_ext(TOP_PTE(to), pfn_pte(pfn, PAGE_KERNEL), 0);
-       flush_tlb_kernel_page(to);
+       set_top_pte(to, pfn_pte(pfn, PAGE_KERNEL));
 
        asm(    "mcrr   p15, 0, %1, %0, c14\n"
        "       mcr     p15, 0, %2, c7, c10, 4"
@@ -41,13 +38,12 @@ static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
 
 static void flush_icache_alias(unsigned long pfn, unsigned long vaddr, unsigned long len)
 {
-       unsigned long colour = CACHE_COLOUR(vaddr);
+       unsigned long va = FLUSH_ALIAS_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT);
        unsigned long offset = vaddr & (PAGE_SIZE - 1);
        unsigned long to;
 
-       set_pte_ext(TOP_PTE(ALIAS_FLUSH_START) + colour, pfn_pte(pfn, PAGE_KERNEL), 0);
-       to = ALIAS_FLUSH_START + (colour << PAGE_SHIFT) + offset;
-       flush_tlb_kernel_page(to);
+       set_top_pte(va, pfn_pte(pfn, PAGE_KERNEL));
+       to = va + offset;
        flush_icache_range(to, to + len);
 }
 
index 5a21505d75508fd80a495a9a31945c108a489b99..21b9e1bf9b7714106b13ea7a3f3606875fb25ae3 100644 (file)
@@ -69,15 +69,14 @@ void *kmap_atomic(struct page *page)
         * With debugging enabled, kunmap_atomic forces that entry to 0.
         * Make sure it was indeed properly unmapped.
         */
-       BUG_ON(!pte_none(*(TOP_PTE(vaddr))));
+       BUG_ON(!pte_none(get_top_pte(vaddr)));
 #endif
-       set_pte_ext(TOP_PTE(vaddr), mk_pte(page, kmap_prot), 0);
        /*
         * When debugging is off, kunmap_atomic leaves the previous mapping
-        * in place, so this TLB flush ensures the TLB is updated with the
-        * new mapping.
+        * in place, so the contained TLB flush ensures the TLB is updated
+        * with the new mapping.
         */
-       local_flush_tlb_kernel_page(vaddr);
+       set_top_pte(vaddr, mk_pte(page, kmap_prot));
 
        return (void *)vaddr;
 }
@@ -96,8 +95,7 @@ void __kunmap_atomic(void *kvaddr)
                        __cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE);
 #ifdef CONFIG_DEBUG_HIGHMEM
                BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
-               set_pte_ext(TOP_PTE(vaddr), __pte(0), 0);
-               local_flush_tlb_kernel_page(vaddr);
+               set_top_pte(vaddr, __pte(0));
 #else
                (void) idx;  /* to kill a warning */
 #endif
@@ -121,10 +119,9 @@ void *kmap_atomic_pfn(unsigned long pfn)
        idx = type + KM_TYPE_NR * smp_processor_id();
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 #ifdef CONFIG_DEBUG_HIGHMEM
-       BUG_ON(!pte_none(*(TOP_PTE(vaddr))));
+       BUG_ON(!pte_none(get_top_pte(vaddr)));
 #endif
-       set_pte_ext(TOP_PTE(vaddr), pfn_pte(pfn, kmap_prot), 0);
-       local_flush_tlb_kernel_page(vaddr);
+       set_top_pte(vaddr, pfn_pte(pfn, kmap_prot));
 
        return (void *)vaddr;
 }
@@ -132,11 +129,9 @@ void *kmap_atomic_pfn(unsigned long pfn)
 struct page *kmap_atomic_to_page(const void *ptr)
 {
        unsigned long vaddr = (unsigned long)ptr;
-       pte_t *pte;
 
        if (vaddr < FIXADDR_START)
                return virt_to_page(ptr);
 
-       pte = TOP_PTE(vaddr);
-       return pte_page(*pte);
+       return pte_page(get_top_pte(vaddr));
 }
index 245a55a0a5bbcd0db13beda940b16533533d1b61..595079fa9d1d2eb342afae05f3b29a4395b87331 100644 (file)
@@ -658,7 +658,9 @@ void __init mem_init(void)
 #ifdef CONFIG_HIGHMEM
                        "    pkmap   : 0x%08lx - 0x%08lx   (%4ld MB)\n"
 #endif
+#ifdef CONFIG_MODULES
                        "    modules : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+#endif
                        "      .text : 0x%p" " - 0x%p" "   (%4d kB)\n"
                        "      .init : 0x%p" " - 0x%p" "   (%4d kB)\n"
                        "      .data : 0x%p" " - 0x%p" "   (%4d kB)\n"
@@ -677,7 +679,9 @@ void __init mem_init(void)
                        MLM(PKMAP_BASE, (PKMAP_BASE) + (LAST_PKMAP) *
                                (PAGE_SIZE)),
 #endif
+#ifdef CONFIG_MODULES
                        MLM(MODULES_VADDR, MODULES_END),
+#endif
 
                        MLK_ROUNDUP(_text, _etext),
                        MLK_ROUNDUP(__init_begin, __init_end),
index 70f6d3ea48340fb7d8ac2aa6d8e9046a467117c8..27f4a619b35d1c0039d7883c7804994c0540cdc6 100644 (file)
@@ -3,7 +3,31 @@
 /* the upper-most page table pointer */
 extern pmd_t *top_pmd;
 
-#define TOP_PTE(x)     pte_offset_kernel(top_pmd, x)
+/*
+ * 0xffff8000 to 0xffffffff is reserved for any ARM architecture
+ * specific hacks for copying pages efficiently, while 0xffff4000
+ * is reserved for VIPT aliasing flushing by generic code.
+ *
+ * Note that we don't allow VIPT aliasing caches with SMP.
+ */
+#define COPYPAGE_MINICACHE     0xffff8000
+#define COPYPAGE_V6_FROM       0xffff8000
+#define COPYPAGE_V6_TO         0xffffc000
+/* PFN alias flushing, for VIPT caches */
+#define FLUSH_ALIAS_START      0xffff4000
+
+static inline void set_top_pte(unsigned long va, pte_t pte)
+{
+       pte_t *ptep = pte_offset_kernel(top_pmd, va);
+       set_pte_ext(ptep, pte, 0);
+       local_flush_tlb_kernel_page(va);
+}
+
+static inline pte_t get_top_pte(unsigned long va)
+{
+       pte_t *ptep = pte_offset_kernel(top_pmd, va);
+       return *ptep;
+}
 
 static inline pmd_t *pmd_off_k(unsigned long virt)
 {
index cd439c1dd506d101421dde5d970e2fb11a6d127f..b86f8933ff918908e107afe40553388e0e207988 100644 (file)
@@ -999,11 +999,14 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
 {
        struct map_desc map;
        unsigned long addr;
+       void *vectors;
 
        /*
         * Allocate the vector page early.
         */
-       vectors_page = early_alloc(PAGE_SIZE);
+       vectors = early_alloc(PAGE_SIZE);
+
+       early_trap_init(vectors);
 
        for (addr = VMALLOC_START; addr; addr += PMD_SIZE)
                pmd_clear(pmd_off_k(addr));
@@ -1043,7 +1046,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
         * location (0xffff0000).  If we aren't using high-vectors, also
         * create a mapping at the low-vectors virtual address.
         */
-       map.pfn = __phys_to_pfn(virt_to_phys(vectors_page));
+       map.pfn = __phys_to_pfn(virt_to_phys(vectors));
        map.virtual = 0xffff0000;
        map.length = PAGE_SIZE;
        map.type = MT_HIGH_VECTORS;
index 036fdbfdd62f6e91e0c329c7c12a9152dca21d7b..a631016e1f8f6927961b12fc8377d32d7ea1662a 100644 (file)
@@ -1,5 +1,8 @@
+#include <linux/fs.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/slab.h>
 
 #include "vmregion.h"
@@ -36,7 +39,7 @@
 
 struct arm_vmregion *
 arm_vmregion_alloc(struct arm_vmregion_head *head, size_t align,
-                  size_t size, gfp_t gfp)
+                  size_t size, gfp_t gfp, const void *caller)
 {
        unsigned long start = head->vm_start, addr = head->vm_end;
        unsigned long flags;
@@ -52,6 +55,8 @@ arm_vmregion_alloc(struct arm_vmregion_head *head, size_t align,
        if (!new)
                goto out;
 
+       new->caller = caller;
+
        spin_lock_irqsave(&head->vm_lock, flags);
 
        addr = rounddown(addr - size, align);
@@ -129,3 +134,72 @@ void arm_vmregion_free(struct arm_vmregion_head *head, struct arm_vmregion *c)
 
        kfree(c);
 }
+
+#ifdef CONFIG_PROC_FS
+static int arm_vmregion_show(struct seq_file *m, void *p)
+{
+       struct arm_vmregion *c = list_entry(p, struct arm_vmregion, vm_list);
+
+       seq_printf(m, "0x%08lx-0x%08lx %7lu", c->vm_start, c->vm_end,
+               c->vm_end - c->vm_start);
+       if (c->caller)
+               seq_printf(m, " %pS", (void *)c->caller);
+       seq_putc(m, '\n');
+       return 0;
+}
+
+static void *arm_vmregion_start(struct seq_file *m, loff_t *pos)
+{
+       struct arm_vmregion_head *h = m->private;
+       spin_lock_irq(&h->vm_lock);
+       return seq_list_start(&h->vm_list, *pos);
+}
+
+static void *arm_vmregion_next(struct seq_file *m, void *p, loff_t *pos)
+{
+       struct arm_vmregion_head *h = m->private;
+       return seq_list_next(p, &h->vm_list, pos);
+}
+
+static void arm_vmregion_stop(struct seq_file *m, void *p)
+{
+       struct arm_vmregion_head *h = m->private;
+       spin_unlock_irq(&h->vm_lock);
+}
+
+static const struct seq_operations arm_vmregion_ops = {
+       .start  = arm_vmregion_start,
+       .stop   = arm_vmregion_stop,
+       .next   = arm_vmregion_next,
+       .show   = arm_vmregion_show,
+};
+
+static int arm_vmregion_open(struct inode *inode, struct file *file)
+{
+       struct arm_vmregion_head *h = PDE(inode)->data;
+       int ret = seq_open(file, &arm_vmregion_ops);
+       if (!ret) {
+               struct seq_file *m = file->private_data;
+               m->private = h;
+       }
+       return ret;
+}
+
+static const struct file_operations arm_vmregion_fops = {
+       .open   = arm_vmregion_open,
+       .read   = seq_read,
+       .llseek = seq_lseek,
+       .release = seq_release,
+};
+
+int arm_vmregion_create_proc(const char *path, struct arm_vmregion_head *h)
+{
+       proc_create_data(path, S_IRUSR, NULL, &arm_vmregion_fops, h);
+       return 0;
+}
+#else
+int arm_vmregion_create_proc(const char *path, struct arm_vmregion_head *h)
+{
+       return 0;
+}
+#endif
index 15e9f044db9feab45a25d79eed9e1f0dce5a2a1a..162be662c0888c87b492bd2e13a8b51d1e2288e7 100644 (file)
@@ -19,11 +19,14 @@ struct arm_vmregion {
        unsigned long           vm_end;
        struct page             *vm_pages;
        int                     vm_active;
+       const void              *caller;
 };
 
-struct arm_vmregion *arm_vmregion_alloc(struct arm_vmregion_head *, size_t, size_t, gfp_t);
+struct arm_vmregion *arm_vmregion_alloc(struct arm_vmregion_head *, size_t, size_t, gfp_t, const void *);
 struct arm_vmregion *arm_vmregion_find(struct arm_vmregion_head *, unsigned long);
 struct arm_vmregion *arm_vmregion_find_remove(struct arm_vmregion_head *, unsigned long);
 void arm_vmregion_free(struct arm_vmregion_head *, struct arm_vmregion *);
 
+int arm_vmregion_create_proc(const char *, struct arm_vmregion_head *);
+
 #endif
diff --git a/arch/arm/net/Makefile b/arch/arm/net/Makefile
new file mode 100644 (file)
index 0000000..c2c1084
--- /dev/null
@@ -0,0 +1,3 @@
+# ARM-specific networking code
+
+obj-$(CONFIG_BPF_JIT) += bpf_jit_32.o
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
new file mode 100644 (file)
index 0000000..6213584
--- /dev/null
@@ -0,0 +1,915 @@
+/*
+ * Just-In-Time compiler for BPF filters on 32bit ARM
+ *
+ * Copyright (c) 2011 Mircea Gherzan <mgherzan@gmail.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; version 2 of the License.
+ */
+
+#include <linux/bitops.h>
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/filter.h>
+#include <linux/moduleloader.h>
+#include <linux/netdevice.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <asm/cacheflush.h>
+#include <asm/hwcap.h>
+
+#include "bpf_jit_32.h"
+
+/*
+ * ABI:
+ *
+ * r0  scratch register
+ * r4  BPF register A
+ * r5  BPF register X
+ * r6  pointer to the skb
+ * r7  skb->data
+ * r8  skb_headlen(skb)
+ */
+
+#define r_scratch      ARM_R0
+/* r1-r3 are (also) used for the unaligned loads on the non-ARMv7 slowpath */
+#define r_off          ARM_R1
+#define r_A            ARM_R4
+#define r_X            ARM_R5
+#define r_skb          ARM_R6
+#define r_skb_data     ARM_R7
+#define r_skb_hl       ARM_R8
+
+#define SCRATCH_SP_OFFSET      0
+#define SCRATCH_OFF(k)         (SCRATCH_SP_OFFSET + (k))
+
+#define SEEN_MEM               ((1 << BPF_MEMWORDS) - 1)
+#define SEEN_MEM_WORD(k)       (1 << (k))
+#define SEEN_X                 (1 << BPF_MEMWORDS)
+#define SEEN_CALL              (1 << (BPF_MEMWORDS + 1))
+#define SEEN_SKB               (1 << (BPF_MEMWORDS + 2))
+#define SEEN_DATA              (1 << (BPF_MEMWORDS + 3))
+
+#define FLAG_NEED_X_RESET      (1 << 0)
+
+struct jit_ctx {
+       const struct sk_filter *skf;
+       unsigned idx;
+       unsigned prologue_bytes;
+       int ret0_fp_idx;
+       u32 seen;
+       u32 flags;
+       u32 *offsets;
+       u32 *target;
+#if __LINUX_ARM_ARCH__ < 7
+       u16 epilogue_bytes;
+       u16 imm_count;
+       u32 *imms;
+#endif
+};
+
+int bpf_jit_enable __read_mostly;
+
+static u64 jit_get_skb_b(struct sk_buff *skb, unsigned offset)
+{
+       u8 ret;
+       int err;
+
+       err = skb_copy_bits(skb, offset, &ret, 1);
+
+       return (u64)err << 32 | ret;
+}
+
+static u64 jit_get_skb_h(struct sk_buff *skb, unsigned offset)
+{
+       u16 ret;
+       int err;
+
+       err = skb_copy_bits(skb, offset, &ret, 2);
+
+       return (u64)err << 32 | ntohs(ret);
+}
+
+static u64 jit_get_skb_w(struct sk_buff *skb, unsigned offset)
+{
+       u32 ret;
+       int err;
+
+       err = skb_copy_bits(skb, offset, &ret, 4);
+
+       return (u64)err << 32 | ntohl(ret);
+}
+
+/*
+ * Wrapper that handles both OABI and EABI and assures Thumb2 interworking
+ * (where the assembly routines like __aeabi_uidiv could cause problems).
+ */
+static u32 jit_udiv(u32 dividend, u32 divisor)
+{
+       return dividend / divisor;
+}
+
+static inline void _emit(int cond, u32 inst, struct jit_ctx *ctx)
+{
+       if (ctx->target != NULL)
+               ctx->target[ctx->idx] = inst | (cond << 28);
+
+       ctx->idx++;
+}
+
+/*
+ * Emit an instruction that will be executed unconditionally.
+ */
+static inline void emit(u32 inst, struct jit_ctx *ctx)
+{
+       _emit(ARM_COND_AL, inst, ctx);
+}
+
+static u16 saved_regs(struct jit_ctx *ctx)
+{
+       u16 ret = 0;
+
+       if ((ctx->skf->len > 1) ||
+           (ctx->skf->insns[0].code == BPF_S_RET_A))
+               ret |= 1 << r_A;
+
+#ifdef CONFIG_FRAME_POINTER
+       ret |= (1 << ARM_FP) | (1 << ARM_IP) | (1 << ARM_LR) | (1 << ARM_PC);
+#else
+       if (ctx->seen & SEEN_CALL)
+               ret |= 1 << ARM_LR;
+#endif
+       if (ctx->seen & (SEEN_DATA | SEEN_SKB))
+               ret |= 1 << r_skb;
+       if (ctx->seen & SEEN_DATA)
+               ret |= (1 << r_skb_data) | (1 << r_skb_hl);
+       if (ctx->seen & SEEN_X)
+               ret |= 1 << r_X;
+
+       return ret;
+}
+
+static inline int mem_words_used(struct jit_ctx *ctx)
+{
+       /* yes, we do waste some stack space IF there are "holes" in the set" */
+       return fls(ctx->seen & SEEN_MEM);
+}
+
+static inline bool is_load_to_a(u16 inst)
+{
+       switch (inst) {
+       case BPF_S_LD_W_LEN:
+       case BPF_S_LD_W_ABS:
+       case BPF_S_LD_H_ABS:
+       case BPF_S_LD_B_ABS:
+       case BPF_S_ANC_CPU:
+       case BPF_S_ANC_IFINDEX:
+       case BPF_S_ANC_MARK:
+       case BPF_S_ANC_PROTOCOL:
+       case BPF_S_ANC_RXHASH:
+       case BPF_S_ANC_QUEUE:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static void build_prologue(struct jit_ctx *ctx)
+{
+       u16 reg_set = saved_regs(ctx);
+       u16 first_inst = ctx->skf->insns[0].code;
+       u16 off;
+
+#ifdef CONFIG_FRAME_POINTER
+       emit(ARM_MOV_R(ARM_IP, ARM_SP), ctx);
+       emit(ARM_PUSH(reg_set), ctx);
+       emit(ARM_SUB_I(ARM_FP, ARM_IP, 4), ctx);
+#else
+       if (reg_set)
+               emit(ARM_PUSH(reg_set), ctx);
+#endif
+
+       if (ctx->seen & (SEEN_DATA | SEEN_SKB))
+               emit(ARM_MOV_R(r_skb, ARM_R0), ctx);
+
+       if (ctx->seen & SEEN_DATA) {
+               off = offsetof(struct sk_buff, data);
+               emit(ARM_LDR_I(r_skb_data, r_skb, off), ctx);
+               /* headlen = len - data_len */
+               off = offsetof(struct sk_buff, len);
+               emit(ARM_LDR_I(r_skb_hl, r_skb, off), ctx);
+               off = offsetof(struct sk_buff, data_len);
+               emit(ARM_LDR_I(r_scratch, r_skb, off), ctx);
+               emit(ARM_SUB_R(r_skb_hl, r_skb_hl, r_scratch), ctx);
+       }
+
+       if (ctx->flags & FLAG_NEED_X_RESET)
+               emit(ARM_MOV_I(r_X, 0), ctx);
+
+       /* do not leak kernel data to userspace */
+       if ((first_inst != BPF_S_RET_K) && !(is_load_to_a(first_inst)))
+               emit(ARM_MOV_I(r_A, 0), ctx);
+
+       /* stack space for the BPF_MEM words */
+       if (ctx->seen & SEEN_MEM)
+               emit(ARM_SUB_I(ARM_SP, ARM_SP, mem_words_used(ctx) * 4), ctx);
+}
+
+static void build_epilogue(struct jit_ctx *ctx)
+{
+       u16 reg_set = saved_regs(ctx);
+
+       if (ctx->seen & SEEN_MEM)
+               emit(ARM_ADD_I(ARM_SP, ARM_SP, mem_words_used(ctx) * 4), ctx);
+
+       reg_set &= ~(1 << ARM_LR);
+
+#ifdef CONFIG_FRAME_POINTER
+       /* the first instruction of the prologue was: mov ip, sp */
+       reg_set &= ~(1 << ARM_IP);
+       reg_set |= (1 << ARM_SP);
+       emit(ARM_LDM(ARM_SP, reg_set), ctx);
+#else
+       if (reg_set) {
+               if (ctx->seen & SEEN_CALL)
+                       reg_set |= 1 << ARM_PC;
+               emit(ARM_POP(reg_set), ctx);
+       }
+
+       if (!(ctx->seen & SEEN_CALL))
+               emit(ARM_BX(ARM_LR), ctx);
+#endif
+}
+
+static int16_t imm8m(u32 x)
+{
+       u32 rot;
+
+       for (rot = 0; rot < 16; rot++)
+               if ((x & ~ror32(0xff, 2 * rot)) == 0)
+                       return rol32(x, 2 * rot) | (rot << 8);
+
+       return -1;
+}
+
+#if __LINUX_ARM_ARCH__ < 7
+
+static u16 imm_offset(u32 k, struct jit_ctx *ctx)
+{
+       unsigned i = 0, offset;
+       u16 imm;
+
+       /* on the "fake" run we just count them (duplicates included) */
+       if (ctx->target == NULL) {
+               ctx->imm_count++;
+               return 0;
+       }
+
+       while ((i < ctx->imm_count) && ctx->imms[i]) {
+               if (ctx->imms[i] == k)
+                       break;
+               i++;
+       }
+
+       if (ctx->imms[i] == 0)
+               ctx->imms[i] = k;
+
+       /* constants go just after the epilogue */
+       offset =  ctx->offsets[ctx->skf->len];
+       offset += ctx->prologue_bytes;
+       offset += ctx->epilogue_bytes;
+       offset += i * 4;
+
+       ctx->target[offset / 4] = k;
+
+       /* PC in ARM mode == address of the instruction + 8 */
+       imm = offset - (8 + ctx->idx * 4);
+
+       return imm;
+}
+
+#endif /* __LINUX_ARM_ARCH__ */
+
+/*
+ * Move an immediate that's not an imm8m to a core register.
+ */
+static inline void emit_mov_i_no8m(int rd, u32 val, struct jit_ctx *ctx)
+{
+#if __LINUX_ARM_ARCH__ < 7
+       emit(ARM_LDR_I(rd, ARM_PC, imm_offset(val, ctx)), ctx);
+#else
+       emit(ARM_MOVW(rd, val & 0xffff), ctx);
+       if (val > 0xffff)
+               emit(ARM_MOVT(rd, val >> 16), ctx);
+#endif
+}
+
+static inline void emit_mov_i(int rd, u32 val, struct jit_ctx *ctx)
+{
+       int imm12 = imm8m(val);
+
+       if (imm12 >= 0)
+               emit(ARM_MOV_I(rd, imm12), ctx);
+       else
+               emit_mov_i_no8m(rd, val, ctx);
+}
+
+#if __LINUX_ARM_ARCH__ < 6
+
+static void emit_load_be32(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx)
+{
+       _emit(cond, ARM_LDRB_I(ARM_R3, r_addr, 1), ctx);
+       _emit(cond, ARM_LDRB_I(ARM_R1, r_addr, 0), ctx);
+       _emit(cond, ARM_LDRB_I(ARM_R2, r_addr, 3), ctx);
+       _emit(cond, ARM_LSL_I(ARM_R3, ARM_R3, 16), ctx);
+       _emit(cond, ARM_LDRB_I(ARM_R0, r_addr, 2), ctx);
+       _emit(cond, ARM_ORR_S(ARM_R3, ARM_R3, ARM_R1, SRTYPE_LSL, 24), ctx);
+       _emit(cond, ARM_ORR_R(ARM_R3, ARM_R3, ARM_R2), ctx);
+       _emit(cond, ARM_ORR_S(r_res, ARM_R3, ARM_R0, SRTYPE_LSL, 8), ctx);
+}
+
+static void emit_load_be16(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx)
+{
+       _emit(cond, ARM_LDRB_I(ARM_R1, r_addr, 0), ctx);
+       _emit(cond, ARM_LDRB_I(ARM_R2, r_addr, 1), ctx);
+       _emit(cond, ARM_ORR_S(r_res, ARM_R2, ARM_R1, SRTYPE_LSL, 8), ctx);
+}
+
+static inline void emit_swap16(u8 r_dst, u8 r_src, struct jit_ctx *ctx)
+{
+       emit(ARM_LSL_R(ARM_R1, r_src, 8), ctx);
+       emit(ARM_ORR_S(r_dst, ARM_R1, r_src, SRTYPE_LSL, 8), ctx);
+       emit(ARM_LSL_I(r_dst, r_dst, 8), ctx);
+       emit(ARM_LSL_R(r_dst, r_dst, 8), ctx);
+}
+
+#else  /* ARMv6+ */
+
+static void emit_load_be32(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx)
+{
+       _emit(cond, ARM_LDR_I(r_res, r_addr, 0), ctx);
+#ifdef __LITTLE_ENDIAN
+       _emit(cond, ARM_REV(r_res, r_res), ctx);
+#endif
+}
+
+static void emit_load_be16(u8 cond, u8 r_res, u8 r_addr, struct jit_ctx *ctx)
+{
+       _emit(cond, ARM_LDRH_I(r_res, r_addr, 0), ctx);
+#ifdef __LITTLE_ENDIAN
+       _emit(cond, ARM_REV16(r_res, r_res), ctx);
+#endif
+}
+
+static inline void emit_swap16(u8 r_dst __maybe_unused,
+                              u8 r_src __maybe_unused,
+                              struct jit_ctx *ctx __maybe_unused)
+{
+#ifdef __LITTLE_ENDIAN
+       emit(ARM_REV16(r_dst, r_src), ctx);
+#endif
+}
+
+#endif /* __LINUX_ARM_ARCH__ < 6 */
+
+
+/* Compute the immediate value for a PC-relative branch. */
+static inline u32 b_imm(unsigned tgt, struct jit_ctx *ctx)
+{
+       u32 imm;
+
+       if (ctx->target == NULL)
+               return 0;
+       /*
+        * BPF allows only forward jumps and the offset of the target is
+        * still the one computed during the first pass.
+        */
+       imm  = ctx->offsets[tgt] + ctx->prologue_bytes - (ctx->idx * 4 + 8);
+
+       return imm >> 2;
+}
+
+#define OP_IMM3(op, r1, r2, imm_val, ctx)                              \
+       do {                                                            \
+               imm12 = imm8m(imm_val);                                 \
+               if (imm12 < 0) {                                        \
+                       emit_mov_i_no8m(r_scratch, imm_val, ctx);       \
+                       emit(op ## _R((r1), (r2), r_scratch), ctx);     \
+               } else {                                                \
+                       emit(op ## _I((r1), (r2), imm12), ctx);         \
+               }                                                       \
+       } while (0)
+
+static inline void emit_err_ret(u8 cond, struct jit_ctx *ctx)
+{
+       if (ctx->ret0_fp_idx >= 0) {
+               _emit(cond, ARM_B(b_imm(ctx->ret0_fp_idx, ctx)), ctx);
+               /* NOP to keep the size constant between passes */
+               emit(ARM_MOV_R(ARM_R0, ARM_R0), ctx);
+       } else {
+               _emit(cond, ARM_MOV_I(ARM_R0, 0), ctx);
+               _emit(cond, ARM_B(b_imm(ctx->skf->len, ctx)), ctx);
+       }
+}
+
+static inline void emit_blx_r(u8 tgt_reg, struct jit_ctx *ctx)
+{
+#if __LINUX_ARM_ARCH__ < 5
+       emit(ARM_MOV_R(ARM_LR, ARM_PC), ctx);
+
+       if (elf_hwcap & HWCAP_THUMB)
+               emit(ARM_BX(tgt_reg), ctx);
+       else
+               emit(ARM_MOV_R(ARM_PC, tgt_reg), ctx);
+#else
+       emit(ARM_BLX_R(tgt_reg), ctx);
+#endif
+}
+
+static inline void emit_udiv(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx)
+{
+#if __LINUX_ARM_ARCH__ == 7
+       if (elf_hwcap & HWCAP_IDIVA) {
+               emit(ARM_UDIV(rd, rm, rn), ctx);
+               return;
+       }
+#endif
+       if (rm != ARM_R0)
+               emit(ARM_MOV_R(ARM_R0, rm), ctx);
+       if (rn != ARM_R1)
+               emit(ARM_MOV_R(ARM_R1, rn), ctx);
+
+       ctx->seen |= SEEN_CALL;
+       emit_mov_i(ARM_R3, (u32)jit_udiv, ctx);
+       emit_blx_r(ARM_R3, ctx);
+
+       if (rd != ARM_R0)
+               emit(ARM_MOV_R(rd, ARM_R0), ctx);
+}
+
+static inline void update_on_xread(struct jit_ctx *ctx)
+{
+       if (!(ctx->seen & SEEN_X))
+               ctx->flags |= FLAG_NEED_X_RESET;
+
+       ctx->seen |= SEEN_X;
+}
+
+static int build_body(struct jit_ctx *ctx)
+{
+       void *load_func[] = {jit_get_skb_b, jit_get_skb_h, jit_get_skb_w};
+       const struct sk_filter *prog = ctx->skf;
+       const struct sock_filter *inst;
+       unsigned i, load_order, off, condt;
+       int imm12;
+       u32 k;
+
+       for (i = 0; i < prog->len; i++) {
+               inst = &(prog->insns[i]);
+               /* K as an immediate value operand */
+               k = inst->k;
+
+               /* compute offsets only in the fake pass */
+               if (ctx->target == NULL)
+                       ctx->offsets[i] = ctx->idx * 4;
+
+               switch (inst->code) {
+               case BPF_S_LD_IMM:
+                       emit_mov_i(r_A, k, ctx);
+                       break;
+               case BPF_S_LD_W_LEN:
+                       ctx->seen |= SEEN_SKB;
+                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, len) != 4);
+                       emit(ARM_LDR_I(r_A, r_skb,
+                                      offsetof(struct sk_buff, len)), ctx);
+                       break;
+               case BPF_S_LD_MEM:
+                       /* A = scratch[k] */
+                       ctx->seen |= SEEN_MEM_WORD(k);
+                       emit(ARM_LDR_I(r_A, ARM_SP, SCRATCH_OFF(k)), ctx);
+                       break;
+               case BPF_S_LD_W_ABS:
+                       load_order = 2;
+                       goto load;
+               case BPF_S_LD_H_ABS:
+                       load_order = 1;
+                       goto load;
+               case BPF_S_LD_B_ABS:
+                       load_order = 0;
+load:
+                       /* the interpreter will deal with the negative K */
+                       if ((int)k < 0)
+                               return -ENOTSUPP;
+                       emit_mov_i(r_off, k, ctx);
+load_common:
+                       ctx->seen |= SEEN_DATA | SEEN_CALL;
+
+                       if (load_order > 0) {
+                               emit(ARM_SUB_I(r_scratch, r_skb_hl,
+                                              1 << load_order), ctx);
+                               emit(ARM_CMP_R(r_scratch, r_off), ctx);
+                               condt = ARM_COND_HS;
+                       } else {
+                               emit(ARM_CMP_R(r_skb_hl, r_off), ctx);
+                               condt = ARM_COND_HI;
+                       }
+
+                       _emit(condt, ARM_ADD_R(r_scratch, r_off, r_skb_data),
+                             ctx);
+
+                       if (load_order == 0)
+                               _emit(condt, ARM_LDRB_I(r_A, r_scratch, 0),
+                                     ctx);
+                       else if (load_order == 1)
+                               emit_load_be16(condt, r_A, r_scratch, ctx);
+                       else if (load_order == 2)
+                               emit_load_be32(condt, r_A, r_scratch, ctx);
+
+                       _emit(condt, ARM_B(b_imm(i + 1, ctx)), ctx);
+
+                       /* the slowpath */
+                       emit_mov_i(ARM_R3, (u32)load_func[load_order], ctx);
+                       emit(ARM_MOV_R(ARM_R0, r_skb), ctx);
+                       /* the offset is already in R1 */
+                       emit_blx_r(ARM_R3, ctx);
+                       /* check the result of skb_copy_bits */
+                       emit(ARM_CMP_I(ARM_R1, 0), ctx);
+                       emit_err_ret(ARM_COND_NE, ctx);
+                       emit(ARM_MOV_R(r_A, ARM_R0), ctx);
+                       break;
+               case BPF_S_LD_W_IND:
+                       load_order = 2;
+                       goto load_ind;
+               case BPF_S_LD_H_IND:
+                       load_order = 1;
+                       goto load_ind;
+               case BPF_S_LD_B_IND:
+                       load_order = 0;
+load_ind:
+                       OP_IMM3(ARM_ADD, r_off, r_X, k, ctx);
+                       goto load_common;
+               case BPF_S_LDX_IMM:
+                       ctx->seen |= SEEN_X;
+                       emit_mov_i(r_X, k, ctx);
+                       break;
+               case BPF_S_LDX_W_LEN:
+                       ctx->seen |= SEEN_X | SEEN_SKB;
+                       emit(ARM_LDR_I(r_X, r_skb,
+                                      offsetof(struct sk_buff, len)), ctx);
+                       break;
+               case BPF_S_LDX_MEM:
+                       ctx->seen |= SEEN_X | SEEN_MEM_WORD(k);
+                       emit(ARM_LDR_I(r_X, ARM_SP, SCRATCH_OFF(k)), ctx);
+                       break;
+               case BPF_S_LDX_B_MSH:
+                       /* x = ((*(frame + k)) & 0xf) << 2; */
+                       ctx->seen |= SEEN_X | SEEN_DATA | SEEN_CALL;
+                       /* the interpreter should deal with the negative K */
+                       if (k < 0)
+                               return -1;
+                       /* offset in r1: we might have to take the slow path */
+                       emit_mov_i(r_off, k, ctx);
+                       emit(ARM_CMP_R(r_skb_hl, r_off), ctx);
+
+                       /* load in r0: common with the slowpath */
+                       _emit(ARM_COND_HI, ARM_LDRB_R(ARM_R0, r_skb_data,
+                                                     ARM_R1), ctx);
+                       /*
+                        * emit_mov_i() might generate one or two instructions,
+                        * the same holds for emit_blx_r()
+                        */
+                       _emit(ARM_COND_HI, ARM_B(b_imm(i + 1, ctx) - 2), ctx);
+
+                       emit(ARM_MOV_R(ARM_R0, r_skb), ctx);
+                       /* r_off is r1 */
+                       emit_mov_i(ARM_R3, (u32)jit_get_skb_b, ctx);
+                       emit_blx_r(ARM_R3, ctx);
+                       /* check the return value of skb_copy_bits */
+                       emit(ARM_CMP_I(ARM_R1, 0), ctx);
+                       emit_err_ret(ARM_COND_NE, ctx);
+
+                       emit(ARM_AND_I(r_X, ARM_R0, 0x00f), ctx);
+                       emit(ARM_LSL_I(r_X, r_X, 2), ctx);
+                       break;
+               case BPF_S_ST:
+                       ctx->seen |= SEEN_MEM_WORD(k);
+                       emit(ARM_STR_I(r_A, ARM_SP, SCRATCH_OFF(k)), ctx);
+                       break;
+               case BPF_S_STX:
+                       update_on_xread(ctx);
+                       ctx->seen |= SEEN_MEM_WORD(k);
+                       emit(ARM_STR_I(r_X, ARM_SP, SCRATCH_OFF(k)), ctx);
+                       break;
+               case BPF_S_ALU_ADD_K:
+                       /* A += K */
+                       OP_IMM3(ARM_ADD, r_A, r_A, k, ctx);
+                       break;
+               case BPF_S_ALU_ADD_X:
+                       update_on_xread(ctx);
+                       emit(ARM_ADD_R(r_A, r_A, r_X), ctx);
+                       break;
+               case BPF_S_ALU_SUB_K:
+                       /* A -= K */
+                       OP_IMM3(ARM_SUB, r_A, r_A, k, ctx);
+                       break;
+               case BPF_S_ALU_SUB_X:
+                       update_on_xread(ctx);
+                       emit(ARM_SUB_R(r_A, r_A, r_X), ctx);
+                       break;
+               case BPF_S_ALU_MUL_K:
+                       /* A *= K */
+                       emit_mov_i(r_scratch, k, ctx);
+                       emit(ARM_MUL(r_A, r_A, r_scratch), ctx);
+                       break;
+               case BPF_S_ALU_MUL_X:
+                       update_on_xread(ctx);
+                       emit(ARM_MUL(r_A, r_A, r_X), ctx);
+                       break;
+               case BPF_S_ALU_DIV_K:
+                       /* current k == reciprocal_value(userspace k) */
+                       emit_mov_i(r_scratch, k, ctx);
+                       /* A = top 32 bits of the product */
+                       emit(ARM_UMULL(r_scratch, r_A, r_A, r_scratch), ctx);
+                       break;
+               case BPF_S_ALU_DIV_X:
+                       update_on_xread(ctx);
+                       emit(ARM_CMP_I(r_X, 0), ctx);
+                       emit_err_ret(ARM_COND_EQ, ctx);
+                       emit_udiv(r_A, r_A, r_X, ctx);
+                       break;
+               case BPF_S_ALU_OR_K:
+                       /* A |= K */
+                       OP_IMM3(ARM_ORR, r_A, r_A, k, ctx);
+                       break;
+               case BPF_S_ALU_OR_X:
+                       update_on_xread(ctx);
+                       emit(ARM_ORR_R(r_A, r_A, r_X), ctx);
+                       break;
+               case BPF_S_ALU_AND_K:
+                       /* A &= K */
+                       OP_IMM3(ARM_AND, r_A, r_A, k, ctx);
+                       break;
+               case BPF_S_ALU_AND_X:
+                       update_on_xread(ctx);
+                       emit(ARM_AND_R(r_A, r_A, r_X), ctx);
+                       break;
+               case BPF_S_ALU_LSH_K:
+                       if (unlikely(k > 31))
+                               return -1;
+                       emit(ARM_LSL_I(r_A, r_A, k), ctx);
+                       break;
+               case BPF_S_ALU_LSH_X:
+                       update_on_xread(ctx);
+                       emit(ARM_LSL_R(r_A, r_A, r_X), ctx);
+                       break;
+               case BPF_S_ALU_RSH_K:
+                       if (unlikely(k > 31))
+                               return -1;
+                       emit(ARM_LSR_I(r_A, r_A, k), ctx);
+                       break;
+               case BPF_S_ALU_RSH_X:
+                       update_on_xread(ctx);
+                       emit(ARM_LSR_R(r_A, r_A, r_X), ctx);
+                       break;
+               case BPF_S_ALU_NEG:
+                       /* A = -A */
+                       emit(ARM_RSB_I(r_A, r_A, 0), ctx);
+                       break;
+               case BPF_S_JMP_JA:
+                       /* pc += K */
+                       emit(ARM_B(b_imm(i + k + 1, ctx)), ctx);
+                       break;
+               case BPF_S_JMP_JEQ_K:
+                       /* pc += (A == K) ? pc->jt : pc->jf */
+                       condt  = ARM_COND_EQ;
+                       goto cmp_imm;
+               case BPF_S_JMP_JGT_K:
+                       /* pc += (A > K) ? pc->jt : pc->jf */
+                       condt  = ARM_COND_HI;
+                       goto cmp_imm;
+               case BPF_S_JMP_JGE_K:
+                       /* pc += (A >= K) ? pc->jt : pc->jf */
+                       condt  = ARM_COND_HS;
+cmp_imm:
+                       imm12 = imm8m(k);
+                       if (imm12 < 0) {
+                               emit_mov_i_no8m(r_scratch, k, ctx);
+                               emit(ARM_CMP_R(r_A, r_scratch), ctx);
+                       } else {
+                               emit(ARM_CMP_I(r_A, imm12), ctx);
+                       }
+cond_jump:
+                       if (inst->jt)
+                               _emit(condt, ARM_B(b_imm(i + inst->jt + 1,
+                                                  ctx)), ctx);
+                       if (inst->jf)
+                               _emit(condt ^ 1, ARM_B(b_imm(i + inst->jf + 1,
+                                                            ctx)), ctx);
+                       break;
+               case BPF_S_JMP_JEQ_X:
+                       /* pc += (A == X) ? pc->jt : pc->jf */
+                       condt   = ARM_COND_EQ;
+                       goto cmp_x;
+               case BPF_S_JMP_JGT_X:
+                       /* pc += (A > X) ? pc->jt : pc->jf */
+                       condt   = ARM_COND_HI;
+                       goto cmp_x;
+               case BPF_S_JMP_JGE_X:
+                       /* pc += (A >= X) ? pc->jt : pc->jf */
+                       condt   = ARM_COND_CS;
+cmp_x:
+                       update_on_xread(ctx);
+                       emit(ARM_CMP_R(r_A, r_X), ctx);
+                       goto cond_jump;
+               case BPF_S_JMP_JSET_K:
+                       /* pc += (A & K) ? pc->jt : pc->jf */
+                       condt  = ARM_COND_NE;
+                       /* not set iff all zeroes iff Z==1 iff EQ */
+
+                       imm12 = imm8m(k);
+                       if (imm12 < 0) {
+                               emit_mov_i_no8m(r_scratch, k, ctx);
+                               emit(ARM_TST_R(r_A, r_scratch), ctx);
+                       } else {
+                               emit(ARM_TST_I(r_A, imm12), ctx);
+                       }
+                       goto cond_jump;
+               case BPF_S_JMP_JSET_X:
+                       /* pc += (A & X) ? pc->jt : pc->jf */
+                       update_on_xread(ctx);
+                       condt  = ARM_COND_NE;
+                       emit(ARM_TST_R(r_A, r_X), ctx);
+                       goto cond_jump;
+               case BPF_S_RET_A:
+                       emit(ARM_MOV_R(ARM_R0, r_A), ctx);
+                       goto b_epilogue;
+               case BPF_S_RET_K:
+                       if ((k == 0) && (ctx->ret0_fp_idx < 0))
+                               ctx->ret0_fp_idx = i;
+                       emit_mov_i(ARM_R0, k, ctx);
+b_epilogue:
+                       if (i != ctx->skf->len - 1)
+                               emit(ARM_B(b_imm(prog->len, ctx)), ctx);
+                       break;
+               case BPF_S_MISC_TAX:
+                       /* X = A */
+                       ctx->seen |= SEEN_X;
+                       emit(ARM_MOV_R(r_X, r_A), ctx);
+                       break;
+               case BPF_S_MISC_TXA:
+                       /* A = X */
+                       update_on_xread(ctx);
+                       emit(ARM_MOV_R(r_A, r_X), ctx);
+                       break;
+               case BPF_S_ANC_PROTOCOL:
+                       /* A = ntohs(skb->protocol) */
+                       ctx->seen |= SEEN_SKB;
+                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+                                                 protocol) != 2);
+                       off = offsetof(struct sk_buff, protocol);
+                       emit(ARM_LDRH_I(r_scratch, r_skb, off), ctx);
+                       emit_swap16(r_A, r_scratch, ctx);
+                       break;
+               case BPF_S_ANC_CPU:
+                       /* r_scratch = current_thread_info() */
+                       OP_IMM3(ARM_BIC, r_scratch, ARM_SP, THREAD_SIZE - 1, ctx);
+                       /* A = current_thread_info()->cpu */
+                       BUILD_BUG_ON(FIELD_SIZEOF(struct thread_info, cpu) != 4);
+                       off = offsetof(struct thread_info, cpu);
+                       emit(ARM_LDR_I(r_A, r_scratch, off), ctx);
+                       break;
+               case BPF_S_ANC_IFINDEX:
+                       /* A = skb->dev->ifindex */
+                       ctx->seen |= SEEN_SKB;
+                       off = offsetof(struct sk_buff, dev);
+                       emit(ARM_LDR_I(r_scratch, r_skb, off), ctx);
+
+                       emit(ARM_CMP_I(r_scratch, 0), ctx);
+                       emit_err_ret(ARM_COND_EQ, ctx);
+
+                       BUILD_BUG_ON(FIELD_SIZEOF(struct net_device,
+                                                 ifindex) != 4);
+                       off = offsetof(struct net_device, ifindex);
+                       emit(ARM_LDR_I(r_A, r_scratch, off), ctx);
+                       break;
+               case BPF_S_ANC_MARK:
+                       ctx->seen |= SEEN_SKB;
+                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4);
+                       off = offsetof(struct sk_buff, mark);
+                       emit(ARM_LDR_I(r_A, r_skb, off), ctx);
+                       break;
+               case BPF_S_ANC_RXHASH:
+                       ctx->seen |= SEEN_SKB;
+                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, rxhash) != 4);
+                       off = offsetof(struct sk_buff, rxhash);
+                       emit(ARM_LDR_I(r_A, r_skb, off), ctx);
+                       break;
+               case BPF_S_ANC_QUEUE:
+                       ctx->seen |= SEEN_SKB;
+                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+                                                 queue_mapping) != 2);
+                       BUILD_BUG_ON(offsetof(struct sk_buff,
+                                             queue_mapping) > 0xff);
+                       off = offsetof(struct sk_buff, queue_mapping);
+                       emit(ARM_LDRH_I(r_A, r_skb, off), ctx);
+                       break;
+               default:
+                       return -1;
+               }
+       }
+
+       /* compute offsets only during the first pass */
+       if (ctx->target == NULL)
+               ctx->offsets[i] = ctx->idx * 4;
+
+       return 0;
+}
+
+
+void bpf_jit_compile(struct sk_filter *fp)
+{
+       struct jit_ctx ctx;
+       unsigned tmp_idx;
+       unsigned alloc_size;
+
+       if (!bpf_jit_enable)
+               return;
+
+       memset(&ctx, 0, sizeof(ctx));
+       ctx.skf         = fp;
+       ctx.ret0_fp_idx = -1;
+
+       ctx.offsets = kzalloc(GFP_KERNEL, 4 * (ctx.skf->len + 1));
+       if (ctx.offsets == NULL)
+               return;
+
+       /* fake pass to fill in the ctx->seen */
+       if (unlikely(build_body(&ctx)))
+               goto out;
+
+       tmp_idx = ctx.idx;
+       build_prologue(&ctx);
+       ctx.prologue_bytes = (ctx.idx - tmp_idx) * 4;
+
+#if __LINUX_ARM_ARCH__ < 7
+       tmp_idx = ctx.idx;
+       build_epilogue(&ctx);
+       ctx.epilogue_bytes = (ctx.idx - tmp_idx) * 4;
+
+       ctx.idx += ctx.imm_count;
+       if (ctx.imm_count) {
+               ctx.imms = kzalloc(GFP_KERNEL, 4 * ctx.imm_count);
+               if (ctx.imms == NULL)
+                       goto out;
+       }
+#else
+       /* there's nothing after the epilogue on ARMv7 */
+       build_epilogue(&ctx);
+#endif
+
+       alloc_size = 4 * ctx.idx;
+       ctx.target = module_alloc(max(sizeof(struct work_struct),
+                                     alloc_size));
+       if (unlikely(ctx.target == NULL))
+               goto out;
+
+       ctx.idx = 0;
+       build_prologue(&ctx);
+       build_body(&ctx);
+       build_epilogue(&ctx);
+
+       flush_icache_range((u32)ctx.target, (u32)(ctx.target + ctx.idx));
+
+#if __LINUX_ARM_ARCH__ < 7
+       if (ctx.imm_count)
+               kfree(ctx.imms);
+#endif
+
+       if (bpf_jit_enable > 1)
+               print_hex_dump(KERN_INFO, "BPF JIT code: ",
+                              DUMP_PREFIX_ADDRESS, 16, 4, ctx.target,
+                              alloc_size, false);
+
+       fp->bpf_func = (void *)ctx.target;
+out:
+       kfree(ctx.offsets);
+       return;
+}
+
+static void bpf_jit_free_worker(struct work_struct *work)
+{
+       module_free(NULL, work);
+}
+
+void bpf_jit_free(struct sk_filter *fp)
+{
+       struct work_struct *work;
+
+       if (fp->bpf_func != sk_run_filter) {
+               work = (struct work_struct *)fp->bpf_func;
+
+               INIT_WORK(work, bpf_jit_free_worker);
+               schedule_work(work);
+       }
+}
diff --git a/arch/arm/net/bpf_jit_32.h b/arch/arm/net/bpf_jit_32.h
new file mode 100644 (file)
index 0000000..99ae5e3
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Just-In-Time compiler for BPF filters on 32bit ARM
+ *
+ * Copyright (c) 2011 Mircea Gherzan <mgherzan@gmail.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; version 2 of the License.
+ */
+
+#ifndef PFILTER_OPCODES_ARM_H
+#define PFILTER_OPCODES_ARM_H
+
+#define ARM_R0 0
+#define ARM_R1 1
+#define ARM_R2 2
+#define ARM_R3 3
+#define ARM_R4 4
+#define ARM_R5 5
+#define ARM_R6 6
+#define ARM_R7 7
+#define ARM_R8 8
+#define ARM_R9 9
+#define ARM_R10        10
+#define ARM_FP 11
+#define ARM_IP 12
+#define ARM_SP 13
+#define ARM_LR 14
+#define ARM_PC 15
+
+#define ARM_COND_EQ            0x0
+#define ARM_COND_NE            0x1
+#define ARM_COND_CS            0x2
+#define ARM_COND_HS            ARM_COND_CS
+#define ARM_COND_CC            0x3
+#define ARM_COND_LO            ARM_COND_CC
+#define ARM_COND_MI            0x4
+#define ARM_COND_PL            0x5
+#define ARM_COND_VS            0x6
+#define ARM_COND_VC            0x7
+#define ARM_COND_HI            0x8
+#define ARM_COND_LS            0x9
+#define ARM_COND_GE            0xa
+#define ARM_COND_LT            0xb
+#define ARM_COND_GT            0xc
+#define ARM_COND_LE            0xd
+#define ARM_COND_AL            0xe
+
+/* register shift types */
+#define SRTYPE_LSL             0
+#define SRTYPE_LSR             1
+#define SRTYPE_ASR             2
+#define SRTYPE_ROR             3
+
+#define ARM_INST_ADD_R         0x00800000
+#define ARM_INST_ADD_I         0x02800000
+
+#define ARM_INST_AND_R         0x00000000
+#define ARM_INST_AND_I         0x02000000
+
+#define ARM_INST_BIC_R         0x01c00000
+#define ARM_INST_BIC_I         0x03c00000
+
+#define ARM_INST_B             0x0a000000
+#define ARM_INST_BX            0x012FFF10
+#define ARM_INST_BLX_R         0x012fff30
+
+#define ARM_INST_CMP_R         0x01500000
+#define ARM_INST_CMP_I         0x03500000
+
+#define ARM_INST_LDRB_I                0x05d00000
+#define ARM_INST_LDRB_R                0x07d00000
+#define ARM_INST_LDRH_I                0x01d000b0
+#define ARM_INST_LDR_I         0x05900000
+
+#define ARM_INST_LDM           0x08900000
+
+#define ARM_INST_LSL_I         0x01a00000
+#define ARM_INST_LSL_R         0x01a00010
+
+#define ARM_INST_LSR_I         0x01a00020
+#define ARM_INST_LSR_R         0x01a00030
+
+#define ARM_INST_MOV_R         0x01a00000
+#define ARM_INST_MOV_I         0x03a00000
+#define ARM_INST_MOVW          0x03000000
+#define ARM_INST_MOVT          0x03400000
+
+#define ARM_INST_MUL           0x00000090
+
+#define ARM_INST_POP           0x08bd0000
+#define ARM_INST_PUSH          0x092d0000
+
+#define ARM_INST_ORR_R         0x01800000
+#define ARM_INST_ORR_I         0x03800000
+
+#define ARM_INST_REV           0x06bf0f30
+#define ARM_INST_REV16         0x06bf0fb0
+
+#define ARM_INST_RSB_I         0x02600000
+
+#define ARM_INST_SUB_R         0x00400000
+#define ARM_INST_SUB_I         0x02400000
+
+#define ARM_INST_STR_I         0x05800000
+
+#define ARM_INST_TST_R         0x01100000
+#define ARM_INST_TST_I         0x03100000
+
+#define ARM_INST_UDIV          0x0730f010
+
+#define ARM_INST_UMULL         0x00800090
+
+/* register */
+#define _AL3_R(op, rd, rn, rm) ((op ## _R) | (rd) << 12 | (rn) << 16 | (rm))
+/* immediate */
+#define _AL3_I(op, rd, rn, imm)        ((op ## _I) | (rd) << 12 | (rn) << 16 | (imm))
+
+#define ARM_ADD_R(rd, rn, rm)  _AL3_R(ARM_INST_ADD, rd, rn, rm)
+#define ARM_ADD_I(rd, rn, imm) _AL3_I(ARM_INST_ADD, rd, rn, imm)
+
+#define ARM_AND_R(rd, rn, rm)  _AL3_R(ARM_INST_AND, rd, rn, rm)
+#define ARM_AND_I(rd, rn, imm) _AL3_I(ARM_INST_AND, rd, rn, imm)
+
+#define ARM_BIC_R(rd, rn, rm)  _AL3_R(ARM_INST_BIC, rd, rn, rm)
+#define ARM_BIC_I(rd, rn, imm) _AL3_I(ARM_INST_BIC, rd, rn, imm)
+
+#define ARM_B(imm24)           (ARM_INST_B | ((imm24) & 0xffffff))
+#define ARM_BX(rm)             (ARM_INST_BX | (rm))
+#define ARM_BLX_R(rm)          (ARM_INST_BLX_R | (rm))
+
+#define ARM_CMP_R(rn, rm)      _AL3_R(ARM_INST_CMP, 0, rn, rm)
+#define ARM_CMP_I(rn, imm)     _AL3_I(ARM_INST_CMP, 0, rn, imm)
+
+#define ARM_LDR_I(rt, rn, off) (ARM_INST_LDR_I | (rt) << 12 | (rn) << 16 \
+                                | (off))
+#define ARM_LDRB_I(rt, rn, off)        (ARM_INST_LDRB_I | (rt) << 12 | (rn) << 16 \
+                                | (off))
+#define ARM_LDRB_R(rt, rn, rm) (ARM_INST_LDRB_R | (rt) << 12 | (rn) << 16 \
+                                | (rm))
+#define ARM_LDRH_I(rt, rn, off)        (ARM_INST_LDRH_I | (rt) << 12 | (rn) << 16 \
+                                | (((off) & 0xf0) << 4) | ((off) & 0xf))
+
+#define ARM_LDM(rn, regs)      (ARM_INST_LDM | (rn) << 16 | (regs))
+
+#define ARM_LSL_R(rd, rn, rm)  (_AL3_R(ARM_INST_LSL, rd, 0, rn) | (rm) << 8)
+#define ARM_LSL_I(rd, rn, imm) (_AL3_I(ARM_INST_LSL, rd, 0, rn) | (imm) << 7)
+
+#define ARM_LSR_R(rd, rn, rm)  (_AL3_R(ARM_INST_LSR, rd, 0, rn) | (rm) << 8)
+#define ARM_LSR_I(rd, rn, imm) (_AL3_I(ARM_INST_LSR, rd, 0, rn) | (imm) << 7)
+
+#define ARM_MOV_R(rd, rm)      _AL3_R(ARM_INST_MOV, rd, 0, rm)
+#define ARM_MOV_I(rd, imm)     _AL3_I(ARM_INST_MOV, rd, 0, imm)
+
+#define ARM_MOVW(rd, imm)      \
+       (ARM_INST_MOVW | ((imm) >> 12) << 16 | (rd) << 12 | ((imm) & 0x0fff))
+
+#define ARM_MOVT(rd, imm)      \
+       (ARM_INST_MOVT | ((imm) >> 12) << 16 | (rd) << 12 | ((imm) & 0x0fff))
+
+#define ARM_MUL(rd, rm, rn)    (ARM_INST_MUL | (rd) << 16 | (rm) << 8 | (rn))
+
+#define ARM_POP(regs)          (ARM_INST_POP | (regs))
+#define ARM_PUSH(regs)         (ARM_INST_PUSH | (regs))
+
+#define ARM_ORR_R(rd, rn, rm)  _AL3_R(ARM_INST_ORR, rd, rn, rm)
+#define ARM_ORR_I(rd, rn, imm) _AL3_I(ARM_INST_ORR, rd, rn, imm)
+#define ARM_ORR_S(rd, rn, rm, type, rs)        \
+       (ARM_ORR_R(rd, rn, rm) | (type) << 5 | (rs) << 7)
+
+#define ARM_REV(rd, rm)                (ARM_INST_REV | (rd) << 12 | (rm))
+#define ARM_REV16(rd, rm)      (ARM_INST_REV16 | (rd) << 12 | (rm))
+
+#define ARM_RSB_I(rd, rn, imm) _AL3_I(ARM_INST_RSB, rd, rn, imm)
+
+#define ARM_SUB_R(rd, rn, rm)  _AL3_R(ARM_INST_SUB, rd, rn, rm)
+#define ARM_SUB_I(rd, rn, imm) _AL3_I(ARM_INST_SUB, rd, rn, imm)
+
+#define ARM_STR_I(rt, rn, off) (ARM_INST_STR_I | (rt) << 12 | (rn) << 16 \
+                                | (off))
+
+#define ARM_TST_R(rn, rm)      _AL3_R(ARM_INST_TST, 0, rn, rm)
+#define ARM_TST_I(rn, imm)     _AL3_I(ARM_INST_TST, 0, rn, imm)
+
+#define ARM_UDIV(rd, rn, rm)   (ARM_INST_UDIV | (rd) << 16 | (rn) | (rm) << 8)
+
+#define ARM_UMULL(rd_lo, rd_hi, rn, rm)        (ARM_INST_UMULL | (rd_hi) << 16 \
+                                        | (rd_lo) << 12 | (rm) << 8 | rn)
+
+#endif /* PFILTER_OPCODES_ARM_H */
index bca4914b4b9dab344f19c6fd6eb84a084e91030d..4c48c8b60b54e4672a0ff10c85d4a6fe93c9d8d6 100644 (file)
@@ -23,7 +23,6 @@ config HAS_MTU
 config NOMADIK_MTU_SCHED_CLOCK
        bool
        depends on HAS_MTU
-       select HAVE_SCHED_CLOCK
        help
          Use the Multi Timer Unit as the sched_clock.
 
index 52353beb369d635ebfd51de7b2d0fa3bf6b21966..043f7b02a9e709b239d81d2715ab0258748986d3 100644 (file)
@@ -11,7 +11,6 @@ config PLAT_VERSATILE_LEDS
        depends on ARCH_REALVIEW || ARCH_VERSATILE
 
 config PLAT_VERSATILE_SCHED_CLOCK
-       def_bool y if !ARCH_INTEGRATOR_AP
-       select HAVE_SCHED_CLOCK
+       def_bool y
 
 endif
index 3c64b2894c13ffcd589aa877a008c16885ad67b8..1c3ccd416d50ad374d05331ea547f6835fcbab10 100644 (file)
@@ -11,7 +11,7 @@ config TMS320C6X
        select HAVE_DMA_API_DEBUG
        select HAVE_GENERIC_HARDIRQS
        select HAVE_MEMBLOCK
-       select HAVE_SPARSE_IRQ
+       select SPARSE_IRQ
        select IRQ_DOMAIN
        select OF
        select OF_EARLY_FLATTREE
index eeaa5328b862ab0bd18cafc96e6be63c62bea891..feab3bad6d0f265ca51c5b88c50f073d20f29e93 100644 (file)
@@ -133,7 +133,6 @@ config PPC
        select HAVE_REGS_AND_STACK_ACCESS_API
        select HAVE_HW_BREAKPOINT if PERF_EVENTS && PPC_BOOK3S_64
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_SPARSE_IRQ
        select SPARSE_IRQ
        select IRQ_PER_CPU
        select IRQ_DOMAIN
index 713fb58ca50724309d14f326c047bc4443df4772..b190eb17a75beb088f90a2b5eccdcbaf13c506b7 100644 (file)
@@ -22,7 +22,7 @@ config SUPERH
        select HAVE_SYSCALL_TRACEPOINTS
        select HAVE_REGS_AND_STACK_ACCESS_API
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_SPARSE_IRQ
+       select MAY_HAVE_SPARSE_IRQ
        select IRQ_FORCED_THREADING
        select RTC_LIB
        select GENERIC_ATOMIC64
index 45d08b6a5ef71de204578bb0569f4fba3c836cbd..2a62017eb2750705d1b07f7defb21532c8ccbf27 100644 (file)
  */
 #define NO_IRQ_IGNORE          ((unsigned int)-1)
 
-/*
- * Convert back and forth between INTEVT and IRQ values.
- */
-#ifdef CONFIG_CPU_HAS_INTEVT
-#define evt2irq(evt)           (((evt) >> 5) - 16)
-#define irq2evt(irq)           (((irq) + 16) << 5)
-#else
-#define evt2irq(evt)           (evt)
-#define irq2evt(irq)           (irq)
-#endif
-
 /*
  * Simple Mask Register Support
  */
index e3974694078bf531001b52a859d359bec3cbf0c7..abfb953c131d7fe833b535a68927decd8bdb03e2 100644 (file)
@@ -69,7 +69,6 @@ config X86
        select HAVE_ARCH_JUMP_LABEL
        select HAVE_TEXT_POKE_SMP
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_SPARSE_IRQ
        select SPARSE_IRQ
        select GENERIC_FIND_FIRST_BIT
        select GENERIC_IRQ_PROBE
index 999d6a03e43689c4d82a14f80034aed452c95f38..5138927a416c99acdf13deed3e6d717a616a5af8 100644 (file)
@@ -26,7 +26,6 @@ config CLKSRC_DBX500_PRCMU
 config CLKSRC_DBX500_PRCMU_SCHED_CLOCK
        bool "Clocksource PRCMU Timer sched_clock"
        depends on (CLKSRC_DBX500_PRCMU && !NOMADIK_MTU_SCHED_CLOCK)
-       select HAVE_SCHED_CLOCK
        default y
        help
          Use the always on PRCMU Timer as sched_clock
index b2d3ee1d183a50b2da33ac819d2a74375966b726..5689ce62fd81badc2fdeceeb604fdf866d5b3bda 100644 (file)
@@ -22,6 +22,8 @@
 #include <linux/syscore_ops.h>
 #include <linux/slab.h>
 
+#include <mach/irqs.h>
+
 /*
  * We handle the GPIOs by banks, each bank covers up to 32 GPIOs with
  * one set of registers. The register offsets are organized below:
index cec7a96f2c098f632d3a50865b7cece306007f92..bc780807ccb0febf460bc5de45517a8c26b82bd2 100644 (file)
@@ -9,7 +9,7 @@
  */
 #include "internals.h"
 
-static unsigned long dist_handle[NR_IRQS];
+static unsigned long dist_handle[INTC_NR_IRQS];
 
 void intc_balancing_enable(unsigned int irq)
 {
index e53e449b4ecab0b83ab6fe110cb0df4ff8dff963..2fde8970dfd0716dda4fcf69395da9be7bf80214 100644 (file)
@@ -42,7 +42,7 @@ unsigned int nr_intc_controllers;
  * - this needs to be at least 2 for 5-bit priorities on 7780
  */
 static unsigned int default_prio_level = 2;    /* 2 - 16 */
-static unsigned int intc_prio_level[NR_IRQS];  /* for now */
+static unsigned int intc_prio_level[INTC_NR_IRQS];     /* for now */
 
 unsigned int intc_get_dfl_prio_level(void)
 {
index 057ce56829bf37b1c57093eb0734ed80b2dad36a..f461d5300b81d77fcc06915669c3eb9b56ea8e91 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/spinlock.h>
 #include "internals.h"
 
-static unsigned long ack_handle[NR_IRQS];
+static unsigned long ack_handle[INTC_NR_IRQS];
 
 static intc_enum __init intc_grp_id(struct intc_desc *desc,
                                    intc_enum enum_id)
index c7ec49ffd9f63806a73b14e39ec6bbedbf6de8cf..93cec21e788bdb7b4024fa5237b9d7a8801c1333 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/export.h>
 #include "internals.h"
 
-static struct intc_map_entry intc_irq_xlate[NR_IRQS];
+static struct intc_map_entry intc_irq_xlate[INTC_NR_IRQS];
 
 struct intc_virq_list {
        unsigned int irq;
index b160645f5599f51547694c1c1771d3e2b03bd04e..6aed0805927f8ea608e3bce754974d53a9bc372f 100644 (file)
@@ -3,6 +3,23 @@
 
 #include <linux/ioport.h>
 
+#ifdef CONFIG_SUPERH
+#define INTC_NR_IRQS   512
+#else
+#define INTC_NR_IRQS   1024
+#endif
+
+/*
+ * Convert back and forth between INTEVT and IRQ values.
+ */
+#ifdef CONFIG_CPU_HAS_INTEVT
+#define evt2irq(evt)           (((evt) >> 5) - 16)
+#define irq2evt(irq)           (((irq) + 16) << 5)
+#else
+#define evt2irq(evt)           (evt)
+#define irq2evt(irq)           (irq)
+#endif
+
 typedef unsigned char intc_enum;
 
 struct intc_vect {
index d8e323d12496c558065d42b356454fa0e4f55eba..cf1a4a68ce444f03218ea0adbbd1f0ea178cc4d0 100644 (file)
@@ -13,7 +13,7 @@ config GENERIC_HARDIRQS
 # Options selectable by the architecture code
 
 # Make sparse irq Kconfig switch below available
-config HAVE_SPARSE_IRQ
+config MAY_HAVE_SPARSE_IRQ
        bool
 
 # Enable the generic irq autoprobe mechanism
@@ -71,8 +71,7 @@ config IRQ_FORCED_THREADING
        bool
 
 config SPARSE_IRQ
-       bool "Support sparse irq numbering"
-       depends on HAVE_SPARSE_IRQ
+       bool "Support sparse irq numbering" if MAY_HAVE_SPARSE_IRQ
        ---help---
 
          Sparse irq numbering is useful for distro kernels that want
index 98cffcb941ea6e319fd4bee04db7f06de379031b..a2af2e88daf3e094bc786f368ce4fe88d5b947d7 100644 (file)
@@ -2,4 +2,20 @@
 # Test for gcc 'asm goto' support
 # Copyright (C) 2010, Jason Baron <jbaron@redhat.com>
 
-echo "int main(void) { entry: asm goto (\"\"::::entry); return 0; }" | $@ -x c - -c -o /dev/null >/dev/null 2>&1 && echo "y"
+cat << "END" | $@ -x c - -c -o /dev/null >/dev/null 2>&1 && echo "y"
+int main(void)
+{
+#ifdef __arm__
+       /*
+        * Not related to asm goto, but used by jump label
+        * and broken on some ARM GCC versions (see GCC Bug 48637).
+        */
+       static struct { int dummy; int state; } tp;
+       asm (".long %c0" :: "i" (&tp.state));
+#endif
+
+entry:
+       asm goto ("" :::: entry);
+       return 0;
+}
+END
index d1aa4218f1299ebccb813d0b8ef6c6fb9d8c3479..0e9e82262479fbb6908aa5b0377bfcc094d9c64e 100644 (file)
@@ -21,7 +21,7 @@
 #include <sound/ac97_codec.h>
 #include <sound/pxa2xx-lib.h>
 
-#include <asm/irq.h>
+#include <mach/irqs.h>
 #include <mach/regs-ac97.h>
 #include <mach/audio.h>