···11+* ARM Generic Interrupt Controller22+33+ARM SMP cores are often associated with a GIC, providing per processor44+interrupts (PPI), shared processor interrupts (SPI) and software55+generated interrupts (SGI).66+77+Primary GIC is attached directly to the CPU and typically has PPIs and SGIs.88+Secondary GICs are cascaded into the upward interrupt controller and do not99+have PPIs or SGIs.1010+1111+Main node required properties:1212+1313+- compatible : should be one of:1414+ "arm,cortex-a9-gic"1515+ "arm,arm11mp-gic"1616+- interrupt-controller : Identifies the node as an interrupt controller1717+- #interrupt-cells : Specifies the number of cells needed to encode an1818+ interrupt source. The type shall be a <u32> and the value shall be 3.1919+2020+ The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI2121+ interrupts.2222+2323+ The 2nd cell contains the interrupt number for the interrupt type.2424+ SPI interrupts are in the range [0-987]. PPI interrupts are in the2525+ range [0-15].2626+2727+ The 3rd cell is the flags, encoded as follows:2828+ bits[3:0] trigger type and level flags.2929+ 1 = low-to-high edge triggered3030+ 2 = high-to-low edge triggered3131+ 4 = active high level-sensitive3232+ 8 = active low level-sensitive3333+ bits[15:8] PPI interrupt cpu mask. Each bit corresponds to each of3434+ the 8 possible cpus attached to the GIC. A bit set to '1' indicated3535+ the interrupt is wired to that CPU. Only valid for PPI interrupts.3636+3737+- reg : Specifies base physical address(s) and size of the GIC registers. The3838+ first region is the GIC distributor register base and size. The 2nd region is3939+ the GIC cpu interface register base and size.4040+4141+Optional4242+- interrupts : Interrupt source of the parent interrupt controller. Only4343+ present on secondary GICs.4444+4545+Example:4646+4747+ intc: interrupt-controller@fff11000 {4848+ compatible = "arm,cortex-a9-gic";4949+ #interrupt-cells = <3>;5050+ #address-cells = <1>;5151+ interrupt-controller;5252+ reg = <0xfff11000 0x1000>,5353+ <0xfff10100 0x100>;5454+ };5555+
+94-10
arch/arm/Kconfig
···2929 select HAVE_GENERIC_HARDIRQS3030 select HAVE_SPARSE_IRQ3131 select GENERIC_IRQ_SHOW3232+ select CPU_PM if (SUSPEND || CPU_IDLE)3233 help3334 The ARM series is a line of low-power-consumption RISC chip designs3435 licensed by ARM Ltd and targeted at embedded applications and···196195 The base address of exception vectors.197196198197config ARM_PATCH_PHYS_VIRT199199- bool "Patch physical to virtual translations at runtime"198198+ bool "Patch physical to virtual translations at runtime" if EMBEDDED199199+ default y200200 depends on !XIP_KERNEL && MMU201201 depends on !ARCH_REALVIEW || !SPARSEMEM202202 help···206204 kernel in system memory.207205208206 This can only be used with non-XIP MMU kernels where the base209209- of physical memory is at a 16MB boundary, or theoretically 64K210210- for the MSM machine class.207207+ of physical memory is at a 16MB boundary.211208212212-config ARM_PATCH_PHYS_VIRT_16BIT213213- def_bool y214214- depends on ARM_PATCH_PHYS_VIRT && ARCH_MSM209209+ Only disable this option if you know that you do not require210210+ this feature (eg, building a kernel for a single machine) and211211+ you need to shrink the kernel to the minimal size.212212+213213+config NEED_MACH_MEMORY_H214214+ bool215215 help216216- This option extends the physical to virtual translation patching217217- to allow physical memory down to a theoretical minimum of 64K218218- boundaries.216216+ Select this when mach/memory.h is required to provide special217217+ definitions for this platform. The need for mach/memory.h should218218+ be avoided when possible.219219+220220+config PHYS_OFFSET221221+ hex "Physical address of main memory"222222+ depends on !ARM_PATCH_PHYS_VIRT && !NEED_MACH_MEMORY_H223223+ help224224+ Please provide the physical address corresponding to the225225+ location of main memory in your system.219226220227source "init/Kconfig"221228···257246 select GENERIC_CLOCKEVENTS258247 select PLAT_VERSATILE259248 select PLAT_VERSATILE_FPGA_IRQ249249+ select NEED_MACH_MEMORY_H260250 help261251 Support for ARM's Integrator platform.262252···273261 select PLAT_VERSATILE_CLCD274262 select ARM_TIMER_SP804275263 select GPIO_PL061 if GPIOLIB264264+ select NEED_MACH_MEMORY_H276265 help277266 This enables support for ARM Ltd RealView boards.278267···314301 select ARCH_REQUIRE_GPIOLIB315302 select HAVE_CLK316303 select CLKDEV_LOOKUP317317- select ARM_PATCH_PHYS_VIRT if MMU318304 help319305 This enables support for systems based on the Atmel AT91RM9200,320306 AT91SAM9 and AT91CAP9 processors.···334322 bool "Cirrus Logic CLPS711x/EP721x-based"335323 select CPU_ARM720T336324 select ARCH_USES_GETTIMEOFFSET325325+ select NEED_MACH_MEMORY_H337326 help338327 Support for Cirrus Logic 711x/721x based boards.339328···375362 select ISA376363 select NO_IOPORT377364 select ARCH_USES_GETTIMEOFFSET365365+ select NEED_MACH_MEMORY_H378366 help379367 This is an evaluation board for the StrongARM processor available380368 from Digital. It has limited hardware on-board, including an···391377 select ARCH_REQUIRE_GPIOLIB392378 select ARCH_HAS_HOLES_MEMORYMODEL393379 select ARCH_USES_GETTIMEOFFSET380380+ select NEED_MEMORY_H394381 help395382 This enables support for the Cirrus EP93xx series of CPUs.396383···400385 select CPU_SA110401386 select FOOTBRIDGE402387 select GENERIC_CLOCKEVENTS388388+ select NEED_MACH_MEMORY_H403389 help404390 Support for systems based on the DC21285 companion chip405391 ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.···450434 select PCI451435 select ARCH_SUPPORTS_MSI452436 select VMSPLIT_1G437437+ select NEED_MACH_MEMORY_H453438 help454439 Support for Intel's IOP13XX (XScale) family of processors.455440···481464 select CPU_XSC3482465 select PCI483466 select ARCH_USES_GETTIMEOFFSET467467+ select NEED_MACH_MEMORY_H484468 help485469 Support for Intel's IXP23xx (XScale) family of processors.486470···491473 select CPU_XSCALE492474 select PCI493475 select ARCH_USES_GETTIMEOFFSET476476+ select NEED_MACH_MEMORY_H494477 help495478 Support for Intel's IXP2400/2800 (XScale) family of processors.496479···585566 select CPU_ARM922T586567 select ARCH_REQUIRE_GPIOLIB587568 select ARCH_USES_GETTIMEOFFSET569569+ select NEED_MACH_MEMORY_H588570 help589571 Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based590572 System-on-Chip devices.···677657 select SPARSE_IRQ678658 select MULTI_IRQ_HANDLER679659 select PM_GENERIC_DOMAINS if PM660660+ select NEED_MACH_MEMORY_H680661 help681662 Support for Renesas's SH-Mobile and R-Mobile ARM platforms.682663···692671 select NO_IOPORT693672 select ARCH_SPARSEMEM_ENABLE694673 select ARCH_USES_GETTIMEOFFSET674674+ select NEED_MACH_MEMORY_H695675 help696676 On the Acorn Risc-PC, Linux can support the internal IDE disk and697677 CD-ROM interface, serial and parallel port, and the floppy drive.···711689 select HAVE_SCHED_CLOCK712690 select TICK_ONESHOT713691 select ARCH_REQUIRE_GPIOLIB692692+ select NEED_MACH_MEMORY_H714693 help715694 Support for StrongARM 11x0 based boards.716695···804781 select HAVE_S3C2410_I2C if I2C805782 select HAVE_S3C_RTC if RTC_CLASS806783 select HAVE_S3C2410_WATCHDOG if WATCHDOG784784+ select NEED_MACH_MEMORY_H807785 help808786 Samsung S5PV210/S5PC110 series based systems809787···821797 select HAVE_S3C_RTC if RTC_CLASS822798 select HAVE_S3C2410_I2C if I2C823799 select HAVE_S3C2410_WATCHDOG if WATCHDOG800800+ select NEED_MACH_MEMORY_H824801 help825802 Samsung EXYNOS4 series based systems826803···833808 select ZONE_DMA834809 select PCI835810 select ARCH_USES_GETTIMEOFFSET811811+ select NEED_MACH_MEMORY_H836812 help837813 Support for the StrongARM based Digital DNARD machine, also known838814 as "Shark" (<http://www.shark-linux.de/shark.html>).···861835 select CLKDEV_LOOKUP862836 select HAVE_MACH_CLKDEV863837 select GENERIC_GPIO838838+ select NEED_MACH_MEMORY_H864839 help865840 Support for ST-Ericsson U300 series mobile platforms.866841···1434140714351408 If you don't know what to do here, say Y.1436140914101410+config ARM_CPU_TOPOLOGY14111411+ bool "Support cpu topology definition"14121412+ depends on SMP && CPU_V714131413+ default y14141414+ help14151415+ Support ARM cpu topology definition. The MPIDR register defines14161416+ affinity between processors which is then used to describe the cpu14171417+ topology of an ARM System.14181418+14191419+config SCHED_MC14201420+ bool "Multi-core scheduler support"14211421+ depends on ARM_CPU_TOPOLOGY14221422+ help14231423+ Multi-core scheduler support improves the CPU scheduler's decision14241424+ making when dealing with multi-core CPU chips at a cost of slightly14251425+ increased overhead in some places. If unsure say N here.14261426+14271427+config SCHED_SMT14281428+ bool "SMT scheduler support"14291429+ depends on ARM_CPU_TOPOLOGY14301430+ help14311431+ Improves the CPU scheduler's decision making when dealing with14321432+ MultiThreading at a cost of slightly increased overhead in some14331433+ places. If unsure say N here.14341434+14371435config HAVE_ARM_SCU14381436 bool14391437 help···18581806 Load image from SDHI hardware block1859180718601808endchoice18091809+18101810+config ARM_APPENDED_DTB18111811+ bool "Use appended device tree blob to zImage (EXPERIMENTAL)"18121812+ depends on OF && !ZBOOT_ROM && EXPERIMENTAL18131813+ help18141814+ With this option, the boot code will look for a device tree binary18151815+ (DTB) appended to zImage18161816+ (e.g. cat zImage <filename>.dtb > zImage_w_dtb).18171817+18181818+ This is meant as a backward compatibility convenience for those18191819+ systems with a bootloader that can't be upgraded to accommodate18201820+ the documented boot protocol using a device tree.18211821+18221822+ Beware that there is very little in terms of protection against18231823+ this option being confused by leftover garbage in memory that might18241824+ look like a DTB header after a reboot if no actual DTB is appended18251825+ to zImage. Do not leave this option active in a production kernel18261826+ if you don't intend to always append a DTB. Proper passing of the18271827+ location into r2 of a bootloader provided DTB is always preferable18281828+ to this option.18291829+18301830+config ARM_ATAG_DTB_COMPAT18311831+ bool "Supplement the appended DTB with traditional ATAG information"18321832+ depends on ARM_APPENDED_DTB18331833+ help18341834+ Some old bootloaders can't be updated to a DTB capable one, yet18351835+ they provide ATAGs with memory configuration, the ramdisk address,18361836+ the kernel cmdline string, etc. Such information is dynamically18371837+ provided by the bootloader and can't always be stored in a static18381838+ DTB. To allow a device tree enabled kernel to be used with such18391839+ bootloaders, this option allows zImage to extract the information18401840+ from the ATAG list and store it at run time into the appended DTB.1861184118621842config CMDLINE18631843 string "Default kernel command string"
+6
arch/arm/Kconfig.debug
···129129 The uncompressor code port configuration is now handled130130 by CONFIG_S3C_LOWLEVEL_UART_PORT.131131132132+config ARM_KPROBES_TEST133133+ tristate "Kprobes test module"134134+ depends on KPROBES && MODULES135135+ help136136+ Perform tests of kprobes API and instruction set simulation.137137+132138endmenu
+3
arch/arm/Makefile
···128128ifeq ($(CONFIG_ARCH_SA1100),y)129129textofs-$(CONFIG_SA1111) := 0x00208000130130endif131131+textofs-$(CONFIG_ARCH_MSM7X30) := 0x00208000132132+textofs-$(CONFIG_ARCH_MSM8X60) := 0x00208000133133+textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000131134132135# Machine directory name. This list is sorted alphanumerically133136# by CONFIG_* macro name.
···2626OBJS += misc.o decompress.o2727FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c28282929+# string library code (-Os is enforced to keep it much smaller)3030+OBJS += string.o3131+CFLAGS_string.o := -Os3232+2933#3034# Architecture dependencies3135#···9389suffix_$(CONFIG_KERNEL_LZO) = lzo9490suffix_$(CONFIG_KERNEL_LZMA) = lzma95919292+# Borrowed libfdt files for the ATAG compatibility mode9393+9494+libfdt := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c9595+libfdt_hdrs := fdt.h libfdt.h libfdt_internal.h9696+9797+libfdt_objs := $(addsuffix .o, $(basename $(libfdt)))9898+9999+$(addprefix $(obj)/,$(libfdt) $(libfdt_hdrs)): $(obj)/%: $(srctree)/scripts/dtc/libfdt/%100100+ $(call cmd,shipped)101101+102102+$(addprefix $(obj)/,$(libfdt_objs) atags_to_fdt.o): \103103+ $(addprefix $(obj)/,$(libfdt_hdrs))104104+105105+ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y)106106+OBJS += $(libfdt_objs) atags_to_fdt.o107107+endif108108+96109targets := vmlinux vmlinux.lds \97110 piggy.$(suffix_y) piggy.$(suffix_y).o \9898- font.o font.c head.o misc.o $(OBJS)111111+ lib1funcs.o lib1funcs.S font.o font.c head.o misc.o $(OBJS)99112100113# Make sure files are removed during clean101101-extra-y += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S114114+extra-y += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S $(libfdt) $(libfdt_hdrs)102115103116ifeq ($(CONFIG_FUNCTION_TRACER),y)104117ORIG_CFLAGS := $(KBUILD_CFLAGS)105118KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))106119endif107120108108-ccflags-y := -fpic -fno-builtin121121+ccflags-y := -fpic -fno-builtin -I$(obj)109122asflags-y := -Wa,-march=all110123124124+# Supply kernel BSS size to the decompressor via a linker symbol.125125+KBSS_SZ = $(shell size $(obj)/../../../../vmlinux | awk 'END{print $$3}')126126+LDFLAGS_vmlinux = --defsym _kernel_bss_size=$(KBSS_SZ)111127# Supply ZRELADDR to the decompressor via a linker symbol.112128ifneq ($(CONFIG_AUTO_ZRELADDR),y)113129LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR)···147123# For __aeabi_uidivmod148124lib1funcs = $(obj)/lib1funcs.o149125150150-$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE126126+$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S151127 $(call cmd,shipped)152128153129# We need to prevent any GOTOFF relocs being used with references
+97
arch/arm/boot/compressed/atags_to_fdt.c
···11+#include <asm/setup.h>22+#include <libfdt.h>33+44+static int node_offset(void *fdt, const char *node_path)55+{66+ int offset = fdt_path_offset(fdt, node_path);77+ if (offset == -FDT_ERR_NOTFOUND)88+ offset = fdt_add_subnode(fdt, 0, node_path);99+ return offset;1010+}1111+1212+static int setprop(void *fdt, const char *node_path, const char *property,1313+ uint32_t *val_array, int size)1414+{1515+ int offset = node_offset(fdt, node_path);1616+ if (offset < 0)1717+ return offset;1818+ return fdt_setprop(fdt, offset, property, val_array, size);1919+}2020+2121+static int setprop_string(void *fdt, const char *node_path,2222+ const char *property, const char *string)2323+{2424+ int offset = node_offset(fdt, node_path);2525+ if (offset < 0)2626+ return offset;2727+ return fdt_setprop_string(fdt, offset, property, string);2828+}2929+3030+static int setprop_cell(void *fdt, const char *node_path,3131+ const char *property, uint32_t val)3232+{3333+ int offset = node_offset(fdt, node_path);3434+ if (offset < 0)3535+ return offset;3636+ return fdt_setprop_cell(fdt, offset, property, val);3737+}3838+3939+/*4040+ * Convert and fold provided ATAGs into the provided FDT.4141+ *4242+ * REturn values:4343+ * = 0 -> pretend success4444+ * = 1 -> bad ATAG (may retry with another possible ATAG pointer)4545+ * < 0 -> error from libfdt4646+ */4747+int atags_to_fdt(void *atag_list, void *fdt, int total_space)4848+{4949+ struct tag *atag = atag_list;5050+ uint32_t mem_reg_property[2 * NR_BANKS];5151+ int memcount = 0;5252+ int ret;5353+5454+ /* make sure we've got an aligned pointer */5555+ if ((u32)atag_list & 0x3)5656+ return 1;5757+5858+ /* if we get a DTB here we're done already */5959+ if (*(u32 *)atag_list == fdt32_to_cpu(FDT_MAGIC))6060+ return 0;6161+6262+ /* validate the ATAG */6363+ if (atag->hdr.tag != ATAG_CORE ||6464+ (atag->hdr.size != tag_size(tag_core) &&6565+ atag->hdr.size != 2))6666+ return 1;6767+6868+ /* let's give it all the room it could need */6969+ ret = fdt_open_into(fdt, fdt, total_space);7070+ if (ret < 0)7171+ return ret;7272+7373+ for_each_tag(atag, atag_list) {7474+ if (atag->hdr.tag == ATAG_CMDLINE) {7575+ setprop_string(fdt, "/chosen", "bootargs",7676+ atag->u.cmdline.cmdline);7777+ } else if (atag->hdr.tag == ATAG_MEM) {7878+ if (memcount >= sizeof(mem_reg_property)/4)7979+ continue;8080+ mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.start);8181+ mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.size);8282+ } else if (atag->hdr.tag == ATAG_INITRD2) {8383+ uint32_t initrd_start, initrd_size;8484+ initrd_start = atag->u.initrd.start;8585+ initrd_size = atag->u.initrd.size;8686+ setprop_cell(fdt, "/chosen", "linux,initrd-start",8787+ initrd_start);8888+ setprop_cell(fdt, "/chosen", "linux,initrd-end",8989+ initrd_start + initrd_size);9090+ }9191+ }9292+9393+ if (memcount)9494+ setprop(fdt, "/memory", "reg", mem_reg_property, 4*memcount);9595+9696+ return fdt_pack(fdt);9797+}
+114-7
arch/arm/boot/compressed/head.S
···216216 mov r10, r6217217#endif218218219219+ mov r5, #0 @ init dtb size to 0220220+#ifdef CONFIG_ARM_APPENDED_DTB221221+/*222222+ * r0 = delta223223+ * r2 = BSS start224224+ * r3 = BSS end225225+ * r4 = final kernel address226226+ * r5 = appended dtb size (still unknown)227227+ * r6 = _edata228228+ * r7 = architecture ID229229+ * r8 = atags/device tree pointer230230+ * r9 = size of decompressed image231231+ * r10 = end of this image, including bss/stack/malloc space if non XIP232232+ * r11 = GOT start233233+ * r12 = GOT end234234+ * sp = stack pointer235235+ *236236+ * if there are device trees (dtb) appended to zImage, advance r10 so that the237237+ * dtb data will get relocated along with the kernel if necessary.238238+ */239239+240240+ ldr lr, [r6, #0]241241+#ifndef __ARMEB__242242+ ldr r1, =0xedfe0dd0 @ sig is 0xd00dfeed big endian243243+#else244244+ ldr r1, =0xd00dfeed245245+#endif246246+ cmp lr, r1247247+ bne dtb_check_done @ not found248248+249249+#ifdef CONFIG_ARM_ATAG_DTB_COMPAT250250+ /*251251+ * OK... Let's do some funky business here.252252+ * If we do have a DTB appended to zImage, and we do have253253+ * an ATAG list around, we want the later to be translated254254+ * and folded into the former here. To be on the safe side,255255+ * let's temporarily move the stack away into the malloc256256+ * area. No GOT fixup has occurred yet, but none of the257257+ * code we're about to call uses any global variable.258258+ */259259+ add sp, sp, #0x10000260260+ stmfd sp!, {r0-r3, ip, lr}261261+ mov r0, r8262262+ mov r1, r6263263+ sub r2, sp, r6264264+ bl atags_to_fdt265265+266266+ /*267267+ * If returned value is 1, there is no ATAG at the location268268+ * pointed by r8. Try the typical 0x100 offset from start269269+ * of RAM and hope for the best.270270+ */271271+ cmp r0, #1272272+ sub r0, r4, #(TEXT_OFFSET - 0x100)273273+ mov r1, r6274274+ sub r2, sp, r6275275+ blne atags_to_fdt276276+277277+ ldmfd sp!, {r0-r3, ip, lr}278278+ sub sp, sp, #0x10000279279+#endif280280+281281+ mov r8, r6 @ use the appended device tree282282+283283+ /*284284+ * Make sure that the DTB doesn't end up in the final285285+ * kernel's .bss area. To do so, we adjust the decompressed286286+ * kernel size to compensate if that .bss size is larger287287+ * than the relocated code.288288+ */289289+ ldr r5, =_kernel_bss_size290290+ adr r1, wont_overwrite291291+ sub r1, r6, r1292292+ subs r1, r5, r1293293+ addhi r9, r9, r1294294+295295+ /* Get the dtb's size */296296+ ldr r5, [r6, #4]297297+#ifndef __ARMEB__298298+ /* convert r5 (dtb size) to little endian */299299+ eor r1, r5, r5, ror #16300300+ bic r1, r1, #0x00ff0000301301+ mov r5, r5, ror #8302302+ eor r5, r5, r1, lsr #8303303+#endif304304+305305+ /* preserve 64-bit alignment */306306+ add r5, r5, #7307307+ bic r5, r5, #7308308+309309+ /* relocate some pointers past the appended dtb */310310+ add r6, r6, r5311311+ add r10, r10, r5312312+ add sp, sp, r5313313+dtb_check_done:314314+#endif315315+219316/*220317 * Check to see if we will overwrite ourselves.221318 * r4 = final kernel address···320223 * r10 = end of this image, including bss/stack/malloc space if non XIP321224 * We basically want:322225 * r4 - 16k page directory >= r10 -> OK323323- * r4 + image length <= current position (pc) -> OK226226+ * r4 + image length <= address of wont_overwrite -> OK324227 */325228 add r10, r10, #16384326229 cmp r4, r10327230 bhs wont_overwrite328231 add r10, r4, r9329329- ARM( cmp r10, pc )330330- THUMB( mov lr, pc )331331- THUMB( cmp r10, lr )232232+ adr r9, wont_overwrite233233+ cmp r10, r9332234 bls wont_overwrite333235334236/*···381285 * r2 = BSS start382286 * r3 = BSS end383287 * r4 = kernel execution address288288+ * r5 = appended dtb size (0 if not present)384289 * r7 = architecture ID385290 * r8 = atags pointer386291 * r11 = GOT start387292 * r12 = GOT end388293 * sp = stack pointer389294 */390390- teq r0, #0295295+ orrs r1, r0, r5391296 beq not_relocated297297+392298 add r11, r11, r0393299 add r12, r12, r0394300···405307406308 /*407309 * Relocate all entries in the GOT table.310310+ * Bump bss entries to _edata + dtb size408311 */4093121: ldr r1, [r11, #0] @ relocate entries in the GOT410410- add r1, r1, r0 @ table. This fixes up the411411- str r1, [r11], #4 @ C references.313313+ add r1, r1, r0 @ This fixes up C references314314+ cmp r1, r2 @ if entry >= bss_start &&315315+ cmphs r3, r1 @ bss_end > entry316316+ addhi r1, r1, r5 @ entry += dtb size317317+ str r1, [r11], #4 @ next entry412318 cmp r11, r12413319 blo 1b320320+321321+ /* bump our bss pointers too */322322+ add r2, r2, r5323323+ add r3, r3, r5324324+414325#else415326416327 /*
···205205int dma_mmap_writecombine(struct device *, struct vm_area_struct *,206206 void *, dma_addr_t, size_t);207207208208+/*209209+ * This can be called during boot to increase the size of the consistent210210+ * DMA region above it's default value of 2MB. It must be called before the211211+ * memory allocator is initialised, i.e. before any core_initcall.212212+ */213213+extern void __init init_consistent_dma_size(unsigned long size);214214+208215209216#ifdef CONFIG_DMABOUNCE210217/*
···11+/*22+ * Annotations for marking C functions as exception handlers.33+ *44+ * These should only be used for C functions that are called from the low55+ * level exception entry code and not any intervening C code.66+ */77+#ifndef __ASM_ARM_EXCEPTION_H88+#define __ASM_ARM_EXCEPTION_H99+1010+#include <linux/ftrace.h>1111+1212+#define __exception __attribute__((section(".exception.text")))1313+#ifdef CONFIG_FUNCTION_GRAPH_TRACER1414+#define __exception_irq_entry __irq_entry1515+#else1616+#define __exception_irq_entry __exception1717+#endif1818+1919+#endif /* __ASM_ARM_EXCEPTION_H */
-3
arch/arm/include/asm/hardirq.h
···991010typedef struct {1111 unsigned int __softirq_pending;1212-#ifdef CONFIG_LOCAL_TIMERS1313- unsigned int local_timer_irqs;1414-#endif1512#ifdef CONFIG_SMP1613 unsigned int ipi_irqs[NR_IPI];1714#endif
+2-17
arch/arm/include/asm/hardware/entry-macro-gic.S
···2222 * interrupt controller spec. To wit:2323 *2424 * Interrupts 0-15 are IPI2525- * 16-28 are reserved2626- * 29-31 are local. We allow 30 to be used for the watchdog.2525+ * 16-31 are local. We allow 30 to be used for the watchdog.2726 * 32-1020 are global2827 * 1021-1022 are reserved2928 * 1023 is "spurious" (no interrupt)3030- *3131- * For now, we ignore all local interrupts so only return an interrupt if it's3232- * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs.3329 *3430 * A simple read from the controller will tell us the number of the highest3531 * priority enabled interrupt. We then just need to check whether it is in the···39434044 ldr \tmp, =10214145 bic \irqnr, \irqstat, #0x1c004242- cmp \irqnr, #294646+ cmp \irqnr, #154347 cmpcc \irqnr, \irqnr4448 cmpne \irqnr, \tmp4549 cmpcs \irqnr, \irqnr···5761 cmp \irqnr, #165862 strcc \irqstat, [\base, #GIC_CPU_EOI]5963 cmpcs \irqnr, \irqnr6060- .endm6161-6262-/* As above, this assumes that irqstat and base are preserved.. */6363-6464- .macro test_for_ltirq, irqnr, irqstat, base, tmp6565- bic \irqnr, \irqstat, #0x1c006666- mov \tmp, #06767- cmp \irqnr, #296868- moveq \tmp, #16969- streq \irqstat, [\base, #GIC_CPU_EOI]7070- cmp \tmp, #07164 .endm
···1111#define __ASM_ARM_LOCALTIMER_H12121313#include <linux/errno.h>1414+#include <linux/interrupt.h>14151516struct clock_event_device;1617···2019 */2120void percpu_timer_setup(void);22212323-/*2424- * Called from assembly, this is the local timer IRQ handler2525- */2626-asmlinkage void do_local_timer(struct pt_regs *);2727-2828-2922#ifdef CONFIG_LOCAL_TIMERS30233124#ifdef CONFIG_HAVE_ARM_TWD32253326#include "smp_twd.h"34273535-#define local_timer_ack() twd_timer_ack()2828+#define local_timer_stop(c) twd_timer_stop((c))36293730#else38313932/*4040- * Platform provides this to acknowledge a local timer IRQ.4141- * Returns true if the local timer IRQ is to be processed.3333+ * Stop the local timer4234 */4343-int local_timer_ack(void);3535+void local_timer_stop(struct clock_event_device *);44364537#endif4638···4753static inline int local_timer_setup(struct clock_event_device *evt)4854{4955 return -ENXIO;5656+}5757+5858+static inline void local_timer_stop(struct clock_event_device *evt)5959+{5060}5161#endif5262
+1-1
arch/arm/include/asm/mach/arch.h
···1717struct machine_desc {1818 unsigned int nr; /* architecture number */1919 const char *name; /* architecture name */2020- unsigned long boot_params; /* tagged list */2020+ unsigned long atag_offset; /* tagged list (relative) */2121 const char **dt_compat; /* array of device tree2222 * 'compatible' strings */2323
···1616#include <linux/compiler.h>1717#include <linux/const.h>1818#include <linux/types.h>1919-#include <mach/memory.h>2019#include <asm/sizes.h>2020+2121+#ifdef CONFIG_NEED_MACH_MEMORY_H2222+#include <mach/memory.h>2323+#endif21242225/*2326 * Allow for constants defined here to be used from assembly code···8077 */8178#define IOREMAP_MAX_ORDER 2482798383-/*8484- * Size of DMA-consistent memory region. Must be multiple of 2M,8585- * between 2MB and 14MB inclusive.8686- */8787-#ifndef CONSISTENT_DMA_SIZE8888-#define CONSISTENT_DMA_SIZE SZ_2M8989-#endif9090-9180#define CONSISTENT_END (0xffe00000UL)9292-#define CONSISTENT_BASE (CONSISTENT_END - CONSISTENT_DMA_SIZE)93819482#else /* CONFIG_MMU */9583···154160 * so that all we need to do is modify the 8-bit constant field.155161 */156162#define __PV_BITS_31_24 0x81000000157157-#define __PV_BITS_23_16 0x00810000158163159164extern unsigned long __pv_phys_offset;160165#define PHYS_OFFSET __pv_phys_offset···171178{172179 unsigned long t;173180 __pv_stub(x, t, "add", __PV_BITS_31_24);174174-#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT175175- __pv_stub(t, t, "add", __PV_BITS_23_16);176176-#endif177181 return t;178182}179183···178188{179189 unsigned long t;180190 __pv_stub(x, t, "sub", __PV_BITS_31_24);181181-#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT182182- __pv_stub(t, t, "sub", __PV_BITS_23_16);183183-#endif184191 return t;185192}186193#else···187200#endif188201189202#ifndef PHYS_OFFSET203203+#ifdef PLAT_PHYS_OFFSET190204#define PHYS_OFFSET PLAT_PHYS_OFFSET205205+#else206206+#define PHYS_OFFSET UL(CONFIG_PHYS_OFFSET)207207+#endif191208#endif192209193210/*
-4
arch/arm/include/asm/module.h
···31313232/* Add __virt_to_phys patching state as well */3333#ifdef CONFIG_ARM_PATCH_PHYS_VIRT3434-#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT3535-#define MODULE_ARCH_VERMAGIC_P2V "p2v16 "3636-#else3734#define MODULE_ARCH_VERMAGIC_P2V "p2v8 "3838-#endif3935#else4036#define MODULE_ARCH_VERMAGIC_P2V ""4137#endif
···1313#define __ARM_PMU_H__14141515#include <linux/interrupt.h>1616+#include <linux/perf_event.h>16171818+/*1919+ * Types of PMUs that can be accessed directly and require mutual2020+ * exclusion between profiling tools.2121+ */1722enum arm_pmu_type {1823 ARM_PMU_DEVICE_CPU = 0,1924 ARM_NUM_PMU_DEVICES,···4237 * reserve_pmu() - reserve the hardware performance counters4338 *4439 * Reserve the hardware performance counters in the system for exclusive use.4545- * The platform_device for the system is returned on success, ERR_PTR()4646- * encoded error on failure.4040+ * Returns 0 on success or -EBUSY if the lock is already held.4741 */4848-extern struct platform_device *4242+extern int4943reserve_pmu(enum arm_pmu_type type);50445145/**5246 * release_pmu() - Relinquish control of the performance counters5347 *5448 * Release the performance counters and allow someone else to use them.5555- * Callers must have disabled the counters and released IRQs before calling5656- * this. The platform_device returned from reserve_pmu() must be passed as5757- * a cookie.5849 */5959-extern int5050+extern void6051release_pmu(enum arm_pmu_type type);61526253/**···69687069#include <linux/err.h>71707272-static inline struct platform_device *7171+static inline int7372reserve_pmu(enum arm_pmu_type type)7473{7575- return ERR_PTR(-ENODEV);7676-}7777-7878-static inline int7979-release_pmu(enum arm_pmu_type type)8080-{8174 return -ENODEV;8275}83768484-static inline int8585-init_pmu(enum arm_pmu_type type)8686-{8787- return -ENODEV;8888-}7777+static inline void7878+release_pmu(enum arm_pmu_type type) { }89799080#endif /* CONFIG_CPU_HAS_PMU */8181+8282+#ifdef CONFIG_HW_PERF_EVENTS8383+8484+/* The events for a given PMU register set. */8585+struct pmu_hw_events {8686+ /*8787+ * The events that are active on the PMU for the given index.8888+ */8989+ struct perf_event **events;9090+9191+ /*9292+ * A 1 bit for an index indicates that the counter is being used for9393+ * an event. A 0 means that the counter can be used.9494+ */9595+ unsigned long *used_mask;9696+9797+ /*9898+ * Hardware lock to serialize accesses to PMU registers. Needed for the9999+ * read/modify/write sequences.100100+ */101101+ raw_spinlock_t pmu_lock;102102+};103103+104104+struct arm_pmu {105105+ struct pmu pmu;106106+ enum arm_perf_pmu_ids id;107107+ enum arm_pmu_type type;108108+ cpumask_t active_irqs;109109+ const char *name;110110+ irqreturn_t (*handle_irq)(int irq_num, void *dev);111111+ void (*enable)(struct hw_perf_event *evt, int idx);112112+ void (*disable)(struct hw_perf_event *evt, int idx);113113+ int (*get_event_idx)(struct pmu_hw_events *hw_events,114114+ struct hw_perf_event *hwc);115115+ int (*set_event_filter)(struct hw_perf_event *evt,116116+ struct perf_event_attr *attr);117117+ u32 (*read_counter)(int idx);118118+ void (*write_counter)(int idx, u32 val);119119+ void (*start)(void);120120+ void (*stop)(void);121121+ void (*reset)(void *);122122+ int (*map_event)(struct perf_event *event);123123+ int num_events;124124+ atomic_t active_events;125125+ struct mutex reserve_mutex;126126+ u64 max_period;127127+ struct platform_device *plat_device;128128+ struct pmu_hw_events *(*get_hw_events)(void);129129+};130130+131131+#define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))132132+133133+int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type);134134+135135+u64 armpmu_event_update(struct perf_event *event,136136+ struct hw_perf_event *hwc,137137+ int idx, int overflow);138138+139139+int armpmu_event_set_period(struct perf_event *event,140140+ struct hw_perf_event *hwc,141141+ int idx);142142+143143+#endif /* CONFIG_HW_PERF_EVENTS */9114492145#endif /* __ARM_PMU_H__ */
+8
arch/arm/include/asm/proc-fns.h
···8181extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);8282extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext);8383extern void cpu_reset(unsigned long addr) __attribute__((noreturn));8484+8585+/* These three are private to arch/arm/kernel/suspend.c */8686+extern void cpu_do_suspend(void *);8787+extern void cpu_do_resume(void *);8488#else8589#define cpu_proc_init processor._proc_init8690#define cpu_proc_fin processor._proc_fin···9389#define cpu_dcache_clean_area processor.dcache_clean_area9490#define cpu_set_pte_ext processor.set_pte_ext9591#define cpu_do_switch_mm processor.switch_mm9292+9393+/* These three are private to arch/arm/kernel/suspend.c */9494+#define cpu_do_suspend processor.do_suspend9595+#define cpu_do_resume processor.do_resume9696#endif97979898extern void cpu_resume(void);
+11-5
arch/arm/include/asm/smp.h
···3333asmlinkage void do_IPI(int ipinr, struct pt_regs *regs);34343535/*3636+ * Called from C code, this handles an IPI.3737+ */3838+void handle_IPI(int ipinr, struct pt_regs *regs);3939+4040+/*3641 * Setup the set of possible CPUs (via set_cpu_possible)3742 */3843extern void smp_init_cpus(void);···7166extern void platform_smp_prepare_cpus(unsigned int);72677368/*6969+ * Logical CPU mapping.7070+ */7171+extern int __cpu_logical_map[NR_CPUS];7272+#define cpu_logical_map(cpu) __cpu_logical_map[cpu]7373+7474+/*7475 * Initial data for bringing up a secondary CPU.7576 */7677struct secondary_data {···98879988extern void arch_send_call_function_single_ipi(int cpu);10089extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);101101-102102-/*103103- * show local interrupt info104104- */105105-extern void show_local_irqs(struct seq_file *, int);1069010791#endif /* ifndef __ASM_ARM_SMP_H */
···11#ifndef __ASM_ARM_SUSPEND_H22#define __ASM_ARM_SUSPEND_H3344-#include <asm/memory.h>55-#include <asm/tlbflush.h>66-74extern void cpu_resume(void);88-99-/*1010- * Hide the first two arguments to __cpu_suspend - these are an implementation1111- * detail which platform code shouldn't have to know about.1212- */1313-static inline int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))1414-{1515- extern int __cpu_suspend(int, long, unsigned long,1616- int (*)(unsigned long));1717- int ret = __cpu_suspend(0, PHYS_OFFSET - PAGE_OFFSET, arg, fn);1818- flush_tlb_all();1919- return ret;2020-}55+extern int cpu_suspend(unsigned long, int (*)(unsigned long));216227#endif
···9595 sub r4, r3, r4 @ (PHYS_OFFSET - PAGE_OFFSET)9696 add r8, r8, r4 @ PHYS_OFFSET9797#else9898- ldr r8, =PLAT_PHYS_OFFSET9898+ ldr r8, =PHYS_OFFSET @ always constant in this case9999#endif100100101101 /*···234234 * This allows debug messages to be output235235 * via a serial console before paging_init.236236 */237237- addruart r7, r3237237+ addruart r7, r3, r0238238239239 mov r3, r3, lsr #20240240 mov r3, r3, lsl #2···488488 add r5, r5, r3 @ adjust table end address489489 add r7, r7, r3 @ adjust __pv_phys_offset address490490 str r8, [r7] @ save computed PHYS_OFFSET to __pv_phys_offset491491-#ifndef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT492491 mov r6, r3, lsr #24 @ constant for add/sub instructions493492 teq r3, r6, lsl #24 @ must be 16MiB aligned494494-#else495495- mov r6, r3, lsr #16 @ constant for add/sub instructions496496- teq r3, r6, lsl #16 @ must be 64kiB aligned497497-#endif498493THUMB( it ne @ cross section branch )499494 bne __error500495 str r6, [r7, #4] @ save to __pv_offset···505510 .text506511__fixup_a_pv_table:507512#ifdef CONFIG_THUMB2_KERNEL508508-#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT509509- lsls r0, r6, #24510510- lsr r6, #8511511- beq 1f512512- clz r7, r0513513- lsr r0, #24514514- lsl r0, r7515515- bic r0, 0x0080516516- lsrs r7, #1517517- orrcs r0, #0x0080518518- orr r0, r0, r7, lsl #12519519-#endif520520-1: lsls r6, #24521521- beq 4f513513+ lsls r6, #24514514+ beq 2f522515 clz r7, r6523516 lsr r6, #24524517 lsl r6, r7···515532 orrcs r6, #0x0080516533 orr r6, r6, r7, lsl #12517534 orr r6, #0x4000518518- b 4f519519-2: @ at this point the C flag is always clear520520- add r7, r3521521-#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT522522- ldrh ip, [r7]523523- tst ip, 0x0400 @ the i bit tells us LS or MS byte524524- beq 3f525525- cmp r0, #0 @ set C flag, and ...526526- biceq ip, 0x0400 @ immediate zero value has a special encoding527527- streqh ip, [r7] @ that requires the i bit cleared528528-#endif529529-3: ldrh ip, [r7, #2]535535+ b 2f536536+1: add r7, r3537537+ ldrh ip, [r7, #2]530538 and ip, 0x8f00531531- orrcc ip, r6 @ mask in offset bits 31-24532532- orrcs ip, r0 @ mask in offset bits 23-16539539+ orr ip, r6 @ mask in offset bits 31-24533540 strh ip, [r7, #2]534534-4: cmp r4, r5541541+2: cmp r4, r5535542 ldrcc r7, [r4], #4 @ use branch for delay slot536536- bcc 2b543543+ bcc 1b537544 bx lr538545#else539539-#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT540540- and r0, r6, #255 @ offset bits 23-16541541- mov r6, r6, lsr #8 @ offset bits 31-24542542-#else543543- mov r0, #0 @ just in case...544544-#endif545545- b 3f546546-2: ldr ip, [r7, r3]546546+ b 2f547547+1: ldr ip, [r7, r3]547548 bic ip, ip, #0x000000ff548548- tst ip, #0x400 @ rotate shift tells us LS or MS byte549549- orrne ip, ip, r6 @ mask in offset bits 31-24550550- orreq ip, ip, r0 @ mask in offset bits 23-16549549+ orr ip, ip, r6 @ mask in offset bits 31-24551550 str ip, [r7, r3]552552-3: cmp r4, r5551551+2: cmp r4, r5553552 ldrcc r7, [r4], #4 @ use branch for delay slot554554- bcc 2b553553+ bcc 1b555554 mov pc, lr556555#endif557556ENDPROC(__fixup_a_pv_table)
+172-107
arch/arm/kernel/hw_breakpoint.c
···45454646/* Number of BRP/WRP registers on this CPU. */4747static int core_num_brps;4848-static int core_num_reserved_brps;4948static int core_num_wrps;50495150/* Debug architecture version. */···136137 u32 didr;137138138139 /* Do we implement the extended CPUID interface? */139139- if (WARN_ONCE((((read_cpuid_id() >> 16) & 0xf) != 0xf),140140- "CPUID feature registers not supported. "141141- "Assuming v6 debug is present.\n"))140140+ if (((read_cpuid_id() >> 16) & 0xf) != 0xf) {141141+ pr_warning("CPUID feature registers not supported. "142142+ "Assuming v6 debug is present.\n");142143 return ARM_DEBUG_ARCH_V6;144144+ }143145144146 ARM_DBG_READ(c0, 0, didr);145147 return (didr >> 16) & 0xf;···154154static int debug_arch_supported(void)155155{156156 u8 arch = get_debug_arch();157157- return arch >= ARM_DEBUG_ARCH_V6 && arch <= ARM_DEBUG_ARCH_V7_ECP14;157157+158158+ /* We don't support the memory-mapped interface. */159159+ return (arch >= ARM_DEBUG_ARCH_V6 && arch <= ARM_DEBUG_ARCH_V7_ECP14) ||160160+ arch >= ARM_DEBUG_ARCH_V7_1;158161}159162160160-/* Determine number of BRP register available. */163163+/* Determine number of WRP registers available. */164164+static int get_num_wrp_resources(void)165165+{166166+ u32 didr;167167+ ARM_DBG_READ(c0, 0, didr);168168+ return ((didr >> 28) & 0xf) + 1;169169+}170170+171171+/* Determine number of BRP registers available. */161172static int get_num_brp_resources(void)162173{163174 u32 didr;···187176static int get_num_wrps(void)188177{189178 /*190190- * FIXME: When a watchpoint fires, the only way to work out which191191- * watchpoint it was is by disassembling the faulting instruction192192- * and working out the address of the memory access.179179+ * On debug architectures prior to 7.1, when a watchpoint fires, the180180+ * only way to work out which watchpoint it was is by disassembling181181+ * the faulting instruction and working out the address of the memory182182+ * access.193183 *194184 * Furthermore, we can only do this if the watchpoint was precise195185 * since imprecise watchpoints prevent us from calculating register···204192 * [the ARM ARM states that the DFAR is UNKNOWN, but experience shows205193 * that it is set on some implementations].206194 */195195+ if (get_debug_arch() < ARM_DEBUG_ARCH_V7_1)196196+ return 1;207197208208-#if 0209209- int wrps;210210- u32 didr;211211- ARM_DBG_READ(c0, 0, didr);212212- wrps = ((didr >> 28) & 0xf) + 1;213213-#endif214214- int wrps = 1;215215-216216- if (core_has_mismatch_brps() && wrps >= get_num_brp_resources())217217- wrps = get_num_brp_resources() - 1;218218-219219- return wrps;220220-}221221-222222-/* We reserve one breakpoint for each watchpoint. */223223-static int get_num_reserved_brps(void)224224-{225225- if (core_has_mismatch_brps())226226- return get_num_wrps();227227- return 0;198198+ return get_num_wrp_resources();228199}229200230201/* Determine number of usable BRPs available. */231202static int get_num_brps(void)232203{233204 int brps = get_num_brp_resources();234234- if (core_has_mismatch_brps())235235- brps -= get_num_reserved_brps();236236- return brps;205205+ return core_has_mismatch_brps() ? brps - 1 : brps;237206}238207239208/*···232239233240 /* Ensure that halting mode is disabled. */234241 if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN,235235- "halting debug mode enabled. Unable to access hardware resources.\n")) {242242+ "halting debug mode enabled. Unable to access hardware resources.\n")) {236243 ret = -EPERM;237244 goto out;238245 }···248255 ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN));249256 break;250257 case ARM_DEBUG_ARCH_V7_ECP14:258258+ case ARM_DEBUG_ARCH_V7_1:251259 ARM_DBG_WRITE(c2, 2, (dscr | ARM_DSCR_MDBGEN));252260 break;253261 default:···340346 val_base = ARM_BASE_BVR;341347 slots = (struct perf_event **)__get_cpu_var(bp_on_reg);342348 max_slots = core_num_brps;343343- if (info->step_ctrl.enabled) {344344- /* Override the breakpoint data with the step data. */345345- addr = info->trigger & ~0x3;346346- ctrl = encode_ctrl_reg(info->step_ctrl);347347- }348349 } else {349350 /* Watchpoint */350350- if (info->step_ctrl.enabled) {351351- /* Install into the reserved breakpoint region. */352352- ctrl_base = ARM_BASE_BCR + core_num_brps;353353- val_base = ARM_BASE_BVR + core_num_brps;354354- /* Override the watchpoint data with the step data. */355355- addr = info->trigger & ~0x3;356356- ctrl = encode_ctrl_reg(info->step_ctrl);357357- } else {358358- ctrl_base = ARM_BASE_WCR;359359- val_base = ARM_BASE_WVR;360360- }351351+ ctrl_base = ARM_BASE_WCR;352352+ val_base = ARM_BASE_WVR;361353 slots = (struct perf_event **)__get_cpu_var(wp_on_reg);362354 max_slots = core_num_wrps;363355 }···360380 if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n")) {361381 ret = -EBUSY;362382 goto out;383383+ }384384+385385+ /* Override the breakpoint data with the step data. */386386+ if (info->step_ctrl.enabled) {387387+ addr = info->trigger & ~0x3;388388+ ctrl = encode_ctrl_reg(info->step_ctrl);389389+ if (info->ctrl.type != ARM_BREAKPOINT_EXECUTE) {390390+ i = 0;391391+ ctrl_base = ARM_BASE_BCR + core_num_brps;392392+ val_base = ARM_BASE_BVR + core_num_brps;393393+ }363394 }364395365396 /* Setup the address register. */···396405 max_slots = core_num_brps;397406 } else {398407 /* Watchpoint */399399- if (info->step_ctrl.enabled)400400- base = ARM_BASE_BCR + core_num_brps;401401- else402402- base = ARM_BASE_WCR;408408+ base = ARM_BASE_WCR;403409 slots = (struct perf_event **)__get_cpu_var(wp_on_reg);404410 max_slots = core_num_wrps;405411 }···413425414426 if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n"))415427 return;428428+429429+ /* Ensure that we disable the mismatch breakpoint. */430430+ if (info->ctrl.type != ARM_BREAKPOINT_EXECUTE &&431431+ info->step_ctrl.enabled) {432432+ i = 0;433433+ base = ARM_BASE_BCR + core_num_brps;434434+ }416435417436 /* Reset the control register. */418437 write_wb_reg(base + i, 0);···627632 * we can use the mismatch feature as a poor-man's hardware628633 * single-step, but this only works for per-task breakpoints.629634 */630630- if (WARN_ONCE(!bp->overflow_handler &&631631- (arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_brps()632632- || !bp->hw.bp_target),633633- "overflow handler required but none found\n")) {635635+ if (!bp->overflow_handler && (arch_check_bp_in_kernelspace(bp) ||636636+ !core_has_mismatch_brps() || !bp->hw.bp_target)) {637637+ pr_warning("overflow handler required but none found\n");634638 ret = -EINVAL;635639 }636640out:···660666 arch_install_hw_breakpoint(bp);661667}662668663663-static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs)669669+static void watchpoint_handler(unsigned long addr, unsigned int fsr,670670+ struct pt_regs *regs)664671{665665- int i;672672+ int i, access;673673+ u32 val, ctrl_reg, alignment_mask;666674 struct perf_event *wp, **slots;667675 struct arch_hw_breakpoint *info;676676+ struct arch_hw_breakpoint_ctrl ctrl;668677669678 slots = (struct perf_event **)__get_cpu_var(wp_on_reg);670670-671671- /* Without a disassembler, we can only handle 1 watchpoint. */672672- BUG_ON(core_num_wrps > 1);673679674680 for (i = 0; i < core_num_wrps; ++i) {675681 rcu_read_lock();676682677683 wp = slots[i];678684679679- if (wp == NULL) {680680- rcu_read_unlock();681681- continue;685685+ if (wp == NULL)686686+ goto unlock;687687+688688+ info = counter_arch_bp(wp);689689+ /*690690+ * The DFAR is an unknown value on debug architectures prior691691+ * to 7.1. Since we only allow a single watchpoint on these692692+ * older CPUs, we can set the trigger to the lowest possible693693+ * faulting address.694694+ */695695+ if (debug_arch < ARM_DEBUG_ARCH_V7_1) {696696+ BUG_ON(i > 0);697697+ info->trigger = wp->attr.bp_addr;698698+ } else {699699+ if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)700700+ alignment_mask = 0x7;701701+ else702702+ alignment_mask = 0x3;703703+704704+ /* Check if the watchpoint value matches. */705705+ val = read_wb_reg(ARM_BASE_WVR + i);706706+ if (val != (addr & ~alignment_mask))707707+ goto unlock;708708+709709+ /* Possible match, check the byte address select. */710710+ ctrl_reg = read_wb_reg(ARM_BASE_WCR + i);711711+ decode_ctrl_reg(ctrl_reg, &ctrl);712712+ if (!((1 << (addr & alignment_mask)) & ctrl.len))713713+ goto unlock;714714+715715+ /* Check that the access type matches. */716716+ access = (fsr & ARM_FSR_ACCESS_MASK) ? HW_BREAKPOINT_W :717717+ HW_BREAKPOINT_R;718718+ if (!(access & hw_breakpoint_type(wp)))719719+ goto unlock;720720+721721+ /* We have a winner. */722722+ info->trigger = addr;682723 }683724684684- /*685685- * The DFAR is an unknown value. Since we only allow a686686- * single watchpoint, we can set the trigger to the lowest687687- * possible faulting address.688688- */689689- info = counter_arch_bp(wp);690690- info->trigger = wp->attr.bp_addr;691725 pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);692726 perf_bp_event(wp, regs);693727···727705 if (!wp->overflow_handler)728706 enable_single_step(wp, instruction_pointer(regs));729707708708+unlock:730709 rcu_read_unlock();731710 }732711}···740717741718 slots = (struct perf_event **)__get_cpu_var(wp_on_reg);742719743743- for (i = 0; i < core_num_reserved_brps; ++i) {720720+ for (i = 0; i < core_num_wrps; ++i) {744721 rcu_read_lock();745722746723 wp = slots[i];···843820 case ARM_ENTRY_ASYNC_WATCHPOINT:844821 WARN(1, "Asynchronous watchpoint exception taken. Debugging results may be unreliable\n");845822 case ARM_ENTRY_SYNC_WATCHPOINT:846846- watchpoint_handler(addr, regs);823823+ watchpoint_handler(addr, fsr, regs);847824 break;848825 default:849826 ret = 1; /* Unhandled fault. */···857834/*858835 * One-time initialisation.859836 */860860-static void reset_ctrl_regs(void *info)837837+static cpumask_t debug_err_mask;838838+839839+static int debug_reg_trap(struct pt_regs *regs, unsigned int instr)861840{862862- int i, cpu = smp_processor_id();841841+ int cpu = smp_processor_id();842842+843843+ pr_warning("Debug register access (0x%x) caused undefined instruction on CPU %d\n",844844+ instr, cpu);845845+846846+ /* Set the error flag for this CPU and skip the faulting instruction. */847847+ cpumask_set_cpu(cpu, &debug_err_mask);848848+ instruction_pointer(regs) += 4;849849+ return 0;850850+}851851+852852+static struct undef_hook debug_reg_hook = {853853+ .instr_mask = 0x0fe80f10,854854+ .instr_val = 0x0e000e10,855855+ .fn = debug_reg_trap,856856+};857857+858858+static void reset_ctrl_regs(void *unused)859859+{860860+ int i, raw_num_brps, err = 0, cpu = smp_processor_id();863861 u32 dbg_power;864864- cpumask_t *cpumask = info;865862866863 /*867864 * v7 debug contains save and restore registers so that debug state···891848 * Access Register to avoid taking undefined instruction exceptions892849 * later on.893850 */894894- if (debug_arch >= ARM_DEBUG_ARCH_V7_ECP14) {851851+ switch (debug_arch) {852852+ case ARM_DEBUG_ARCH_V6:853853+ case ARM_DEBUG_ARCH_V6_1:854854+ /* ARMv6 cores just need to reset the registers. */855855+ goto reset_regs;856856+ case ARM_DEBUG_ARCH_V7_ECP14:895857 /*896858 * Ensure sticky power-down is clear (i.e. debug logic is897859 * powered up).898860 */899861 asm volatile("mrc p14, 0, %0, c1, c5, 4" : "=r" (dbg_power));900900- if ((dbg_power & 0x1) == 0) {901901- pr_warning("CPU %d debug is powered down!\n", cpu);902902- cpumask_or(cpumask, cpumask, cpumask_of(cpu));903903- return;904904- }905905-862862+ if ((dbg_power & 0x1) == 0)863863+ err = -EPERM;864864+ break;865865+ case ARM_DEBUG_ARCH_V7_1:906866 /*907907- * Unconditionally clear the lock by writing a value908908- * other than 0xC5ACCE55 to the access register.867867+ * Ensure the OS double lock is clear.909868 */910910- asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0));911911- isb();912912-913913- /*914914- * Clear any configured vector-catch events before915915- * enabling monitor mode.916916- */917917- asm volatile("mcr p14, 0, %0, c0, c7, 0" : : "r" (0));918918- isb();869869+ asm volatile("mrc p14, 0, %0, c1, c3, 4" : "=r" (dbg_power));870870+ if ((dbg_power & 0x1) == 1)871871+ err = -EPERM;872872+ break;919873 }920874875875+ if (err) {876876+ pr_warning("CPU %d debug is powered down!\n", cpu);877877+ cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu));878878+ return;879879+ }880880+881881+ /*882882+ * Unconditionally clear the lock by writing a value883883+ * other than 0xC5ACCE55 to the access register.884884+ */885885+ asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0));886886+ isb();887887+888888+ /*889889+ * Clear any configured vector-catch events before890890+ * enabling monitor mode.891891+ */892892+ asm volatile("mcr p14, 0, %0, c0, c7, 0" : : "r" (0));893893+ isb();894894+895895+reset_regs:921896 if (enable_monitor_mode())922897 return;923898924899 /* We must also reset any reserved registers. */925925- for (i = 0; i < core_num_brps + core_num_reserved_brps; ++i) {900900+ raw_num_brps = get_num_brp_resources();901901+ for (i = 0; i < raw_num_brps; ++i) {926902 write_wb_reg(ARM_BASE_BCR + i, 0UL);927903 write_wb_reg(ARM_BASE_BVR + i, 0UL);928904 }···957895{958896 if (action == CPU_ONLINE)959897 smp_call_function_single((int)cpu, reset_ctrl_regs, NULL, 1);898898+960899 return NOTIFY_OK;961900}962901···968905static int __init arch_hw_breakpoint_init(void)969906{970907 u32 dscr;971971- cpumask_t cpumask = { CPU_BITS_NONE };972908973909 debug_arch = get_debug_arch();974910···978916979917 /* Determine how many BRPs/WRPs are available. */980918 core_num_brps = get_num_brps();981981- core_num_reserved_brps = get_num_reserved_brps();982919 core_num_wrps = get_num_wrps();983920984984- pr_info("found %d breakpoint and %d watchpoint registers.\n",985985- core_num_brps + core_num_reserved_brps, core_num_wrps);986986-987987- if (core_num_reserved_brps)988988- pr_info("%d breakpoint(s) reserved for watchpoint "989989- "single-step.\n", core_num_reserved_brps);921921+ /*922922+ * We need to tread carefully here because DBGSWENABLE may be923923+ * driven low on this core and there isn't an architected way to924924+ * determine that.925925+ */926926+ register_undef_hook(&debug_reg_hook);990927991928 /*992929 * Reset the breakpoint resources. We assume that a halting993930 * debugger will leave the world in a nice state for us.994931 */995995- on_each_cpu(reset_ctrl_regs, &cpumask, 1);996996- if (!cpumask_empty(&cpumask)) {932932+ on_each_cpu(reset_ctrl_regs, NULL, 1);933933+ unregister_undef_hook(&debug_reg_hook);934934+ if (!cpumask_empty(&debug_err_mask)) {997935 core_num_brps = 0;998998- core_num_reserved_brps = 0;999936 core_num_wrps = 0;1000937 return 0;1001938 }939939+940940+ pr_info("found %d " "%s" "breakpoint and %d watchpoint registers.\n",941941+ core_num_brps, core_has_mismatch_brps() ? "(+1 reserved) " :942942+ "", core_num_wrps);10029431003944 ARM_DBG_READ(c1, 0, dscr);1004945 if (dscr & ARM_DSCR_HDBGEN) {
···11+/*22+ * arch/arm/kernel/kprobes-test.c33+ *44+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.55+ *66+ * This program is free software; you can redistribute it and/or modify77+ * it under the terms of the GNU General Public License version 2 as88+ * published by the Free Software Foundation.99+ */1010+1111+/*1212+ * This file contains test code for ARM kprobes.1313+ *1414+ * The top level function run_all_tests() executes tests for all of the1515+ * supported instruction sets: ARM, 16-bit Thumb, and 32-bit Thumb. These tests1616+ * fall into two categories; run_api_tests() checks basic functionality of the1717+ * kprobes API, and run_test_cases() is a comprehensive test for kprobes1818+ * instruction decoding and simulation.1919+ *2020+ * run_test_cases() first checks the kprobes decoding table for self consistency2121+ * (using table_test()) then executes a series of test cases for each of the CPU2222+ * instruction forms. coverage_start() and coverage_end() are used to verify2323+ * that these test cases cover all of the possible combinations of instructions2424+ * described by the kprobes decoding tables.2525+ *2626+ * The individual test cases are in kprobes-test-arm.c and kprobes-test-thumb.c2727+ * which use the macros defined in kprobes-test.h. The rest of this2828+ * documentation will describe the operation of the framework used by these2929+ * test cases.3030+ */3131+3232+/*3333+ * TESTING METHODOLOGY3434+ * -------------------3535+ *3636+ * The methodology used to test an ARM instruction 'test_insn' is to use3737+ * inline assembler like:3838+ *3939+ * test_before: nop4040+ * test_case: test_insn4141+ * test_after: nop4242+ *4343+ * When the test case is run a kprobe is placed of each nop. The4444+ * post-handler of the test_before probe is used to modify the saved CPU4545+ * register context to that which we require for the test case. The4646+ * pre-handler of the of the test_after probe saves a copy of the CPU4747+ * register context. In this way we can execute test_insn with a specific4848+ * register context and see the results afterwards.4949+ *5050+ * To actually test the kprobes instruction emulation we perform the above5151+ * step a second time but with an additional kprobe on the test_case5252+ * instruction itself. If the emulation is accurate then the results seen5353+ * by the test_after probe will be identical to the first run which didn't5454+ * have a probe on test_case.5555+ *5656+ * Each test case is run several times with a variety of variations in the5757+ * flags value of stored in CPSR, and for Thumb code, different ITState.5858+ *5959+ * For instructions which can modify PC, a second test_after probe is used6060+ * like this:6161+ *6262+ * test_before: nop6363+ * test_case: test_insn6464+ * test_after: nop6565+ * b test_done6666+ * test_after2: nop6767+ * test_done:6868+ *6969+ * The test case is constructed such that test_insn branches to7070+ * test_after2, or, if testing a conditional instruction, it may just7171+ * continue to test_after. The probes inserted at both locations let us7272+ * determine which happened. A similar approach is used for testing7373+ * backwards branches...7474+ *7575+ * b test_before7676+ * b test_done @ helps to cope with off by 1 branches7777+ * test_after2: nop7878+ * b test_done7979+ * test_before: nop8080+ * test_case: test_insn8181+ * test_after: nop8282+ * test_done:8383+ *8484+ * The macros used to generate the assembler instructions describe above8585+ * are TEST_INSTRUCTION, TEST_BRANCH_F (branch forwards) and TEST_BRANCH_B8686+ * (branch backwards). In these, the local variables numbered 1, 50, 2 and8787+ * 99 represent: test_before, test_case, test_after2 and test_done.8888+ *8989+ * FRAMEWORK9090+ * ---------9191+ *9292+ * Each test case is wrapped between the pair of macros TESTCASE_START and9393+ * TESTCASE_END. As well as performing the inline assembler boilerplate,9494+ * these call out to the kprobes_test_case_start() and9595+ * kprobes_test_case_end() functions which drive the execution of the test9696+ * case. The specific arguments to use for each test case are stored as9797+ * inline data constructed using the various TEST_ARG_* macros. Putting9898+ * this all together, a simple test case may look like:9999+ *100100+ * TESTCASE_START("Testing mov r0, r7")101101+ * TEST_ARG_REG(7, 0x12345678) // Set r7=0x12345678102102+ * TEST_ARG_END("")103103+ * TEST_INSTRUCTION("mov r0, r7")104104+ * TESTCASE_END105105+ *106106+ * Note, in practice the single convenience macro TEST_R would be used for this107107+ * instead.108108+ *109109+ * The above would expand to assembler looking something like:110110+ *111111+ * @ TESTCASE_START112112+ * bl __kprobes_test_case_start113113+ * @ start of inline data...114114+ * .ascii "mov r0, r7" @ text title for test case115115+ * .byte 0116116+ * .align 2117117+ *118118+ * @ TEST_ARG_REG119119+ * .byte ARG_TYPE_REG120120+ * .byte 7121121+ * .short 0122122+ * .word 0x1234567123123+ *124124+ * @ TEST_ARG_END125125+ * .byte ARG_TYPE_END126126+ * .byte TEST_ISA @ flags, including ISA being tested127127+ * .short 50f-0f @ offset of 'test_before'128128+ * .short 2f-0f @ offset of 'test_after2' (if relevent)129129+ * .short 99f-0f @ offset of 'test_done'130130+ * @ start of test case code...131131+ * 0:132132+ * .code TEST_ISA @ switch to ISA being tested133133+ *134134+ * @ TEST_INSTRUCTION135135+ * 50: nop @ location for 'test_before' probe136136+ * 1: mov r0, r7 @ the test case instruction 'test_insn'137137+ * nop @ location for 'test_after' probe138138+ *139139+ * // TESTCASE_END140140+ * 2:141141+ * 99: bl __kprobes_test_case_end_##TEST_ISA142142+ * .code NONMAL_ISA143143+ *144144+ * When the above is execute the following happens...145145+ *146146+ * __kprobes_test_case_start() is an assembler wrapper which sets up space147147+ * for a stack buffer and calls the C function kprobes_test_case_start().148148+ * This C function will do some initial processing of the inline data and149149+ * setup some global state. It then inserts the test_before and test_after150150+ * kprobes and returns a value which causes the assembler wrapper to jump151151+ * to the start of the test case code, (local label '0').152152+ *153153+ * When the test case code executes, the test_before probe will be hit and154154+ * test_before_post_handler will call setup_test_context(). This fills the155155+ * stack buffer and CPU registers with a test pattern and then processes156156+ * the test case arguments. In our example there is one TEST_ARG_REG which157157+ * indicates that R7 should be loaded with the value 0x12345678.158158+ *159159+ * When the test_before probe ends, the test case continues and executes160160+ * the "mov r0, r7" instruction. It then hits the test_after probe and the161161+ * pre-handler for this (test_after_pre_handler) will save a copy of the162162+ * CPU register context. This should now have R0 holding the same value as163163+ * R7.164164+ *165165+ * Finally we get to the call to __kprobes_test_case_end_{32,16}. This is166166+ * an assembler wrapper which switches back to the ISA used by the test167167+ * code and calls the C function kprobes_test_case_end().168168+ *169169+ * For each run through the test case, test_case_run_count is incremented170170+ * by one. For even runs, kprobes_test_case_end() saves a copy of the171171+ * register and stack buffer contents from the test case just run. It then172172+ * inserts a kprobe on the test case instruction 'test_insn' and returns a173173+ * value to cause the test case code to be re-run.174174+ *175175+ * For odd numbered runs, kprobes_test_case_end() compares the register and176176+ * stack buffer contents to those that were saved on the previous even177177+ * numbered run (the one without the kprobe on test_insn). These should be178178+ * the same if the kprobe instruction simulation routine is correct.179179+ *180180+ * The pair of test case runs is repeated with different combinations of181181+ * flag values in CPSR and, for Thumb, different ITState. This is182182+ * controlled by test_context_cpsr().183183+ *184184+ * BUILDING TEST CASES185185+ * -------------------186186+ *187187+ *188188+ * As an aid to building test cases, the stack buffer is initialised with189189+ * some special values:190190+ *191191+ * [SP+13*4] Contains SP+120. This can be used to test instructions192192+ * which load a value into SP.193193+ *194194+ * [SP+15*4] When testing branching instructions using TEST_BRANCH_{F,B},195195+ * this holds the target address of the branch, 'test_after2'.196196+ * This can be used to test instructions which load a PC value197197+ * from memory.198198+ */199199+200200+#include <linux/kernel.h>201201+#include <linux/module.h>202202+#include <linux/slab.h>203203+#include <linux/kprobes.h>204204+205205+#include "kprobes.h"206206+#include "kprobes-test.h"207207+208208+209209+#define BENCHMARKING 1210210+211211+212212+/*213213+ * Test basic API214214+ */215215+216216+static bool test_regs_ok;217217+static int test_func_instance;218218+static int pre_handler_called;219219+static int post_handler_called;220220+static int jprobe_func_called;221221+static int kretprobe_handler_called;222222+223223+#define FUNC_ARG1 0x12345678224224+#define FUNC_ARG2 0xabcdef225225+226226+227227+#ifndef CONFIG_THUMB2_KERNEL228228+229229+long arm_func(long r0, long r1);230230+231231+static void __used __naked __arm_kprobes_test_func(void)232232+{233233+ __asm__ __volatile__ (234234+ ".arm \n\t"235235+ ".type arm_func, %%function \n\t"236236+ "arm_func: \n\t"237237+ "adds r0, r0, r1 \n\t"238238+ "bx lr \n\t"239239+ ".code "NORMAL_ISA /* Back to Thumb if necessary */240240+ : : : "r0", "r1", "cc"241241+ );242242+}243243+244244+#else /* CONFIG_THUMB2_KERNEL */245245+246246+long thumb16_func(long r0, long r1);247247+long thumb32even_func(long r0, long r1);248248+long thumb32odd_func(long r0, long r1);249249+250250+static void __used __naked __thumb_kprobes_test_funcs(void)251251+{252252+ __asm__ __volatile__ (253253+ ".type thumb16_func, %%function \n\t"254254+ "thumb16_func: \n\t"255255+ "adds.n r0, r0, r1 \n\t"256256+ "bx lr \n\t"257257+258258+ ".align \n\t"259259+ ".type thumb32even_func, %%function \n\t"260260+ "thumb32even_func: \n\t"261261+ "adds.w r0, r0, r1 \n\t"262262+ "bx lr \n\t"263263+264264+ ".align \n\t"265265+ "nop.n \n\t"266266+ ".type thumb32odd_func, %%function \n\t"267267+ "thumb32odd_func: \n\t"268268+ "adds.w r0, r0, r1 \n\t"269269+ "bx lr \n\t"270270+271271+ : : : "r0", "r1", "cc"272272+ );273273+}274274+275275+#endif /* CONFIG_THUMB2_KERNEL */276276+277277+278278+static int call_test_func(long (*func)(long, long), bool check_test_regs)279279+{280280+ long ret;281281+282282+ ++test_func_instance;283283+ test_regs_ok = false;284284+285285+ ret = (*func)(FUNC_ARG1, FUNC_ARG2);286286+ if (ret != FUNC_ARG1 + FUNC_ARG2) {287287+ pr_err("FAIL: call_test_func: func returned %lx\n", ret);288288+ return false;289289+ }290290+291291+ if (check_test_regs && !test_regs_ok) {292292+ pr_err("FAIL: test regs not OK\n");293293+ return false;294294+ }295295+296296+ return true;297297+}298298+299299+static int __kprobes pre_handler(struct kprobe *p, struct pt_regs *regs)300300+{301301+ pre_handler_called = test_func_instance;302302+ if (regs->ARM_r0 == FUNC_ARG1 && regs->ARM_r1 == FUNC_ARG2)303303+ test_regs_ok = true;304304+ return 0;305305+}306306+307307+static void __kprobes post_handler(struct kprobe *p, struct pt_regs *regs,308308+ unsigned long flags)309309+{310310+ post_handler_called = test_func_instance;311311+ if (regs->ARM_r0 != FUNC_ARG1 + FUNC_ARG2 || regs->ARM_r1 != FUNC_ARG2)312312+ test_regs_ok = false;313313+}314314+315315+static struct kprobe the_kprobe = {316316+ .addr = 0,317317+ .pre_handler = pre_handler,318318+ .post_handler = post_handler319319+};320320+321321+static int test_kprobe(long (*func)(long, long))322322+{323323+ int ret;324324+325325+ the_kprobe.addr = (kprobe_opcode_t *)func;326326+ ret = register_kprobe(&the_kprobe);327327+ if (ret < 0) {328328+ pr_err("FAIL: register_kprobe failed with %d\n", ret);329329+ return ret;330330+ }331331+332332+ ret = call_test_func(func, true);333333+334334+ unregister_kprobe(&the_kprobe);335335+ the_kprobe.flags = 0; /* Clear disable flag to allow reuse */336336+337337+ if (!ret)338338+ return -EINVAL;339339+ if (pre_handler_called != test_func_instance) {340340+ pr_err("FAIL: kprobe pre_handler not called\n");341341+ return -EINVAL;342342+ }343343+ if (post_handler_called != test_func_instance) {344344+ pr_err("FAIL: kprobe post_handler not called\n");345345+ return -EINVAL;346346+ }347347+ if (!call_test_func(func, false))348348+ return -EINVAL;349349+ if (pre_handler_called == test_func_instance ||350350+ post_handler_called == test_func_instance) {351351+ pr_err("FAIL: probe called after unregistering\n");352352+ return -EINVAL;353353+ }354354+355355+ return 0;356356+}357357+358358+static void __kprobes jprobe_func(long r0, long r1)359359+{360360+ jprobe_func_called = test_func_instance;361361+ if (r0 == FUNC_ARG1 && r1 == FUNC_ARG2)362362+ test_regs_ok = true;363363+ jprobe_return();364364+}365365+366366+static struct jprobe the_jprobe = {367367+ .entry = jprobe_func,368368+};369369+370370+static int test_jprobe(long (*func)(long, long))371371+{372372+ int ret;373373+374374+ the_jprobe.kp.addr = (kprobe_opcode_t *)func;375375+ ret = register_jprobe(&the_jprobe);376376+ if (ret < 0) {377377+ pr_err("FAIL: register_jprobe failed with %d\n", ret);378378+ return ret;379379+ }380380+381381+ ret = call_test_func(func, true);382382+383383+ unregister_jprobe(&the_jprobe);384384+ the_jprobe.kp.flags = 0; /* Clear disable flag to allow reuse */385385+386386+ if (!ret)387387+ return -EINVAL;388388+ if (jprobe_func_called != test_func_instance) {389389+ pr_err("FAIL: jprobe handler function not called\n");390390+ return -EINVAL;391391+ }392392+ if (!call_test_func(func, false))393393+ return -EINVAL;394394+ if (jprobe_func_called == test_func_instance) {395395+ pr_err("FAIL: probe called after unregistering\n");396396+ return -EINVAL;397397+ }398398+399399+ return 0;400400+}401401+402402+static int __kprobes403403+kretprobe_handler(struct kretprobe_instance *ri, struct pt_regs *regs)404404+{405405+ kretprobe_handler_called = test_func_instance;406406+ if (regs_return_value(regs) == FUNC_ARG1 + FUNC_ARG2)407407+ test_regs_ok = true;408408+ return 0;409409+}410410+411411+static struct kretprobe the_kretprobe = {412412+ .handler = kretprobe_handler,413413+};414414+415415+static int test_kretprobe(long (*func)(long, long))416416+{417417+ int ret;418418+419419+ the_kretprobe.kp.addr = (kprobe_opcode_t *)func;420420+ ret = register_kretprobe(&the_kretprobe);421421+ if (ret < 0) {422422+ pr_err("FAIL: register_kretprobe failed with %d\n", ret);423423+ return ret;424424+ }425425+426426+ ret = call_test_func(func, true);427427+428428+ unregister_kretprobe(&the_kretprobe);429429+ the_kretprobe.kp.flags = 0; /* Clear disable flag to allow reuse */430430+431431+ if (!ret)432432+ return -EINVAL;433433+ if (kretprobe_handler_called != test_func_instance) {434434+ pr_err("FAIL: kretprobe handler not called\n");435435+ return -EINVAL;436436+ }437437+ if (!call_test_func(func, false))438438+ return -EINVAL;439439+ if (jprobe_func_called == test_func_instance) {440440+ pr_err("FAIL: kretprobe called after unregistering\n");441441+ return -EINVAL;442442+ }443443+444444+ return 0;445445+}446446+447447+static int run_api_tests(long (*func)(long, long))448448+{449449+ int ret;450450+451451+ pr_info(" kprobe\n");452452+ ret = test_kprobe(func);453453+ if (ret < 0)454454+ return ret;455455+456456+ pr_info(" jprobe\n");457457+ ret = test_jprobe(func);458458+ if (ret < 0)459459+ return ret;460460+461461+ pr_info(" kretprobe\n");462462+ ret = test_kretprobe(func);463463+ if (ret < 0)464464+ return ret;465465+466466+ return 0;467467+}468468+469469+470470+/*471471+ * Benchmarking472472+ */473473+474474+#if BENCHMARKING475475+476476+static void __naked benchmark_nop(void)477477+{478478+ __asm__ __volatile__ (479479+ "nop \n\t"480480+ "bx lr"481481+ );482482+}483483+484484+#ifdef CONFIG_THUMB2_KERNEL485485+#define wide ".w"486486+#else487487+#define wide488488+#endif489489+490490+static void __naked benchmark_pushpop1(void)491491+{492492+ __asm__ __volatile__ (493493+ "stmdb"wide" sp!, {r3-r11,lr} \n\t"494494+ "ldmia"wide" sp!, {r3-r11,pc}"495495+ );496496+}497497+498498+static void __naked benchmark_pushpop2(void)499499+{500500+ __asm__ __volatile__ (501501+ "stmdb"wide" sp!, {r0-r8,lr} \n\t"502502+ "ldmia"wide" sp!, {r0-r8,pc}"503503+ );504504+}505505+506506+static void __naked benchmark_pushpop3(void)507507+{508508+ __asm__ __volatile__ (509509+ "stmdb"wide" sp!, {r4,lr} \n\t"510510+ "ldmia"wide" sp!, {r4,pc}"511511+ );512512+}513513+514514+static void __naked benchmark_pushpop4(void)515515+{516516+ __asm__ __volatile__ (517517+ "stmdb"wide" sp!, {r0,lr} \n\t"518518+ "ldmia"wide" sp!, {r0,pc}"519519+ );520520+}521521+522522+523523+#ifdef CONFIG_THUMB2_KERNEL524524+525525+static void __naked benchmark_pushpop_thumb(void)526526+{527527+ __asm__ __volatile__ (528528+ "push.n {r0-r7,lr} \n\t"529529+ "pop.n {r0-r7,pc}"530530+ );531531+}532532+533533+#endif534534+535535+static int __kprobes536536+benchmark_pre_handler(struct kprobe *p, struct pt_regs *regs)537537+{538538+ return 0;539539+}540540+541541+static int benchmark(void(*fn)(void))542542+{543543+ unsigned n, i, t, t0;544544+545545+ for (n = 1000; ; n *= 2) {546546+ t0 = sched_clock();547547+ for (i = n; i > 0; --i)548548+ fn();549549+ t = sched_clock() - t0;550550+ if (t >= 250000000)551551+ break; /* Stop once we took more than 0.25 seconds */552552+ }553553+ return t / n; /* Time for one iteration in nanoseconds */554554+};555555+556556+static int kprobe_benchmark(void(*fn)(void), unsigned offset)557557+{558558+ struct kprobe k = {559559+ .addr = (kprobe_opcode_t *)((uintptr_t)fn + offset),560560+ .pre_handler = benchmark_pre_handler,561561+ };562562+563563+ int ret = register_kprobe(&k);564564+ if (ret < 0) {565565+ pr_err("FAIL: register_kprobe failed with %d\n", ret);566566+ return ret;567567+ }568568+569569+ ret = benchmark(fn);570570+571571+ unregister_kprobe(&k);572572+ return ret;573573+};574574+575575+struct benchmarks {576576+ void (*fn)(void);577577+ unsigned offset;578578+ const char *title;579579+};580580+581581+static int run_benchmarks(void)582582+{583583+ int ret;584584+ struct benchmarks list[] = {585585+ {&benchmark_nop, 0, "nop"},586586+ /*587587+ * benchmark_pushpop{1,3} will have the optimised588588+ * instruction emulation, whilst benchmark_pushpop{2,4} will589589+ * be the equivalent unoptimised instructions.590590+ */591591+ {&benchmark_pushpop1, 0, "stmdb sp!, {r3-r11,lr}"},592592+ {&benchmark_pushpop1, 4, "ldmia sp!, {r3-r11,pc}"},593593+ {&benchmark_pushpop2, 0, "stmdb sp!, {r0-r8,lr}"},594594+ {&benchmark_pushpop2, 4, "ldmia sp!, {r0-r8,pc}"},595595+ {&benchmark_pushpop3, 0, "stmdb sp!, {r4,lr}"},596596+ {&benchmark_pushpop3, 4, "ldmia sp!, {r4,pc}"},597597+ {&benchmark_pushpop4, 0, "stmdb sp!, {r0,lr}"},598598+ {&benchmark_pushpop4, 4, "ldmia sp!, {r0,pc}"},599599+#ifdef CONFIG_THUMB2_KERNEL600600+ {&benchmark_pushpop_thumb, 0, "push.n {r0-r7,lr}"},601601+ {&benchmark_pushpop_thumb, 2, "pop.n {r0-r7,pc}"},602602+#endif603603+ {0}604604+ };605605+606606+ struct benchmarks *b;607607+ for (b = list; b->fn; ++b) {608608+ ret = kprobe_benchmark(b->fn, b->offset);609609+ if (ret < 0)610610+ return ret;611611+ pr_info(" %dns for kprobe %s\n", ret, b->title);612612+ }613613+614614+ pr_info("\n");615615+ return 0;616616+}617617+618618+#endif /* BENCHMARKING */619619+620620+621621+/*622622+ * Decoding table self-consistency tests623623+ */624624+625625+static const int decode_struct_sizes[NUM_DECODE_TYPES] = {626626+ [DECODE_TYPE_TABLE] = sizeof(struct decode_table),627627+ [DECODE_TYPE_CUSTOM] = sizeof(struct decode_custom),628628+ [DECODE_TYPE_SIMULATE] = sizeof(struct decode_simulate),629629+ [DECODE_TYPE_EMULATE] = sizeof(struct decode_emulate),630630+ [DECODE_TYPE_OR] = sizeof(struct decode_or),631631+ [DECODE_TYPE_REJECT] = sizeof(struct decode_reject)632632+};633633+634634+static int table_iter(const union decode_item *table,635635+ int (*fn)(const struct decode_header *, void *),636636+ void *args)637637+{638638+ const struct decode_header *h = (struct decode_header *)table;639639+ int result;640640+641641+ for (;;) {642642+ enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;643643+644644+ if (type == DECODE_TYPE_END)645645+ return 0;646646+647647+ result = fn(h, args);648648+ if (result)649649+ return result;650650+651651+ h = (struct decode_header *)652652+ ((uintptr_t)h + decode_struct_sizes[type]);653653+654654+ }655655+}656656+657657+static int table_test_fail(const struct decode_header *h, const char* message)658658+{659659+660660+ pr_err("FAIL: kprobes test failure \"%s\" (mask %08x, value %08x)\n",661661+ message, h->mask.bits, h->value.bits);662662+ return -EINVAL;663663+}664664+665665+struct table_test_args {666666+ const union decode_item *root_table;667667+ u32 parent_mask;668668+ u32 parent_value;669669+};670670+671671+static int table_test_fn(const struct decode_header *h, void *args)672672+{673673+ struct table_test_args *a = (struct table_test_args *)args;674674+ enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;675675+676676+ if (h->value.bits & ~h->mask.bits)677677+ return table_test_fail(h, "Match value has bits not in mask");678678+679679+ if ((h->mask.bits & a->parent_mask) != a->parent_mask)680680+ return table_test_fail(h, "Mask has bits not in parent mask");681681+682682+ if ((h->value.bits ^ a->parent_value) & a->parent_mask)683683+ return table_test_fail(h, "Value is inconsistent with parent");684684+685685+ if (type == DECODE_TYPE_TABLE) {686686+ struct decode_table *d = (struct decode_table *)h;687687+ struct table_test_args args2 = *a;688688+ args2.parent_mask = h->mask.bits;689689+ args2.parent_value = h->value.bits;690690+ return table_iter(d->table.table, table_test_fn, &args2);691691+ }692692+693693+ return 0;694694+}695695+696696+static int table_test(const union decode_item *table)697697+{698698+ struct table_test_args args = {699699+ .root_table = table,700700+ .parent_mask = 0,701701+ .parent_value = 0702702+ };703703+ return table_iter(args.root_table, table_test_fn, &args);704704+}705705+706706+707707+/*708708+ * Decoding table test coverage analysis709709+ *710710+ * coverage_start() builds a coverage_table which contains a list of711711+ * coverage_entry's to match each entry in the specified kprobes instruction712712+ * decoding table.713713+ *714714+ * When test cases are run, coverage_add() is called to process each case.715715+ * This looks up the corresponding entry in the coverage_table and sets it as716716+ * being matched, as well as clearing the regs flag appropriate for the test.717717+ *718718+ * After all test cases have been run, coverage_end() is called to check that719719+ * all entries in coverage_table have been matched and that all regs flags are720720+ * cleared. I.e. that all possible combinations of instructions described by721721+ * the kprobes decoding tables have had a test case executed for them.722722+ */723723+724724+bool coverage_fail;725725+726726+#define MAX_COVERAGE_ENTRIES 256727727+728728+struct coverage_entry {729729+ const struct decode_header *header;730730+ unsigned regs;731731+ unsigned nesting;732732+ char matched;733733+};734734+735735+struct coverage_table {736736+ struct coverage_entry *base;737737+ unsigned num_entries;738738+ unsigned nesting;739739+};740740+741741+struct coverage_table coverage;742742+743743+#define COVERAGE_ANY_REG (1<<0)744744+#define COVERAGE_SP (1<<1)745745+#define COVERAGE_PC (1<<2)746746+#define COVERAGE_PCWB (1<<3)747747+748748+static const char coverage_register_lookup[16] = {749749+ [REG_TYPE_ANY] = COVERAGE_ANY_REG | COVERAGE_SP | COVERAGE_PC,750750+ [REG_TYPE_SAMEAS16] = COVERAGE_ANY_REG,751751+ [REG_TYPE_SP] = COVERAGE_SP,752752+ [REG_TYPE_PC] = COVERAGE_PC,753753+ [REG_TYPE_NOSP] = COVERAGE_ANY_REG | COVERAGE_SP,754754+ [REG_TYPE_NOSPPC] = COVERAGE_ANY_REG | COVERAGE_SP | COVERAGE_PC,755755+ [REG_TYPE_NOPC] = COVERAGE_ANY_REG | COVERAGE_PC,756756+ [REG_TYPE_NOPCWB] = COVERAGE_ANY_REG | COVERAGE_PC | COVERAGE_PCWB,757757+ [REG_TYPE_NOPCX] = COVERAGE_ANY_REG,758758+ [REG_TYPE_NOSPPCX] = COVERAGE_ANY_REG | COVERAGE_SP,759759+};760760+761761+unsigned coverage_start_registers(const struct decode_header *h)762762+{763763+ unsigned regs = 0;764764+ int i;765765+ for (i = 0; i < 20; i += 4) {766766+ int r = (h->type_regs.bits >> (DECODE_TYPE_BITS + i)) & 0xf;767767+ regs |= coverage_register_lookup[r] << i;768768+ }769769+ return regs;770770+}771771+772772+static int coverage_start_fn(const struct decode_header *h, void *args)773773+{774774+ struct coverage_table *coverage = (struct coverage_table *)args;775775+ enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;776776+ struct coverage_entry *entry = coverage->base + coverage->num_entries;777777+778778+ if (coverage->num_entries == MAX_COVERAGE_ENTRIES - 1) {779779+ pr_err("FAIL: Out of space for test coverage data");780780+ return -ENOMEM;781781+ }782782+783783+ ++coverage->num_entries;784784+785785+ entry->header = h;786786+ entry->regs = coverage_start_registers(h);787787+ entry->nesting = coverage->nesting;788788+ entry->matched = false;789789+790790+ if (type == DECODE_TYPE_TABLE) {791791+ struct decode_table *d = (struct decode_table *)h;792792+ int ret;793793+ ++coverage->nesting;794794+ ret = table_iter(d->table.table, coverage_start_fn, coverage);795795+ --coverage->nesting;796796+ return ret;797797+ }798798+799799+ return 0;800800+}801801+802802+static int coverage_start(const union decode_item *table)803803+{804804+ coverage.base = kmalloc(MAX_COVERAGE_ENTRIES *805805+ sizeof(struct coverage_entry), GFP_KERNEL);806806+ coverage.num_entries = 0;807807+ coverage.nesting = 0;808808+ return table_iter(table, coverage_start_fn, &coverage);809809+}810810+811811+static void812812+coverage_add_registers(struct coverage_entry *entry, kprobe_opcode_t insn)813813+{814814+ int regs = entry->header->type_regs.bits >> DECODE_TYPE_BITS;815815+ int i;816816+ for (i = 0; i < 20; i += 4) {817817+ enum decode_reg_type reg_type = (regs >> i) & 0xf;818818+ int reg = (insn >> i) & 0xf;819819+ int flag;820820+821821+ if (!reg_type)822822+ continue;823823+824824+ if (reg == 13)825825+ flag = COVERAGE_SP;826826+ else if (reg == 15)827827+ flag = COVERAGE_PC;828828+ else829829+ flag = COVERAGE_ANY_REG;830830+ entry->regs &= ~(flag << i);831831+832832+ switch (reg_type) {833833+834834+ case REG_TYPE_NONE:835835+ case REG_TYPE_ANY:836836+ case REG_TYPE_SAMEAS16:837837+ break;838838+839839+ case REG_TYPE_SP:840840+ if (reg != 13)841841+ return;842842+ break;843843+844844+ case REG_TYPE_PC:845845+ if (reg != 15)846846+ return;847847+ break;848848+849849+ case REG_TYPE_NOSP:850850+ if (reg == 13)851851+ return;852852+ break;853853+854854+ case REG_TYPE_NOSPPC:855855+ case REG_TYPE_NOSPPCX:856856+ if (reg == 13 || reg == 15)857857+ return;858858+ break;859859+860860+ case REG_TYPE_NOPCWB:861861+ if (!is_writeback(insn))862862+ break;863863+ if (reg == 15) {864864+ entry->regs &= ~(COVERAGE_PCWB << i);865865+ return;866866+ }867867+ break;868868+869869+ case REG_TYPE_NOPC:870870+ case REG_TYPE_NOPCX:871871+ if (reg == 15)872872+ return;873873+ break;874874+ }875875+876876+ }877877+}878878+879879+static void coverage_add(kprobe_opcode_t insn)880880+{881881+ struct coverage_entry *entry = coverage.base;882882+ struct coverage_entry *end = coverage.base + coverage.num_entries;883883+ bool matched = false;884884+ unsigned nesting = 0;885885+886886+ for (; entry < end; ++entry) {887887+ const struct decode_header *h = entry->header;888888+ enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK;889889+890890+ if (entry->nesting > nesting)891891+ continue; /* Skip sub-table we didn't match */892892+893893+ if (entry->nesting < nesting)894894+ break; /* End of sub-table we were scanning */895895+896896+ if (!matched) {897897+ if ((insn & h->mask.bits) != h->value.bits)898898+ continue;899899+ entry->matched = true;900900+ }901901+902902+ switch (type) {903903+904904+ case DECODE_TYPE_TABLE:905905+ ++nesting;906906+ break;907907+908908+ case DECODE_TYPE_CUSTOM:909909+ case DECODE_TYPE_SIMULATE:910910+ case DECODE_TYPE_EMULATE:911911+ coverage_add_registers(entry, insn);912912+ return;913913+914914+ case DECODE_TYPE_OR:915915+ matched = true;916916+ break;917917+918918+ case DECODE_TYPE_REJECT:919919+ default:920920+ return;921921+ }922922+923923+ }924924+}925925+926926+static void coverage_end(void)927927+{928928+ struct coverage_entry *entry = coverage.base;929929+ struct coverage_entry *end = coverage.base + coverage.num_entries;930930+931931+ for (; entry < end; ++entry) {932932+ u32 mask = entry->header->mask.bits;933933+ u32 value = entry->header->value.bits;934934+935935+ if (entry->regs) {936936+ pr_err("FAIL: Register test coverage missing for %08x %08x (%05x)\n",937937+ mask, value, entry->regs);938938+ coverage_fail = true;939939+ }940940+ if (!entry->matched) {941941+ pr_err("FAIL: Test coverage entry missing for %08x %08x\n",942942+ mask, value);943943+ coverage_fail = true;944944+ }945945+ }946946+947947+ kfree(coverage.base);948948+}949949+950950+951951+/*952952+ * Framework for instruction set test cases953953+ */954954+955955+void __naked __kprobes_test_case_start(void)956956+{957957+ __asm__ __volatile__ (958958+ "stmdb sp!, {r4-r11} \n\t"959959+ "sub sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"960960+ "bic r0, lr, #1 @ r0 = inline title string \n\t"961961+ "mov r1, sp \n\t"962962+ "bl kprobes_test_case_start \n\t"963963+ "bx r0 \n\t"964964+ );965965+}966966+967967+#ifndef CONFIG_THUMB2_KERNEL968968+969969+void __naked __kprobes_test_case_end_32(void)970970+{971971+ __asm__ __volatile__ (972972+ "mov r4, lr \n\t"973973+ "bl kprobes_test_case_end \n\t"974974+ "cmp r0, #0 \n\t"975975+ "movne pc, r0 \n\t"976976+ "mov r0, r4 \n\t"977977+ "add sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"978978+ "ldmia sp!, {r4-r11} \n\t"979979+ "mov pc, r0 \n\t"980980+ );981981+}982982+983983+#else /* CONFIG_THUMB2_KERNEL */984984+985985+void __naked __kprobes_test_case_end_16(void)986986+{987987+ __asm__ __volatile__ (988988+ "mov r4, lr \n\t"989989+ "bl kprobes_test_case_end \n\t"990990+ "cmp r0, #0 \n\t"991991+ "bxne r0 \n\t"992992+ "mov r0, r4 \n\t"993993+ "add sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t"994994+ "ldmia sp!, {r4-r11} \n\t"995995+ "bx r0 \n\t"996996+ );997997+}998998+999999+void __naked __kprobes_test_case_end_32(void)10001000+{10011001+ __asm__ __volatile__ (10021002+ ".arm \n\t"10031003+ "orr lr, lr, #1 @ will return to Thumb code \n\t"10041004+ "ldr pc, 1f \n\t"10051005+ "1: \n\t"10061006+ ".word __kprobes_test_case_end_16 \n\t"10071007+ );10081008+}10091009+10101010+#endif10111011+10121012+10131013+int kprobe_test_flags;10141014+int kprobe_test_cc_position;10151015+10161016+static int test_try_count;10171017+static int test_pass_count;10181018+static int test_fail_count;10191019+10201020+static struct pt_regs initial_regs;10211021+static struct pt_regs expected_regs;10221022+static struct pt_regs result_regs;10231023+10241024+static u32 expected_memory[TEST_MEMORY_SIZE/sizeof(u32)];10251025+10261026+static const char *current_title;10271027+static struct test_arg *current_args;10281028+static u32 *current_stack;10291029+static uintptr_t current_branch_target;10301030+10311031+static uintptr_t current_code_start;10321032+static kprobe_opcode_t current_instruction;10331033+10341034+10351035+#define TEST_CASE_PASSED -110361036+#define TEST_CASE_FAILED -210371037+10381038+static int test_case_run_count;10391039+static bool test_case_is_thumb;10401040+static int test_instance;10411041+10421042+/*10431043+ * We ignore the state of the imprecise abort disable flag (CPSR.A) because this10441044+ * can change randomly as the kernel doesn't take care to preserve or initialise10451045+ * this across context switches. Also, with Security Extentions, the flag may10461046+ * not be under control of the kernel; for this reason we ignore the state of10471047+ * the FIQ disable flag CPSR.F as well.10481048+ */10491049+#define PSR_IGNORE_BITS (PSR_A_BIT | PSR_F_BIT)10501050+10511051+static unsigned long test_check_cc(int cc, unsigned long cpsr)10521052+{10531053+ unsigned long temp;10541054+10551055+ switch (cc) {10561056+ case 0x0: /* eq */10571057+ return cpsr & PSR_Z_BIT;10581058+10591059+ case 0x1: /* ne */10601060+ return (~cpsr) & PSR_Z_BIT;10611061+10621062+ case 0x2: /* cs */10631063+ return cpsr & PSR_C_BIT;10641064+10651065+ case 0x3: /* cc */10661066+ return (~cpsr) & PSR_C_BIT;10671067+10681068+ case 0x4: /* mi */10691069+ return cpsr & PSR_N_BIT;10701070+10711071+ case 0x5: /* pl */10721072+ return (~cpsr) & PSR_N_BIT;10731073+10741074+ case 0x6: /* vs */10751075+ return cpsr & PSR_V_BIT;10761076+10771077+ case 0x7: /* vc */10781078+ return (~cpsr) & PSR_V_BIT;10791079+10801080+ case 0x8: /* hi */10811081+ cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */10821082+ return cpsr & PSR_C_BIT;10831083+10841084+ case 0x9: /* ls */10851085+ cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */10861086+ return (~cpsr) & PSR_C_BIT;10871087+10881088+ case 0xa: /* ge */10891089+ cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */10901090+ return (~cpsr) & PSR_N_BIT;10911091+10921092+ case 0xb: /* lt */10931093+ cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */10941094+ return cpsr & PSR_N_BIT;10951095+10961096+ case 0xc: /* gt */10971097+ temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */10981098+ temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */10991099+ return (~temp) & PSR_N_BIT;11001100+11011101+ case 0xd: /* le */11021102+ temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */11031103+ temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */11041104+ return temp & PSR_N_BIT;11051105+11061106+ case 0xe: /* al */11071107+ case 0xf: /* unconditional */11081108+ return true;11091109+ }11101110+ BUG();11111111+ return false;11121112+}11131113+11141114+static int is_last_scenario;11151115+static int probe_should_run; /* 0 = no, 1 = yes, -1 = unknown */11161116+static int memory_needs_checking;11171117+11181118+static unsigned long test_context_cpsr(int scenario)11191119+{11201120+ unsigned long cpsr;11211121+11221122+ probe_should_run = 1;11231123+11241124+ /* Default case is that we cycle through 16 combinations of flags */11251125+ cpsr = (scenario & 0xf) << 28; /* N,Z,C,V flags */11261126+ cpsr |= (scenario & 0xf) << 16; /* GE flags */11271127+ cpsr |= (scenario & 0x1) << 27; /* Toggle Q flag */11281128+11291129+ if (!test_case_is_thumb) {11301130+ /* Testing ARM code */11311131+ probe_should_run = test_check_cc(current_instruction >> 28, cpsr) != 0;11321132+ if (scenario == 15)11331133+ is_last_scenario = true;11341134+11351135+ } else if (kprobe_test_flags & TEST_FLAG_NO_ITBLOCK) {11361136+ /* Testing Thumb code without setting ITSTATE */11371137+ if (kprobe_test_cc_position) {11381138+ int cc = (current_instruction >> kprobe_test_cc_position) & 0xf;11391139+ probe_should_run = test_check_cc(cc, cpsr) != 0;11401140+ }11411141+11421142+ if (scenario == 15)11431143+ is_last_scenario = true;11441144+11451145+ } else if (kprobe_test_flags & TEST_FLAG_FULL_ITBLOCK) {11461146+ /* Testing Thumb code with all combinations of ITSTATE */11471147+ unsigned x = (scenario >> 4);11481148+ unsigned cond_base = x % 7; /* ITSTATE<7:5> */11491149+ unsigned mask = x / 7 + 2; /* ITSTATE<4:0>, bits reversed */11501150+11511151+ if (mask > 0x1f) {11521152+ /* Finish by testing state from instruction 'itt al' */11531153+ cond_base = 7;11541154+ mask = 0x4;11551155+ if ((scenario & 0xf) == 0xf)11561156+ is_last_scenario = true;11571157+ }11581158+11591159+ cpsr |= cond_base << 13; /* ITSTATE<7:5> */11601160+ cpsr |= (mask & 0x1) << 12; /* ITSTATE<4> */11611161+ cpsr |= (mask & 0x2) << 10; /* ITSTATE<3> */11621162+ cpsr |= (mask & 0x4) << 8; /* ITSTATE<2> */11631163+ cpsr |= (mask & 0x8) << 23; /* ITSTATE<1> */11641164+ cpsr |= (mask & 0x10) << 21; /* ITSTATE<0> */11651165+11661166+ probe_should_run = test_check_cc((cpsr >> 12) & 0xf, cpsr) != 0;11671167+11681168+ } else {11691169+ /* Testing Thumb code with several combinations of ITSTATE */11701170+ switch (scenario) {11711171+ case 16: /* Clear NZCV flags and 'it eq' state (false as Z=0) */11721172+ cpsr = 0x00000800;11731173+ probe_should_run = 0;11741174+ break;11751175+ case 17: /* Set NZCV flags and 'it vc' state (false as V=1) */11761176+ cpsr = 0xf0007800;11771177+ probe_should_run = 0;11781178+ break;11791179+ case 18: /* Clear NZCV flags and 'it ls' state (true as C=0) */11801180+ cpsr = 0x00009800;11811181+ break;11821182+ case 19: /* Set NZCV flags and 'it cs' state (true as C=1) */11831183+ cpsr = 0xf0002800;11841184+ is_last_scenario = true;11851185+ break;11861186+ }11871187+ }11881188+11891189+ return cpsr;11901190+}11911191+11921192+static void setup_test_context(struct pt_regs *regs)11931193+{11941194+ int scenario = test_case_run_count>>1;11951195+ unsigned long val;11961196+ struct test_arg *args;11971197+ int i;11981198+11991199+ is_last_scenario = false;12001200+ memory_needs_checking = false;12011201+12021202+ /* Initialise test memory on stack */12031203+ val = (scenario & 1) ? VALM : ~VALM;12041204+ for (i = 0; i < TEST_MEMORY_SIZE / sizeof(current_stack[0]); ++i)12051205+ current_stack[i] = val + (i << 8);12061206+ /* Put target of branch on stack for tests which load PC from memory */12071207+ if (current_branch_target)12081208+ current_stack[15] = current_branch_target;12091209+ /* Put a value for SP on stack for tests which load SP from memory */12101210+ current_stack[13] = (u32)current_stack + 120;12111211+12121212+ /* Initialise register values to their default state */12131213+ val = (scenario & 2) ? VALR : ~VALR;12141214+ for (i = 0; i < 13; ++i)12151215+ regs->uregs[i] = val ^ (i << 8);12161216+ regs->ARM_lr = val ^ (14 << 8);12171217+ regs->ARM_cpsr &= ~(APSR_MASK | PSR_IT_MASK);12181218+ regs->ARM_cpsr |= test_context_cpsr(scenario);12191219+12201220+ /* Perform testcase specific register setup */12211221+ args = current_args;12221222+ for (; args[0].type != ARG_TYPE_END; ++args)12231223+ switch (args[0].type) {12241224+ case ARG_TYPE_REG: {12251225+ struct test_arg_regptr *arg =12261226+ (struct test_arg_regptr *)args;12271227+ regs->uregs[arg->reg] = arg->val;12281228+ break;12291229+ }12301230+ case ARG_TYPE_PTR: {12311231+ struct test_arg_regptr *arg =12321232+ (struct test_arg_regptr *)args;12331233+ regs->uregs[arg->reg] =12341234+ (unsigned long)current_stack + arg->val;12351235+ memory_needs_checking = true;12361236+ break;12371237+ }12381238+ case ARG_TYPE_MEM: {12391239+ struct test_arg_mem *arg = (struct test_arg_mem *)args;12401240+ current_stack[arg->index] = arg->val;12411241+ break;12421242+ }12431243+ default:12441244+ break;12451245+ }12461246+}12471247+12481248+struct test_probe {12491249+ struct kprobe kprobe;12501250+ bool registered;12511251+ int hit;12521252+};12531253+12541254+static void unregister_test_probe(struct test_probe *probe)12551255+{12561256+ if (probe->registered) {12571257+ unregister_kprobe(&probe->kprobe);12581258+ probe->kprobe.flags = 0; /* Clear disable flag to allow reuse */12591259+ }12601260+ probe->registered = false;12611261+}12621262+12631263+static int register_test_probe(struct test_probe *probe)12641264+{12651265+ int ret;12661266+12671267+ if (probe->registered)12681268+ BUG();12691269+12701270+ ret = register_kprobe(&probe->kprobe);12711271+ if (ret >= 0) {12721272+ probe->registered = true;12731273+ probe->hit = -1;12741274+ }12751275+ return ret;12761276+}12771277+12781278+static int __kprobes12791279+test_before_pre_handler(struct kprobe *p, struct pt_regs *regs)12801280+{12811281+ container_of(p, struct test_probe, kprobe)->hit = test_instance;12821282+ return 0;12831283+}12841284+12851285+static void __kprobes12861286+test_before_post_handler(struct kprobe *p, struct pt_regs *regs,12871287+ unsigned long flags)12881288+{12891289+ setup_test_context(regs);12901290+ initial_regs = *regs;12911291+ initial_regs.ARM_cpsr &= ~PSR_IGNORE_BITS;12921292+}12931293+12941294+static int __kprobes12951295+test_case_pre_handler(struct kprobe *p, struct pt_regs *regs)12961296+{12971297+ container_of(p, struct test_probe, kprobe)->hit = test_instance;12981298+ return 0;12991299+}13001300+13011301+static int __kprobes13021302+test_after_pre_handler(struct kprobe *p, struct pt_regs *regs)13031303+{13041304+ if (container_of(p, struct test_probe, kprobe)->hit == test_instance)13051305+ return 0; /* Already run for this test instance */13061306+13071307+ result_regs = *regs;13081308+ result_regs.ARM_cpsr &= ~PSR_IGNORE_BITS;13091309+13101310+ /* Undo any changes done to SP by the test case */13111311+ regs->ARM_sp = (unsigned long)current_stack;13121312+13131313+ container_of(p, struct test_probe, kprobe)->hit = test_instance;13141314+ return 0;13151315+}13161316+13171317+static struct test_probe test_before_probe = {13181318+ .kprobe.pre_handler = test_before_pre_handler,13191319+ .kprobe.post_handler = test_before_post_handler,13201320+};13211321+13221322+static struct test_probe test_case_probe = {13231323+ .kprobe.pre_handler = test_case_pre_handler,13241324+};13251325+13261326+static struct test_probe test_after_probe = {13271327+ .kprobe.pre_handler = test_after_pre_handler,13281328+};13291329+13301330+static struct test_probe test_after2_probe = {13311331+ .kprobe.pre_handler = test_after_pre_handler,13321332+};13331333+13341334+static void test_case_cleanup(void)13351335+{13361336+ unregister_test_probe(&test_before_probe);13371337+ unregister_test_probe(&test_case_probe);13381338+ unregister_test_probe(&test_after_probe);13391339+ unregister_test_probe(&test_after2_probe);13401340+}13411341+13421342+static void print_registers(struct pt_regs *regs)13431343+{13441344+ pr_err("r0 %08lx | r1 %08lx | r2 %08lx | r3 %08lx\n",13451345+ regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, regs->ARM_r3);13461346+ pr_err("r4 %08lx | r5 %08lx | r6 %08lx | r7 %08lx\n",13471347+ regs->ARM_r4, regs->ARM_r5, regs->ARM_r6, regs->ARM_r7);13481348+ pr_err("r8 %08lx | r9 %08lx | r10 %08lx | r11 %08lx\n",13491349+ regs->ARM_r8, regs->ARM_r9, regs->ARM_r10, regs->ARM_fp);13501350+ pr_err("r12 %08lx | sp %08lx | lr %08lx | pc %08lx\n",13511351+ regs->ARM_ip, regs->ARM_sp, regs->ARM_lr, regs->ARM_pc);13521352+ pr_err("cpsr %08lx\n", regs->ARM_cpsr);13531353+}13541354+13551355+static void print_memory(u32 *mem, size_t size)13561356+{13571357+ int i;13581358+ for (i = 0; i < size / sizeof(u32); i += 4)13591359+ pr_err("%08x %08x %08x %08x\n", mem[i], mem[i+1],13601360+ mem[i+2], mem[i+3]);13611361+}13621362+13631363+static size_t expected_memory_size(u32 *sp)13641364+{13651365+ size_t size = sizeof(expected_memory);13661366+ int offset = (uintptr_t)sp - (uintptr_t)current_stack;13671367+ if (offset > 0)13681368+ size -= offset;13691369+ return size;13701370+}13711371+13721372+static void test_case_failed(const char *message)13731373+{13741374+ test_case_cleanup();13751375+13761376+ pr_err("FAIL: %s\n", message);13771377+ pr_err("FAIL: Test %s\n", current_title);13781378+ pr_err("FAIL: Scenario %d\n", test_case_run_count >> 1);13791379+}13801380+13811381+static unsigned long next_instruction(unsigned long pc)13821382+{13831383+#ifdef CONFIG_THUMB2_KERNEL13841384+ if ((pc & 1) && !is_wide_instruction(*(u16 *)(pc - 1)))13851385+ return pc + 2;13861386+ else13871387+#endif13881388+ return pc + 4;13891389+}13901390+13911391+static uintptr_t __used kprobes_test_case_start(const char *title, void *stack)13921392+{13931393+ struct test_arg *args;13941394+ struct test_arg_end *end_arg;13951395+ unsigned long test_code;13961396+13971397+ args = (struct test_arg *)PTR_ALIGN(title + strlen(title) + 1, 4);13981398+13991399+ current_title = title;14001400+ current_args = args;14011401+ current_stack = stack;14021402+14031403+ ++test_try_count;14041404+14051405+ while (args->type != ARG_TYPE_END)14061406+ ++args;14071407+ end_arg = (struct test_arg_end *)args;14081408+14091409+ test_code = (unsigned long)(args + 1); /* Code starts after args */14101410+14111411+ test_case_is_thumb = end_arg->flags & ARG_FLAG_THUMB;14121412+ if (test_case_is_thumb)14131413+ test_code |= 1;14141414+14151415+ current_code_start = test_code;14161416+14171417+ current_branch_target = 0;14181418+ if (end_arg->branch_offset != end_arg->end_offset)14191419+ current_branch_target = test_code + end_arg->branch_offset;14201420+14211421+ test_code += end_arg->code_offset;14221422+ test_before_probe.kprobe.addr = (kprobe_opcode_t *)test_code;14231423+14241424+ test_code = next_instruction(test_code);14251425+ test_case_probe.kprobe.addr = (kprobe_opcode_t *)test_code;14261426+14271427+ if (test_case_is_thumb) {14281428+ u16 *p = (u16 *)(test_code & ~1);14291429+ current_instruction = p[0];14301430+ if (is_wide_instruction(current_instruction)) {14311431+ current_instruction <<= 16;14321432+ current_instruction |= p[1];14331433+ }14341434+ } else {14351435+ current_instruction = *(u32 *)test_code;14361436+ }14371437+14381438+ if (current_title[0] == '.')14391439+ verbose("%s\n", current_title);14401440+ else14411441+ verbose("%s\t@ %0*x\n", current_title,14421442+ test_case_is_thumb ? 4 : 8,14431443+ current_instruction);14441444+14451445+ test_code = next_instruction(test_code);14461446+ test_after_probe.kprobe.addr = (kprobe_opcode_t *)test_code;14471447+14481448+ if (kprobe_test_flags & TEST_FLAG_NARROW_INSTR) {14491449+ if (!test_case_is_thumb ||14501450+ is_wide_instruction(current_instruction)) {14511451+ test_case_failed("expected 16-bit instruction");14521452+ goto fail;14531453+ }14541454+ } else {14551455+ if (test_case_is_thumb &&14561456+ !is_wide_instruction(current_instruction)) {14571457+ test_case_failed("expected 32-bit instruction");14581458+ goto fail;14591459+ }14601460+ }14611461+14621462+ coverage_add(current_instruction);14631463+14641464+ if (end_arg->flags & ARG_FLAG_UNSUPPORTED) {14651465+ if (register_test_probe(&test_case_probe) < 0)14661466+ goto pass;14671467+ test_case_failed("registered probe for unsupported instruction");14681468+ goto fail;14691469+ }14701470+14711471+ if (end_arg->flags & ARG_FLAG_SUPPORTED) {14721472+ if (register_test_probe(&test_case_probe) >= 0)14731473+ goto pass;14741474+ test_case_failed("couldn't register probe for supported instruction");14751475+ goto fail;14761476+ }14771477+14781478+ if (register_test_probe(&test_before_probe) < 0) {14791479+ test_case_failed("register test_before_probe failed");14801480+ goto fail;14811481+ }14821482+ if (register_test_probe(&test_after_probe) < 0) {14831483+ test_case_failed("register test_after_probe failed");14841484+ goto fail;14851485+ }14861486+ if (current_branch_target) {14871487+ test_after2_probe.kprobe.addr =14881488+ (kprobe_opcode_t *)current_branch_target;14891489+ if (register_test_probe(&test_after2_probe) < 0) {14901490+ test_case_failed("register test_after2_probe failed");14911491+ goto fail;14921492+ }14931493+ }14941494+14951495+ /* Start first run of test case */14961496+ test_case_run_count = 0;14971497+ ++test_instance;14981498+ return current_code_start;14991499+pass:15001500+ test_case_run_count = TEST_CASE_PASSED;15011501+ return (uintptr_t)test_after_probe.kprobe.addr;15021502+fail:15031503+ test_case_run_count = TEST_CASE_FAILED;15041504+ return (uintptr_t)test_after_probe.kprobe.addr;15051505+}15061506+15071507+static bool check_test_results(void)15081508+{15091509+ size_t mem_size = 0;15101510+ u32 *mem = 0;15111511+15121512+ if (memcmp(&expected_regs, &result_regs, sizeof(expected_regs))) {15131513+ test_case_failed("registers differ");15141514+ goto fail;15151515+ }15161516+15171517+ if (memory_needs_checking) {15181518+ mem = (u32 *)result_regs.ARM_sp;15191519+ mem_size = expected_memory_size(mem);15201520+ if (memcmp(expected_memory, mem, mem_size)) {15211521+ test_case_failed("test memory differs");15221522+ goto fail;15231523+ }15241524+ }15251525+15261526+ return true;15271527+15281528+fail:15291529+ pr_err("initial_regs:\n");15301530+ print_registers(&initial_regs);15311531+ pr_err("expected_regs:\n");15321532+ print_registers(&expected_regs);15331533+ pr_err("result_regs:\n");15341534+ print_registers(&result_regs);15351535+15361536+ if (mem) {15371537+ pr_err("current_stack=%p\n", current_stack);15381538+ pr_err("expected_memory:\n");15391539+ print_memory(expected_memory, mem_size);15401540+ pr_err("result_memory:\n");15411541+ print_memory(mem, mem_size);15421542+ }15431543+15441544+ return false;15451545+}15461546+15471547+static uintptr_t __used kprobes_test_case_end(void)15481548+{15491549+ if (test_case_run_count < 0) {15501550+ if (test_case_run_count == TEST_CASE_PASSED)15511551+ /* kprobes_test_case_start did all the needed testing */15521552+ goto pass;15531553+ else15541554+ /* kprobes_test_case_start failed */15551555+ goto fail;15561556+ }15571557+15581558+ if (test_before_probe.hit != test_instance) {15591559+ test_case_failed("test_before_handler not run");15601560+ goto fail;15611561+ }15621562+15631563+ if (test_after_probe.hit != test_instance &&15641564+ test_after2_probe.hit != test_instance) {15651565+ test_case_failed("test_after_handler not run");15661566+ goto fail;15671567+ }15681568+15691569+ /*15701570+ * Even numbered test runs ran without a probe on the test case so15711571+ * we can gather reference results. The subsequent odd numbered run15721572+ * will have the probe inserted.15731573+ */15741574+ if ((test_case_run_count & 1) == 0) {15751575+ /* Save results from run without probe */15761576+ u32 *mem = (u32 *)result_regs.ARM_sp;15771577+ expected_regs = result_regs;15781578+ memcpy(expected_memory, mem, expected_memory_size(mem));15791579+15801580+ /* Insert probe onto test case instruction */15811581+ if (register_test_probe(&test_case_probe) < 0) {15821582+ test_case_failed("register test_case_probe failed");15831583+ goto fail;15841584+ }15851585+ } else {15861586+ /* Check probe ran as expected */15871587+ if (probe_should_run == 1) {15881588+ if (test_case_probe.hit != test_instance) {15891589+ test_case_failed("test_case_handler not run");15901590+ goto fail;15911591+ }15921592+ } else if (probe_should_run == 0) {15931593+ if (test_case_probe.hit == test_instance) {15941594+ test_case_failed("test_case_handler ran");15951595+ goto fail;15961596+ }15971597+ }15981598+15991599+ /* Remove probe for any subsequent reference run */16001600+ unregister_test_probe(&test_case_probe);16011601+16021602+ if (!check_test_results())16031603+ goto fail;16041604+16051605+ if (is_last_scenario)16061606+ goto pass;16071607+ }16081608+16091609+ /* Do next test run */16101610+ ++test_case_run_count;16111611+ ++test_instance;16121612+ return current_code_start;16131613+fail:16141614+ ++test_fail_count;16151615+ goto end;16161616+pass:16171617+ ++test_pass_count;16181618+end:16191619+ test_case_cleanup();16201620+ return 0;16211621+}16221622+16231623+16241624+/*16251625+ * Top level test functions16261626+ */16271627+16281628+static int run_test_cases(void (*tests)(void), const union decode_item *table)16291629+{16301630+ int ret;16311631+16321632+ pr_info(" Check decoding tables\n");16331633+ ret = table_test(table);16341634+ if (ret)16351635+ return ret;16361636+16371637+ pr_info(" Run test cases\n");16381638+ ret = coverage_start(table);16391639+ if (ret)16401640+ return ret;16411641+16421642+ tests();16431643+16441644+ coverage_end();16451645+ return 0;16461646+}16471647+16481648+16491649+static int __init run_all_tests(void)16501650+{16511651+ int ret = 0;16521652+16531653+ pr_info("Begining kprobe tests...\n");16541654+16551655+#ifndef CONFIG_THUMB2_KERNEL16561656+16571657+ pr_info("Probe ARM code\n");16581658+ ret = run_api_tests(arm_func);16591659+ if (ret)16601660+ goto out;16611661+16621662+ pr_info("ARM instruction simulation\n");16631663+ ret = run_test_cases(kprobe_arm_test_cases, kprobe_decode_arm_table);16641664+ if (ret)16651665+ goto out;16661666+16671667+#else /* CONFIG_THUMB2_KERNEL */16681668+16691669+ pr_info("Probe 16-bit Thumb code\n");16701670+ ret = run_api_tests(thumb16_func);16711671+ if (ret)16721672+ goto out;16731673+16741674+ pr_info("Probe 32-bit Thumb code, even halfword\n");16751675+ ret = run_api_tests(thumb32even_func);16761676+ if (ret)16771677+ goto out;16781678+16791679+ pr_info("Probe 32-bit Thumb code, odd halfword\n");16801680+ ret = run_api_tests(thumb32odd_func);16811681+ if (ret)16821682+ goto out;16831683+16841684+ pr_info("16-bit Thumb instruction simulation\n");16851685+ ret = run_test_cases(kprobe_thumb16_test_cases,16861686+ kprobe_decode_thumb16_table);16871687+ if (ret)16881688+ goto out;16891689+16901690+ pr_info("32-bit Thumb instruction simulation\n");16911691+ ret = run_test_cases(kprobe_thumb32_test_cases,16921692+ kprobe_decode_thumb32_table);16931693+ if (ret)16941694+ goto out;16951695+#endif16961696+16971697+ pr_info("Total instruction simulation tests=%d, pass=%d fail=%d\n",16981698+ test_try_count, test_pass_count, test_fail_count);16991699+ if (test_fail_count) {17001700+ ret = -EINVAL;17011701+ goto out;17021702+ }17031703+17041704+#if BENCHMARKING17051705+ pr_info("Benchmarks\n");17061706+ ret = run_benchmarks();17071707+ if (ret)17081708+ goto out;17091709+#endif17101710+17111711+#if __LINUX_ARM_ARCH__ >= 717121712+ /* We are able to run all test cases so coverage should be complete */17131713+ if (coverage_fail) {17141714+ pr_err("FAIL: Test coverage checks failed\n");17151715+ ret = -EINVAL;17161716+ goto out;17171717+ }17181718+#endif17191719+17201720+out:17211721+ if (ret == 0)17221722+ pr_info("Finished kprobe tests OK\n");17231723+ else17241724+ pr_err("kprobe tests failed\n");17251725+17261726+ return ret;17271727+}17281728+17291729+17301730+/*17311731+ * Module setup17321732+ */17331733+17341734+#ifdef MODULE17351735+17361736+static void __exit kprobe_test_exit(void)17371737+{17381738+}17391739+17401740+module_init(run_all_tests)17411741+module_exit(kprobe_test_exit)17421742+MODULE_LICENSE("GPL");17431743+17441744+#else /* !MODULE */17451745+17461746+late_initcall(run_all_tests);17471747+17481748+#endif
+392
arch/arm/kernel/kprobes-test.h
···11+/*22+ * arch/arm/kernel/kprobes-test.h33+ *44+ * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>.55+ *66+ * This program is free software; you can redistribute it and/or modify77+ * it under the terms of the GNU General Public License version 2 as88+ * published by the Free Software Foundation.99+ */1010+1111+#define VERBOSE 0 /* Set to '1' for more logging of test cases */1212+1313+#ifdef CONFIG_THUMB2_KERNEL1414+#define NORMAL_ISA "16"1515+#else1616+#define NORMAL_ISA "32"1717+#endif1818+1919+2020+/* Flags used in kprobe_test_flags */2121+#define TEST_FLAG_NO_ITBLOCK (1<<0)2222+#define TEST_FLAG_FULL_ITBLOCK (1<<1)2323+#define TEST_FLAG_NARROW_INSTR (1<<2)2424+2525+extern int kprobe_test_flags;2626+extern int kprobe_test_cc_position;2727+2828+2929+#define TEST_MEMORY_SIZE 2563030+3131+3232+/*3333+ * Test case structures.3434+ *3535+ * The arguments given to test cases can be one of three types.3636+ *3737+ * ARG_TYPE_REG3838+ * Load a register with the given value.3939+ *4040+ * ARG_TYPE_PTR4141+ * Load a register with a pointer into the stack buffer (SP + given value).4242+ *4343+ * ARG_TYPE_MEM4444+ * Store the given value into the stack buffer at [SP+index].4545+ *4646+ */4747+4848+#define ARG_TYPE_END 04949+#define ARG_TYPE_REG 15050+#define ARG_TYPE_PTR 25151+#define ARG_TYPE_MEM 35252+5353+#define ARG_FLAG_UNSUPPORTED 0x015454+#define ARG_FLAG_SUPPORTED 0x025555+#define ARG_FLAG_THUMB 0x10 /* Must be 16 so TEST_ISA can be used */5656+#define ARG_FLAG_ARM 0x20 /* Must be 32 so TEST_ISA can be used */5757+5858+struct test_arg {5959+ u8 type; /* ARG_TYPE_x */6060+ u8 _padding[7];6161+};6262+6363+struct test_arg_regptr {6464+ u8 type; /* ARG_TYPE_REG or ARG_TYPE_PTR */6565+ u8 reg;6666+ u8 _padding[2];6767+ u32 val;6868+};6969+7070+struct test_arg_mem {7171+ u8 type; /* ARG_TYPE_MEM */7272+ u8 index;7373+ u8 _padding[2];7474+ u32 val;7575+};7676+7777+struct test_arg_end {7878+ u8 type; /* ARG_TYPE_END */7979+ u8 flags; /* ARG_FLAG_x */8080+ u16 code_offset;8181+ u16 branch_offset;8282+ u16 end_offset;8383+};8484+8585+8686+/*8787+ * Building blocks for test cases.8888+ *8989+ * Each test case is wrapped between TESTCASE_START and TESTCASE_END.9090+ *9191+ * To specify arguments for a test case the TEST_ARG_{REG,PTR,MEM} macros are9292+ * used followed by a terminating TEST_ARG_END.9393+ *9494+ * After this, the instruction to be tested is defined with TEST_INSTRUCTION.9595+ * Or for branches, TEST_BRANCH_B and TEST_BRANCH_F (branch forwards/backwards).9696+ *9797+ * Some specific test cases may make use of other custom constructs.9898+ */9999+100100+#if VERBOSE101101+#define verbose(fmt, ...) pr_info(fmt, ##__VA_ARGS__)102102+#else103103+#define verbose(fmt, ...)104104+#endif105105+106106+#define TEST_GROUP(title) \107107+ verbose("\n"); \108108+ verbose(title"\n"); \109109+ verbose("---------------------------------------------------------\n");110110+111111+#define TESTCASE_START(title) \112112+ __asm__ __volatile__ ( \113113+ "bl __kprobes_test_case_start \n\t" \114114+ /* don't use .asciz here as 'title' may be */ \115115+ /* multiple strings to be concatenated. */ \116116+ ".ascii "#title" \n\t" \117117+ ".byte 0 \n\t" \118118+ ".align 2 \n\t"119119+120120+#define TEST_ARG_REG(reg, val) \121121+ ".byte "__stringify(ARG_TYPE_REG)" \n\t" \122122+ ".byte "#reg" \n\t" \123123+ ".short 0 \n\t" \124124+ ".word "#val" \n\t"125125+126126+#define TEST_ARG_PTR(reg, val) \127127+ ".byte "__stringify(ARG_TYPE_PTR)" \n\t" \128128+ ".byte "#reg" \n\t" \129129+ ".short 0 \n\t" \130130+ ".word "#val" \n\t"131131+132132+#define TEST_ARG_MEM(index, val) \133133+ ".byte "__stringify(ARG_TYPE_MEM)" \n\t" \134134+ ".byte "#index" \n\t" \135135+ ".short 0 \n\t" \136136+ ".word "#val" \n\t"137137+138138+#define TEST_ARG_END(flags) \139139+ ".byte "__stringify(ARG_TYPE_END)" \n\t" \140140+ ".byte "TEST_ISA flags" \n\t" \141141+ ".short 50f-0f \n\t" \142142+ ".short 2f-0f \n\t" \143143+ ".short 99f-0f \n\t" \144144+ ".code "TEST_ISA" \n\t" \145145+ "0: \n\t"146146+147147+#define TEST_INSTRUCTION(instruction) \148148+ "50: nop \n\t" \149149+ "1: "instruction" \n\t" \150150+ " nop \n\t"151151+152152+#define TEST_BRANCH_F(instruction, xtra_dist) \153153+ TEST_INSTRUCTION(instruction) \154154+ ".if "#xtra_dist" \n\t" \155155+ " b 99f \n\t" \156156+ ".space "#xtra_dist" \n\t" \157157+ ".endif \n\t" \158158+ " b 99f \n\t" \159159+ "2: nop \n\t"160160+161161+#define TEST_BRANCH_B(instruction, xtra_dist) \162162+ " b 50f \n\t" \163163+ " b 99f \n\t" \164164+ "2: nop \n\t" \165165+ " b 99f \n\t" \166166+ ".if "#xtra_dist" \n\t" \167167+ ".space "#xtra_dist" \n\t" \168168+ ".endif \n\t" \169169+ TEST_INSTRUCTION(instruction)170170+171171+#define TESTCASE_END \172172+ "2: \n\t" \173173+ "99: \n\t" \174174+ " bl __kprobes_test_case_end_"TEST_ISA" \n\t" \175175+ ".code "NORMAL_ISA" \n\t" \176176+ : : \177177+ : "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc" \178178+ );179179+180180+181181+/*182182+ * Macros to define test cases.183183+ *184184+ * Those of the form TEST_{R,P,M}* can be used to define test cases185185+ * which take combinations of the three basic types of arguments. E.g.186186+ *187187+ * TEST_R One register argument188188+ * TEST_RR Two register arguments189189+ * TEST_RPR A register, a pointer, then a register argument190190+ *191191+ * For testing instructions which may branch, there are macros TEST_BF_*192192+ * and TEST_BB_* for branching forwards and backwards.193193+ *194194+ * TEST_SUPPORTED and TEST_UNSUPPORTED don't cause the code to be executed,195195+ * the just verify that a kprobe is or is not allowed on the given instruction.196196+ */197197+198198+#define TEST(code) \199199+ TESTCASE_START(code) \200200+ TEST_ARG_END("") \201201+ TEST_INSTRUCTION(code) \202202+ TESTCASE_END203203+204204+#define TEST_UNSUPPORTED(code) \205205+ TESTCASE_START(code) \206206+ TEST_ARG_END("|"__stringify(ARG_FLAG_UNSUPPORTED)) \207207+ TEST_INSTRUCTION(code) \208208+ TESTCASE_END209209+210210+#define TEST_SUPPORTED(code) \211211+ TESTCASE_START(code) \212212+ TEST_ARG_END("|"__stringify(ARG_FLAG_SUPPORTED)) \213213+ TEST_INSTRUCTION(code) \214214+ TESTCASE_END215215+216216+#define TEST_R(code1, reg, val, code2) \217217+ TESTCASE_START(code1 #reg code2) \218218+ TEST_ARG_REG(reg, val) \219219+ TEST_ARG_END("") \220220+ TEST_INSTRUCTION(code1 #reg code2) \221221+ TESTCASE_END222222+223223+#define TEST_RR(code1, reg1, val1, code2, reg2, val2, code3) \224224+ TESTCASE_START(code1 #reg1 code2 #reg2 code3) \225225+ TEST_ARG_REG(reg1, val1) \226226+ TEST_ARG_REG(reg2, val2) \227227+ TEST_ARG_END("") \228228+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3) \229229+ TESTCASE_END230230+231231+#define TEST_RRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\232232+ TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \233233+ TEST_ARG_REG(reg1, val1) \234234+ TEST_ARG_REG(reg2, val2) \235235+ TEST_ARG_REG(reg3, val3) \236236+ TEST_ARG_END("") \237237+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \238238+ TESTCASE_END239239+240240+#define TEST_RRRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4, reg4, val4) \241241+ TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4 #reg4) \242242+ TEST_ARG_REG(reg1, val1) \243243+ TEST_ARG_REG(reg2, val2) \244244+ TEST_ARG_REG(reg3, val3) \245245+ TEST_ARG_REG(reg4, val4) \246246+ TEST_ARG_END("") \247247+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4 #reg4) \248248+ TESTCASE_END249249+250250+#define TEST_P(code1, reg1, val1, code2) \251251+ TESTCASE_START(code1 #reg1 code2) \252252+ TEST_ARG_PTR(reg1, val1) \253253+ TEST_ARG_END("") \254254+ TEST_INSTRUCTION(code1 #reg1 code2) \255255+ TESTCASE_END256256+257257+#define TEST_PR(code1, reg1, val1, code2, reg2, val2, code3) \258258+ TESTCASE_START(code1 #reg1 code2 #reg2 code3) \259259+ TEST_ARG_PTR(reg1, val1) \260260+ TEST_ARG_REG(reg2, val2) \261261+ TEST_ARG_END("") \262262+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3) \263263+ TESTCASE_END264264+265265+#define TEST_RP(code1, reg1, val1, code2, reg2, val2, code3) \266266+ TESTCASE_START(code1 #reg1 code2 #reg2 code3) \267267+ TEST_ARG_REG(reg1, val1) \268268+ TEST_ARG_PTR(reg2, val2) \269269+ TEST_ARG_END("") \270270+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3) \271271+ TESTCASE_END272272+273273+#define TEST_PRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\274274+ TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \275275+ TEST_ARG_PTR(reg1, val1) \276276+ TEST_ARG_REG(reg2, val2) \277277+ TEST_ARG_REG(reg3, val3) \278278+ TEST_ARG_END("") \279279+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \280280+ TESTCASE_END281281+282282+#define TEST_RPR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\283283+ TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \284284+ TEST_ARG_REG(reg1, val1) \285285+ TEST_ARG_PTR(reg2, val2) \286286+ TEST_ARG_REG(reg3, val3) \287287+ TEST_ARG_END("") \288288+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \289289+ TESTCASE_END290290+291291+#define TEST_RRP(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\292292+ TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \293293+ TEST_ARG_REG(reg1, val1) \294294+ TEST_ARG_REG(reg2, val2) \295295+ TEST_ARG_PTR(reg3, val3) \296296+ TEST_ARG_END("") \297297+ TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \298298+ TESTCASE_END299299+300300+#define TEST_BF_P(code1, reg1, val1, code2) \301301+ TESTCASE_START(code1 #reg1 code2) \302302+ TEST_ARG_PTR(reg1, val1) \303303+ TEST_ARG_END("") \304304+ TEST_BRANCH_F(code1 #reg1 code2, 0) \305305+ TESTCASE_END306306+307307+#define TEST_BF_X(code, xtra_dist) \308308+ TESTCASE_START(code) \309309+ TEST_ARG_END("") \310310+ TEST_BRANCH_F(code, xtra_dist) \311311+ TESTCASE_END312312+313313+#define TEST_BB_X(code, xtra_dist) \314314+ TESTCASE_START(code) \315315+ TEST_ARG_END("") \316316+ TEST_BRANCH_B(code, xtra_dist) \317317+ TESTCASE_END318318+319319+#define TEST_BF_RX(code1, reg, val, code2, xtra_dist) \320320+ TESTCASE_START(code1 #reg code2) \321321+ TEST_ARG_REG(reg, val) \322322+ TEST_ARG_END("") \323323+ TEST_BRANCH_F(code1 #reg code2, xtra_dist) \324324+ TESTCASE_END325325+326326+#define TEST_BB_RX(code1, reg, val, code2, xtra_dist) \327327+ TESTCASE_START(code1 #reg code2) \328328+ TEST_ARG_REG(reg, val) \329329+ TEST_ARG_END("") \330330+ TEST_BRANCH_B(code1 #reg code2, xtra_dist) \331331+ TESTCASE_END332332+333333+#define TEST_BF(code) TEST_BF_X(code, 0)334334+#define TEST_BB(code) TEST_BB_X(code, 0)335335+336336+#define TEST_BF_R(code1, reg, val, code2) TEST_BF_RX(code1, reg, val, code2, 0)337337+#define TEST_BB_R(code1, reg, val, code2) TEST_BB_RX(code1, reg, val, code2, 0)338338+339339+#define TEST_BF_RR(code1, reg1, val1, code2, reg2, val2, code3) \340340+ TESTCASE_START(code1 #reg1 code2 #reg2 code3) \341341+ TEST_ARG_REG(reg1, val1) \342342+ TEST_ARG_REG(reg2, val2) \343343+ TEST_ARG_END("") \344344+ TEST_BRANCH_F(code1 #reg1 code2 #reg2 code3, 0) \345345+ TESTCASE_END346346+347347+#define TEST_X(code, codex) \348348+ TESTCASE_START(code) \349349+ TEST_ARG_END("") \350350+ TEST_INSTRUCTION(code) \351351+ " b 99f \n\t" \352352+ " "codex" \n\t" \353353+ TESTCASE_END354354+355355+#define TEST_RX(code1, reg, val, code2, codex) \356356+ TESTCASE_START(code1 #reg code2) \357357+ TEST_ARG_REG(reg, val) \358358+ TEST_ARG_END("") \359359+ TEST_INSTRUCTION(code1 __stringify(reg) code2) \360360+ " b 99f \n\t" \361361+ " "codex" \n\t" \362362+ TESTCASE_END363363+364364+#define TEST_RRX(code1, reg1, val1, code2, reg2, val2, code3, codex) \365365+ TESTCASE_START(code1 #reg1 code2 #reg2 code3) \366366+ TEST_ARG_REG(reg1, val1) \367367+ TEST_ARG_REG(reg2, val2) \368368+ TEST_ARG_END("") \369369+ TEST_INSTRUCTION(code1 __stringify(reg1) code2 __stringify(reg2) code3) \370370+ " b 99f \n\t" \371371+ " "codex" \n\t" \372372+ TESTCASE_END373373+374374+375375+/* Various values used in test cases... */376376+#define N(val) (val ^ 0xffffffff)377377+#define VAL1 0x12345678378378+#define VAL2 N(VAL1)379379+#define VAL3 0xa5f801380380+#define VAL4 N(VAL3)381381+#define VALM 0x456789ab382382+#define VALR 0xdeaddead383383+#define HH1 0x0123fecb384384+#define HH2 0xa9874567385385+386386+387387+#ifdef CONFIG_THUMB2_KERNEL388388+void kprobe_thumb16_test_cases(void);389389+void kprobe_thumb32_test_cases(void);390390+#else391391+void kprobe_arm_test_cases(void);392392+#endif
···1010 *1111 */12121313-#define pr_fmt(fmt) "PMU: " fmt1414-1515-#include <linux/cpumask.h>1613#include <linux/err.h>1717-#include <linux/interrupt.h>1814#include <linux/kernel.h>1915#include <linux/module.h>2020-#include <linux/of_device.h>2121-#include <linux/platform_device.h>22162317#include <asm/pmu.h>24182525-static volatile long pmu_lock;1919+/*2020+ * PMU locking to ensure mutual exclusion between different subsystems.2121+ */2222+static unsigned long pmu_lock[BITS_TO_LONGS(ARM_NUM_PMU_DEVICES)];26232727-static struct platform_device *pmu_devices[ARM_NUM_PMU_DEVICES];2828-2929-static int __devinit pmu_register(struct platform_device *pdev,3030- enum arm_pmu_type type)3131-{3232- if (type < 0 || type >= ARM_NUM_PMU_DEVICES) {3333- pr_warning("received registration request for unknown "3434- "PMU device type %d\n", type);3535- return -EINVAL;3636- }3737-3838- if (pmu_devices[type]) {3939- pr_warning("rejecting duplicate registration of PMU device "4040- "type %d.", type);4141- return -ENOSPC;4242- }4343-4444- pr_info("registered new PMU device of type %d\n", type);4545- pmu_devices[type] = pdev;4646- return 0;4747-}4848-4949-#define OF_MATCH_PMU(_name, _type) { \5050- .compatible = _name, \5151- .data = (void *)_type, \5252-}5353-5454-#define OF_MATCH_CPU(name) OF_MATCH_PMU(name, ARM_PMU_DEVICE_CPU)5555-5656-static struct of_device_id armpmu_of_device_ids[] = {5757- OF_MATCH_CPU("arm,cortex-a9-pmu"),5858- OF_MATCH_CPU("arm,cortex-a8-pmu"),5959- OF_MATCH_CPU("arm,arm1136-pmu"),6060- OF_MATCH_CPU("arm,arm1176-pmu"),6161- {},6262-};6363-6464-#define PLAT_MATCH_PMU(_name, _type) { \6565- .name = _name, \6666- .driver_data = _type, \6767-}6868-6969-#define PLAT_MATCH_CPU(_name) PLAT_MATCH_PMU(_name, ARM_PMU_DEVICE_CPU)7070-7171-static struct platform_device_id armpmu_plat_device_ids[] = {7272- PLAT_MATCH_CPU("arm-pmu"),7373- {},7474-};7575-7676-enum arm_pmu_type armpmu_device_type(struct platform_device *pdev)7777-{7878- const struct of_device_id *of_id;7979- const struct platform_device_id *pdev_id;8080-8181- /* provided by of_device_id table */8282- if (pdev->dev.of_node) {8383- of_id = of_match_device(armpmu_of_device_ids, &pdev->dev);8484- BUG_ON(!of_id);8585- return (enum arm_pmu_type)of_id->data;8686- }8787-8888- /* Provided by platform_device_id table */8989- pdev_id = platform_get_device_id(pdev);9090- BUG_ON(!pdev_id);9191- return pdev_id->driver_data;9292-}9393-9494-static int __devinit armpmu_device_probe(struct platform_device *pdev)9595-{9696- return pmu_register(pdev, armpmu_device_type(pdev));9797-}9898-9999-static struct platform_driver armpmu_driver = {100100- .driver = {101101- .name = "arm-pmu",102102- .of_match_table = armpmu_of_device_ids,103103- },104104- .probe = armpmu_device_probe,105105- .id_table = armpmu_plat_device_ids,106106-};107107-108108-static int __init register_pmu_driver(void)109109-{110110- return platform_driver_register(&armpmu_driver);111111-}112112-device_initcall(register_pmu_driver);113113-114114-struct platform_device *2424+int11525reserve_pmu(enum arm_pmu_type type)11626{117117- struct platform_device *pdev;118118-119119- if (test_and_set_bit_lock(type, &pmu_lock)) {120120- pdev = ERR_PTR(-EBUSY);121121- } else if (pmu_devices[type] == NULL) {122122- clear_bit_unlock(type, &pmu_lock);123123- pdev = ERR_PTR(-ENODEV);124124- } else {125125- pdev = pmu_devices[type];126126- }127127-128128- return pdev;2727+ return test_and_set_bit_lock(type, pmu_lock) ? -EBUSY : 0;12928}13029EXPORT_SYMBOL_GPL(reserve_pmu);13130132132-int3131+void13332release_pmu(enum arm_pmu_type type)13433{135135- if (WARN_ON(!pmu_devices[type]))136136- return -EINVAL;137137- clear_bit_unlock(type, &pmu_lock);138138- return 0;3434+ clear_bit_unlock(type, pmu_lock);13935}140140-EXPORT_SYMBOL_GPL(release_pmu);141141-142142-static int143143-set_irq_affinity(int irq,144144- unsigned int cpu)145145-{146146-#ifdef CONFIG_SMP147147- int err = irq_set_affinity(irq, cpumask_of(cpu));148148- if (err)149149- pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",150150- irq, cpu);151151- return err;152152-#else153153- return -EINVAL;154154-#endif155155-}156156-157157-static int158158-init_cpu_pmu(void)159159-{160160- int i, irqs, err = 0;161161- struct platform_device *pdev = pmu_devices[ARM_PMU_DEVICE_CPU];162162-163163- if (!pdev)164164- return -ENODEV;165165-166166- irqs = pdev->num_resources;167167-168168- /*169169- * If we have a single PMU interrupt that we can't shift, assume that170170- * we're running on a uniprocessor machine and continue.171171- */172172- if (irqs == 1 && !irq_can_set_affinity(platform_get_irq(pdev, 0)))173173- return 0;174174-175175- for (i = 0; i < irqs; ++i) {176176- err = set_irq_affinity(platform_get_irq(pdev, i), i);177177- if (err)178178- break;179179- }180180-181181- return err;182182-}183183-184184-int185185-init_pmu(enum arm_pmu_type type)186186-{187187- int err = 0;188188-189189- switch (type) {190190- case ARM_PMU_DEVICE_CPU:191191- err = init_cpu_pmu();192192- break;193193- default:194194- pr_warning("attempt to initialise PMU of unknown "195195- "type %d\n", type);196196- err = -EINVAL;197197- }198198-199199- return err;200200-}201201-EXPORT_SYMBOL_GPL(init_pmu);
+2-19
arch/arm/kernel/setup.c
···820820821821 if (__atags_pointer)822822 tags = phys_to_virt(__atags_pointer);823823- else if (mdesc->boot_params) {824824-#ifdef CONFIG_MMU825825- /*826826- * We still are executing with a minimal MMU mapping created827827- * with the presumption that the machine default for this828828- * is located in the first MB of RAM. Anything else will829829- * fault and silently hang the kernel at this point.830830- */831831- if (mdesc->boot_params < PHYS_OFFSET ||832832- mdesc->boot_params >= PHYS_OFFSET + SZ_1M) {833833- printk(KERN_WARNING834834- "Default boot params at physical 0x%08lx out of reach\n",835835- mdesc->boot_params);836836- } else837837-#endif838838- {839839- tags = phys_to_virt(mdesc->boot_params);840840- }841841- }823823+ else if (mdesc->atag_offset)824824+ tags = (void *)(PAGE_OFFSET + mdesc->atag_offset);842825843826#if defined(CONFIG_DEPRECATED_PARAM_STRUCT)844827 /*
+28-59
arch/arm/kernel/sleep.S
···88 .text991010/*1111- * Save CPU state for a suspend1212- * r1 = v:p offset1313- * r2 = suspend function arg01414- * r3 = suspend function1111+ * Save CPU state for a suspend. This saves the CPU general purpose1212+ * registers, and allocates space on the kernel stack to save the CPU1313+ * specific registers and some other data for resume.1414+ * r0 = suspend function arg01515+ * r1 = suspend function1516 */1617ENTRY(__cpu_suspend)1718 stmfd sp!, {r4 - r11, lr}1819#ifdef MULTI_CPU1920 ldr r10, =processor2020- ldr r5, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state2121- ldr ip, [r10, #CPU_DO_RESUME] @ virtual resume function2121+ ldr r4, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state2222#else2323- ldr r5, =cpu_suspend_size2424- ldr ip, =cpu_do_resume2323+ ldr r4, =cpu_suspend_size2524#endif2626- mov r6, sp @ current virtual SP2727- sub sp, sp, r5 @ allocate CPU state on stack2828- mov r0, sp @ save pointer to CPU save block2929- add ip, ip, r1 @ convert resume fn to phys3030- stmfd sp!, {r1, r6, ip} @ save v:p, virt SP, phys resume fn3131- ldr r5, =sleep_save_sp3232- add r6, sp, r1 @ convert SP to phys3333- stmfd sp!, {r2, r3} @ save suspend func arg and pointer2525+ mov r5, sp @ current virtual SP2626+ add r4, r4, #12 @ Space for pgd, virt sp, phys resume fn2727+ sub sp, sp, r4 @ allocate CPU state on stack2828+ stmfd sp!, {r0, r1} @ save suspend func arg and pointer2929+ add r0, sp, #8 @ save pointer to save block3030+ mov r1, r4 @ size of save block3131+ mov r2, r5 @ virtual SP3232+ ldr r3, =sleep_save_sp3433#ifdef CONFIG_SMP3534 ALT_SMP(mrc p15, 0, lr, c0, c0, 5)3635 ALT_UP(mov lr, #0)3736 and lr, lr, #153838- str r6, [r5, lr, lsl #2] @ save phys SP3939-#else4040- str r6, [r5] @ save phys SP3737+ add r3, r3, lr, lsl #24138#endif4242-#ifdef MULTI_CPU4343- mov lr, pc4444- ldr pc, [r10, #CPU_DO_SUSPEND] @ save CPU state4545-#else4646- bl cpu_do_suspend4747-#endif4848-4949- @ flush data cache5050-#ifdef MULTI_CACHE5151- ldr r10, =cpu_cache5252- mov lr, pc5353- ldr pc, [r10, #CACHE_FLUSH_KERN_ALL]5454-#else5555- bl __cpuc_flush_kern_all5656-#endif3939+ bl __cpu_suspend_save5740 adr lr, BSYM(cpu_suspend_abort)5841 ldmfd sp!, {r0, pc} @ call suspend fn5942ENDPROC(__cpu_suspend)6043 .ltorg61446245cpu_suspend_abort:6363- ldmia sp!, {r1 - r3} @ pop v:p, virt SP, phys resume fn4646+ ldmia sp!, {r1 - r3} @ pop phys pgd, virt SP, phys resume fn4747+ teq r0, #04848+ moveq r0, #1 @ force non-zero value6449 mov sp, r26550 ldmfd sp!, {r4 - r11, pc}6651ENDPROC(cpu_suspend_abort)67526853/*6954 * r0 = control register value7070- * r1 = v:p offset (preserved by cpu_do_resume)7171- * r2 = phys page table base7272- * r3 = L1 section flags7355 */7474-ENTRY(cpu_resume_mmu)7575- adr r4, cpu_resume_turn_mmu_on7676- mov r4, r4, lsr #207777- orr r3, r3, r4, lsl #207878- ldr r5, [r2, r4, lsl #2] @ save old mapping7979- str r3, [r2, r4, lsl #2] @ setup 1:1 mapping for mmu code8080- sub r2, r2, r18181- ldr r3, =cpu_resume_after_mmu8282- bic r1, r0, #CR_C @ ensure D-cache is disabled8383- b cpu_resume_turn_mmu_on8484-ENDPROC(cpu_resume_mmu)8585- .ltorg8656 .align 58787-cpu_resume_turn_mmu_on:8888- mcr p15, 0, r1, c1, c0, 0 @ turn on MMU, I-cache, etc8989- mrc p15, 0, r1, c0, c0, 0 @ read id reg9090- mov r1, r19191- mov r1, r15757+ENTRY(cpu_resume_mmu)5858+ ldr r3, =cpu_resume_after_mmu5959+ mcr p15, 0, r0, c1, c0, 0 @ turn on MMU, I-cache, etc6060+ mrc p15, 0, r0, c0, c0, 0 @ read id reg6161+ mov r0, r06262+ mov r0, r09263 mov pc, r3 @ jump to virtual address9393-ENDPROC(cpu_resume_turn_mmu_on)6464+ENDPROC(cpu_resume_mmu)9465cpu_resume_after_mmu:9595- str r5, [r2, r4, lsl #2] @ restore old mapping9696- mcr p15, 0, r0, c1, c0, 0 @ turn on D-cache9766 bl cpu_init @ restore the und/abt/irq banked regs9867 mov r0, #0 @ return zero on success9968 ldmfd sp!, {r4 - r11, pc}···88119 ldr r0, sleep_save_sp @ stack phys addr89120#endif90121 setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1 @ set SVC, irqs off9191- @ load v:p, stack, resume fn122122+ @ load phys pgd, stack, resume fn92123 ARM( ldmia r0!, {r1, sp, pc} )93124THUMB( ldmia r0!, {r1, r2, r3} )94125THUMB( mov sp, r2 )
+27-33
arch/arm/kernel/smp.c
···1616#include <linux/cache.h>1717#include <linux/profile.h>1818#include <linux/errno.h>1919-#include <linux/ftrace.h>2019#include <linux/mm.h>2120#include <linux/err.h>2221#include <linux/cpu.h>···3031#include <asm/cacheflush.h>3132#include <asm/cpu.h>3233#include <asm/cputype.h>3434+#include <asm/exception.h>3535+#include <asm/topology.h>3336#include <asm/mmu_context.h>3437#include <asm/pgtable.h>3538#include <asm/pgalloc.h>···4039#include <asm/tlbflush.h>4140#include <asm/ptrace.h>4241#include <asm/localtimer.h>4242+#include <asm/smp_plat.h>43434444/*4545 * as from 2.5, kernels no longer have an init_tasks structure···261259}262260#endif /* CONFIG_HOTPLUG_CPU */263261262262+int __cpu_logical_map[NR_CPUS];263263+264264+void __init smp_setup_processor_id(void)265265+{266266+ int i;267267+ u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0;268268+269269+ cpu_logical_map(0) = cpu;270270+ for (i = 1; i < NR_CPUS; ++i)271271+ cpu_logical_map(i) = i == cpu ? 0 : i;272272+273273+ printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu);274274+}275275+264276/*265277 * Called by both boot and secondaries to move global data into266278 * per-processor storage.···284268 struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid);285269286270 cpu_info->loops_per_jiffy = loops_per_jiffy;271271+272272+ store_cpu_topology(cpuid);287273}288274289275/*···376358{377359 unsigned int ncores = num_possible_cpus();378360361361+ init_cpu_topology();362362+379363 smp_store_cpu_info(smp_processor_id());380364381365 /*···457437 for (i = 0; i < NR_IPI; i++)458438 sum += __get_irq_stat(cpu, ipi_irqs[i]);459439460460-#ifdef CONFIG_LOCAL_TIMERS461461- sum += __get_irq_stat(cpu, local_timer_irqs);462462-#endif463463-464440 return sum;465441}466442···472456 evt->event_handler(evt);473457 irq_exit();474458}475475-476476-#ifdef CONFIG_LOCAL_TIMERS477477-asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs)478478-{479479- struct pt_regs *old_regs = set_irq_regs(regs);480480- int cpu = smp_processor_id();481481-482482- if (local_timer_ack()) {483483- __inc_irq_stat(cpu, local_timer_irqs);484484- ipi_timer();485485- }486486-487487- set_irq_regs(old_regs);488488-}489489-490490-void show_local_irqs(struct seq_file *p, int prec)491491-{492492- unsigned int cpu;493493-494494- seq_printf(p, "%*s: ", prec, "LOC");495495-496496- for_each_present_cpu(cpu)497497- seq_printf(p, "%10u ", __get_irq_stat(cpu, local_timer_irqs));498498-499499- seq_printf(p, " Local timer interrupts\n");500500-}501501-#endif502459503460#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST504461static void smp_timer_broadcast(const struct cpumask *mask)···523534 unsigned int cpu = smp_processor_id();524535 struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);525536526526- evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);537537+ local_timer_stop(evt);527538}528539#endif529540···555566 * Main handler for inter-processor interrupts556567 */557568asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)569569+{570570+ handle_IPI(ipinr, regs);571571+}572572+573573+void handle_IPI(int ipinr, struct pt_regs *regs)558574{559575 unsigned int cpu = smp_processor_id();560576 struct pt_regs *old_regs = set_irq_regs(regs);
···1919#include <linux/io.h>20202121#include <asm/smp_twd.h>2222+#include <asm/localtimer.h>2223#include <asm/hardware/gic.h>23242425/* set up by the platform code */2526void __iomem *twd_base;26272728static unsigned long twd_timer_rate;2929+3030+static struct clock_event_device __percpu **twd_evt;28312932static void twd_set_mode(enum clock_event_mode mode,3033 struct clock_event_device *clk)···8380 return 0;8481}85828383+void twd_timer_stop(struct clock_event_device *clk)8484+{8585+ twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk);8686+ disable_percpu_irq(clk->irq);8787+}8888+8689static void __cpuinit twd_calibrate_rate(void)8790{8891 unsigned long count;···128119 }129120}130121122122+static irqreturn_t twd_handler(int irq, void *dev_id)123123+{124124+ struct clock_event_device *evt = *(struct clock_event_device **)dev_id;125125+126126+ if (twd_timer_ack()) {127127+ evt->event_handler(evt);128128+ return IRQ_HANDLED;129129+ }130130+131131+ return IRQ_NONE;132132+}133133+131134/*132135 * Setup the local clock events for a CPU.133136 */134137void __cpuinit twd_timer_setup(struct clock_event_device *clk)135138{139139+ struct clock_event_device **this_cpu_clk;140140+141141+ if (!twd_evt) {142142+ int err;143143+144144+ twd_evt = alloc_percpu(struct clock_event_device *);145145+ if (!twd_evt) {146146+ pr_err("twd: can't allocate memory\n");147147+ return;148148+ }149149+150150+ err = request_percpu_irq(clk->irq, twd_handler,151151+ "twd", twd_evt);152152+ if (err) {153153+ pr_err("twd: can't register interrupt %d (%d)\n",154154+ clk->irq, err);155155+ return;156156+ }157157+ }158158+136159 twd_calibrate_rate();137160138161 clk->name = "local_timer";···178137 clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk);179138 clk->min_delta_ns = clockevent_delta2ns(0xf, clk);180139140140+ this_cpu_clk = __this_cpu_ptr(twd_evt);141141+ *this_cpu_clk = clk;142142+181143 clockevents_register_device(clk);182144183183- /* Make sure our local interrupt controller has this enabled */184184- gic_enable_ppi(clk->irq);145145+ enable_percpu_irq(clk->irq, 0);185146}
+72
arch/arm/kernel/suspend.c
···11+#include <linux/init.h>22+33+#include <asm/pgalloc.h>44+#include <asm/pgtable.h>55+#include <asm/memory.h>66+#include <asm/suspend.h>77+#include <asm/tlbflush.h>88+99+static pgd_t *suspend_pgd;1010+1111+extern int __cpu_suspend(unsigned long, int (*)(unsigned long));1212+extern void cpu_resume_mmu(void);1313+1414+/*1515+ * This is called by __cpu_suspend() to save the state, and do whatever1616+ * flushing is required to ensure that when the CPU goes to sleep we have1717+ * the necessary data available when the caches are not searched.1818+ */1919+void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr)2020+{2121+ *save_ptr = virt_to_phys(ptr);2222+2323+ /* This must correspond to the LDM in cpu_resume() assembly */2424+ *ptr++ = virt_to_phys(suspend_pgd);2525+ *ptr++ = sp;2626+ *ptr++ = virt_to_phys(cpu_do_resume);2727+2828+ cpu_do_suspend(ptr);2929+3030+ flush_cache_all();3131+ outer_clean_range(*save_ptr, *save_ptr + ptrsz);3232+ outer_clean_range(virt_to_phys(save_ptr),3333+ virt_to_phys(save_ptr) + sizeof(*save_ptr));3434+}3535+3636+/*3737+ * Hide the first two arguments to __cpu_suspend - these are an implementation3838+ * detail which platform code shouldn't have to know about.3939+ */4040+int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))4141+{4242+ struct mm_struct *mm = current->active_mm;4343+ int ret;4444+4545+ if (!suspend_pgd)4646+ return -EINVAL;4747+4848+ /*4949+ * Provide a temporary page table with an identity mapping for5050+ * the MMU-enable code, required for resuming. On successful5151+ * resume (indicated by a zero return code), we need to switch5252+ * back to the correct page tables.5353+ */5454+ ret = __cpu_suspend(arg, fn);5555+ if (ret == 0) {5656+ cpu_switch_mm(mm->pgd, mm);5757+ local_flush_tlb_all();5858+ }5959+6060+ return ret;6161+}6262+6363+static int __init cpu_suspend_init(void)6464+{6565+ suspend_pgd = pgd_alloc(&init_mm);6666+ if (suspend_pgd) {6767+ unsigned long addr = virt_to_phys(cpu_resume_mmu);6868+ identity_mapping_add(suspend_pgd, addr, addr + SECTION_SIZE);6969+ }7070+ return suspend_pgd ? 0 : -ENOMEM;7171+}7272+core_initcall(cpu_suspend_init);
+148
arch/arm/kernel/topology.c
···11+/*22+ * arch/arm/kernel/topology.c33+ *44+ * Copyright (C) 2011 Linaro Limited.55+ * Written by: Vincent Guittot66+ *77+ * based on arch/sh/kernel/topology.c88+ *99+ * This file is subject to the terms and conditions of the GNU General Public1010+ * License. See the file "COPYING" in the main directory of this archive1111+ * for more details.1212+ */1313+1414+#include <linux/cpu.h>1515+#include <linux/cpumask.h>1616+#include <linux/init.h>1717+#include <linux/percpu.h>1818+#include <linux/node.h>1919+#include <linux/nodemask.h>2020+#include <linux/sched.h>2121+2222+#include <asm/cputype.h>2323+#include <asm/topology.h>2424+2525+#define MPIDR_SMP_BITMASK (0x3 << 30)2626+#define MPIDR_SMP_VALUE (0x2 << 30)2727+2828+#define MPIDR_MT_BITMASK (0x1 << 24)2929+3030+/*3131+ * These masks reflect the current use of the affinity levels.3232+ * The affinity level can be up to 16 bits according to ARM ARM3333+ */3434+3535+#define MPIDR_LEVEL0_MASK 0x33636+#define MPIDR_LEVEL0_SHIFT 03737+3838+#define MPIDR_LEVEL1_MASK 0xF3939+#define MPIDR_LEVEL1_SHIFT 84040+4141+#define MPIDR_LEVEL2_MASK 0xFF4242+#define MPIDR_LEVEL2_SHIFT 164343+4444+struct cputopo_arm cpu_topology[NR_CPUS];4545+4646+const struct cpumask *cpu_coregroup_mask(unsigned int cpu)4747+{4848+ return &cpu_topology[cpu].core_sibling;4949+}5050+5151+/*5252+ * store_cpu_topology is called at boot when only one cpu is running5353+ * and with the mutex cpu_hotplug.lock locked, when several cpus have booted,5454+ * which prevents simultaneous write access to cpu_topology array5555+ */5656+void store_cpu_topology(unsigned int cpuid)5757+{5858+ struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid];5959+ unsigned int mpidr;6060+ unsigned int cpu;6161+6262+ /* If the cpu topology has been already set, just return */6363+ if (cpuid_topo->core_id != -1)6464+ return;6565+6666+ mpidr = read_cpuid_mpidr();6767+6868+ /* create cpu topology mapping */6969+ if ((mpidr & MPIDR_SMP_BITMASK) == MPIDR_SMP_VALUE) {7070+ /*7171+ * This is a multiprocessor system7272+ * multiprocessor format & multiprocessor mode field are set7373+ */7474+7575+ if (mpidr & MPIDR_MT_BITMASK) {7676+ /* core performance interdependency */7777+ cpuid_topo->thread_id = (mpidr >> MPIDR_LEVEL0_SHIFT)7878+ & MPIDR_LEVEL0_MASK;7979+ cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL1_SHIFT)8080+ & MPIDR_LEVEL1_MASK;8181+ cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL2_SHIFT)8282+ & MPIDR_LEVEL2_MASK;8383+ } else {8484+ /* largely independent cores */8585+ cpuid_topo->thread_id = -1;8686+ cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL0_SHIFT)8787+ & MPIDR_LEVEL0_MASK;8888+ cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL1_SHIFT)8989+ & MPIDR_LEVEL1_MASK;9090+ }9191+ } else {9292+ /*9393+ * This is an uniprocessor system9494+ * we are in multiprocessor format but uniprocessor system9595+ * or in the old uniprocessor format9696+ */9797+ cpuid_topo->thread_id = -1;9898+ cpuid_topo->core_id = 0;9999+ cpuid_topo->socket_id = -1;100100+ }101101+102102+ /* update core and thread sibling masks */103103+ for_each_possible_cpu(cpu) {104104+ struct cputopo_arm *cpu_topo = &cpu_topology[cpu];105105+106106+ if (cpuid_topo->socket_id == cpu_topo->socket_id) {107107+ cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);108108+ if (cpu != cpuid)109109+ cpumask_set_cpu(cpu,110110+ &cpuid_topo->core_sibling);111111+112112+ if (cpuid_topo->core_id == cpu_topo->core_id) {113113+ cpumask_set_cpu(cpuid,114114+ &cpu_topo->thread_sibling);115115+ if (cpu != cpuid)116116+ cpumask_set_cpu(cpu,117117+ &cpuid_topo->thread_sibling);118118+ }119119+ }120120+ }121121+ smp_wmb();122122+123123+ printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n",124124+ cpuid, cpu_topology[cpuid].thread_id,125125+ cpu_topology[cpuid].core_id,126126+ cpu_topology[cpuid].socket_id, mpidr);127127+}128128+129129+/*130130+ * init_cpu_topology is called at boot when only one cpu is running131131+ * which prevent simultaneous write access to cpu_topology array132132+ */133133+void init_cpu_topology(void)134134+{135135+ unsigned int cpu;136136+137137+ /* init core mask */138138+ for_each_possible_cpu(cpu) {139139+ struct cputopo_arm *cpu_topo = &(cpu_topology[cpu]);140140+141141+ cpu_topo->thread_id = -1;142142+ cpu_topo->core_id = -1;143143+ cpu_topo->socket_id = -1;144144+ cpumask_clear(&cpu_topo->core_sibling);145145+ cpumask_clear(&cpu_topo->thread_sibling);146146+ }147147+ smp_wmb();148148+}
···2222#define __ASM_ARCH_HARDWARE_H23232424#include <asm/sizes.h>2525-#include <mach/memory.h>2625#include <cfg_global.h>2726#include <mach/csp/mm_io.h>2827···3031 * *_SIZE is the size of the region3132 * *_BASE is the virtual address3233 */3333-#define RAM_START PLAT_PHYS_OFFSET3434+#define RAM_START PHYS_OFFSET34353536#define RAM_SIZE (CFG_GLOBAL_RAM_SIZE-CFG_GLOBAL_RAM_SIZE_RESERVED)3637#define RAM_BASE PAGE_OFFSET
-33
arch/arm/mach-bcmring/include/mach/memory.h
···11-/*****************************************************************************22-* Copyright 2005 - 2008 Broadcom Corporation. All rights reserved.33-*44-* Unless you and Broadcom execute a separate written software license55-* agreement governing use of this software, this software is licensed to you66-* under the terms of the GNU General Public License version 2, available at77-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").88-*99-* Notwithstanding the above, under no circumstances may you combine this1010-* software in any way with any other Broadcom software provided under a1111-* license other than the GPL, without Broadcom's express prior written1212-* consent.1313-*****************************************************************************/1414-1515-#ifndef __ASM_ARCH_MEMORY_H1616-#define __ASM_ARCH_MEMORY_H1717-1818-#include <cfg_global.h>1919-2020-/*2121- * Physical vs virtual RAM address space conversion. These are2222- * private definitions which should NOT be used outside memory.h2323- * files. Use virt_to_phys/phys_to_virt/__pa/__va instead.2424- */2525-2626-#define PLAT_PHYS_OFFSET CFG_GLOBAL_RAM_BASE2727-2828-/*2929- * Maximum DMA memory allowed is 14M3030- */3131-#define CONSISTENT_DMA_SIZE (SZ_16M - SZ_2M)3232-3333-#endif
+3
arch/arm/mach-bcmring/mm.c
···1313*****************************************************************************/14141515#include <linux/platform_device.h>1616+#include <linux/dma-mapping.h>1617#include <asm/mach/map.h>17181819#include <mach/hardware.h>···5453{55545655 iotable_init(bcmring_io_desc, ARRAY_SIZE(bcmring_io_desc));5656+ /* Maximum DMA memory allowed is 14M */5757+ init_consistent_dma_size(14 << 20);5758}
···1010 * published by the Free Software Foundation.1111 */12121313- .macro addruart,rp,rv1313+ .macro addruart,rp,rv,tmp1414 mov \rp, #0x000090001515 orr \rv, \rp, #0xf0000000 @ virtual base1616 orr \rp, \rp, #0x10000000
-26
arch/arm/mach-cns3xxx/include/mach/memory.h
···11-/*22- * Copyright 2003 ARM Limited33- * Copyright 2008 Cavium Networks44- *55- * This file is free software; you can redistribute it and/or modify66- * it under the terms of the GNU General Public License, Version 2, as77- * published by the Free Software Foundation.88- */99-1010-#ifndef __MACH_MEMORY_H1111-#define __MACH_MEMORY_H1212-1313-/*1414- * Physical DRAM offset.1515- */1616-#define PLAT_PHYS_OFFSET UL(0x00000000)1717-1818-#define __phys_to_bus(x) ((x) + PHYS_OFFSET)1919-#define __bus_to_phys(x) ((x) - PHYS_OFFSET)2020-2121-#define __virt_to_bus(v) __phys_to_bus(__virt_to_phys(v))2222-#define __bus_to_virt(b) __phys_to_virt(__bus_to_phys(b))2323-#define __pfn_to_bus(p) __phys_to_bus(__pfn_to_phys(p))2424-#define __bus_to_pfn(b) __phys_to_pfn(__bus_to_phys(b))2525-2626-#endif
···11-/*22- * DaVinci memory space definitions33- *44- * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>55- *66- * 2007 (c) MontaVista Software, Inc. This file is licensed under77- * the terms of the GNU General Public License version 2. This program88- * is licensed "as is" without any warranty of any kind, whether express99- * or implied.1010- */1111-#ifndef __ASM_ARCH_MEMORY_H1212-#define __ASM_ARCH_MEMORY_H1313-1414-/**************************************************************************1515- * Included Files1616- **************************************************************************/1717-#include <asm/page.h>1818-#include <asm/sizes.h>1919-2020-/**************************************************************************2121- * Definitions2222- **************************************************************************/2323-#define DAVINCI_DDR_BASE 0x800000002424-#define DA8XX_DDR_BASE 0xc00000002525-2626-#if defined(CONFIG_ARCH_DAVINCI_DA8XX) && defined(CONFIG_ARCH_DAVINCI_DMx)2727-#error Cannot enable DaVinci and DA8XX platforms concurrently2828-#elif defined(CONFIG_ARCH_DAVINCI_DA8XX)2929-#define PLAT_PHYS_OFFSET DA8XX_DDR_BASE3030-#else3131-#define PLAT_PHYS_OFFSET DAVINCI_DDR_BASE3232-#endif3333-3434-#define DDR2_SDRCR_OFFSET 0xc3535-#define DDR2_SRPD_BIT BIT(23)3636-#define DDR2_MCLKSTOPEN_BIT BIT(30)3737-#define DDR2_LPMODEN_BIT BIT(31)3838-3939-/*4040- * Increase size of DMA-consistent memory region4141- */4242-#define CONSISTENT_DMA_SIZE (14<<20)4343-4444-#endif /* __ASM_ARCH_MEMORY_H */
+2-1
arch/arm/mach-davinci/include/mach/serial.h
···2121 * macros in debug-macro.S.2222 *2323 * This area sits just below the page tables (see arch/arm/kernel/head.S).2424+ * We define it as a relative offset from start of usable RAM.2425 */2525-#define DAVINCI_UART_INFO (PLAT_PHYS_OFFSET + 0x3ff8)2626+#define DAVINCI_UART_INFO_OFS 0x3ff826272728#define DAVINCI_UART0_BASE (IO_PHYS + 0x20000)2829#define DAVINCI_UART1_BASE (IO_PHYS + 0x20400)
+6-1
arch/arm/mach-davinci/include/mach/uncompress.h
···43434444static inline void set_uart_info(u32 phys, void * __iomem virt)4545{4646- u32 *uart_info = (u32 *)(DAVINCI_UART_INFO);4646+ /*4747+ * Get address of some.bss variable and round it down4848+ * a la CONFIG_AUTO_ZRELADDR.4949+ */5050+ u32 ram_start = (u32)&uart & 0xf8000000;5151+ u32 *uart_info = (u32 *)(ram_start + DAVINCI_UART_INFO_OFS);47524853 uart = (u32 *)phys;4954 uart_info[0] = phys;
···2020 * aligned and add in the offset when we load the value here.2121 */22222323- .macro addruart, rp, rv2323+ .macro addruart, rp, rv, tmp2424 ldr \rp, = S3C_PA_UART2525 ldr \rv, = S3C_VA_UART2626#if CONFIG_DEBUG_S3C_UART != 0
+1-6
arch/arm/mach-exynos4/include/mach/entry-macro.S
···55555656 bic \irqnr, \irqstat, #0x1c0057575858- cmp \irqnr, #295858+ cmp \irqnr, #155959 cmpcc \irqnr, \irqnr6060 cmpne \irqnr, \tmp6161 cmpcs \irqnr, \irqnr···7575 cmp \irqnr, #167676 strcc \irqstat, [\base, #GIC_CPU_EOI]7777 cmpcs \irqnr, \irqnr7878- .endm7979-8080- /* As above, this assumes that irqstat and base are preserved.. */8181-8282- .macro test_for_ltirq, irqnr, irqstat, base, tmp8378 .endm
···11-/*22- * Copyright (C) 2001-2006 Storlink, Corp.33- * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>44- *55- * This program is free software; you can redistribute it and/or modify66- * it under the terms of the GNU General Public License as published by77- * the Free Software Foundation; either version 2 of the License, or88- * (at your option) any later version.99- */1010-#ifndef __MACH_MEMORY_H1111-#define __MACH_MEMORY_H1212-1313-#ifdef CONFIG_GEMINI_MEM_SWAP1414-# define PLAT_PHYS_OFFSET UL(0x00000000)1515-#else1616-# define PLAT_PHYS_OFFSET UL(0x10000000)1717-#endif1818-1919-#endif /* __MACH_MEMORY_H */
···1111 * published by the Free Software Foundation.1212 */13131414- .macro addruart, rp, rv1414+ .macro addruart, rp, rv, tmp1515 mov \rp, #0xfe000000 @ physical as well as virtual1616 orr \rp, \rp, #0x00800000 @ location of the UART1717 mov \rv, \rp
···1010 * published by the Free Software Foundation.1111*/12121313- .macro addruart, rp, rv1313+ .macro addruart, rp, rv, tmp1414#ifdef __ARMEB__1515 mov \rp, #3 @ Uart regs are at off set of 3 if1616 @ byte writes used - Big Endian.
···2020 * Debug output is hardcoded to standard UART 52121*/22222323- .macro addruart, rp, rv2323+ .macro addruart, rp, rv, tmp2424 ldreq \rp, =0x400900002525 ldrne \rv, =0xF40900002626 .endm
-27
arch/arm/mach-lpc32xx/include/mach/memory.h
···11-/*22- * arch/arm/mach-lpc32xx/include/mach/memory.h33- *44- * Author: Kevin Wells <kevin.wells@nxp.com>55- *66- * Copyright (C) 2010 NXP Semiconductors77- *88- * This program is free software; you can redistribute it and/or modify99- * it under the terms of the GNU General Public License as published by1010- * the Free Software Foundation; either version 2 of the License, or1111- * (at your option) any later version.1212- *1313- * This program is distributed in the hope that it will be useful,1414- * but WITHOUT ANY WARRANTY; without even the implied warranty of1515- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1616- * GNU General Public License for more details.1717- */1818-1919-#ifndef __ASM_ARCH_MEMORY_H2020-#define __ASM_ARCH_MEMORY_H2121-2222-/*2323- * Physical DRAM offset of bank 02424- */2525-#define PLAT_PHYS_OFFSET UL(0x80000000)2626-2727-#endif
+1-1
arch/arm/mach-lpc32xx/phy3250.c
···382382383383MACHINE_START(PHY3250, "Phytec 3250 board with the LPC3250 Microcontroller")384384 /* Maintainer: Kevin Wells, NXP Semiconductors */385385- .boot_params = 0x80000100,385385+ .atag_offset = 0x100,386386 .map_io = lpc32xx_map_io,387387 .init_irq = lpc32xx_init_irq,388388 .timer = &lpc32xx_timer,
···11-/*22- * linux/arch/arm/mach-mmp/include/mach/memory.h33- *44- * This program is free software; you can redistribute it and/or modify55- * it under the terms of the GNU General Public License version 2 as66- * published by the Free Software Foundation.77- */88-99-#ifndef __ASM_MACH_MEMORY_H1010-#define __ASM_MACH_MEMORY_H1111-1212-#define PLAT_PHYS_OFFSET UL(0x00000000)1313-1414-#endif /* __ASM_MACH_MEMORY_H */
···88 * warranty of any kind, whether express or implied.99 */10101111-#include <mach/hardware.h>1212-#include <asm/hardware/gic.h>1111+#include <asm/hardware/entry-macro-gic.S>13121413 .macro disable_fiq1514 .endm16151717- .macro get_irqnr_preamble, base, tmp1818- ldr \base, =gic_cpu_base_addr1919- ldr \base, [\base]2020- .endm2121-2216 .macro arch_ret_to_user, tmp1, tmp22323- .endm2424-2525- /*2626- * The interrupt numbering scheme is defined in the2727- * interrupt controller spec. To wit:2828- *2929- * Migrated the code from ARM MP port to be more consistent3030- * with interrupt processing , the following still holds true3131- * however, all interrupts are treated the same regardless of3232- * if they are local IPI or PPI3333- *3434- * Interrupts 0-15 are IPI3535- * 16-31 are PPI3636- * (16-18 are the timers)3737- * 32-1020 are global3838- * 1021-1022 are reserved3939- * 1023 is "spurious" (no interrupt)4040- *4141- * A simple read from the controller will tell us the number of the4242- * highest priority enabled interrupt. We then just need to check4343- * whether it is in the valid range for an IRQ (0-1020 inclusive).4444- *4545- * Base ARM code assumes that the local (private) peripheral interrupts4646- * are not valid, we treat them differently, in that the privates are4747- * handled like normal shared interrupts with the exception that only4848- * one processor can register the interrupt and the handler must be4949- * the same for all processors.5050- */5151-5252- .macro get_irqnr_and_base, irqnr, irqstat, base, tmp5353-5454- ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 =srcCPU,5555- 9-0 =int # */5656-5757- bic \irqnr, \irqstat, #0x1c00 @mask src5858- cmp \irqnr, #155959- ldr \tmp, =10216060- cmpcc \irqnr, \irqnr6161- cmpne \irqnr, \tmp6262- cmpcs \irqnr, \irqnr6363-6464- .endm6565-6666- /* We assume that irqstat (the raw value of the IRQ acknowledge6767- * register) is preserved from the macro above.6868- * If there is an IPI, we immediately signal end of interrupt on the6969- * controller, since this requires the original irqstat value which7070- * we won't easily be able to recreate later.7171- */7272- .macro test_for_ipi, irqnr, irqstat, base, tmp7373- bic \irqnr, \irqstat, #0x1c007474- cmp \irqnr, #167575- strcc \irqstat, [\base, #GIC_CPU_EOI]7676- cmpcs \irqnr, \irqnr7777- .endm7878-7979- /* As above, this assumes that irqstat and base are preserved.. */8080-8181- .macro test_for_ltirq, irqnr, irqstat, base, tmp8282- bic \irqnr, \irqstat, #0x1c008383- mov \tmp, #08484- cmp \irqnr, #168585- moveq \tmp, #18686- streq \irqstat, [\base, #GIC_CPU_EOI]8787- cmp \tmp, #08817 .endm
-35
arch/arm/mach-msm/include/mach/memory.h
···11-/* arch/arm/mach-msm/include/mach/memory.h22- *33- * Copyright (C) 2007 Google, Inc.44- *55- * This software is licensed under the terms of the GNU General Public66- * License version 2, as published by the Free Software Foundation, and77- * may be copied, distributed, and modified under those terms.88- *99- * This program is distributed in the hope that it will be useful,1010- * but WITHOUT ANY WARRANTY; without even the implied warranty of1111- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212- * GNU General Public License for more details.1313- *1414- */1515-1616-#ifndef __ASM_ARCH_MEMORY_H1717-#define __ASM_ARCH_MEMORY_H1818-1919-/* physical offset of RAM */2020-#if defined(CONFIG_ARCH_QSD8X50) && defined(CONFIG_MSM_SOC_REV_A)2121-#define PLAT_PHYS_OFFSET UL(0x00000000)2222-#elif defined(CONFIG_ARCH_QSD8X50)2323-#define PLAT_PHYS_OFFSET UL(0x20000000)2424-#elif defined(CONFIG_ARCH_MSM7X30)2525-#define PLAT_PHYS_OFFSET UL(0x00200000)2626-#elif defined(CONFIG_ARCH_MSM8X60)2727-#define PLAT_PHYS_OFFSET UL(0x40200000)2828-#elif defined(CONFIG_ARCH_MSM8960)2929-#define PLAT_PHYS_OFFSET UL(0x40200000)3030-#else3131-#define PLAT_PHYS_OFFSET UL(0x10000000)3232-#endif3333-3434-#endif3535-
+6
arch/arm/mach-msm/platsmp.c
···156156{157157 unsigned int i, ncores = get_core_count();158158159159+ if (ncores > nr_cpu_ids) {160160+ pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",161161+ ncores, nr_cpu_ids);162162+ ncores = nr_cpu_ids;163163+ }164164+159165 for (i = 0; i < ncores; i++)160166 set_cpu_possible(i, true);161167
···11-/*22- * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.33- *44- * This program is free software; you can redistribute it and/or modify55- * it under the terms of the GNU General Public License as published by66- * the Free Software Foundation; either version 2 of the License, or77- * (at your option) any later version.88- *99- * This program is distributed in the hope that it will be useful,1010- * but WITHOUT ANY WARRANTY; without even the implied warranty of1111- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212- * GNU General Public License for more details.1313- *1414- * You should have received a copy of the GNU General Public License along1515- * with this program; if not, write to the Free Software Foundation, Inc.,1616- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.1717- */1818-1919-#ifndef __MACH_MXS_MEMORY_H__2020-#define __MACH_MXS_MEMORY_H__2121-2222-#define PHYS_OFFSET UL(0x40000000)2323-2424-#endif /* __MACH_MXS_MEMORY_H__ */
···11-/*22- * arch/arm/mach-netx/include/mach/memory.h33- *44- * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix55- *66- * This program is free software; you can redistribute it and/or modify77- * it under the terms of the GNU General Public License version 288- * as published by the Free Software Foundation.99- *1010- * This program is distributed in the hope that it will be useful,1111- * but WITHOUT ANY WARRANTY; without even the implied warranty of1212- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1313- * GNU General Public License for more details.1414- *1515- * You should have received a copy of the GNU General Public License1616- * along with this program; if not, write to the Free Software1717- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA1818- */1919-2020-#ifndef __ASM_ARCH_MEMORY_H2121-#define __ASM_ARCH_MEMORY_H2222-2323-#define PLAT_PHYS_OFFSET UL(0x80000000)2424-2525-#endif2626-
···11-/*22- * mach-nomadik/include/mach/memory.h33- *44- * Copyright (C) 1999 ARM Limited55- *66- * This program is free software; you can redistribute it and/or modify77- * it under the terms of the GNU General Public License as published by88- * the Free Software Foundation; either version 2 of the License, or99- * (at your option) any later version.1010- *1111- * This program is distributed in the hope that it will be useful,1212- * but WITHOUT ANY WARRANTY; without even the implied warranty of1313- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1414- * GNU General Public License for more details.1515- *1616- * You should have received a copy of the GNU General Public License1717- * along with this program; if not, write to the Free Software1818- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA1919- */2020-#ifndef __ASM_ARCH_MEMORY_H2121-#define __ASM_ARCH_MEMORY_H2222-2323-/*2424- * Physical DRAM offset.2525- */2626-#define PLAT_PHYS_OFFSET UL(0x00000000)2727-2828-#endif
-21
arch/arm/mach-nuc93x/include/mach/memory.h
···11-/*22- * arch/arm/mach-nuc93x/include/mach/memory.h33- *44- * Copyright (c) 2008 Nuvoton technology corporation55- * All rights reserved.66- *77- * Wan ZongShun <mcuos.com@gmail.com>88- *99- * This program is free software; you can redistribute it and/or modify1010- * it under the terms of the GNU General Public License as published by1111- * the Free Software Foundation; either version 2 of the License, or1212- * (at your option) any later version.1313- *1414- */1515-1616-#ifndef __ASM_ARCH_MEMORY_H1717-#define __ASM_ARCH_MEMORY_H1818-1919-#define PLAT_PHYS_OFFSET UL(0x00000000)2020-2121-#endif
···13131414#include <linux/serial_reg.h>15151616-#include <asm/memory.h>1717-1816#include <plat/serial.h>1919-2020-#define omap_uart_v2p(x) ((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET)2121-#define omap_uart_p2v(x) ((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET)22172318 .pushsection .data2419omap_uart_phys: .word 0x0···2631 * the desired UART phys and virt addresses temporarily into2732 * the omap_uart_phys and omap_uart_virt above.2833 */2929- .macro addruart, rp, rv3434+ .macro addruart, rp, rv, tmp30353136 /* Use omap_uart_phys/virt if already configured */3232-9: mrc p15, 0, \rp, c1, c03333- tst \rp, #1 @ MMU enabled?3434- ldreq \rp, =omap_uart_v2p(omap_uart_phys) @ MMU disabled3535- ldrne \rp, =omap_uart_phys @ MMU enabled3636- add \rv, \rp, #4 @ omap_uart_virt3737- ldr \rp, [\rp, #0]3838- ldr \rv, [\rv, #0]3737+9: adr \rp, 99f @ get effective addr of 99f3838+ ldr \rv, [\rp] @ get absolute addr of 99f3939+ sub \rv, \rv, \rp @ offset between the two4040+ ldr \rp, [\rp, #4] @ abs addr of omap_uart_phys4141+ sub \tmp, \rp, \rv @ make it effective4242+ ldr \rp, [\tmp, #0] @ omap_uart_phys4343+ ldr \rv, [\tmp, #4] @ omap_uart_virt3944 cmp \rp, #0 @ is port configured?4045 cmpne \rv, #04141- bne 99f @ already configured4646+ bne 100f @ already configured42474348 /* Check the debug UART configuration set in uncompress.h */4444- mrc p15, 0, \rp, c1, c04545- tst \rp, #1 @ MMU enabled?4646- ldreq \rp, =OMAP_UART_INFO @ MMU not enabled4747- ldrne \rp, =omap_uart_p2v(OMAP_UART_INFO) @ MMU enabled4848- ldr \rp, [\rp, #0]4949+ and \rp, pc, #0xff0000005050+ ldr \rv, =OMAP_UART_INFO_OFS5151+ ldr \rp, [\rp, \rv]49525053 /* Select the UART to use based on the UART1 scratchpad value */515410: cmp \rp, #0 @ no port configured?···67746875 /* Store both phys and virt address for the uart */697698: add \rp, \rp, #0xff000000 @ phys base7070- mrc p15, 0, \rv, c1, c07171- tst \rv, #1 @ MMU enabled?7272- ldreq \rv, =omap_uart_v2p(omap_uart_phys) @ MMU disabled7373- ldrne \rv, =omap_uart_phys @ MMU enabled7474- str \rp, [\rv, #0]7777+ str \rp, [\tmp, #0] @ omap_uart_phys7578 sub \rp, \rp, #0xff000000 @ phys base7679 add \rp, \rp, #0xfe000000 @ virt base7777- add \rv, \rv, #4 @ omap_uart_lsr7878- str \rp, [\rv, #0]8080+ str \rp, [\tmp, #4] @ omap_uart_virt7981 b 9b8080-99:8282+8383+ .align8484+99: .word .8585+ .word omap_uart_phys8686+ .ltorg8787+8888+100:8189 .endm82908391 .macro senduart,rd,rx
+52-1
arch/arm/mach-omap1/include/mach/memory.h
···22 * arch/arm/mach-omap1/include/mach/memory.h33 */4455-#include <plat/memory.h>55+#ifndef __ASM_ARCH_MEMORY_H66+#define __ASM_ARCH_MEMORY_H77+88+/*99+ * Physical DRAM offset.1010+ */1111+#define PLAT_PHYS_OFFSET UL(0x10000000)1212+1313+/*1414+ * Bus address is physical address, except for OMAP-1510 Local Bus.1515+ * OMAP-1510 bus address is translated into a Local Bus address if the1616+ * OMAP bus type is lbus. We do the address translation based on the1717+ * device overriding the defaults used in the dma-mapping API.1818+ * Note that the is_lbus_device() test is not very efficient on 15101919+ * because of the strncmp().2020+ */2121+#ifdef CONFIG_ARCH_OMAP15XX2222+2323+/*2424+ * OMAP-1510 Local Bus address offset2525+ */2626+#define OMAP1510_LB_OFFSET UL(0x30000000)2727+2828+#define virt_to_lbus(x) ((x) - PAGE_OFFSET + OMAP1510_LB_OFFSET)2929+#define lbus_to_virt(x) ((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)3030+#define is_lbus_device(dev) (cpu_is_omap15xx() && dev && (strncmp(dev_name(dev), "ohci", 4) == 0))3131+3232+#define __arch_pfn_to_dma(dev, pfn) \3333+ ({ dma_addr_t __dma = __pfn_to_phys(pfn); \3434+ if (is_lbus_device(dev)) \3535+ __dma = __dma - PHYS_OFFSET + OMAP1510_LB_OFFSET; \3636+ __dma; })3737+3838+#define __arch_dma_to_pfn(dev, addr) \3939+ ({ dma_addr_t __dma = addr; \4040+ if (is_lbus_device(dev)) \4141+ __dma += PHYS_OFFSET - OMAP1510_LB_OFFSET; \4242+ __phys_to_pfn(__dma); \4343+ })4444+4545+#define __arch_dma_to_virt(dev, addr) ({ (void *) (is_lbus_device(dev) ? \4646+ lbus_to_virt(addr) : \4747+ __phys_to_virt(addr)); })4848+4949+#define __arch_virt_to_dma(dev, addr) ({ unsigned long __addr = (unsigned long)(addr); \5050+ (dma_addr_t) (is_lbus_device(dev) ? \5151+ virt_to_lbus(__addr) : \5252+ __virt_to_phys(__addr)); })5353+5454+#endif /* CONFIG_ARCH_OMAP15XX */5555+5656+#endif
···1616 * it under the terms of the GNU General Public License version 2 as1717 * published by the Free Software Foundation.1818 */1919-2019#include <linux/module.h>2120#include <linux/kernel.h>2221#include <linux/init.h>···250251251252 omap2_check_revision();252253 omap_sram_init();254254+ omap_init_consistent_dma_size();253255}254256255257#ifdef CONFIG_SOC_OMAP2420
+4-6
arch/arm/mach-omap2/omap-smp.c
···109109 ncores = scu_get_core_count(scu_base);110110111111 /* sanity check */112112- if (ncores > NR_CPUS) {113113- printk(KERN_WARNING114114- "OMAP4: no. of cores (%d) greater than configured "115115- "maximum of %d - clipping\n",116116- ncores, NR_CPUS);117117- ncores = NR_CPUS;112112+ if (ncores > nr_cpu_ids) {113113+ pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",114114+ ncores, nr_cpu_ids);115115+ ncores = nr_cpu_ids;118116 }119117120118 for (i = 0; i < ncores; i++)
···730730/* Warning: D-Link uses a wrong mach-type (=526) in their bootloader */731731MACHINE_START(DNS323, "D-Link DNS-323")732732 /* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */733733- .boot_params = 0x00000100,733733+ .atag_offset = 0x100,734734 .init_machine = dns323_init,735735 .map_io = orion5x_map_io,736736 .init_early = orion5x_init_early,
+1-1
arch/arm/mach-orion5x/edmini_v2-setup.c
···251251/* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */252252MACHINE_START(EDMINI_V2, "LaCie Ethernet Disk mini V2")253253 /* Maintainer: Christopher Moore <moore@free.fr> */254254- .boot_params = 0x00000100,254254+ .atag_offset = 0x100,255255 .init_machine = edmini_v2_init,256256 .map_io = orion5x_map_io,257257 .init_early = orion5x_init_early,
···11-/*22- * arch/arm/mach-pnx4008/include/mach/memory.h33- *44- * Copyright (c) 2005 Philips Semiconductors55- * Copyright (c) 2005 MontaVista Software, Inc.66- *77- * This program is free software; you can redistribute it and/or modify it88- * under the terms of the GNU General Public License as published by the99- * Free Software Foundation; either version 2 of the License, or (at your1010- * option) any later version.1111- */1212-1313-#ifndef __ASM_ARCH_MEMORY_H1414-#define __ASM_ARCH_MEMORY_H1515-1616-/*1717- * Physical DRAM offset.1818- */1919-#define PLAT_PHYS_OFFSET UL(0x80000000)2020-2121-#endif
···11-/*22- * arch/arm/mach-prima2/include/mach/memory.h33- *44- * Copyright (c) 2010 – 2011 Cambridge Silicon Radio Limited, a CSR plc group company.55- *66- * Licensed under GPLv2 or later.77- */88-99-#ifndef __ASM_ARCH_MEMORY_H1010-#define __ASM_ARCH_MEMORY_H1111-1212-#define PLAT_PHYS_OFFSET UL(0x00000000)1313-1414-/*1515- * Restrict DMA-able region to workaround silicon limitation.1616- * The limitation restricts buffers available for DMA to SD/MMC1717- * hardware to be below 256MB1818- */1919-#define ARM_DMA_ZONE_SIZE (SZ_256M)2020-2121-#endif
···11-/*22- * arch/arm/mach-pxa/include/mach/memory.h33- *44- * Author: Nicolas Pitre55- * Copyright: (C) 2001 MontaVista Software Inc.66- *77- * This program is free software; you can redistribute it and/or modify88- * it under the terms of the GNU General Public License version 2 as99- * published by the Free Software Foundation.1010- */1111-1212-#ifndef __ASM_ARCH_MEMORY_H1313-#define __ASM_ARCH_MEMORY_H1414-1515-/*1616- * Physical DRAM offset.1717- */1818-#define PLAT_PHYS_OFFSET UL(0xa0000000)1919-2020-#endif
···11-/* arch/arm/mach-s3c2400/include/mach/memory.h22- * from arch/arm/mach-rpc/include/mach/memory.h33- *44- * Copyright 2007 Simtec Electronics55- * http://armlinux.simtec.co.uk/66- * Ben Dooks <ben@simtec.co.uk>77- *88- * Copyright (C) 1996,1997,1998 Russell King.99- *1010- * This program is free software; you can redistribute it and/or modify1111- * it under the terms of the GNU General Public License version 2 as1212- * published by the Free Software Foundation.1313-*/1414-1515-#ifndef __ASM_ARCH_MEMORY_H1616-#define __ASM_ARCH_MEMORY_H1717-1818-#define PLAT_PHYS_OFFSET UL(0x0C000000)1919-2020-#endif
···11-/* arch/arm/mach-s3c2410/include/mach/memory.h22- * from arch/arm/mach-rpc/include/mach/memory.h33- *44- * Copyright (C) 1996,1997,1998 Russell King.55- *66- * This program is free software; you can redistribute it and/or modify77- * it under the terms of the GNU General Public License version 2 as88- * published by the Free Software Foundation.99-*/1010-1111-#ifndef __ASM_ARCH_MEMORY_H1212-#define __ASM_ARCH_MEMORY_H1313-1414-#define PLAT_PHYS_OFFSET UL(0x30000000)1515-1616-#endif
···2020#include <linux/serial_core.h>2121#include <linux/platform_device.h>2222#include <linux/io.h>2323+#include <linux/dma-mapping.h>23242425#include <mach/hardware.h>2526#include <mach/map.h>···146145 /* initialise the io descriptors we need for initialisation */147146 iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));148147 iotable_init(mach_desc, size);148148+ init_consistent_dma_size(SZ_8M);149149150150 idcode = __raw_readl(S3C_VA_SYS + 0x118);151151 if (!idcode) {
+1-1
arch/arm/mach-s3c64xx/include/mach/debug-macro.S
···2121 * aligned and add in the offset when we load the value here.2222 */23232424- .macro addruart, rp, rv2424+ .macro addruart, rp, rv, tmp2525 ldr \rp, = S3C_PA_UART2626 ldr \rv, = (S3C_VA_UART + S3C_PA_UART & 0xfffff)2727#if CONFIG_DEBUG_S3C_UART != 0
-20
arch/arm/mach-s3c64xx/include/mach/memory.h
···11-/* arch/arm/mach-s3c6400/include/mach/memory.h22- *33- * Copyright 2008 Openmoko, Inc.44- * Copyright 2008 Simtec Electronics55- * Ben Dooks <ben@simtec.co.uk>66- * http://armlinux.simtec.co.uk/77- *88- * This program is free software; you can redistribute it and/or modify99- * it under the terms of the GNU General Public License version 2 as1010- * published by the Free Software Foundation.1111-*/1212-1313-#ifndef __ASM_ARCH_MEMORY_H1414-#define __ASM_ARCH_MEMORY_H1515-1616-#define PLAT_PHYS_OFFSET UL(0x50000000)1717-1818-#define CONSISTENT_DMA_SIZE SZ_8M1919-2020-#endif
···11-/* linux/arch/arm/mach-s5p64x0/include/mach/memory.h22- *33- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.44- * http://www.samsung.com55- *66- * S5P64X0 - Memory definitions77- *88- * This program is free software; you can redistribute it and/or modify99- * it under the terms of the GNU General Public License version 2 as1010- * published by the Free Software Foundation.1111-*/1212-1313-#ifndef __ASM_ARCH_MEMORY_H1414-#define __ASM_ARCH_MEMORY_H __FILE__1515-1616-#define PLAT_PHYS_OFFSET UL(0x20000000)1717-#define CONSISTENT_DMA_SIZE SZ_8M1818-1919-#endif /* __ASM_ARCH_MEMORY_H */
···2222 * aligned and add in the offset when we load the value here.2323 */24242525- .macro addruart, rp, rv2525+ .macro addruart, rp, rv, tmp2626 ldr \rp, = S3C_PA_UART2727 ldr \rv, = S3C_VA_UART2828#if CONFIG_DEBUG_S3C_UART != 0
-18
arch/arm/mach-s5pc100/include/mach/memory.h
···11-/* arch/arm/mach-s5pc100/include/mach/memory.h22- *33- * Copyright 2008 Samsung Electronics Co.44- * Byungho Min <bhmin@samsung.com>55- *66- * Based on mach-s3c6400/include/mach/memory.h77- *88- * This program is free software; you can redistribute it and/or modify99- * it under the terms of the GNU General Public License version 2 as1010- * published by the Free Software Foundation.1111-*/1212-1313-#ifndef __ASM_ARCH_MEMORY_H1414-#define __ASM_ARCH_MEMORY_H1515-1616-#define PLAT_PHYS_OFFSET UL(0x20000000)1717-1818-#endif
···2121 * aligned and add in the offset when we load the value here.2222 */23232424- .macro addruart, rp, rv2424+ .macro addruart, rp, rv, tmp2525 ldr \rp, = S3C_PA_UART2626 ldr \rv, = S3C_VA_UART2727#if CONFIG_DEBUG_S3C_UART != 0
···5656 unsigned int ncores = shmobile_smp_get_core_count();5757 unsigned int i;58585959+ if (ncores > nr_cpu_ids) {6060+ pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",6161+ ncores, nr_cpu_ids);6262+ ncores = nr_cpu_ids;6363+ }6464+5965 for (i = 0; i < ncores; i++)6066 set_cpu_possible(i, true);6167
-19
arch/arm/mach-spear3xx/include/mach/memory.h
···11-/*22- * arch/arm/mach-spear3xx/include/mach/memory.h33- *44- * Memory map for SPEAr3xx machine family55- *66- * Copyright (C) 2009 ST Microelectronics77- * Viresh Kumar<viresh.kumar@st.com>88- *99- * This file is licensed under the terms of the GNU General Public1010- * License version 2. This program is licensed "as is" without any1111- * warranty of any kind, whether express or implied.1212- */1313-1414-#ifndef __MACH_MEMORY_H1515-#define __MACH_MEMORY_H1616-1717-#include <plat/memory.h>1818-1919-#endif /* __MACH_MEMORY_H */
···11-/*22- * arch/arm/mach-spear6xx/include/mach/memory.h33- *44- * Memory map for SPEAr6xx machine family55- *66- * Copyright (C) 2009 ST Microelectronics77- * Rajeev Kumar<rajeev-dlh.kumar@st.com>88- *99- * This file is licensed under the terms of the GNU General Public1010- * License version 2. This program is licensed "as is" without any1111- * warranty of any kind, whether express or implied.1212- */1313-1414-#ifndef __MACH_MEMORY_H1515-#define __MACH_MEMORY_H1616-1717-#include <plat/memory.h>1818-1919-#endif /* __MACH_MEMORY_H */
···11-/*22- * arch/arm/mach-tegra/include/mach/memory.h33- *44- * Copyright (C) 2010 Google, Inc.55- *66- * Author:77- * Colin Cross <ccross@google.com>88- * Erik Gilling <konkers@google.com>99- *1010- * This software is licensed under the terms of the GNU General Public1111- * License version 2, as published by the Free Software Foundation, and1212- * may be copied, distributed, and modified under those terms.1313- *1414- * This program is distributed in the hope that it will be useful,1515- * but WITHOUT ANY WARRANTY; without even the implied warranty of1616- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1717- * GNU General Public License for more details.1818- *1919- */2020-2121-#ifndef __MACH_TEGRA_MEMORY_H2222-#define __MACH_TEGRA_MEMORY_H2323-2424-/* physical offset of RAM */2525-#define PLAT_PHYS_OFFSET UL(0)2626-2727-#endif2828-
+4-4
arch/arm/mach-tegra/platsmp.c
···114114{115115 unsigned int i, ncores = scu_get_core_count(scu_base);116116117117- if (ncores > NR_CPUS) {118118- printk(KERN_ERR "Tegra: no. of cores (%u) greater than configured (%u), clipping\n",119119- ncores, NR_CPUS);120120- ncores = NR_CPUS;117117+ if (ncores > nr_cpu_ids) {118118+ pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",119119+ ncores, nr_cpu_ids);120120+ ncores = nr_cpu_ids;121121 }122122123123 for (i = 0; i < ncores; i++)
+3
arch/arm/mach-u300/core.c
···2525#include <linux/err.h>2626#include <linux/mtd/nand.h>2727#include <linux/mtd/fsmc.h>2828+#include <linux/dma-mapping.h>28292930#include <asm/types.h>3031#include <asm/setup.h>···9392void __init u300_map_io(void)9493{9594 iotable_init(u300_io_desc, ARRAY_SIZE(u300_io_desc));9595+ /* We enable a real big DMA buffer if need be. */9696+ init_consistent_dma_size(SZ_4M);9697}97989899/*
+1-1
arch/arm/mach-u300/include/mach/debug-macro.S
···1010 */1111#include <mach/hardware.h>12121313- .macro addruart, rp, rv1313+ .macro addruart, rp, rv, tmp1414 /* If we move the address using MMU, use this. */1515 ldr \rp, = U300_SLOW_PER_PHYS_BASE @ MMU off, physical address1616 ldr \rv, = U300_SLOW_PER_VIRT_BASE @ MMU on, virtual address
···11-/*22- * Copyright (C) 2009 ST-Ericsson33- *44- * This program is free software; you can redistribute it and/or modify55- * it under the terms of the GNU General Public License as published by66- * the Free Software Foundation; either version 2 of the License, or77- * (at your option) any later version.88- */99-#ifndef __ASM_ARCH_MEMORY_H1010-#define __ASM_ARCH_MEMORY_H1111-1212-/*1313- * Physical DRAM offset.1414- */1515-#define PLAT_PHYS_OFFSET UL(0x00000000)1616-#define BUS_OFFSET UL(0x00000000)1717-1818-#endif
+4-6
arch/arm/mach-ux500/platsmp.c
···156156 ncores = scu_base ? scu_get_core_count(scu_base) : 1;157157158158 /* sanity check */159159- if (ncores > NR_CPUS) {160160- printk(KERN_WARNING161161- "U8500: no. of cores (%d) greater than configured "162162- "maximum of %d - clipping\n",163163- ncores, NR_CPUS);164164- ncores = NR_CPUS;159159+ if (ncores > nr_cpu_ids) {160160+ pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",161161+ ncores, nr_cpu_ids);162162+ ncores = nr_cpu_ids;165163 }166164167165 for (i = 0; i < ncores; i++)
···11-/*22- * arch/arm/mach-versatile/include/mach/memory.h33- *44- * Copyright (C) 2003 ARM Limited55- *66- * This program is free software; you can redistribute it and/or modify77- * it under the terms of the GNU General Public License as published by88- * the Free Software Foundation; either version 2 of the License, or99- * (at your option) any later version.1010- *1111- * This program is distributed in the hope that it will be useful,1212- * but WITHOUT ANY WARRANTY; without even the implied warranty of1313- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1414- * GNU General Public License for more details.1515- *1616- * You should have received a copy of the GNU General Public License1717- * along with this program; if not, write to the Free Software1818- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA1919- */2020-#ifndef __ASM_ARCH_MEMORY_H2121-#define __ASM_ARCH_MEMORY_H2222-2323-/*2424- * Physical DRAM offset.2525- */2626-#define PLAT_PHYS_OFFSET UL(0x00000000)2727-2828-#endif
···221221{222222 int i, ncores = scu_get_core_count(MMIO_P2V(A9_MPCORE_SCU));223223224224+ if (ncores > nr_cpu_ids) {225225+ pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",226226+ ncores, nr_cpu_ids);227227+ ncores = nr_cpu_ids;228228+ }229229+224230 for (i = 0; i < ncores; ++i)225231 set_cpu_possible(i, true);226232
···11-/*22- * arch/arm/mach-vexpress/include/mach/memory.h33- *44- * Copyright (C) 2003 ARM Limited55- *66- * This program is free software; you can redistribute it and/or modify77- * it under the terms of the GNU General Public License as published by88- * the Free Software Foundation; either version 2 of the License, or99- * (at your option) any later version.1010- *1111- * This program is distributed in the hope that it will be useful,1212- * but WITHOUT ANY WARRANTY; without even the implied warranty of1313- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1414- * GNU General Public License for more details.1515- *1616- * You should have received a copy of the GNU General Public License1717- * along with this program; if not, write to the Free Software1818- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA1919- */2020-#ifndef __ASM_ARCH_MEMORY_H2121-#define __ASM_ARCH_MEMORY_H2222-2323-#define PLAT_PHYS_OFFSET UL(0x60000000)2424-2525-#endif
···11-/*22- * arch/arm/mach-vt8500/include/mach/memory.h33- *44- * Copyright (C) 2003 ARM Limited55- *66- * This program is free software; you can redistribute it and/or modify77- * it under the terms of the GNU General Public License as published by88- * the Free Software Foundation; either version 2 of the License, or99- * (at your option) any later version.1010- *1111- * This program is distributed in the hope that it will be useful,1212- * but WITHOUT ANY WARRANTY; without even the implied warranty of1313- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1414- * GNU General Public License for more details.1515- *1616- * You should have received a copy of the GNU General Public License1717- * along with this program; if not, write to the Free Software1818- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA1919- */2020-#ifndef __ASM_ARCH_MEMORY_H2121-#define __ASM_ARCH_MEMORY_H2222-2323-/*2424- * Physical DRAM offset.2525- */2626-#define PHYS_OFFSET UL(0x00000000)2727-2828-#endif
···11-/*22- * arch/arm/mach-w90x900/include/mach/memory.h33- *44- * Copyright (c) 2008 Nuvoton technology corporation55- * All rights reserved.66- *77- * Wan ZongShun <mcuos.com@gmail.com>88- *99- * Based on arch/arm/mach-s3c2410/include/mach/memory.h1010- *1111- * This program is free software; you can redistribute it and/or modify1212- * it under the terms of the GNU General Public License as published by1313- * the Free Software Foundation; either version 2 of the License, or1414- * (at your option) any later version.1515- *1616- */1717-1818-#ifndef __ASM_ARCH_MEMORY_H1919-#define __ASM_ARCH_MEMORY_H2020-2121-#define PLAT_PHYS_OFFSET UL(0x00000000)2222-2323-#endif
···11-/* arch/arm/mach-zynq/include/mach/memory.h22- *33- * Copyright (C) 2011 Xilinx44- *55- * This software is licensed under the terms of the GNU General Public66- * License version 2, as published by the Free Software Foundation, and77- * may be copied, distributed, and modified under those terms.88- *99- * This program is distributed in the hope that it will be useful,1010- * but WITHOUT ANY WARRANTY; without even the implied warranty of1111- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1212- * GNU General Public License for more details.1313- */1414-1515-#ifndef __MACH_MEMORY_H__1616-#define __MACH_MEMORY_H__1717-1818-#include <asm/sizes.h>1919-2020-#define PLAT_PHYS_OFFSET UL(0x0)2121-2222-#endif
+34-11
arch/arm/mm/dma-mapping.c
···1818#include <linux/device.h>1919#include <linux/dma-mapping.h>2020#include <linux/highmem.h>2121+#include <linux/slab.h>21222223#include <asm/memory.h>2324#include <asm/highmem.h>2425#include <asm/cacheflush.h>2526#include <asm/tlbflush.h>2627#include <asm/sizes.h>2828+#include <asm/mach/arch.h>27292830#include "mm.h"2931···119117}120118121119#ifdef CONFIG_MMU122122-/* Sanity check size */123123-#if (CONSISTENT_DMA_SIZE % SZ_2M)124124-#error "CONSISTENT_DMA_SIZE must be multiple of 2MiB"125125-#endif126120127127-#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)128128-#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT)129129-#define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PGDIR_SHIFT)121121+122122+#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - consistent_base) >> PAGE_SHIFT)123123+#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - consistent_base) >> PGDIR_SHIFT)130124131125/*132126 * These are the page tables (2MB each) covering uncached, DMA consistent allocations133127 */134134-static pte_t *consistent_pte[NUM_CONSISTENT_PTES];128128+static pte_t **consistent_pte;129129+130130+#define DEFAULT_CONSISTENT_DMA_SIZE SZ_2M131131+132132+unsigned long consistent_base = CONSISTENT_END - DEFAULT_CONSISTENT_DMA_SIZE;133133+134134+void __init init_consistent_dma_size(unsigned long size)135135+{136136+ unsigned long base = CONSISTENT_END - ALIGN(size, SZ_2M);137137+138138+ BUG_ON(consistent_pte); /* Check we're called before DMA region init */139139+ BUG_ON(base < VMALLOC_END);140140+141141+ /* Grow region to accommodate specified size */142142+ if (base < consistent_base)143143+ consistent_base = base;144144+}135145136146#include "vmregion.h"137147138148static struct arm_vmregion_head consistent_head = {139149 .vm_lock = __SPIN_LOCK_UNLOCKED(&consistent_head.vm_lock),140150 .vm_list = LIST_HEAD_INIT(consistent_head.vm_list),141141- .vm_start = CONSISTENT_BASE,142151 .vm_end = CONSISTENT_END,143152};144153···168155 pmd_t *pmd;169156 pte_t *pte;170157 int i = 0;171171- u32 base = CONSISTENT_BASE;158158+ unsigned long base = consistent_base;159159+ unsigned long num_ptes = (CONSISTENT_END - base) >> PGDIR_SHIFT;160160+161161+ consistent_pte = kmalloc(num_ptes * sizeof(pte_t), GFP_KERNEL);162162+ if (!consistent_pte) {163163+ pr_err("%s: no memory\n", __func__);164164+ return -ENOMEM;165165+ }166166+167167+ pr_debug("DMA memory: 0x%08lx - 0x%08lx:\n", base, CONSISTENT_END);168168+ consistent_head.vm_start = base;172169173170 do {174171 pgd = pgd_offset(&init_mm, base);···221198 size_t align;222199 int bit;223200224224- if (!consistent_pte[0]) {201201+ if (!consistent_pte) {225202 printk(KERN_ERR "%s: not initialised\n", __func__);226203 dump_stack();227204 return NULL;
···11-/*22- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.33- */44-55-/*66- * This program is free software; you can redistribute it and/or modify77- * it under the terms of the GNU General Public License version 2 as88- * published by the Free Software Foundation.99- */1010-1111-#ifndef __ASM_ARCH_MXC_MEMORY_H__1212-#define __ASM_ARCH_MXC_MEMORY_H__1313-1414-#define MX1_PHYS_OFFSET UL(0x08000000)1515-#define MX21_PHYS_OFFSET UL(0xc0000000)1616-#define MX25_PHYS_OFFSET UL(0x80000000)1717-#define MX27_PHYS_OFFSET UL(0xa0000000)1818-#define MX3x_PHYS_OFFSET UL(0x80000000)1919-#define MX50_PHYS_OFFSET UL(0x70000000)2020-#define MX51_PHYS_OFFSET UL(0x90000000)2121-#define MX53_PHYS_OFFSET UL(0x70000000)2222-2323-#if !defined(CONFIG_RUNTIME_PHYS_OFFSET)2424-# if defined CONFIG_ARCH_MX12525-# define PLAT_PHYS_OFFSET MX1_PHYS_OFFSET2626-# elif defined CONFIG_MACH_MX212727-# define PLAT_PHYS_OFFSET MX21_PHYS_OFFSET2828-# elif defined CONFIG_ARCH_MX252929-# define PLAT_PHYS_OFFSET MX25_PHYS_OFFSET3030-# elif defined CONFIG_MACH_MX273131-# define PLAT_PHYS_OFFSET MX27_PHYS_OFFSET3232-# elif defined CONFIG_ARCH_MX33333-# define PLAT_PHYS_OFFSET MX3x_PHYS_OFFSET3434-# elif defined CONFIG_ARCH_MX503535-# define PLAT_PHYS_OFFSET MX50_PHYS_OFFSET3636-# elif defined CONFIG_ARCH_MX513737-# define PLAT_PHYS_OFFSET MX51_PHYS_OFFSET3838-# elif defined CONFIG_ARCH_MX533939-# define PLAT_PHYS_OFFSET MX53_PHYS_OFFSET4040-# endif4141-#endif4242-4343-#if defined(CONFIG_MX3_VIDEO)4444-/*4545- * Increase size of DMA-consistent memory region.4646- * This is required for mx3 camera driver to capture at least two QXGA frames.4747- */4848-#define CONSISTENT_DMA_SIZE SZ_8M4949-5050-#elif defined(CONFIG_MX1_VIDEO) || defined(CONFIG_VIDEO_MX2_HOSTSUPPORT)5151-/*5252- * Increase size of DMA-consistent memory region.5353- * This is required for i.MX camera driver to capture at least four VGA frames.5454- */5555-#define CONSISTENT_DMA_SIZE SZ_4M5656-#endif /* CONFIG_MX1_VIDEO || CONFIG_VIDEO_MX2_HOSTSUPPORT */5757-5858-#endif /* __ASM_ARCH_MXC_MEMORY_H__ */
+1
arch/arm/plat-omap/Kconfig
···1414 select CLKDEV_LOOKUP1515 select CLKSRC_MMIO1616 select GENERIC_IRQ_CHIP1717+ select NEED_MACH_MEMORY_H1718 help1819 "Systems based on omap7xx, omap15xx or omap16xx"1920
+2
arch/arm/plat-omap/include/plat/io.h
···309309void __iomem *omap_ioremap(unsigned long phys, size_t size, unsigned int type);310310void omap_iounmap(volatile void __iomem *addr);311311312312+extern void __init omap_init_consistent_dma_size(void);313313+312314#endif313315314316#endif
-102
arch/arm/plat-omap/include/plat/memory.h
···11-/*22- * arch/arm/plat-omap/include/mach/memory.h33- *44- * Memory map for OMAP-1510 and 161055- *66- * Copyright (C) 2000 RidgeRun, Inc.77- * Author: Greg Lonnon <glonnon@ridgerun.com>88- *99- * This file was derived from arch/arm/mach-intergrator/include/mach/memory.h1010- * Copyright (C) 1999 ARM Limited1111- *1212- * This program is free software; you can redistribute it and/or modify it1313- * under the terms of the GNU General Public License as published by the1414- * Free Software Foundation; either version 2 of the License, or (at your1515- * option) any later version.1616- *1717- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED1818- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF1919- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN2020- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,2121- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT2222- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF2323- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON2424- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT2525- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF2626- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.2727- *2828- * You should have received a copy of the GNU General Public License along2929- * with this program; if not, write to the Free Software Foundation, Inc.,3030- * 675 Mass Ave, Cambridge, MA 02139, USA.3131- */3232-3333-#ifndef __ASM_ARCH_MEMORY_H3434-#define __ASM_ARCH_MEMORY_H3535-3636-/*3737- * Physical DRAM offset.3838- */3939-#if defined(CONFIG_ARCH_OMAP1)4040-#define PLAT_PHYS_OFFSET UL(0x10000000)4141-#else4242-#define PLAT_PHYS_OFFSET UL(0x80000000)4343-#endif4444-4545-/*4646- * Bus address is physical address, except for OMAP-1510 Local Bus.4747- * OMAP-1510 bus address is translated into a Local Bus address if the4848- * OMAP bus type is lbus. We do the address translation based on the4949- * device overriding the defaults used in the dma-mapping API.5050- * Note that the is_lbus_device() test is not very efficient on 15105151- * because of the strncmp().5252- */5353-#ifdef CONFIG_ARCH_OMAP15XX5454-5555-/*5656- * OMAP-1510 Local Bus address offset5757- */5858-#define OMAP1510_LB_OFFSET UL(0x30000000)5959-6060-#define virt_to_lbus(x) ((x) - PAGE_OFFSET + OMAP1510_LB_OFFSET)6161-#define lbus_to_virt(x) ((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)6262-#define is_lbus_device(dev) (cpu_is_omap15xx() && dev && (strncmp(dev_name(dev), "ohci", 4) == 0))6363-6464-#define __arch_pfn_to_dma(dev, pfn) \6565- ({ dma_addr_t __dma = __pfn_to_phys(pfn); \6666- if (is_lbus_device(dev)) \6767- __dma = __dma - PHYS_OFFSET + OMAP1510_LB_OFFSET; \6868- __dma; })6969-7070-#define __arch_dma_to_pfn(dev, addr) \7171- ({ dma_addr_t __dma = addr; \7272- if (is_lbus_device(dev)) \7373- __dma += PHYS_OFFSET - OMAP1510_LB_OFFSET; \7474- __phys_to_pfn(__dma); \7575- })7676-7777-#define __arch_dma_to_virt(dev, addr) ({ (void *) (is_lbus_device(dev) ? \7878- lbus_to_virt(addr) : \7979- __phys_to_virt(addr)); })8080-8181-#define __arch_virt_to_dma(dev, addr) ({ unsigned long __addr = (unsigned long)(addr); \8282- (dma_addr_t) (is_lbus_device(dev) ? \8383- virt_to_lbus(__addr) : \8484- __virt_to_phys(__addr)); })8585-8686-#endif /* CONFIG_ARCH_OMAP15XX */8787-8888-/* Override the ARM default */8989-#ifdef CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE9090-9191-#if (CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE == 0)9292-#undef CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE9393-#define CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE 29494-#endif9595-9696-#define CONSISTENT_DMA_SIZE \9797- (((CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE + 1) & ~1) * 1024 * 1024)9898-9999-#endif100100-101101-#endif102102-
+3-3
arch/arm/plat-omap/include/plat/serial.h
···1616#include <linux/init.h>17171818/*1919- * Memory entry used for the DEBUG_LL UART configuration. See also2020- * uncompress.h and debug-macro.S.1919+ * Memory entry used for the DEBUG_LL UART configuration, relative to2020+ * start of RAM. See also uncompress.h and debug-macro.S.2121 *2222 * Note that using a memory location for storing the UART configuration2323 * has at least two limitations:···2727 * 2. We assume printascii is called at least once before paging_init,2828 * and addruart has a chance to read OMAP_UART_INFO2929 */3030-#define OMAP_UART_INFO (PLAT_PHYS_OFFSET + 0x3ffc)3030+#define OMAP_UART_INFO_OFS 0x3ffc31313232/* OMAP1 serial ports */3333#define OMAP1_UART1_BASE 0xfffb0000
+7-1
arch/arm/plat-omap/include/plat/uncompress.h
···3636 */3737static void set_omap_uart_info(unsigned char port)3838{3939- *(volatile u32 *)OMAP_UART_INFO = port;3939+ /*4040+ * Get address of some.bss variable and round it down4141+ * a la CONFIG_AUTO_ZRELADDR.4242+ */4343+ u32 ram_start = (u32)&uart_shift & 0xf8000000;4444+ u32 *uart_info = (u32 *)(ram_start + OMAP_UART_INFO_OFS);4545+ *uart_info = port;4046}41474248static void putc(int c)
···11-/*22- * arch/arm/plat-spear/include/plat/memory.h33- *44- * Memory map for SPEAr platform55- *66- * Copyright (C) 2009 ST Microelectronics77- * Viresh Kumar<viresh.kumar@st.com>88- *99- * This file is licensed under the terms of the GNU General Public1010- * License version 2. This program is licensed "as is" without any1111- * warranty of any kind, whether express or implied.1212- */1313-1414-#ifndef __PLAT_MEMORY_H1515-#define __PLAT_MEMORY_H1616-1717-/* Physical DRAM offset */1818-#define PLAT_PHYS_OFFSET UL(0x00000000)1919-2020-#endif /* __PLAT_MEMORY_H */
···11-/*22- * Copyright (C) 1999 ARM Limited33- * Copyright (C) 2000 RidgeRun, Inc.44- * Copyright (C) 2008-2009 Telechips55- * Copyright (C) 2010 Hans J. Koch <hjk@linutronix.de>66- *77- * Licensed under the terms of the GPL v2.88- */99-1010-#ifndef __ASM_ARCH_MEMORY_H1111-#define __ASM_ARCH_MEMORY_H1212-1313-/*1414- * Physical DRAM offset.1515- */1616-#define PLAT_PHYS_OFFSET UL(0x20000000)1717-1818-#endif
+22-9
arch/arm/vfp/vfpmodule.c
···1111#include <linux/module.h>1212#include <linux/types.h>1313#include <linux/cpu.h>1414+#include <linux/cpu_pm.h>1415#include <linux/kernel.h>1516#include <linux/notifier.h>1617#include <linux/signal.h>···6968/*7069 * Force a reload of the VFP context from the thread structure. We do7170 * this by ensuring that access to the VFP hardware is disabled, and7272- * clear last_VFP_context. Must be called from non-preemptible context.7171+ * clear vfp_current_hw_state. Must be called from non-preemptible context.7372 */7473static void vfp_force_reload(unsigned int cpu, struct thread_info *thread)7574{···437436 set_copro_access(access | CPACC_FULL(10) | CPACC_FULL(11));438437}439438440440-#ifdef CONFIG_PM441441-#include <linux/syscore_ops.h>442442-439439+#ifdef CONFIG_CPU_PM443440static int vfp_pm_suspend(void)444441{445442 struct thread_info *ti = current_thread_info();···467468 fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);468469}469470470470-static struct syscore_ops vfp_pm_syscore_ops = {471471- .suspend = vfp_pm_suspend,472472- .resume = vfp_pm_resume,471471+static int vfp_cpu_pm_notifier(struct notifier_block *self, unsigned long cmd,472472+ void *v)473473+{474474+ switch (cmd) {475475+ case CPU_PM_ENTER:476476+ vfp_pm_suspend();477477+ break;478478+ case CPU_PM_ENTER_FAILED:479479+ case CPU_PM_EXIT:480480+ vfp_pm_resume();481481+ break;482482+ }483483+ return NOTIFY_OK;484484+}485485+486486+static struct notifier_block vfp_cpu_pm_notifier_block = {487487+ .notifier_call = vfp_cpu_pm_notifier,473488};474489475490static void vfp_pm_init(void)476491{477477- register_syscore_ops(&vfp_pm_syscore_ops);492492+ cpu_pm_register_notifier(&vfp_cpu_pm_notifier_block);478493}479494480495#else481496static inline void vfp_pm_init(void) { }482482-#endif /* CONFIG_PM */497497+#endif /* CONFIG_CPU_PM */483498484499/*485500 * Ensure that the VFP state stored in 'thread->vfpstate' is up to date
+107
drivers/of/irq.c
···1919 */20202121#include <linux/errno.h>2222+#include <linux/list.h>2223#include <linux/module.h>2324#include <linux/of.h>2425#include <linux/of_irq.h>2526#include <linux/string.h>2727+#include <linux/slab.h>26282729/* For archs that don't support NO_IRQ (such as x86), provide a dummy value */2830#ifndef NO_IRQ···387385 break;388386389387 return i;388388+}389389+390390+struct intc_desc {391391+ struct list_head list;392392+ struct device_node *dev;393393+ struct device_node *interrupt_parent;394394+};395395+396396+/**397397+ * of_irq_init - Scan and init matching interrupt controllers in DT398398+ * @matches: 0 terminated array of nodes to match and init function to call399399+ *400400+ * This function scans the device tree for matching interrupt controller nodes,401401+ * and calls their initialization functions in order with parents first.402402+ */403403+void __init of_irq_init(const struct of_device_id *matches)404404+{405405+ struct device_node *np, *parent = NULL;406406+ struct intc_desc *desc, *temp_desc;407407+ struct list_head intc_desc_list, intc_parent_list;408408+409409+ INIT_LIST_HEAD(&intc_desc_list);410410+ INIT_LIST_HEAD(&intc_parent_list);411411+412412+ for_each_matching_node(np, matches) {413413+ if (!of_find_property(np, "interrupt-controller", NULL))414414+ continue;415415+ /*416416+ * Here, we allocate and populate an intc_desc with the node417417+ * pointer, interrupt-parent device_node etc.418418+ */419419+ desc = kzalloc(sizeof(*desc), GFP_KERNEL);420420+ if (WARN_ON(!desc))421421+ goto err;422422+423423+ desc->dev = np;424424+ desc->interrupt_parent = of_irq_find_parent(np);425425+ list_add_tail(&desc->list, &intc_desc_list);426426+ }427427+428428+ /*429429+ * The root irq controller is the one without an interrupt-parent.430430+ * That one goes first, followed by the controllers that reference it,431431+ * followed by the ones that reference the 2nd level controllers, etc.432432+ */433433+ while (!list_empty(&intc_desc_list)) {434434+ /*435435+ * Process all controllers with the current 'parent'.436436+ * First pass will be looking for NULL as the parent.437437+ * The assumption is that NULL parent means a root controller.438438+ */439439+ list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {440440+ const struct of_device_id *match;441441+ int ret;442442+ of_irq_init_cb_t irq_init_cb;443443+444444+ if (desc->interrupt_parent != parent)445445+ continue;446446+447447+ list_del(&desc->list);448448+ match = of_match_node(matches, desc->dev);449449+ if (WARN(!match->data,450450+ "of_irq_init: no init function for %s\n",451451+ match->compatible)) {452452+ kfree(desc);453453+ continue;454454+ }455455+456456+ pr_debug("of_irq_init: init %s @ %p, parent %p\n",457457+ match->compatible,458458+ desc->dev, desc->interrupt_parent);459459+ irq_init_cb = match->data;460460+ ret = irq_init_cb(desc->dev, desc->interrupt_parent);461461+ if (ret) {462462+ kfree(desc);463463+ continue;464464+ }465465+466466+ /*467467+ * This one is now set up; add it to the parent list so468468+ * its children can get processed in a subsequent pass.469469+ */470470+ list_add_tail(&desc->list, &intc_parent_list);471471+ }472472+473473+ /* Get the next pending parent that might have children */474474+ desc = list_first_entry(&intc_parent_list, typeof(*desc), list);475475+ if (list_empty(&intc_parent_list) || !desc) {476476+ pr_err("of_irq_init: children remain, but no parents\n");477477+ break;478478+ }479479+ list_del(&desc->list);480480+ parent = desc->dev;481481+ kfree(desc);482482+ }483483+484484+ list_for_each_entry_safe(desc, temp_desc, &intc_parent_list, list) {485485+ list_del(&desc->list);486486+ kfree(desc);487487+ }488488+err:489489+ list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {490490+ list_del(&desc->list);491491+ kfree(desc);492492+ }390493}
···11+/*22+ * Copyright (C) 2011 Google, Inc.33+ *44+ * Author:55+ * Colin Cross <ccross@android.com>66+ *77+ * This software is licensed under the terms of the GNU General Public88+ * License version 2, as published by the Free Software Foundation, and99+ * may be copied, distributed, and modified under those terms.1010+ *1111+ * This program is distributed in the hope that it will be useful,1212+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1313+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1414+ * GNU General Public License for more details.1515+ *1616+ */1717+1818+#ifndef _LINUX_CPU_PM_H1919+#define _LINUX_CPU_PM_H2020+2121+#include <linux/kernel.h>2222+#include <linux/notifier.h>2323+2424+/*2525+ * When a CPU goes to a low power state that turns off power to the CPU's2626+ * power domain, the contents of some blocks (floating point coprocessors,2727+ * interrupt controllers, caches, timers) in the same power domain can2828+ * be lost. The cpm_pm notifiers provide a method for platform idle, suspend,2929+ * and hotplug implementations to notify the drivers for these blocks that3030+ * they may be reset.3131+ *3232+ * All cpu_pm notifications must be called with interrupts disabled.3333+ *3434+ * The notifications are split into two classes: CPU notifications and CPU3535+ * cluster notifications.3636+ *3737+ * CPU notifications apply to a single CPU and must be called on the affected3838+ * CPU. They are used to save per-cpu context for affected blocks.3939+ *4040+ * CPU cluster notifications apply to all CPUs in a single power domain. They4141+ * are used to save any global context for affected blocks, and must be called4242+ * after all the CPUs in the power domain have been notified of the low power4343+ * state.4444+ */4545+4646+/*4747+ * Event codes passed as unsigned long val to notifier calls4848+ */4949+enum cpu_pm_event {5050+ /* A single cpu is entering a low power state */5151+ CPU_PM_ENTER,5252+5353+ /* A single cpu failed to enter a low power state */5454+ CPU_PM_ENTER_FAILED,5555+5656+ /* A single cpu is exiting a low power state */5757+ CPU_PM_EXIT,5858+5959+ /* A cpu power domain is entering a low power state */6060+ CPU_CLUSTER_PM_ENTER,6161+6262+ /* A cpu power domain failed to enter a low power state */6363+ CPU_CLUSTER_PM_ENTER_FAILED,6464+6565+ /* A cpu power domain is exiting a low power state */6666+ CPU_CLUSTER_PM_EXIT,6767+};6868+6969+#ifdef CONFIG_CPU_PM7070+int cpu_pm_register_notifier(struct notifier_block *nb);7171+int cpu_pm_unregister_notifier(struct notifier_block *nb);7272+int cpu_pm_enter(void);7373+int cpu_pm_exit(void);7474+int cpu_cluster_pm_enter(void);7575+int cpu_cluster_pm_exit(void);7676+7777+#else7878+7979+static inline int cpu_pm_register_notifier(struct notifier_block *nb)8080+{8181+ return 0;8282+}8383+8484+static inline int cpu_pm_unregister_notifier(struct notifier_block *nb)8585+{8686+ return 0;8787+}8888+8989+static inline int cpu_pm_enter(void)9090+{9191+ return 0;9292+}9393+9494+static inline int cpu_pm_exit(void)9595+{9696+ return 0;9797+}9898+9999+static inline int cpu_cluster_pm_enter(void)100100+{101101+ return 0;102102+}103103+104104+static inline int cpu_cluster_pm_exit(void)105105+{106106+ return 0;107107+}108108+#endif109109+#endif
+27-11
include/linux/interrupt.h
···9595 * @flags: flags (see IRQF_* above)9696 * @name: name of the device9797 * @dev_id: cookie to identify the device9898+ * @percpu_dev_id: cookie to identify the device9899 * @next: pointer to the next irqaction for shared interrupts99100 * @irq: interrupt number100101 * @dir: pointer to the proc/irq/NN/name entry···105104 * @thread_mask: bitmask for keeping track of @thread activity106105 */107106struct irqaction {108108- irq_handler_t handler;109109- unsigned long flags;110110- void *dev_id;111111- struct irqaction *next;112112- int irq;113113- irq_handler_t thread_fn;114114- struct task_struct *thread;115115- unsigned long thread_flags;116116- unsigned long thread_mask;117117- const char *name;118118- struct proc_dir_entry *dir;107107+ irq_handler_t handler;108108+ unsigned long flags;109109+ void *dev_id;110110+ void __percpu *percpu_dev_id;111111+ struct irqaction *next;112112+ int irq;113113+ irq_handler_t thread_fn;114114+ struct task_struct *thread;115115+ unsigned long thread_flags;116116+ unsigned long thread_mask;117117+ const char *name;118118+ struct proc_dir_entry *dir;119119} ____cacheline_internodealigned_in_smp;120120121121extern irqreturn_t no_action(int cpl, void *dev_id);···137135extern int __must_check138136request_any_context_irq(unsigned int irq, irq_handler_t handler,139137 unsigned long flags, const char *name, void *dev_id);138138+139139+extern int __must_check140140+request_percpu_irq(unsigned int irq, irq_handler_t handler,141141+ const char *devname, void __percpu *percpu_dev_id);140142141143extern void exit_irq_thread(void);142144#else···170164 return request_irq(irq, handler, flags, name, dev_id);171165}172166167167+static inline int __must_check168168+request_percpu_irq(unsigned int irq, irq_handler_t handler,169169+ const char *devname, void __percpu *percpu_dev_id)170170+{171171+ return request_irq(irq, handler, 0, devname, percpu_dev_id);172172+}173173+173174static inline void exit_irq_thread(void) { }174175#endif175176176177extern void free_irq(unsigned int, void *);178178+extern void free_percpu_irq(unsigned int, void __percpu *);177179178180struct device;179181···221207222208extern void disable_irq_nosync(unsigned int irq);223209extern void disable_irq(unsigned int irq);210210+extern void disable_percpu_irq(unsigned int irq);224211extern void enable_irq(unsigned int irq);212212+extern void enable_percpu_irq(unsigned int irq, unsigned int type);225213226214/* The following three functions are for the core kernel use only. */227215#ifdef CONFIG_GENERIC_HARDIRQS
+17-1
include/linux/irq.h
···6666 * IRQ_NO_BALANCING - Interrupt cannot be balanced (affinity set)6767 * IRQ_MOVE_PCNTXT - Interrupt can be migrated from process context6868 * IRQ_NESTED_TRHEAD - Interrupt nests into another thread6969+ * IRQ_PER_CPU_DEVID - Dev_id is a per-cpu variable6970 */7071enum {7172 IRQ_TYPE_NONE = 0x00000000,···8988 IRQ_MOVE_PCNTXT = (1 << 14),9089 IRQ_NESTED_THREAD = (1 << 15),9190 IRQ_NOTHREAD = (1 << 16),9191+ IRQ_PER_CPU_DEVID = (1 << 17),9292};93939494#define IRQF_MODIFY_MASK \9595 (IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \9696 IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL | IRQ_NO_BALANCING | \9797- IRQ_PER_CPU | IRQ_NESTED_THREAD)9797+ IRQ_PER_CPU | IRQ_NESTED_THREAD | IRQ_NOTHREAD | IRQ_PER_CPU_DEVID)98989999#define IRQ_NO_BALANCING_MASK (IRQ_PER_CPU | IRQ_NO_BALANCING)100100···338336 * IRQCHIP_MASK_ON_SUSPEND: Mask non wake irqs in the suspend path339337 * IRQCHIP_ONOFFLINE_ENABLED: Only call irq_on/off_line callbacks340338 * when irq enabled339339+ * IRQCHIP_SKIP_SET_WAKE: Skip chip.irq_set_wake(), for this irq chip341340 */342341enum {343342 IRQCHIP_SET_TYPE_MASKED = (1 << 0),344343 IRQCHIP_EOI_IF_HANDLED = (1 << 1),345344 IRQCHIP_MASK_ON_SUSPEND = (1 << 2),346345 IRQCHIP_ONOFFLINE_ENABLED = (1 << 3),346346+ IRQCHIP_SKIP_SET_WAKE = (1 << 4),347347};348348349349/* This include will go away once we isolated irq_desc usage to core code */···369365struct irqaction;370366extern int setup_irq(unsigned int irq, struct irqaction *new);371367extern void remove_irq(unsigned int irq, struct irqaction *act);368368+extern int setup_percpu_irq(unsigned int irq, struct irqaction *new);369369+extern void remove_percpu_irq(unsigned int irq, struct irqaction *act);372370373371extern void irq_cpu_online(void);374372extern void irq_cpu_offline(void);···398392extern void handle_edge_eoi_irq(unsigned int irq, struct irq_desc *desc);399393extern void handle_simple_irq(unsigned int irq, struct irq_desc *desc);400394extern void handle_percpu_irq(unsigned int irq, struct irq_desc *desc);395395+extern void handle_percpu_devid_irq(unsigned int irq, struct irq_desc *desc);401396extern void handle_bad_irq(unsigned int irq, struct irq_desc *desc);402397extern void handle_nested_irq(unsigned int irq);403398···426419{427420 irq_set_chip_and_handler_name(irq, chip, handle, NULL);428421}422422+423423+extern int irq_set_percpu_devid(unsigned int irq);429424430425extern void431426__irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,···488479 irq_set_status_flags(irq, IRQ_NESTED_THREAD);489480 else490481 irq_clear_status_flags(irq, IRQ_NESTED_THREAD);482482+}483483+484484+static inline void irq_set_percpu_devid_flags(unsigned int irq)485485+{486486+ irq_set_status_flags(irq,487487+ IRQ_NOAUTOEN | IRQ_PER_CPU | IRQ_NOTHREAD |488488+ IRQ_NOPROBE | IRQ_PER_CPU_DEVID);491489}492490493491/* Handle dynamic irq creation and destruction */
+1
include/linux/irqdesc.h
···5353 unsigned long last_unhandled; /* Aging timer for unhandled count */5454 unsigned int irqs_unhandled;5555 raw_spinlock_t lock;5656+ struct cpumask *percpu_enabled;5657#ifdef CONFIG_SMP5758 const struct cpumask *affinity_hint;5859 struct irq_affinity_notify *affinity_notify;
+15-1
include/linux/irqdomain.h
···4747 * of the irq_domain is responsible for allocating the array of4848 * irq_desc structures.4949 * @nr_irq: Number of irqs managed by the irq domain5050+ * @hwirq_base: Starting number for hwirqs managed by the irq domain5051 * @ops: pointer to irq_domain methods5152 * @priv: private data pointer for use by owner. Not touched by irq_domain5253 * core code.···5857 struct list_head list;5958 unsigned int irq_base;6059 unsigned int nr_irq;6060+ unsigned int hwirq_base;6161 const struct irq_domain_ops *ops;6262 void *priv;6363 struct device_node *of_node;···7472static inline unsigned int irq_domain_to_irq(struct irq_domain *d,7573 unsigned long hwirq)7674{7777- return d->ops->to_irq ? d->ops->to_irq(d, hwirq) : d->irq_base + hwirq;7575+ if (d->ops->to_irq)7676+ return d->ops->to_irq(d, hwirq);7777+ if (WARN_ON(hwirq < d->hwirq_base))7878+ return 0;7979+ return d->irq_base + hwirq - d->hwirq_base;7880}8181+8282+#define irq_domain_for_each_hwirq(d, hw) \8383+ for (hw = d->hwirq_base; hw < d->hwirq_base + d->nr_irq; hw++)8484+8585+#define irq_domain_for_each_irq(d, hw, irq) \8686+ for (hw = d->hwirq_base, irq = irq_domain_to_irq(d, hw); \8787+ hw < d->hwirq_base + d->nr_irq; \8888+ hw++, irq = irq_domain_to_irq(d, hw))79898090extern void irq_domain_add(struct irq_domain *domain);8191extern void irq_domain_del(struct irq_domain *domain);
···11+/*22+ * Copyright (C) 2011 Google, Inc.33+ *44+ * Author:55+ * Colin Cross <ccross@android.com>66+ *77+ * This software is licensed under the terms of the GNU General Public88+ * License version 2, as published by the Free Software Foundation, and99+ * may be copied, distributed, and modified under those terms.1010+ *1111+ * This program is distributed in the hope that it will be useful,1212+ * but WITHOUT ANY WARRANTY; without even the implied warranty of1313+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1414+ * GNU General Public License for more details.1515+ *1616+ */1717+1818+#include <linux/kernel.h>1919+#include <linux/cpu_pm.h>2020+#include <linux/module.h>2121+#include <linux/notifier.h>2222+#include <linux/spinlock.h>2323+#include <linux/syscore_ops.h>2424+2525+static DEFINE_RWLOCK(cpu_pm_notifier_lock);2626+static RAW_NOTIFIER_HEAD(cpu_pm_notifier_chain);2727+2828+static int cpu_pm_notify(enum cpu_pm_event event, int nr_to_call, int *nr_calls)2929+{3030+ int ret;3131+3232+ ret = __raw_notifier_call_chain(&cpu_pm_notifier_chain, event, NULL,3333+ nr_to_call, nr_calls);3434+3535+ return notifier_to_errno(ret);3636+}3737+3838+/**3939+ * cpu_pm_register_notifier - register a driver with cpu_pm4040+ * @nb: notifier block to register4141+ *4242+ * Add a driver to a list of drivers that are notified about4343+ * CPU and CPU cluster low power entry and exit.4444+ *4545+ * This function may sleep, and has the same return conditions as4646+ * raw_notifier_chain_register.4747+ */4848+int cpu_pm_register_notifier(struct notifier_block *nb)4949+{5050+ unsigned long flags;5151+ int ret;5252+5353+ write_lock_irqsave(&cpu_pm_notifier_lock, flags);5454+ ret = raw_notifier_chain_register(&cpu_pm_notifier_chain, nb);5555+ write_unlock_irqrestore(&cpu_pm_notifier_lock, flags);5656+5757+ return ret;5858+}5959+EXPORT_SYMBOL_GPL(cpu_pm_register_notifier);6060+6161+/**6262+ * cpu_pm_unregister_notifier - unregister a driver with cpu_pm6363+ * @nb: notifier block to be unregistered6464+ *6565+ * Remove a driver from the CPU PM notifier list.6666+ *6767+ * This function may sleep, and has the same return conditions as6868+ * raw_notifier_chain_unregister.6969+ */7070+int cpu_pm_unregister_notifier(struct notifier_block *nb)7171+{7272+ unsigned long flags;7373+ int ret;7474+7575+ write_lock_irqsave(&cpu_pm_notifier_lock, flags);7676+ ret = raw_notifier_chain_unregister(&cpu_pm_notifier_chain, nb);7777+ write_unlock_irqrestore(&cpu_pm_notifier_lock, flags);7878+7979+ return ret;8080+}8181+EXPORT_SYMBOL_GPL(cpu_pm_unregister_notifier);8282+8383+/**8484+ * cpm_pm_enter - CPU low power entry notifier8585+ *8686+ * Notifies listeners that a single CPU is entering a low power state that may8787+ * cause some blocks in the same power domain as the cpu to reset.8888+ *8989+ * Must be called on the affected CPU with interrupts disabled. Platform is9090+ * responsible for ensuring that cpu_pm_enter is not called twice on the same9191+ * CPU before cpu_pm_exit is called. Notified drivers can include VFP9292+ * co-processor, interrupt controller and it's PM extensions, local CPU9393+ * timers context save/restore which shouldn't be interrupted. Hence it9494+ * must be called with interrupts disabled.9595+ *9696+ * Return conditions are same as __raw_notifier_call_chain.9797+ */9898+int cpu_pm_enter(void)9999+{100100+ int nr_calls;101101+ int ret = 0;102102+103103+ read_lock(&cpu_pm_notifier_lock);104104+ ret = cpu_pm_notify(CPU_PM_ENTER, -1, &nr_calls);105105+ if (ret)106106+ /*107107+ * Inform listeners (nr_calls - 1) about failure of CPU PM108108+ * PM entry who are notified earlier to prepare for it.109109+ */110110+ cpu_pm_notify(CPU_PM_ENTER_FAILED, nr_calls - 1, NULL);111111+ read_unlock(&cpu_pm_notifier_lock);112112+113113+ return ret;114114+}115115+EXPORT_SYMBOL_GPL(cpu_pm_enter);116116+117117+/**118118+ * cpm_pm_exit - CPU low power exit notifier119119+ *120120+ * Notifies listeners that a single CPU is exiting a low power state that may121121+ * have caused some blocks in the same power domain as the cpu to reset.122122+ *123123+ * Notified drivers can include VFP co-processor, interrupt controller124124+ * and it's PM extensions, local CPU timers context save/restore which125125+ * shouldn't be interrupted. Hence it must be called with interrupts disabled.126126+ *127127+ * Return conditions are same as __raw_notifier_call_chain.128128+ */129129+int cpu_pm_exit(void)130130+{131131+ int ret;132132+133133+ read_lock(&cpu_pm_notifier_lock);134134+ ret = cpu_pm_notify(CPU_PM_EXIT, -1, NULL);135135+ read_unlock(&cpu_pm_notifier_lock);136136+137137+ return ret;138138+}139139+EXPORT_SYMBOL_GPL(cpu_pm_exit);140140+141141+/**142142+ * cpm_cluster_pm_enter - CPU cluster low power entry notifier143143+ *144144+ * Notifies listeners that all cpus in a power domain are entering a low power145145+ * state that may cause some blocks in the same power domain to reset.146146+ *147147+ * Must be called after cpu_pm_enter has been called on all cpus in the power148148+ * domain, and before cpu_pm_exit has been called on any cpu in the power149149+ * domain. Notified drivers can include VFP co-processor, interrupt controller150150+ * and it's PM extensions, local CPU timers context save/restore which151151+ * shouldn't be interrupted. Hence it must be called with interrupts disabled.152152+ *153153+ * Must be called with interrupts disabled.154154+ *155155+ * Return conditions are same as __raw_notifier_call_chain.156156+ */157157+int cpu_cluster_pm_enter(void)158158+{159159+ int nr_calls;160160+ int ret = 0;161161+162162+ read_lock(&cpu_pm_notifier_lock);163163+ ret = cpu_pm_notify(CPU_CLUSTER_PM_ENTER, -1, &nr_calls);164164+ if (ret)165165+ /*166166+ * Inform listeners (nr_calls - 1) about failure of CPU cluster167167+ * PM entry who are notified earlier to prepare for it.168168+ */169169+ cpu_pm_notify(CPU_CLUSTER_PM_ENTER_FAILED, nr_calls - 1, NULL);170170+ read_unlock(&cpu_pm_notifier_lock);171171+172172+ return ret;173173+}174174+EXPORT_SYMBOL_GPL(cpu_cluster_pm_enter);175175+176176+/**177177+ * cpm_cluster_pm_exit - CPU cluster low power exit notifier178178+ *179179+ * Notifies listeners that all cpus in a power domain are exiting form a180180+ * low power state that may have caused some blocks in the same power domain181181+ * to reset.182182+ *183183+ * Must be called after cpu_pm_exit has been called on all cpus in the power184184+ * domain, and before cpu_pm_exit has been called on any cpu in the power185185+ * domain. Notified drivers can include VFP co-processor, interrupt controller186186+ * and it's PM extensions, local CPU timers context save/restore which187187+ * shouldn't be interrupted. Hence it must be called with interrupts disabled.188188+ *189189+ * Return conditions are same as __raw_notifier_call_chain.190190+ */191191+int cpu_cluster_pm_exit(void)192192+{193193+ int ret;194194+195195+ read_lock(&cpu_pm_notifier_lock);196196+ ret = cpu_pm_notify(CPU_CLUSTER_PM_EXIT, -1, NULL);197197+ read_unlock(&cpu_pm_notifier_lock);198198+199199+ return ret;200200+}201201+EXPORT_SYMBOL_GPL(cpu_cluster_pm_exit);202202+203203+#ifdef CONFIG_PM204204+static int cpu_pm_suspend(void)205205+{206206+ int ret;207207+208208+ ret = cpu_pm_enter();209209+ if (ret)210210+ return ret;211211+212212+ ret = cpu_cluster_pm_enter();213213+ return ret;214214+}215215+216216+static void cpu_pm_resume(void)217217+{218218+ cpu_cluster_pm_exit();219219+ cpu_pm_exit();220220+}221221+222222+static struct syscore_ops cpu_pm_syscore_ops = {223223+ .suspend = cpu_pm_suspend,224224+ .resume = cpu_pm_resume,225225+};226226+227227+static int cpu_pm_init(void)228228+{229229+ register_syscore_ops(&cpu_pm_syscore_ops);230230+ return 0;231231+}232232+core_initcall(cpu_pm_init);233233+#endif
···2626int irq_set_chip(unsigned int irq, struct irq_chip *chip)2727{2828 unsigned long flags;2929- struct irq_desc *desc = irq_get_desc_lock(irq, &flags);2929+ struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);30303131 if (!desc)3232 return -EINVAL;···5454int irq_set_irq_type(unsigned int irq, unsigned int type)5555{5656 unsigned long flags;5757- struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);5757+ struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);5858 int ret = 0;59596060 if (!desc)···7878int irq_set_handler_data(unsigned int irq, void *data)7979{8080 unsigned long flags;8181- struct irq_desc *desc = irq_get_desc_lock(irq, &flags);8181+ struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);82828383 if (!desc)8484 return -EINVAL;···9898int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry)9999{100100 unsigned long flags;101101- struct irq_desc *desc = irq_get_desc_lock(irq, &flags);101101+ struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);102102103103 if (!desc)104104 return -EINVAL;···119119int irq_set_chip_data(unsigned int irq, void *data)120120{121121 unsigned long flags;122122- struct irq_desc *desc = irq_get_desc_lock(irq, &flags);122122+ struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);123123124124 if (!desc)125125 return -EINVAL;···202202 desc->irq_data.chip->irq_disable(&desc->irq_data);203203 irq_state_set_masked(desc);204204 }205205+}206206+207207+void irq_percpu_enable(struct irq_desc *desc, unsigned int cpu)208208+{209209+ if (desc->irq_data.chip->irq_enable)210210+ desc->irq_data.chip->irq_enable(&desc->irq_data);211211+ else212212+ desc->irq_data.chip->irq_unmask(&desc->irq_data);213213+ cpumask_set_cpu(cpu, desc->percpu_enabled);214214+}215215+216216+void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu)217217+{218218+ if (desc->irq_data.chip->irq_disable)219219+ desc->irq_data.chip->irq_disable(&desc->irq_data);220220+ else221221+ desc->irq_data.chip->irq_mask(&desc->irq_data);222222+ cpumask_clear_cpu(cpu, desc->percpu_enabled);205223}206224207225static inline void mask_ack_irq(struct irq_desc *desc)···562544 chip->irq_eoi(&desc->irq_data);563545}564546547547+/**548548+ * handle_percpu_devid_irq - Per CPU local irq handler with per cpu dev ids549549+ * @irq: the interrupt number550550+ * @desc: the interrupt description structure for this irq551551+ *552552+ * Per CPU interrupts on SMP machines without locking requirements. Same as553553+ * handle_percpu_irq() above but with the following extras:554554+ *555555+ * action->percpu_dev_id is a pointer to percpu variables which556556+ * contain the real device id for the cpu on which this handler is557557+ * called558558+ */559559+void handle_percpu_devid_irq(unsigned int irq, struct irq_desc *desc)560560+{561561+ struct irq_chip *chip = irq_desc_get_chip(desc);562562+ struct irqaction *action = desc->action;563563+ void *dev_id = __this_cpu_ptr(action->percpu_dev_id);564564+ irqreturn_t res;565565+566566+ kstat_incr_irqs_this_cpu(irq, desc);567567+568568+ if (chip->irq_ack)569569+ chip->irq_ack(&desc->irq_data);570570+571571+ trace_irq_handler_entry(irq, action);572572+ res = action->handler(irq, dev_id);573573+ trace_irq_handler_exit(irq, action, res);574574+575575+ if (chip->irq_eoi)576576+ chip->irq_eoi(&desc->irq_data);577577+}578578+565579void566580__irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,567581 const char *name)568582{569583 unsigned long flags;570570- struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);584584+ struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, 0);571585572586 if (!desc)573587 return;···643593void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set)644594{645595 unsigned long flags;646646- struct irq_desc *desc = irq_get_desc_lock(irq, &flags);596596+ struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);647597648598 if (!desc)649599 return;
+14-5
kernel/irq/internals.h
···7171extern void irq_shutdown(struct irq_desc *desc);7272extern void irq_enable(struct irq_desc *desc);7373extern void irq_disable(struct irq_desc *desc);7474+extern void irq_percpu_enable(struct irq_desc *desc, unsigned int cpu);7575+extern void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu);7476extern void mask_irq(struct irq_desc *desc);7577extern void unmask_irq(struct irq_desc *desc);7678···116114 desc->irq_data.chip->irq_bus_sync_unlock(&desc->irq_data);117115}118116117117+#define _IRQ_DESC_CHECK (1 << 0)118118+#define _IRQ_DESC_PERCPU (1 << 1)119119+120120+#define IRQ_GET_DESC_CHECK_GLOBAL (_IRQ_DESC_CHECK)121121+#define IRQ_GET_DESC_CHECK_PERCPU (_IRQ_DESC_CHECK | _IRQ_DESC_PERCPU)122122+119123struct irq_desc *120120-__irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus);124124+__irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus,125125+ unsigned int check);121126void __irq_put_desc_unlock(struct irq_desc *desc, unsigned long flags, bool bus);122127123128static inline struct irq_desc *124124-irq_get_desc_buslock(unsigned int irq, unsigned long *flags)129129+irq_get_desc_buslock(unsigned int irq, unsigned long *flags, unsigned int check)125130{126126- return __irq_get_desc_lock(irq, flags, true);131131+ return __irq_get_desc_lock(irq, flags, true, check);127132}128133129134static inline void···140131}141132142133static inline struct irq_desc *143143-irq_get_desc_lock(unsigned int irq, unsigned long *flags)134134+irq_get_desc_lock(unsigned int irq, unsigned long *flags, unsigned int check)144135{145145- return __irq_get_desc_lock(irq, flags, false);136136+ return __irq_get_desc_lock(irq, flags, false, check);146137}147138148139static inline void
+31-1
kernel/irq/irqdesc.c
···424424}425425426426struct irq_desc *427427-__irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus)427427+__irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus,428428+ unsigned int check)428429{429430 struct irq_desc *desc = irq_to_desc(irq);430431431432 if (desc) {433433+ if (check & _IRQ_DESC_CHECK) {434434+ if ((check & _IRQ_DESC_PERCPU) &&435435+ !irq_settings_is_per_cpu_devid(desc))436436+ return NULL;437437+438438+ if (!(check & _IRQ_DESC_PERCPU) &&439439+ irq_settings_is_per_cpu_devid(desc))440440+ return NULL;441441+ }442442+432443 if (bus)433444 chip_bus_lock(desc);434445 raw_spin_lock_irqsave(&desc->lock, *flags);···452441 raw_spin_unlock_irqrestore(&desc->lock, flags);453442 if (bus)454443 chip_bus_sync_unlock(desc);444444+}445445+446446+int irq_set_percpu_devid(unsigned int irq)447447+{448448+ struct irq_desc *desc = irq_to_desc(irq);449449+450450+ if (!desc)451451+ return -EINVAL;452452+453453+ if (desc->percpu_enabled)454454+ return -EINVAL;455455+456456+ desc->percpu_enabled = kzalloc(sizeof(*desc->percpu_enabled), GFP_KERNEL);457457+458458+ if (!desc->percpu_enabled)459459+ return -ENOMEM;460460+461461+ irq_set_percpu_devid_flags(irq);462462+ return 0;455463}456464457465/**
+6-6
kernel/irq/irqdomain.c
···2020void irq_domain_add(struct irq_domain *domain)2121{2222 struct irq_data *d;2323- int hwirq;2323+ int hwirq, irq;24242525 /*2626 * This assumes that the irq_domain owner has already allocated2727 * the irq_descs. This block will be removed when support for dynamic2828 * allocation of irq_descs is added to irq_domain.2929 */3030- for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {3131- d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));3030+ irq_domain_for_each_irq(domain, hwirq, irq) {3131+ d = irq_get_irq_data(irq);3232 if (!d) {3333 WARN(1, "error: assigning domain to non existant irq_desc");3434 return;···5454void irq_domain_del(struct irq_domain *domain)5555{5656 struct irq_data *d;5757- int hwirq;5757+ int hwirq, irq;58585959 mutex_lock(&irq_domain_mutex);6060 list_del(&domain->list);6161 mutex_unlock(&irq_domain_mutex);62626363 /* Clear the irq_domain assignments */6464- for (hwirq = 0; hwirq < domain->nr_irq; hwirq++) {6565- d = irq_get_irq_data(irq_domain_to_irq(domain, hwirq));6464+ irq_domain_for_each_irq(domain, hwirq, irq) {6565+ d = irq_get_irq_data(irq);6666 d->domain = NULL;6767 }6868}
+209-9
kernel/irq/manage.c
···195195int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m)196196{197197 unsigned long flags;198198- struct irq_desc *desc = irq_get_desc_lock(irq, &flags);198198+ struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);199199200200 if (!desc)201201 return -EINVAL;···356356static int __disable_irq_nosync(unsigned int irq)357357{358358 unsigned long flags;359359- struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);359359+ struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);360360361361 if (!desc)362362 return -EINVAL;···448448void enable_irq(unsigned int irq)449449{450450 unsigned long flags;451451- struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);451451+ struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);452452453453 if (!desc)454454 return;···466466{467467 struct irq_desc *desc = irq_to_desc(irq);468468 int ret = -ENXIO;469469+470470+ if (irq_desc_get_chip(desc)->flags & IRQCHIP_SKIP_SET_WAKE)471471+ return 0;469472470473 if (desc->irq_data.chip->irq_set_wake)471474 ret = desc->irq_data.chip->irq_set_wake(&desc->irq_data, on);···491488int irq_set_irq_wake(unsigned int irq, unsigned int on)492489{493490 unsigned long flags;494494- struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);491491+ struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);495492 int ret = 0;496493497494 if (!desc)···532529int can_request_irq(unsigned int irq, unsigned long irqflags)533530{534531 unsigned long flags;535535- struct irq_desc *desc = irq_get_desc_lock(irq, &flags);532532+ struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);536533 int canrequest = 0;537534538535 if (!desc)···11211118 int retval;11221119 struct irq_desc *desc = irq_to_desc(irq);1123112011211121+ if (WARN_ON(irq_settings_is_per_cpu_devid(desc)))11221122+ return -EINVAL;11241123 chip_bus_lock(desc);11251124 retval = __setup_irq(irq, desc, act);11261125 chip_bus_sync_unlock(desc);···11311126}11321127EXPORT_SYMBOL_GPL(setup_irq);1133112811341134- /*11291129+/*11351130 * Internal function to unregister an irqaction - used to free11361131 * regular and special interrupts that are part of the architecture.11371132 */···12291224 */12301225void remove_irq(unsigned int irq, struct irqaction *act)12311226{12321232- __free_irq(irq, act->dev_id);12271227+ struct irq_desc *desc = irq_to_desc(irq);12281228+12291229+ if (desc && !WARN_ON(irq_settings_is_per_cpu_devid(desc)))12301230+ __free_irq(irq, act->dev_id);12331231}12341232EXPORT_SYMBOL_GPL(remove_irq);12351233···12541246{12551247 struct irq_desc *desc = irq_to_desc(irq);1256124812571257- if (!desc)12491249+ if (!desc || WARN_ON(irq_settings_is_per_cpu_devid(desc)))12581250 return;1259125112601252#ifdef CONFIG_SMP···13321324 if (!desc)13331325 return -EINVAL;1334132613351335- if (!irq_settings_can_request(desc))13271327+ if (!irq_settings_can_request(desc) ||13281328+ WARN_ON(irq_settings_is_per_cpu_devid(desc)))13361329 return -EINVAL;1337133013381331 if (!handler) {···14181409 return !ret ? IRQC_IS_HARDIRQ : ret;14191410}14201411EXPORT_SYMBOL_GPL(request_any_context_irq);14121412+14131413+void enable_percpu_irq(unsigned int irq, unsigned int type)14141414+{14151415+ unsigned int cpu = smp_processor_id();14161416+ unsigned long flags;14171417+ struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_PERCPU);14181418+14191419+ if (!desc)14201420+ return;14211421+14221422+ type &= IRQ_TYPE_SENSE_MASK;14231423+ if (type != IRQ_TYPE_NONE) {14241424+ int ret;14251425+14261426+ ret = __irq_set_trigger(desc, irq, type);14271427+14281428+ if (ret) {14291429+ WARN(1, "failed to set type for IRQ%d\n", irq);14301430+ goto out;14311431+ }14321432+ }14331433+14341434+ irq_percpu_enable(desc, cpu);14351435+out:14361436+ irq_put_desc_unlock(desc, flags);14371437+}14381438+14391439+void disable_percpu_irq(unsigned int irq)14401440+{14411441+ unsigned int cpu = smp_processor_id();14421442+ unsigned long flags;14431443+ struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_PERCPU);14441444+14451445+ if (!desc)14461446+ return;14471447+14481448+ irq_percpu_disable(desc, cpu);14491449+ irq_put_desc_unlock(desc, flags);14501450+}14511451+14521452+/*14531453+ * Internal function to unregister a percpu irqaction.14541454+ */14551455+static struct irqaction *__free_percpu_irq(unsigned int irq, void __percpu *dev_id)14561456+{14571457+ struct irq_desc *desc = irq_to_desc(irq);14581458+ struct irqaction *action;14591459+ unsigned long flags;14601460+14611461+ WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq);14621462+14631463+ if (!desc)14641464+ return NULL;14651465+14661466+ raw_spin_lock_irqsave(&desc->lock, flags);14671467+14681468+ action = desc->action;14691469+ if (!action || action->percpu_dev_id != dev_id) {14701470+ WARN(1, "Trying to free already-free IRQ %d\n", irq);14711471+ goto bad;14721472+ }14731473+14741474+ if (!cpumask_empty(desc->percpu_enabled)) {14751475+ WARN(1, "percpu IRQ %d still enabled on CPU%d!\n",14761476+ irq, cpumask_first(desc->percpu_enabled));14771477+ goto bad;14781478+ }14791479+14801480+ /* Found it - now remove it from the list of entries: */14811481+ desc->action = NULL;14821482+14831483+ raw_spin_unlock_irqrestore(&desc->lock, flags);14841484+14851485+ unregister_handler_proc(irq, action);14861486+14871487+ module_put(desc->owner);14881488+ return action;14891489+14901490+bad:14911491+ raw_spin_unlock_irqrestore(&desc->lock, flags);14921492+ return NULL;14931493+}14941494+14951495+/**14961496+ * remove_percpu_irq - free a per-cpu interrupt14971497+ * @irq: Interrupt line to free14981498+ * @act: irqaction for the interrupt14991499+ *15001500+ * Used to remove interrupts statically setup by the early boot process.15011501+ */15021502+void remove_percpu_irq(unsigned int irq, struct irqaction *act)15031503+{15041504+ struct irq_desc *desc = irq_to_desc(irq);15051505+15061506+ if (desc && irq_settings_is_per_cpu_devid(desc))15071507+ __free_percpu_irq(irq, act->percpu_dev_id);15081508+}15091509+15101510+/**15111511+ * free_percpu_irq - free an interrupt allocated with request_percpu_irq15121512+ * @irq: Interrupt line to free15131513+ * @dev_id: Device identity to free15141514+ *15151515+ * Remove a percpu interrupt handler. The handler is removed, but15161516+ * the interrupt line is not disabled. This must be done on each15171517+ * CPU before calling this function. The function does not return15181518+ * until any executing interrupts for this IRQ have completed.15191519+ *15201520+ * This function must not be called from interrupt context.15211521+ */15221522+void free_percpu_irq(unsigned int irq, void __percpu *dev_id)15231523+{15241524+ struct irq_desc *desc = irq_to_desc(irq);15251525+15261526+ if (!desc || !irq_settings_is_per_cpu_devid(desc))15271527+ return;15281528+15291529+ chip_bus_lock(desc);15301530+ kfree(__free_percpu_irq(irq, dev_id));15311531+ chip_bus_sync_unlock(desc);15321532+}15331533+15341534+/**15351535+ * setup_percpu_irq - setup a per-cpu interrupt15361536+ * @irq: Interrupt line to setup15371537+ * @act: irqaction for the interrupt15381538+ *15391539+ * Used to statically setup per-cpu interrupts in the early boot process.15401540+ */15411541+int setup_percpu_irq(unsigned int irq, struct irqaction *act)15421542+{15431543+ struct irq_desc *desc = irq_to_desc(irq);15441544+ int retval;15451545+15461546+ if (!desc || !irq_settings_is_per_cpu_devid(desc))15471547+ return -EINVAL;15481548+ chip_bus_lock(desc);15491549+ retval = __setup_irq(irq, desc, act);15501550+ chip_bus_sync_unlock(desc);15511551+15521552+ return retval;15531553+}15541554+15551555+/**15561556+ * request_percpu_irq - allocate a percpu interrupt line15571557+ * @irq: Interrupt line to allocate15581558+ * @handler: Function to be called when the IRQ occurs.15591559+ * @devname: An ascii name for the claiming device15601560+ * @dev_id: A percpu cookie passed back to the handler function15611561+ *15621562+ * This call allocates interrupt resources, but doesn't15631563+ * automatically enable the interrupt. It has to be done on each15641564+ * CPU using enable_percpu_irq().15651565+ *15661566+ * Dev_id must be globally unique. It is a per-cpu variable, and15671567+ * the handler gets called with the interrupted CPU's instance of15681568+ * that variable.15691569+ */15701570+int request_percpu_irq(unsigned int irq, irq_handler_t handler,15711571+ const char *devname, void __percpu *dev_id)15721572+{15731573+ struct irqaction *action;15741574+ struct irq_desc *desc;15751575+ int retval;15761576+15771577+ if (!dev_id)15781578+ return -EINVAL;15791579+15801580+ desc = irq_to_desc(irq);15811581+ if (!desc || !irq_settings_can_request(desc) ||15821582+ !irq_settings_is_per_cpu_devid(desc))15831583+ return -EINVAL;15841584+15851585+ action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);15861586+ if (!action)15871587+ return -ENOMEM;15881588+15891589+ action->handler = handler;15901590+ action->flags = IRQF_PERCPU;15911591+ action->name = devname;15921592+ action->percpu_dev_id = dev_id;15931593+15941594+ chip_bus_lock(desc);15951595+ retval = __setup_irq(irq, desc, action);15961596+ chip_bus_sync_unlock(desc);15971597+15981598+ if (retval)15991599+ kfree(action);16001600+16011601+ return retval;16021602+}