diff options
Diffstat (limited to 'ANDROID_3.4.5/arch/arm/kernel')
87 files changed, 0 insertions, 31938 deletions
diff --git a/ANDROID_3.4.5/arch/arm/kernel/Makefile b/ANDROID_3.4.5/arch/arm/kernel/Makefile deleted file mode 100644 index d6ee77fb..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/Makefile +++ /dev/null @@ -1,85 +0,0 @@ -# -# Makefile for the linux kernel. -# - -CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET) -AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET) - -ifdef CONFIG_FUNCTION_TRACER -CFLAGS_REMOVE_ftrace.o = -pg -CFLAGS_REMOVE_insn.o = -pg -CFLAGS_REMOVE_patch.o = -pg -endif - -CFLAGS_REMOVE_return_address.o = -pg - -# Object file lists. - -obj-y := elf.o entry-armv.o entry-common.o irq.o opcodes.o \ - process.o ptrace.o return_address.o sched_clock.o \ - setup.o signal.o stacktrace.o sys_arm.o time.o traps.o - -obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += compat.o - -obj-$(CONFIG_LEDS) += leds.o -obj-$(CONFIG_OC_ETM) += etm.o -obj-$(CONFIG_CPU_IDLE) += cpuidle.o -obj-$(CONFIG_ISA_DMA_API) += dma.o -obj-$(CONFIG_FIQ) += fiq.o fiqasm.o -obj-$(CONFIG_MODULES) += armksyms.o module.o -obj-$(CONFIG_ARTHUR) += arthur.o -obj-$(CONFIG_ISA_DMA) += dma-isa.o -obj-$(CONFIG_PCI) += bios32.o isa.o -obj-$(CONFIG_ARM_CPU_SUSPEND) += sleep.o suspend.o -obj-$(CONFIG_HIBERNATION) += hibernate.o -obj-$(CONFIG_SMP) += smp.o smp_tlb.o -obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o -obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o -obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o -obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o -obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o -obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o -obj-$(CONFIG_KPROBES) += kprobes.o kprobes-common.o patch.o -ifdef CONFIG_THUMB2_KERNEL -obj-$(CONFIG_KPROBES) += kprobes-thumb.o -else -obj-$(CONFIG_KPROBES) += kprobes-arm.o -endif -obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o -test-kprobes-objs := kprobes-test.o -ifdef CONFIG_THUMB2_KERNEL -test-kprobes-objs += kprobes-test-thumb.o -else -test-kprobes-objs += kprobes-test-arm.o -endif -obj-$(CONFIG_ATAGS_PROC) += atags.o -obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o -obj-$(CONFIG_ARM_THUMBEE) += thumbee.o -obj-$(CONFIG_KGDB) += kgdb.o -obj-$(CONFIG_ARM_UNWIND) += unwind.o -obj-$(CONFIG_HAVE_TCM) += tcm.o -obj-$(CONFIG_OF) += devtree.o -obj-$(CONFIG_CRASH_DUMP) += crash_dump.o -obj-$(CONFIG_SWP_EMULATE) += swp_emulate.o -CFLAGS_swp_emulate.o := -Wa,-march=armv7-a -obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o - -obj-$(CONFIG_CPU_XSCALE) += xscale-cp0.o -obj-$(CONFIG_CPU_XSC3) += xscale-cp0.o -obj-$(CONFIG_CPU_MOHAWK) += xscale-cp0.o -obj-$(CONFIG_CPU_PJ4) += pj4-cp0.o -obj-$(CONFIG_IWMMXT) += iwmmxt.o -obj-$(CONFIG_CPU_HAS_PMU) += pmu.o -obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o -AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt -obj-$(CONFIG_ARM_CPU_TOPOLOGY) += topology.o - -ifneq ($(CONFIG_ARCH_EBSA110),y) - obj-y += io.o -endif - -head-y := head$(MMUEXT).o -obj-$(CONFIG_DEBUG_LL) += debug.o -obj-$(CONFIG_EARLY_PRINTK) += early_printk.o - -extra-y := $(head-y) init_task.o vmlinux.lds diff --git a/ANDROID_3.4.5/arch/arm/kernel/armksyms.c b/ANDROID_3.4.5/arch/arm/kernel/armksyms.c deleted file mode 100644 index b57c75e0..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/armksyms.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * linux/arch/arm/kernel/armksyms.c - * - * Copyright (C) 2000 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/export.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/cryptohash.h> -#include <linux/delay.h> -#include <linux/in6.h> -#include <linux/syscalls.h> -#include <linux/uaccess.h> -#include <linux/io.h> - -#include <asm/checksum.h> -#include <asm/ftrace.h> - -/* - * libgcc functions - functions that are used internally by the - * compiler... (prototypes are not correct though, but that - * doesn't really matter since they're not versioned). - */ -extern void __ashldi3(void); -extern void __ashrdi3(void); -extern void __divsi3(void); -extern void __lshrdi3(void); -extern void __modsi3(void); -extern void __muldi3(void); -extern void __ucmpdi2(void); -extern void __udivsi3(void); -extern void __umodsi3(void); -extern void __do_div64(void); - -extern void __aeabi_idiv(void); -extern void __aeabi_idivmod(void); -extern void __aeabi_lasr(void); -extern void __aeabi_llsl(void); -extern void __aeabi_llsr(void); -extern void __aeabi_lmul(void); -extern void __aeabi_uidiv(void); -extern void __aeabi_uidivmod(void); -extern void __aeabi_ulcmp(void); - -extern void fpundefinstr(void); - - /* platform dependent support */ -EXPORT_SYMBOL(__udelay); -EXPORT_SYMBOL(__const_udelay); - - /* networking */ -EXPORT_SYMBOL(csum_partial); -EXPORT_SYMBOL(csum_partial_copy_from_user); -EXPORT_SYMBOL(csum_partial_copy_nocheck); -EXPORT_SYMBOL(__csum_ipv6_magic); - - /* io */ -#ifndef __raw_readsb -EXPORT_SYMBOL(__raw_readsb); -#endif -#ifndef __raw_readsw -EXPORT_SYMBOL(__raw_readsw); -#endif -#ifndef __raw_readsl -EXPORT_SYMBOL(__raw_readsl); -#endif -#ifndef __raw_writesb -EXPORT_SYMBOL(__raw_writesb); -#endif -#ifndef __raw_writesw -EXPORT_SYMBOL(__raw_writesw); -#endif -#ifndef __raw_writesl -EXPORT_SYMBOL(__raw_writesl); -#endif - - /* string / mem functions */ -EXPORT_SYMBOL(strchr); -EXPORT_SYMBOL(strrchr); -EXPORT_SYMBOL(memset); -EXPORT_SYMBOL(memcpy); -EXPORT_SYMBOL(memmove); -EXPORT_SYMBOL(memchr); -EXPORT_SYMBOL(__memzero); - - /* user mem (segment) */ -EXPORT_SYMBOL(__strnlen_user); -EXPORT_SYMBOL(__strncpy_from_user); - -#ifdef CONFIG_MMU -EXPORT_SYMBOL(copy_page); - -EXPORT_SYMBOL(__copy_from_user); -EXPORT_SYMBOL(__copy_to_user); -EXPORT_SYMBOL(__clear_user); - -EXPORT_SYMBOL(__get_user_1); -EXPORT_SYMBOL(__get_user_2); -EXPORT_SYMBOL(__get_user_4); - -EXPORT_SYMBOL(__put_user_1); -EXPORT_SYMBOL(__put_user_2); -EXPORT_SYMBOL(__put_user_4); -EXPORT_SYMBOL(__put_user_8); -#endif - - /* gcc lib functions */ -EXPORT_SYMBOL(__ashldi3); -EXPORT_SYMBOL(__ashrdi3); -EXPORT_SYMBOL(__divsi3); -EXPORT_SYMBOL(__lshrdi3); -EXPORT_SYMBOL(__modsi3); -EXPORT_SYMBOL(__muldi3); -EXPORT_SYMBOL(__ucmpdi2); -EXPORT_SYMBOL(__udivsi3); -EXPORT_SYMBOL(__umodsi3); -EXPORT_SYMBOL(__do_div64); - -#ifdef CONFIG_AEABI -EXPORT_SYMBOL(__aeabi_idiv); -EXPORT_SYMBOL(__aeabi_idivmod); -EXPORT_SYMBOL(__aeabi_lasr); -EXPORT_SYMBOL(__aeabi_llsl); -EXPORT_SYMBOL(__aeabi_llsr); -EXPORT_SYMBOL(__aeabi_lmul); -EXPORT_SYMBOL(__aeabi_uidiv); -EXPORT_SYMBOL(__aeabi_uidivmod); -EXPORT_SYMBOL(__aeabi_ulcmp); -#endif - - /* bitops */ -EXPORT_SYMBOL(_set_bit); -EXPORT_SYMBOL(_test_and_set_bit); -EXPORT_SYMBOL(_clear_bit); -EXPORT_SYMBOL(_test_and_clear_bit); -EXPORT_SYMBOL(_change_bit); -EXPORT_SYMBOL(_test_and_change_bit); -EXPORT_SYMBOL(_find_first_zero_bit_le); -EXPORT_SYMBOL(_find_next_zero_bit_le); -EXPORT_SYMBOL(_find_first_bit_le); -EXPORT_SYMBOL(_find_next_bit_le); - -#ifdef __ARMEB__ -EXPORT_SYMBOL(_find_first_zero_bit_be); -EXPORT_SYMBOL(_find_next_zero_bit_be); -EXPORT_SYMBOL(_find_first_bit_be); -EXPORT_SYMBOL(_find_next_bit_be); -#endif - -#ifdef CONFIG_FUNCTION_TRACER -#ifdef CONFIG_OLD_MCOUNT -EXPORT_SYMBOL(mcount); -#endif -EXPORT_SYMBOL(__gnu_mcount_nc); -#endif - -#ifdef CONFIG_ARM_PATCH_PHYS_VIRT -EXPORT_SYMBOL(__pv_phys_offset); -#endif diff --git a/ANDROID_3.4.5/arch/arm/kernel/arthur.c b/ANDROID_3.4.5/arch/arm/kernel/arthur.c deleted file mode 100644 index 321c5291..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/arthur.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * linux/arch/arm/kernel/arthur.c - * - * Copyright (C) 1998, 1999, 2000, 2001 Philip Blundell - * - * Arthur personality - */ - -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include <linux/module.h> -#include <linux/personality.h> -#include <linux/stddef.h> -#include <linux/signal.h> -#include <linux/init.h> -#include <linux/sched.h> - -#include <asm/ptrace.h> - -/* Arthur doesn't have many signals, and a lot of those that it does - have don't map easily to any Linux equivalent. Never mind. */ - -#define ARTHUR_SIGABRT 1 -#define ARTHUR_SIGFPE 2 -#define ARTHUR_SIGILL 3 -#define ARTHUR_SIGINT 4 -#define ARTHUR_SIGSEGV 5 -#define ARTHUR_SIGTERM 6 -#define ARTHUR_SIGSTAK 7 -#define ARTHUR_SIGUSR1 8 -#define ARTHUR_SIGUSR2 9 -#define ARTHUR_SIGOSERROR 10 - -static unsigned long arthur_to_linux_signals[32] = { - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31 -}; - -static unsigned long linux_to_arthur_signals[32] = { - 0, -1, ARTHUR_SIGINT, -1, - ARTHUR_SIGILL, 5, ARTHUR_SIGABRT, 7, - ARTHUR_SIGFPE, 9, ARTHUR_SIGUSR1, ARTHUR_SIGSEGV, - ARTHUR_SIGUSR2, 13, 14, ARTHUR_SIGTERM, - 16, 17, 18, 19, - 20, 21, 22, 23, - 24, 25, 26, 27, - 28, 29, 30, 31 -}; - -static void arthur_lcall7(int nr, struct pt_regs *regs) -{ - struct siginfo info; - info.si_signo = SIGSWI; - info.si_errno = nr; - /* Bounce it to the emulator */ - send_sig_info(SIGSWI, &info, current); -} - -static struct exec_domain arthur_exec_domain = { - .name = "Arthur", - .handler = arthur_lcall7, - .pers_low = PER_RISCOS, - .pers_high = PER_RISCOS, - .signal_map = arthur_to_linux_signals, - .signal_invmap = linux_to_arthur_signals, - .module = THIS_MODULE, -}; - -/* - * We could do with some locking to stop Arthur being removed while - * processes are using it. - */ - -static int __init arthur_init(void) -{ - return register_exec_domain(&arthur_exec_domain); -} - -static void __exit arthur_exit(void) -{ - unregister_exec_domain(&arthur_exec_domain); -} - -module_init(arthur_init); -module_exit(arthur_exit); - -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/arch/arm/kernel/asm-offsets.c b/ANDROID_3.4.5/arch/arm/kernel/asm-offsets.c deleted file mode 100644 index 1429d898..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/asm-offsets.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 1995-2003 Russell King - * 2001-2002 Keith Owens - * - * Generate definitions needed by assembly language modules. - * This code generates raw asm output which is post-processed to extract - * and format the required data. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/dma-mapping.h> -#include <asm/cacheflush.h> -#include <asm/glue-df.h> -#include <asm/glue-pf.h> -#include <asm/mach/arch.h> -#include <asm/thread_info.h> -#include <asm/memory.h> -#include <asm/procinfo.h> -#include <asm/hardware/cache-l2x0.h> -#include <linux/kbuild.h> - -/* - * Make sure that the compiler and target are compatible. - */ -#if defined(__APCS_26__) -#error Sorry, your compiler targets APCS-26 but this kernel requires APCS-32 -#endif -/* - * GCC 3.0, 3.1: general bad code generation. - * GCC 3.2.0: incorrect function argument offset calculation. - * GCC 3.2.x: miscompiles NEW_AUX_ENT in fs/binfmt_elf.c - * (http://gcc.gnu.org/PR8896) and incorrect structure - * initialisation in fs/jffs2/erase.c - */ -#if (__GNUC__ == 3 && __GNUC_MINOR__ < 3) -#error Your compiler is too buggy; it is known to miscompile kernels. -#error Known good compilers: 3.3 -#endif - -int main(void) -{ - DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); -#ifdef CONFIG_CC_STACKPROTECTOR - DEFINE(TSK_STACK_CANARY, offsetof(struct task_struct, stack_canary)); -#endif - BLANK(); - DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); - DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); - DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit)); - DEFINE(TI_TASK, offsetof(struct thread_info, task)); - DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain)); - DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); - DEFINE(TI_CPU_DOMAIN, offsetof(struct thread_info, cpu_domain)); - DEFINE(TI_CPU_SAVE, offsetof(struct thread_info, cpu_context)); - DEFINE(TI_USED_CP, offsetof(struct thread_info, used_cp)); - DEFINE(TI_TP_VALUE, offsetof(struct thread_info, tp_value)); - DEFINE(TI_FPSTATE, offsetof(struct thread_info, fpstate)); - DEFINE(TI_VFPSTATE, offsetof(struct thread_info, vfpstate)); -#ifdef CONFIG_SMP - DEFINE(VFP_CPU, offsetof(union vfp_state, hard.cpu)); -#endif -#ifdef CONFIG_ARM_THUMBEE - DEFINE(TI_THUMBEE_STATE, offsetof(struct thread_info, thumbee_state)); -#endif -#ifdef CONFIG_IWMMXT - DEFINE(TI_IWMMXT_STATE, offsetof(struct thread_info, fpstate.iwmmxt)); -#endif -#ifdef CONFIG_CRUNCH - DEFINE(TI_CRUNCH_STATE, offsetof(struct thread_info, crunchstate)); -#endif - BLANK(); - DEFINE(S_R0, offsetof(struct pt_regs, ARM_r0)); - DEFINE(S_R1, offsetof(struct pt_regs, ARM_r1)); - DEFINE(S_R2, offsetof(struct pt_regs, ARM_r2)); - DEFINE(S_R3, offsetof(struct pt_regs, ARM_r3)); - DEFINE(S_R4, offsetof(struct pt_regs, ARM_r4)); - DEFINE(S_R5, offsetof(struct pt_regs, ARM_r5)); - DEFINE(S_R6, offsetof(struct pt_regs, ARM_r6)); - DEFINE(S_R7, offsetof(struct pt_regs, ARM_r7)); - DEFINE(S_R8, offsetof(struct pt_regs, ARM_r8)); - DEFINE(S_R9, offsetof(struct pt_regs, ARM_r9)); - DEFINE(S_R10, offsetof(struct pt_regs, ARM_r10)); - DEFINE(S_FP, offsetof(struct pt_regs, ARM_fp)); - DEFINE(S_IP, offsetof(struct pt_regs, ARM_ip)); - DEFINE(S_SP, offsetof(struct pt_regs, ARM_sp)); - DEFINE(S_LR, offsetof(struct pt_regs, ARM_lr)); - DEFINE(S_PC, offsetof(struct pt_regs, ARM_pc)); - DEFINE(S_PSR, offsetof(struct pt_regs, ARM_cpsr)); - DEFINE(S_OLD_R0, offsetof(struct pt_regs, ARM_ORIG_r0)); - DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs)); - BLANK(); -#ifdef CONFIG_CACHE_L2X0 - DEFINE(L2X0_R_PHY_BASE, offsetof(struct l2x0_regs, phy_base)); - DEFINE(L2X0_R_AUX_CTRL, offsetof(struct l2x0_regs, aux_ctrl)); - DEFINE(L2X0_R_TAG_LATENCY, offsetof(struct l2x0_regs, tag_latency)); - DEFINE(L2X0_R_DATA_LATENCY, offsetof(struct l2x0_regs, data_latency)); - DEFINE(L2X0_R_FILTER_START, offsetof(struct l2x0_regs, filter_start)); - DEFINE(L2X0_R_FILTER_END, offsetof(struct l2x0_regs, filter_end)); - DEFINE(L2X0_R_PREFETCH_CTRL, offsetof(struct l2x0_regs, prefetch_ctrl)); - DEFINE(L2X0_R_PWR_CTRL, offsetof(struct l2x0_regs, pwr_ctrl)); - BLANK(); -#endif -#ifdef CONFIG_CPU_HAS_ASID - DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id)); - BLANK(); -#endif - DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm)); - DEFINE(VMA_VM_FLAGS, offsetof(struct vm_area_struct, vm_flags)); - BLANK(); - DEFINE(VM_EXEC, VM_EXEC); - BLANK(); - DEFINE(PAGE_SZ, PAGE_SIZE); - BLANK(); - DEFINE(SYS_ERROR0, 0x9f0000); - BLANK(); - DEFINE(SIZEOF_MACHINE_DESC, sizeof(struct machine_desc)); - DEFINE(MACHINFO_TYPE, offsetof(struct machine_desc, nr)); - DEFINE(MACHINFO_NAME, offsetof(struct machine_desc, name)); - BLANK(); - DEFINE(PROC_INFO_SZ, sizeof(struct proc_info_list)); - DEFINE(PROCINFO_INITFUNC, offsetof(struct proc_info_list, __cpu_flush)); - DEFINE(PROCINFO_MM_MMUFLAGS, offsetof(struct proc_info_list, __cpu_mm_mmu_flags)); - DEFINE(PROCINFO_IO_MMUFLAGS, offsetof(struct proc_info_list, __cpu_io_mmu_flags)); - BLANK(); -#ifdef MULTI_DABORT - DEFINE(PROCESSOR_DABT_FUNC, offsetof(struct processor, _data_abort)); -#endif -#ifdef MULTI_PABORT - DEFINE(PROCESSOR_PABT_FUNC, offsetof(struct processor, _prefetch_abort)); -#endif -#ifdef MULTI_CPU - DEFINE(CPU_SLEEP_SIZE, offsetof(struct processor, suspend_size)); - DEFINE(CPU_DO_SUSPEND, offsetof(struct processor, do_suspend)); - DEFINE(CPU_DO_RESUME, offsetof(struct processor, do_resume)); -#endif -#ifdef MULTI_CACHE - DEFINE(CACHE_FLUSH_KERN_ALL, offsetof(struct cpu_cache_fns, flush_kern_all)); -#endif - BLANK(); - DEFINE(DMA_BIDIRECTIONAL, DMA_BIDIRECTIONAL); - DEFINE(DMA_TO_DEVICE, DMA_TO_DEVICE); - DEFINE(DMA_FROM_DEVICE, DMA_FROM_DEVICE); - return 0; -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/atags.c b/ANDROID_3.4.5/arch/arm/kernel/atags.c deleted file mode 100644 index 42a1a141..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/atags.c +++ /dev/null @@ -1,83 +0,0 @@ -#include <linux/slab.h> -#include <linux/proc_fs.h> -#include <asm/setup.h> -#include <asm/types.h> -#include <asm/page.h> - -struct buffer { - size_t size; - char data[]; -}; - -static int -read_buffer(char* page, char** start, off_t off, int count, - int* eof, void* data) -{ - struct buffer *buffer = (struct buffer *)data; - - if (off >= buffer->size) { - *eof = 1; - return 0; - } - - count = min((int) (buffer->size - off), count); - - memcpy(page, &buffer->data[off], count); - - return count; -} - -#define BOOT_PARAMS_SIZE 1536 -static char __initdata atags_copy[BOOT_PARAMS_SIZE]; - -void __init save_atags(const struct tag *tags) -{ - memcpy(atags_copy, tags, sizeof(atags_copy)); -} - -static int __init init_atags_procfs(void) -{ - /* - * This cannot go into save_atags() because kmalloc and proc don't work - * yet when it is called. - */ - struct proc_dir_entry *tags_entry; - struct tag *tag = (struct tag *)atags_copy; - struct buffer *b; - size_t size; - - if (tag->hdr.tag != ATAG_CORE) { - printk(KERN_INFO "No ATAGs?"); - return -EINVAL; - } - - for (; tag->hdr.size; tag = tag_next(tag)) - ; - - /* include the terminating ATAG_NONE */ - size = (char *)tag - atags_copy + sizeof(struct tag_header); - - WARN_ON(tag->hdr.tag != ATAG_NONE); - - b = kmalloc(sizeof(*b) + size, GFP_KERNEL); - if (!b) - goto nomem; - - b->size = size; - memcpy(b->data, atags_copy, size); - - tags_entry = create_proc_read_entry("atags", 0400, - NULL, read_buffer, b); - - if (!tags_entry) - goto nomem; - - return 0; - -nomem: - kfree(b); - printk(KERN_ERR "Exporting ATAGs: not enough memory\n"); - - return -ENOMEM; -} -arch_initcall(init_atags_procfs); diff --git a/ANDROID_3.4.5/arch/arm/kernel/atags.h b/ANDROID_3.4.5/arch/arm/kernel/atags.h deleted file mode 100644 index e5f028d2..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/atags.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifdef CONFIG_ATAGS_PROC -extern void save_atags(struct tag *tags); -#else -static inline void save_atags(struct tag *tags) { } -#endif diff --git a/ANDROID_3.4.5/arch/arm/kernel/bios32.c b/ANDROID_3.4.5/arch/arm/kernel/bios32.c deleted file mode 100644 index c3232b36..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/bios32.c +++ /dev/null @@ -1,615 +0,0 @@ -/* - * linux/arch/arm/kernel/bios32.c - * - * PCI bios-type initialisation for PCI machines - * - * Bits taken from various places. - */ -#include <linux/export.h> -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/io.h> - -#include <asm/mach-types.h> -#include <asm/mach/pci.h> - -static int debug_pci; - -/* - * We can't use pci_find_device() here since we are - * called from interrupt context. - */ -static void pcibios_bus_report_status(struct pci_bus *bus, u_int status_mask, int warn) -{ - struct pci_dev *dev; - - list_for_each_entry(dev, &bus->devices, bus_list) { - u16 status; - - /* - * ignore host bridge - we handle - * that separately - */ - if (dev->bus->number == 0 && dev->devfn == 0) - continue; - - pci_read_config_word(dev, PCI_STATUS, &status); - if (status == 0xffff) - continue; - - if ((status & status_mask) == 0) - continue; - - /* clear the status errors */ - pci_write_config_word(dev, PCI_STATUS, status & status_mask); - - if (warn) - printk("(%s: %04X) ", pci_name(dev), status); - } - - list_for_each_entry(dev, &bus->devices, bus_list) - if (dev->subordinate) - pcibios_bus_report_status(dev->subordinate, status_mask, warn); -} - -void pcibios_report_status(u_int status_mask, int warn) -{ - struct list_head *l; - - list_for_each(l, &pci_root_buses) { - struct pci_bus *bus = pci_bus_b(l); - - pcibios_bus_report_status(bus, status_mask, warn); - } -} - -/* - * We don't use this to fix the device, but initialisation of it. - * It's not the correct use for this, but it works. - * Note that the arbiter/ISA bridge appears to be buggy, specifically in - * the following area: - * 1. park on CPU - * 2. ISA bridge ping-pong - * 3. ISA bridge master handling of target RETRY - * - * Bug 3 is responsible for the sound DMA grinding to a halt. We now - * live with bug 2. - */ -static void __devinit pci_fixup_83c553(struct pci_dev *dev) -{ - /* - * Set memory region to start at address 0, and enable IO - */ - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_SPACE_MEMORY); - pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_IO); - - dev->resource[0].end -= dev->resource[0].start; - dev->resource[0].start = 0; - - /* - * All memory requests from ISA to be channelled to PCI - */ - pci_write_config_byte(dev, 0x48, 0xff); - - /* - * Enable ping-pong on bus master to ISA bridge transactions. - * This improves the sound DMA substantially. The fixed - * priority arbiter also helps (see below). - */ - pci_write_config_byte(dev, 0x42, 0x01); - - /* - * Enable PCI retry - */ - pci_write_config_byte(dev, 0x40, 0x22); - - /* - * We used to set the arbiter to "park on last master" (bit - * 1 set), but unfortunately the CyberPro does not park the - * bus. We must therefore park on CPU. Unfortunately, this - * may trigger yet another bug in the 553. - */ - pci_write_config_byte(dev, 0x83, 0x02); - - /* - * Make the ISA DMA request lowest priority, and disable - * rotating priorities completely. - */ - pci_write_config_byte(dev, 0x80, 0x11); - pci_write_config_byte(dev, 0x81, 0x00); - - /* - * Route INTA input to IRQ 11, and set IRQ11 to be level - * sensitive. - */ - pci_write_config_word(dev, 0x44, 0xb000); - outb(0x08, 0x4d1); -} -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, pci_fixup_83c553); - -static void __devinit pci_fixup_unassign(struct pci_dev *dev) -{ - dev->resource[0].end -= dev->resource[0].start; - dev->resource[0].start = 0; -} -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_89C940F, pci_fixup_unassign); - -/* - * Prevent the PCI layer from seeing the resources allocated to this device - * if it is the host bridge by marking it as such. These resources are of - * no consequence to the PCI layer (they are handled elsewhere). - */ -static void __devinit pci_fixup_dec21285(struct pci_dev *dev) -{ - int i; - - if (dev->devfn == 0) { - dev->class &= 0xff; - dev->class |= PCI_CLASS_BRIDGE_HOST << 8; - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - dev->resource[i].start = 0; - dev->resource[i].end = 0; - dev->resource[i].flags = 0; - } - } -} -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, pci_fixup_dec21285); - -/* - * PCI IDE controllers use non-standard I/O port decoding, respect it. - */ -static void __devinit pci_fixup_ide_bases(struct pci_dev *dev) -{ - struct resource *r; - int i; - - if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) - return; - - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - r = dev->resource + i; - if ((r->start & ~0x80) == 0x374) { - r->start |= 2; - r->end = r->start; - } - } -} -DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); - -/* - * Put the DEC21142 to sleep - */ -static void __devinit pci_fixup_dec21142(struct pci_dev *dev) -{ - pci_write_config_dword(dev, 0x40, 0x80000000); -} -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142, pci_fixup_dec21142); - -/* - * The CY82C693 needs some rather major fixups to ensure that it does - * the right thing. Idea from the Alpha people, with a few additions. - * - * We ensure that the IDE base registers are set to 1f0/3f4 for the - * primary bus, and 170/374 for the secondary bus. Also, hide them - * from the PCI subsystem view as well so we won't try to perform - * our own auto-configuration on them. - * - * In addition, we ensure that the PCI IDE interrupts are routed to - * IRQ 14 and IRQ 15 respectively. - * - * The above gets us to a point where the IDE on this device is - * functional. However, The CY82C693U _does not work_ in bus - * master mode without locking the PCI bus solid. - */ -static void __devinit pci_fixup_cy82c693(struct pci_dev *dev) -{ - if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) { - u32 base0, base1; - - if (dev->class & 0x80) { /* primary */ - base0 = 0x1f0; - base1 = 0x3f4; - } else { /* secondary */ - base0 = 0x170; - base1 = 0x374; - } - - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, - base0 | PCI_BASE_ADDRESS_SPACE_IO); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, - base1 | PCI_BASE_ADDRESS_SPACE_IO); - - dev->resource[0].start = 0; - dev->resource[0].end = 0; - dev->resource[0].flags = 0; - - dev->resource[1].start = 0; - dev->resource[1].end = 0; - dev->resource[1].flags = 0; - } else if (PCI_FUNC(dev->devfn) == 0) { - /* - * Setup IDE IRQ routing. - */ - pci_write_config_byte(dev, 0x4b, 14); - pci_write_config_byte(dev, 0x4c, 15); - - /* - * Disable FREQACK handshake, enable USB. - */ - pci_write_config_byte(dev, 0x4d, 0x41); - - /* - * Enable PCI retry, and PCI post-write buffer. - */ - pci_write_config_byte(dev, 0x44, 0x17); - - /* - * Enable ISA master and DMA post write buffering. - */ - pci_write_config_byte(dev, 0x45, 0x03); - } -} -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, pci_fixup_cy82c693); - -static void __init pci_fixup_it8152(struct pci_dev *dev) -{ - int i; - /* fixup for ITE 8152 devices */ - /* FIXME: add defines for class 0x68000 and 0x80103 */ - if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST || - dev->class == 0x68000 || - dev->class == 0x80103) { - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - dev->resource[i].start = 0; - dev->resource[i].end = 0; - dev->resource[i].flags = 0; - } - } -} -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8152, pci_fixup_it8152); - - - -void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) -{ - if (debug_pci) - printk("PCI: Assigning IRQ %02d to %s\n", irq, pci_name(dev)); - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); -} - -/* - * If the bus contains any of these devices, then we must not turn on - * parity checking of any kind. Currently this is CyberPro 20x0 only. - */ -static inline int pdev_bad_for_parity(struct pci_dev *dev) -{ - return ((dev->vendor == PCI_VENDOR_ID_INTERG && - (dev->device == PCI_DEVICE_ID_INTERG_2000 || - dev->device == PCI_DEVICE_ID_INTERG_2010)) || - (dev->vendor == PCI_VENDOR_ID_ITE && - dev->device == PCI_DEVICE_ID_ITE_8152)); - -} - -/* - * pcibios_fixup_bus - Called after each bus is probed, - * but before its children are examined. - */ -void pcibios_fixup_bus(struct pci_bus *bus) -{ - struct pci_dev *dev; - u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_FAST_BACK; - - /* - * Walk the devices on this bus, working out what we can - * and can't support. - */ - list_for_each_entry(dev, &bus->devices, bus_list) { - u16 status; - - pci_read_config_word(dev, PCI_STATUS, &status); - - /* - * If any device on this bus does not support fast back - * to back transfers, then the bus as a whole is not able - * to support them. Having fast back to back transfers - * on saves us one PCI cycle per transaction. - */ - if (!(status & PCI_STATUS_FAST_BACK)) - features &= ~PCI_COMMAND_FAST_BACK; - - if (pdev_bad_for_parity(dev)) - features &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY); - - switch (dev->class >> 8) { - case PCI_CLASS_BRIDGE_PCI: - pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &status); - status |= PCI_BRIDGE_CTL_PARITY|PCI_BRIDGE_CTL_MASTER_ABORT; - status &= ~(PCI_BRIDGE_CTL_BUS_RESET|PCI_BRIDGE_CTL_FAST_BACK); - pci_write_config_word(dev, PCI_BRIDGE_CONTROL, status); - break; - - case PCI_CLASS_BRIDGE_CARDBUS: - pci_read_config_word(dev, PCI_CB_BRIDGE_CONTROL, &status); - status |= PCI_CB_BRIDGE_CTL_PARITY|PCI_CB_BRIDGE_CTL_MASTER_ABORT; - pci_write_config_word(dev, PCI_CB_BRIDGE_CONTROL, status); - break; - } - } - - /* - * Now walk the devices again, this time setting them up. - */ - list_for_each_entry(dev, &bus->devices, bus_list) { - u16 cmd; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - cmd |= features; - pci_write_config_word(dev, PCI_COMMAND, cmd); - - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, - L1_CACHE_BYTES >> 2); - } - - /* - * Propagate the flags to the PCI bridge. - */ - if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) { - if (features & PCI_COMMAND_FAST_BACK) - bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK; - if (features & PCI_COMMAND_PARITY) - bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY; - } - - /* - * Report what we did for this bus - */ - printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n", - bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis"); -} -#ifdef CONFIG_HOTPLUG -EXPORT_SYMBOL(pcibios_fixup_bus); -#endif - -/* - * Swizzle the device pin each time we cross a bridge. - * This might update pin and returns the slot number. - */ -static u8 __devinit pcibios_swizzle(struct pci_dev *dev, u8 *pin) -{ - struct pci_sys_data *sys = dev->sysdata; - int slot = 0, oldpin = *pin; - - if (sys->swizzle) - slot = sys->swizzle(dev, pin); - - if (debug_pci) - printk("PCI: %s swizzling pin %d => pin %d slot %d\n", - pci_name(dev), oldpin, *pin, slot); - - return slot; -} - -/* - * Map a slot/pin to an IRQ. - */ -static int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -{ - struct pci_sys_data *sys = dev->sysdata; - int irq = -1; - - if (sys->map_irq) - irq = sys->map_irq(dev, slot, pin); - - if (debug_pci) - printk("PCI: %s mapping slot %d pin %d => irq %d\n", - pci_name(dev), slot, pin, irq); - - return irq; -} - -static void __init pcibios_init_hw(struct hw_pci *hw) -{ - struct pci_sys_data *sys = NULL; - int ret; - int nr, busnr; - - for (nr = busnr = 0; nr < hw->nr_controllers; nr++) { - sys = kzalloc(sizeof(struct pci_sys_data), GFP_KERNEL); - if (!sys) - panic("PCI: unable to allocate sys data!"); - -#ifdef CONFIG_PCI_DOMAINS - sys->domain = hw->domain; -#endif - sys->hw = hw; - sys->busnr = busnr; - sys->swizzle = hw->swizzle; - sys->map_irq = hw->map_irq; - INIT_LIST_HEAD(&sys->resources); - - ret = hw->setup(nr, sys); - - if (ret > 0) { - if (list_empty(&sys->resources)) { - pci_add_resource_offset(&sys->resources, - &ioport_resource, sys->io_offset); - pci_add_resource_offset(&sys->resources, - &iomem_resource, sys->mem_offset); - } - - sys->bus = hw->scan(nr, sys); - - if (!sys->bus) - panic("PCI: unable to scan bus!"); - - busnr = sys->bus->subordinate + 1; - - list_add(&sys->node, &hw->buses); - } else { - kfree(sys); - if (ret < 0) - break; - } - } -} - -void __init pci_common_init(struct hw_pci *hw) -{ - struct pci_sys_data *sys; - - INIT_LIST_HEAD(&hw->buses); - - pci_add_flags(PCI_REASSIGN_ALL_RSRC); - if (hw->preinit) - hw->preinit(); - pcibios_init_hw(hw); - if (hw->postinit) - hw->postinit(); - - pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq); - - list_for_each_entry(sys, &hw->buses, node) { - struct pci_bus *bus = sys->bus; -#if 0 - if (!pci_has_flag(PCI_PROBE_ONLY)) { - /* - * Size the bridge windows. - */ - pci_bus_size_bridges(bus); - - /* - * Assign resources. - */ - pci_bus_assign_resources(bus); - - /* - * Enable bridges - */ - pci_enable_bridges(bus); - } -#endif - - /* - * Tell drivers about devices found. - */ - pci_bus_add_devices(bus); - } -} - -#ifndef CONFIG_PCI_HOST_ITE8152 -void pcibios_set_master(struct pci_dev *dev) -{ - /* No special bus mastering setup handling */ -} -#endif - -char * __init pcibios_setup(char *str) -{ - if (!strcmp(str, "debug")) { - debug_pci = 1; - return NULL; - } else if (!strcmp(str, "firmware")) { - pci_add_flags(PCI_PROBE_ONLY); - return NULL; - } - return str; -} - -/* - * From arch/i386/kernel/pci-i386.c: - * - * We need to avoid collisions with `mirrored' VGA ports - * and other strange ISA hardware, so we always want the - * addresses to be allocated in the 0x000-0x0ff region - * modulo 0x400. - * - * Why? Because some silly external IO cards only decode - * the low 10 bits of the IO address. The 0x00-0xff region - * is reserved for motherboard devices that decode all 16 - * bits, so it's ok to allocate at, say, 0x2800-0x28ff, - * but we want to try to avoid allocating at 0x2900-0x2bff - * which might be mirrored at 0x0100-0x03ff.. - */ -resource_size_t pcibios_align_resource(void *data, const struct resource *res, - resource_size_t size, resource_size_t align) -{ - resource_size_t start = res->start; - - if (res->flags & IORESOURCE_IO && start & 0x300) - start = (start + 0x3ff) & ~0x3ff; - - start = (start + align - 1) & ~(align - 1); - - return start; -} - -/** - * pcibios_enable_device - Enable I/O and memory. - * @dev: PCI device to be enabled - */ -int pcibios_enable_device(struct pci_dev *dev, int mask) -{ - u16 cmd, old_cmd; - int idx; - struct resource *r; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - for (idx = 0; idx < 6; idx++) { - /* Only set up the requested stuff */ - if (!(mask & (1 << idx))) - continue; - - r = dev->resource + idx; - if (!r->start && r->end) { - printk(KERN_ERR "PCI: Device %s not available because" - " of resource collisions\n", pci_name(dev)); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - - /* - * Bridges (eg, cardbus bridges) need to be fully enabled - */ - if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) - cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY; - - if (cmd != old_cmd) { - printk("PCI: enabling device %s (%04x -> %04x)\n", - pci_name(dev), old_cmd, cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - return 0; -} - -int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, int write_combine) -{ - struct pci_sys_data *root = dev->sysdata; - unsigned long phys; - - if (mmap_state == pci_mmap_io) { - return -EINVAL; - } else { - phys = vma->vm_pgoff + (root->mem_offset >> PAGE_SHIFT); - } - - /* - * Mark this as IO - */ - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - - if (remap_pfn_range(vma, vma->vm_start, phys, - vma->vm_end - vma->vm_start, - vma->vm_page_prot)) - return -EAGAIN; - - return 0; -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/calls.S b/ANDROID_3.4.5/arch/arm/kernel/calls.S deleted file mode 100644 index 463ff4a0..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/calls.S +++ /dev/null @@ -1,396 +0,0 @@ -/* - * linux/arch/arm/kernel/calls.S - * - * Copyright (C) 1995-2005 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This file is included thrice in entry-common.S - */ -/* 0 */ CALL(sys_restart_syscall) - CALL(sys_exit) - CALL(sys_fork_wrapper) - CALL(sys_read) - CALL(sys_write) -/* 5 */ CALL(sys_open) - CALL(sys_close) - CALL(sys_ni_syscall) /* was sys_waitpid */ - CALL(sys_creat) - CALL(sys_link) -/* 10 */ CALL(sys_unlink) - CALL(sys_execve_wrapper) - CALL(sys_chdir) - CALL(OBSOLETE(sys_time)) /* used by libc4 */ - CALL(sys_mknod) -/* 15 */ CALL(sys_chmod) - CALL(sys_lchown16) - CALL(sys_ni_syscall) /* was sys_break */ - CALL(sys_ni_syscall) /* was sys_stat */ - CALL(sys_lseek) -/* 20 */ CALL(sys_getpid) - CALL(sys_mount) - CALL(OBSOLETE(sys_oldumount)) /* used by libc4 */ - CALL(sys_setuid16) - CALL(sys_getuid16) -/* 25 */ CALL(OBSOLETE(sys_stime)) - CALL(sys_ptrace) - CALL(OBSOLETE(sys_alarm)) /* used by libc4 */ - CALL(sys_ni_syscall) /* was sys_fstat */ - CALL(sys_pause) -/* 30 */ CALL(OBSOLETE(sys_utime)) /* used by libc4 */ - CALL(sys_ni_syscall) /* was sys_stty */ - CALL(sys_ni_syscall) /* was sys_getty */ - CALL(sys_access) - CALL(sys_nice) -/* 35 */ CALL(sys_ni_syscall) /* was sys_ftime */ - CALL(sys_sync) - CALL(sys_kill) - CALL(sys_rename) - CALL(sys_mkdir) -/* 40 */ CALL(sys_rmdir) - CALL(sys_dup) - CALL(sys_pipe) - CALL(sys_times) - CALL(sys_ni_syscall) /* was sys_prof */ -/* 45 */ CALL(sys_brk) - CALL(sys_setgid16) - CALL(sys_getgid16) - CALL(sys_ni_syscall) /* was sys_signal */ - CALL(sys_geteuid16) -/* 50 */ CALL(sys_getegid16) - CALL(sys_acct) - CALL(sys_umount) - CALL(sys_ni_syscall) /* was sys_lock */ - CALL(sys_ioctl) -/* 55 */ CALL(sys_fcntl) - CALL(sys_ni_syscall) /* was sys_mpx */ - CALL(sys_setpgid) - CALL(sys_ni_syscall) /* was sys_ulimit */ - CALL(sys_ni_syscall) /* was sys_olduname */ -/* 60 */ CALL(sys_umask) - CALL(sys_chroot) - CALL(sys_ustat) - CALL(sys_dup2) - CALL(sys_getppid) -/* 65 */ CALL(sys_getpgrp) - CALL(sys_setsid) - CALL(sys_sigaction) - CALL(sys_ni_syscall) /* was sys_sgetmask */ - CALL(sys_ni_syscall) /* was sys_ssetmask */ -/* 70 */ CALL(sys_setreuid16) - CALL(sys_setregid16) - CALL(sys_sigsuspend) - CALL(sys_sigpending) - CALL(sys_sethostname) -/* 75 */ CALL(sys_setrlimit) - CALL(OBSOLETE(sys_old_getrlimit)) /* used by libc4 */ - CALL(sys_getrusage) - CALL(sys_gettimeofday) - CALL(sys_settimeofday) -/* 80 */ CALL(sys_getgroups16) - CALL(sys_setgroups16) - CALL(OBSOLETE(sys_old_select)) /* used by libc4 */ - CALL(sys_symlink) - CALL(sys_ni_syscall) /* was sys_lstat */ -/* 85 */ CALL(sys_readlink) - CALL(sys_uselib) - CALL(sys_swapon) - CALL(sys_reboot) - CALL(OBSOLETE(sys_old_readdir)) /* used by libc4 */ -/* 90 */ CALL(OBSOLETE(sys_old_mmap)) /* used by libc4 */ - CALL(sys_munmap) - CALL(sys_truncate) - CALL(sys_ftruncate) - CALL(sys_fchmod) -/* 95 */ CALL(sys_fchown16) - CALL(sys_getpriority) - CALL(sys_setpriority) - CALL(sys_ni_syscall) /* was sys_profil */ - CALL(sys_statfs) -/* 100 */ CALL(sys_fstatfs) - CALL(sys_ni_syscall) /* sys_ioperm */ - CALL(OBSOLETE(ABI(sys_socketcall, sys_oabi_socketcall))) - CALL(sys_syslog) - CALL(sys_setitimer) -/* 105 */ CALL(sys_getitimer) - CALL(sys_newstat) - CALL(sys_newlstat) - CALL(sys_newfstat) - CALL(sys_ni_syscall) /* was sys_uname */ -/* 110 */ CALL(sys_ni_syscall) /* was sys_iopl */ - CALL(sys_vhangup) - CALL(sys_ni_syscall) - CALL(OBSOLETE(sys_syscall)) /* call a syscall */ - CALL(sys_wait4) -/* 115 */ CALL(sys_swapoff) - CALL(sys_sysinfo) - CALL(OBSOLETE(ABI(sys_ipc, sys_oabi_ipc))) - CALL(sys_fsync) - CALL(sys_sigreturn_wrapper) -/* 120 */ CALL(sys_clone_wrapper) - CALL(sys_setdomainname) - CALL(sys_newuname) - CALL(sys_ni_syscall) /* modify_ldt */ - CALL(sys_adjtimex) -/* 125 */ CALL(sys_mprotect) - CALL(sys_sigprocmask) - CALL(sys_ni_syscall) /* was sys_create_module */ - CALL(sys_init_module) - CALL(sys_delete_module) -/* 130 */ CALL(sys_ni_syscall) /* was sys_get_kernel_syms */ - CALL(sys_quotactl) - CALL(sys_getpgid) - CALL(sys_fchdir) - CALL(sys_bdflush) -/* 135 */ CALL(sys_sysfs) - CALL(sys_personality) - CALL(sys_ni_syscall) /* reserved for afs_syscall */ - CALL(sys_setfsuid16) - CALL(sys_setfsgid16) -/* 140 */ CALL(sys_llseek) - CALL(sys_getdents) - CALL(sys_select) - CALL(sys_flock) - CALL(sys_msync) -/* 145 */ CALL(sys_readv) - CALL(sys_writev) - CALL(sys_getsid) - CALL(sys_fdatasync) - CALL(sys_sysctl) -/* 150 */ CALL(sys_mlock) - CALL(sys_munlock) - CALL(sys_mlockall) - CALL(sys_munlockall) - CALL(sys_sched_setparam) -/* 155 */ CALL(sys_sched_getparam) - CALL(sys_sched_setscheduler) - CALL(sys_sched_getscheduler) - CALL(sys_sched_yield) - CALL(sys_sched_get_priority_max) -/* 160 */ CALL(sys_sched_get_priority_min) - CALL(sys_sched_rr_get_interval) - CALL(sys_nanosleep) - CALL(sys_mremap) - CALL(sys_setresuid16) -/* 165 */ CALL(sys_getresuid16) - CALL(sys_ni_syscall) /* vm86 */ - CALL(sys_ni_syscall) /* was sys_query_module */ - CALL(sys_poll) - CALL(sys_ni_syscall) /* was nfsservctl */ -/* 170 */ CALL(sys_setresgid16) - CALL(sys_getresgid16) - CALL(sys_prctl) - CALL(sys_rt_sigreturn_wrapper) - CALL(sys_rt_sigaction) -/* 175 */ CALL(sys_rt_sigprocmask) - CALL(sys_rt_sigpending) - CALL(sys_rt_sigtimedwait) - CALL(sys_rt_sigqueueinfo) - CALL(sys_rt_sigsuspend) -/* 180 */ CALL(ABI(sys_pread64, sys_oabi_pread64)) - CALL(ABI(sys_pwrite64, sys_oabi_pwrite64)) - CALL(sys_chown16) - CALL(sys_getcwd) - CALL(sys_capget) -/* 185 */ CALL(sys_capset) - CALL(sys_sigaltstack_wrapper) - CALL(sys_sendfile) - CALL(sys_ni_syscall) /* getpmsg */ - CALL(sys_ni_syscall) /* putpmsg */ -/* 190 */ CALL(sys_vfork_wrapper) - CALL(sys_getrlimit) - CALL(sys_mmap2) - CALL(ABI(sys_truncate64, sys_oabi_truncate64)) - CALL(ABI(sys_ftruncate64, sys_oabi_ftruncate64)) -/* 195 */ CALL(ABI(sys_stat64, sys_oabi_stat64)) - CALL(ABI(sys_lstat64, sys_oabi_lstat64)) - CALL(ABI(sys_fstat64, sys_oabi_fstat64)) - CALL(sys_lchown) - CALL(sys_getuid) -/* 200 */ CALL(sys_getgid) - CALL(sys_geteuid) - CALL(sys_getegid) - CALL(sys_setreuid) - CALL(sys_setregid) -/* 205 */ CALL(sys_getgroups) - CALL(sys_setgroups) - CALL(sys_fchown) - CALL(sys_setresuid) - CALL(sys_getresuid) -/* 210 */ CALL(sys_setresgid) - CALL(sys_getresgid) - CALL(sys_chown) - CALL(sys_setuid) - CALL(sys_setgid) -/* 215 */ CALL(sys_setfsuid) - CALL(sys_setfsgid) - CALL(sys_getdents64) - CALL(sys_pivot_root) - CALL(sys_mincore) -/* 220 */ CALL(sys_madvise) - CALL(ABI(sys_fcntl64, sys_oabi_fcntl64)) - CALL(sys_ni_syscall) /* TUX */ - CALL(sys_ni_syscall) - CALL(sys_gettid) -/* 225 */ CALL(ABI(sys_readahead, sys_oabi_readahead)) - CALL(sys_setxattr) - CALL(sys_lsetxattr) - CALL(sys_fsetxattr) - CALL(sys_getxattr) -/* 230 */ CALL(sys_lgetxattr) - CALL(sys_fgetxattr) - CALL(sys_listxattr) - CALL(sys_llistxattr) - CALL(sys_flistxattr) -/* 235 */ CALL(sys_removexattr) - CALL(sys_lremovexattr) - CALL(sys_fremovexattr) - CALL(sys_tkill) - CALL(sys_sendfile64) -/* 240 */ CALL(sys_futex) - CALL(sys_sched_setaffinity) - CALL(sys_sched_getaffinity) - CALL(sys_io_setup) - CALL(sys_io_destroy) -/* 245 */ CALL(sys_io_getevents) - CALL(sys_io_submit) - CALL(sys_io_cancel) - CALL(sys_exit_group) - CALL(sys_lookup_dcookie) -/* 250 */ CALL(sys_epoll_create) - CALL(ABI(sys_epoll_ctl, sys_oabi_epoll_ctl)) - CALL(ABI(sys_epoll_wait, sys_oabi_epoll_wait)) - CALL(sys_remap_file_pages) - CALL(sys_ni_syscall) /* sys_set_thread_area */ -/* 255 */ CALL(sys_ni_syscall) /* sys_get_thread_area */ - CALL(sys_set_tid_address) - CALL(sys_timer_create) - CALL(sys_timer_settime) - CALL(sys_timer_gettime) -/* 260 */ CALL(sys_timer_getoverrun) - CALL(sys_timer_delete) - CALL(sys_clock_settime) - CALL(sys_clock_gettime) - CALL(sys_clock_getres) -/* 265 */ CALL(sys_clock_nanosleep) - CALL(sys_statfs64_wrapper) - CALL(sys_fstatfs64_wrapper) - CALL(sys_tgkill) - CALL(sys_utimes) -/* 270 */ CALL(sys_arm_fadvise64_64) - CALL(sys_pciconfig_iobase) - CALL(sys_pciconfig_read) - CALL(sys_pciconfig_write) - CALL(sys_mq_open) -/* 275 */ CALL(sys_mq_unlink) - CALL(sys_mq_timedsend) - CALL(sys_mq_timedreceive) - CALL(sys_mq_notify) - CALL(sys_mq_getsetattr) -/* 280 */ CALL(sys_waitid) - CALL(sys_socket) - CALL(ABI(sys_bind, sys_oabi_bind)) - CALL(ABI(sys_connect, sys_oabi_connect)) - CALL(sys_listen) -/* 285 */ CALL(sys_accept) - CALL(sys_getsockname) - CALL(sys_getpeername) - CALL(sys_socketpair) - CALL(sys_send) -/* 290 */ CALL(ABI(sys_sendto, sys_oabi_sendto)) - CALL(sys_recv) - CALL(sys_recvfrom) - CALL(sys_shutdown) - CALL(sys_setsockopt) -/* 295 */ CALL(sys_getsockopt) - CALL(ABI(sys_sendmsg, sys_oabi_sendmsg)) - CALL(sys_recvmsg) - CALL(ABI(sys_semop, sys_oabi_semop)) - CALL(sys_semget) -/* 300 */ CALL(sys_semctl) - CALL(sys_msgsnd) - CALL(sys_msgrcv) - CALL(sys_msgget) - CALL(sys_msgctl) -/* 305 */ CALL(sys_shmat) - CALL(sys_shmdt) - CALL(sys_shmget) - CALL(sys_shmctl) - CALL(sys_add_key) -/* 310 */ CALL(sys_request_key) - CALL(sys_keyctl) - CALL(ABI(sys_semtimedop, sys_oabi_semtimedop)) -/* vserver */ CALL(sys_ni_syscall) - CALL(sys_ioprio_set) -/* 315 */ CALL(sys_ioprio_get) - CALL(sys_inotify_init) - CALL(sys_inotify_add_watch) - CALL(sys_inotify_rm_watch) - CALL(sys_mbind) -/* 320 */ CALL(sys_get_mempolicy) - CALL(sys_set_mempolicy) - CALL(sys_openat) - CALL(sys_mkdirat) - CALL(sys_mknodat) -/* 325 */ CALL(sys_fchownat) - CALL(sys_futimesat) - CALL(ABI(sys_fstatat64, sys_oabi_fstatat64)) - CALL(sys_unlinkat) - CALL(sys_renameat) -/* 330 */ CALL(sys_linkat) - CALL(sys_symlinkat) - CALL(sys_readlinkat) - CALL(sys_fchmodat) - CALL(sys_faccessat) -/* 335 */ CALL(sys_pselect6) - CALL(sys_ppoll) - CALL(sys_unshare) - CALL(sys_set_robust_list) - CALL(sys_get_robust_list) -/* 340 */ CALL(sys_splice) - CALL(sys_sync_file_range2) - CALL(sys_tee) - CALL(sys_vmsplice) - CALL(sys_move_pages) -/* 345 */ CALL(sys_getcpu) - CALL(sys_epoll_pwait) - CALL(sys_kexec_load) - CALL(sys_utimensat) - CALL(sys_signalfd) -/* 350 */ CALL(sys_timerfd_create) - CALL(sys_eventfd) - CALL(sys_fallocate) - CALL(sys_timerfd_settime) - CALL(sys_timerfd_gettime) -/* 355 */ CALL(sys_signalfd4) - CALL(sys_eventfd2) - CALL(sys_epoll_create1) - CALL(sys_dup3) - CALL(sys_pipe2) -/* 360 */ CALL(sys_inotify_init1) - CALL(sys_preadv) - CALL(sys_pwritev) - CALL(sys_rt_tgsigqueueinfo) - CALL(sys_perf_event_open) -/* 365 */ CALL(sys_recvmmsg) - CALL(sys_accept4) - CALL(sys_fanotify_init) - CALL(sys_fanotify_mark) - CALL(sys_prlimit64) -/* 370 */ CALL(sys_name_to_handle_at) - CALL(sys_open_by_handle_at) - CALL(sys_clock_adjtime) - CALL(sys_syncfs) - CALL(sys_sendmmsg) -/* 375 */ CALL(sys_setns) - CALL(sys_process_vm_readv) - CALL(sys_process_vm_writev) -#ifndef syscalls_counted -.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls -#define syscalls_counted -#endif -.rept syscalls_padding - CALL(sys_ni_syscall) -.endr diff --git a/ANDROID_3.4.5/arch/arm/kernel/compat.c b/ANDROID_3.4.5/arch/arm/kernel/compat.c deleted file mode 100644 index 92565231..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/compat.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * linux/arch/arm/kernel/compat.c - * - * Copyright (C) 2001 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * We keep the old params compatibility cruft in one place (here) - * so we don't end up with lots of mess around other places. - * - * NOTE: - * The old struct param_struct is deprecated, but it will be kept in - * the kernel for 5 years from now (2001). This will allow boot loaders - * to convert to the new struct tag way. - */ -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/init.h> - -#include <asm/setup.h> -#include <asm/mach-types.h> -#include <asm/page.h> - -#include <asm/mach/arch.h> - -#include "compat.h" - -/* - * Usage: - * - do not go blindly adding fields, add them at the end - * - when adding fields, don't rely on the address until - * a patch from me has been released - * - unused fields should be zero (for future expansion) - * - this structure is relatively short-lived - only - * guaranteed to contain useful data in setup_arch() - * - * This is the old deprecated way to pass parameters to the kernel - */ -struct param_struct { - union { - struct { - unsigned long page_size; /* 0 */ - unsigned long nr_pages; /* 4 */ - unsigned long ramdisk_size; /* 8 */ - unsigned long flags; /* 12 */ -#define FLAG_READONLY 1 -#define FLAG_RDLOAD 4 -#define FLAG_RDPROMPT 8 - unsigned long rootdev; /* 16 */ - unsigned long video_num_cols; /* 20 */ - unsigned long video_num_rows; /* 24 */ - unsigned long video_x; /* 28 */ - unsigned long video_y; /* 32 */ - unsigned long memc_control_reg; /* 36 */ - unsigned char sounddefault; /* 40 */ - unsigned char adfsdrives; /* 41 */ - unsigned char bytes_per_char_h; /* 42 */ - unsigned char bytes_per_char_v; /* 43 */ - unsigned long pages_in_bank[4]; /* 44 */ - unsigned long pages_in_vram; /* 60 */ - unsigned long initrd_start; /* 64 */ - unsigned long initrd_size; /* 68 */ - unsigned long rd_start; /* 72 */ - unsigned long system_rev; /* 76 */ - unsigned long system_serial_low; /* 80 */ - unsigned long system_serial_high; /* 84 */ - unsigned long mem_fclk_21285; /* 88 */ - } s; - char unused[256]; - } u1; - union { - char paths[8][128]; - struct { - unsigned long magic; - char n[1024 - sizeof(unsigned long)]; - } s; - } u2; - char commandline[COMMAND_LINE_SIZE]; -}; - -static struct tag * __init memtag(struct tag *tag, unsigned long start, unsigned long size) -{ - tag = tag_next(tag); - tag->hdr.tag = ATAG_MEM; - tag->hdr.size = tag_size(tag_mem32); - tag->u.mem.size = size; - tag->u.mem.start = start; - - return tag; -} - -static void __init build_tag_list(struct param_struct *params, void *taglist) -{ - struct tag *tag = taglist; - - if (params->u1.s.page_size != PAGE_SIZE) { - printk(KERN_WARNING "Warning: bad configuration page, " - "trying to continue\n"); - return; - } - - printk(KERN_DEBUG "Converting old-style param struct to taglist\n"); - -#ifdef CONFIG_ARCH_NETWINDER - if (params->u1.s.nr_pages != 0x02000 && - params->u1.s.nr_pages != 0x04000 && - params->u1.s.nr_pages != 0x08000 && - params->u1.s.nr_pages != 0x10000) { - printk(KERN_WARNING "Warning: bad NeTTrom parameters " - "detected, using defaults\n"); - - params->u1.s.nr_pages = 0x1000; /* 16MB */ - params->u1.s.ramdisk_size = 0; - params->u1.s.flags = FLAG_READONLY; - params->u1.s.initrd_start = 0; - params->u1.s.initrd_size = 0; - params->u1.s.rd_start = 0; - } -#endif - - tag->hdr.tag = ATAG_CORE; - tag->hdr.size = tag_size(tag_core); - tag->u.core.flags = params->u1.s.flags & FLAG_READONLY; - tag->u.core.pagesize = params->u1.s.page_size; - tag->u.core.rootdev = params->u1.s.rootdev; - - tag = tag_next(tag); - tag->hdr.tag = ATAG_RAMDISK; - tag->hdr.size = tag_size(tag_ramdisk); - tag->u.ramdisk.flags = (params->u1.s.flags & FLAG_RDLOAD ? 1 : 0) | - (params->u1.s.flags & FLAG_RDPROMPT ? 2 : 0); - tag->u.ramdisk.size = params->u1.s.ramdisk_size; - tag->u.ramdisk.start = params->u1.s.rd_start; - - tag = tag_next(tag); - tag->hdr.tag = ATAG_INITRD; - tag->hdr.size = tag_size(tag_initrd); - tag->u.initrd.start = params->u1.s.initrd_start; - tag->u.initrd.size = params->u1.s.initrd_size; - - tag = tag_next(tag); - tag->hdr.tag = ATAG_SERIAL; - tag->hdr.size = tag_size(tag_serialnr); - tag->u.serialnr.low = params->u1.s.system_serial_low; - tag->u.serialnr.high = params->u1.s.system_serial_high; - - tag = tag_next(tag); - tag->hdr.tag = ATAG_REVISION; - tag->hdr.size = tag_size(tag_revision); - tag->u.revision.rev = params->u1.s.system_rev; - -#ifdef CONFIG_ARCH_ACORN - if (machine_is_riscpc()) { - int i; - for (i = 0; i < 4; i++) - tag = memtag(tag, PHYS_OFFSET + (i << 26), - params->u1.s.pages_in_bank[i] * PAGE_SIZE); - } else -#endif - tag = memtag(tag, PHYS_OFFSET, params->u1.s.nr_pages * PAGE_SIZE); - -#ifdef CONFIG_FOOTBRIDGE - if (params->u1.s.mem_fclk_21285) { - tag = tag_next(tag); - tag->hdr.tag = ATAG_MEMCLK; - tag->hdr.size = tag_size(tag_memclk); - tag->u.memclk.fmemclk = params->u1.s.mem_fclk_21285; - } -#endif - -#ifdef CONFIG_ARCH_EBSA285 - if (machine_is_ebsa285()) { - tag = tag_next(tag); - tag->hdr.tag = ATAG_VIDEOTEXT; - tag->hdr.size = tag_size(tag_videotext); - tag->u.videotext.x = params->u1.s.video_x; - tag->u.videotext.y = params->u1.s.video_y; - tag->u.videotext.video_page = 0; - tag->u.videotext.video_mode = 0; - tag->u.videotext.video_cols = params->u1.s.video_num_cols; - tag->u.videotext.video_ega_bx = 0; - tag->u.videotext.video_lines = params->u1.s.video_num_rows; - tag->u.videotext.video_isvga = 1; - tag->u.videotext.video_points = 8; - } -#endif - -#ifdef CONFIG_ARCH_ACORN - tag = tag_next(tag); - tag->hdr.tag = ATAG_ACORN; - tag->hdr.size = tag_size(tag_acorn); - tag->u.acorn.memc_control_reg = params->u1.s.memc_control_reg; - tag->u.acorn.vram_pages = params->u1.s.pages_in_vram; - tag->u.acorn.sounddefault = params->u1.s.sounddefault; - tag->u.acorn.adfsdrives = params->u1.s.adfsdrives; -#endif - - tag = tag_next(tag); - tag->hdr.tag = ATAG_CMDLINE; - tag->hdr.size = (strlen(params->commandline) + 3 + - sizeof(struct tag_header)) >> 2; - strcpy(tag->u.cmdline.cmdline, params->commandline); - - tag = tag_next(tag); - tag->hdr.tag = ATAG_NONE; - tag->hdr.size = 0; - - memmove(params, taglist, ((int)tag) - ((int)taglist) + - sizeof(struct tag_header)); -} - -void __init convert_to_tag_list(struct tag *tags) -{ - struct param_struct *params = (struct param_struct *)tags; - build_tag_list(params, ¶ms->u2); -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/compat.h b/ANDROID_3.4.5/arch/arm/kernel/compat.h deleted file mode 100644 index 39264ab1..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/compat.h +++ /dev/null @@ -1,11 +0,0 @@ -/* - * linux/arch/arm/kernel/compat.h - * - * Copyright (C) 2001 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -extern void convert_to_tag_list(struct tag *tags); diff --git a/ANDROID_3.4.5/arch/arm/kernel/cpuidle.c b/ANDROID_3.4.5/arch/arm/kernel/cpuidle.c deleted file mode 100644 index 89545f6c..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/cpuidle.c +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2012 Linaro Ltd. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include <linux/cpuidle.h> -#include <asm/proc-fns.h> - -int arm_cpuidle_simple_enter(struct cpuidle_device *dev, - struct cpuidle_driver *drv, int index) -{ - cpu_do_idle(); - - return index; -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/crash_dump.c b/ANDROID_3.4.5/arch/arm/kernel/crash_dump.c deleted file mode 100644 index 90c50d4b..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/crash_dump.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * arch/arm/kernel/crash_dump.c - * - * Copyright (C) 2010 Nokia Corporation. - * Author: Mika Westerberg - * - * This code is taken from arch/x86/kernel/crash_dump_64.c - * Created by: Hariprasad Nellitheertha (hari@in.ibm.com) - * Copyright (C) IBM Corporation, 2004. All rights reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/errno.h> -#include <linux/crash_dump.h> -#include <linux/uaccess.h> -#include <linux/io.h> - -/** - * copy_oldmem_page() - copy one page from old kernel memory - * @pfn: page frame number to be copied - * @buf: buffer where the copied page is placed - * @csize: number of bytes to copy - * @offset: offset in bytes into the page - * @userbuf: if set, @buf is int he user address space - * - * This function copies one page from old kernel memory into buffer pointed by - * @buf. If @buf is in userspace, set @userbuf to %1. Returns number of bytes - * copied or negative error in case of failure. - */ -ssize_t copy_oldmem_page(unsigned long pfn, char *buf, - size_t csize, unsigned long offset, - int userbuf) -{ - void *vaddr; - - if (!csize) - return 0; - - vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE); - if (!vaddr) - return -ENOMEM; - - if (userbuf) { - if (copy_to_user(buf, vaddr + offset, csize)) { - iounmap(vaddr); - return -EFAULT; - } - } else { - memcpy(buf, vaddr + offset, csize); - } - - iounmap(vaddr); - return csize; -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/debug.S b/ANDROID_3.4.5/arch/arm/kernel/debug.S deleted file mode 100644 index c45522c3..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/debug.S +++ /dev/null @@ -1,203 +0,0 @@ -/* - * linux/arch/arm/kernel/debug.S - * - * Copyright (C) 1994-1999 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 32-bit debugging code - */ -#include <linux/linkage.h> -#include <asm/assembler.h> - - .text - -/* - * Some debugging routines (useful if you've got MM problems and - * printk isn't working). For DEBUGGING ONLY!!! Do not leave - * references to these in a production kernel! - */ - -#if defined(CONFIG_DEBUG_ICEDCC) - @@ debug using ARM EmbeddedICE DCC channel - - .macro addruart, rp, rv, tmp - .endm - -#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7) - - .macro senduart, rd, rx - mcr p14, 0, \rd, c0, c5, 0 - .endm - - .macro busyuart, rd, rx -1001: - mrc p14, 0, \rx, c0, c1, 0 - tst \rx, #0x20000000 - beq 1001b - .endm - - .macro waituart, rd, rx - mov \rd, #0x2000000 -1001: - subs \rd, \rd, #1 - bmi 1002f - mrc p14, 0, \rx, c0, c1, 0 - tst \rx, #0x20000000 - bne 1001b -1002: - .endm - -#elif defined(CONFIG_CPU_XSCALE) - - .macro senduart, rd, rx - mcr p14, 0, \rd, c8, c0, 0 - .endm - - .macro busyuart, rd, rx -1001: - mrc p14, 0, \rx, c14, c0, 0 - tst \rx, #0x10000000 - beq 1001b - .endm - - .macro waituart, rd, rx - mov \rd, #0x10000000 -1001: - subs \rd, \rd, #1 - bmi 1002f - mrc p14, 0, \rx, c14, c0, 0 - tst \rx, #0x10000000 - bne 1001b -1002: - .endm - -#else - - .macro senduart, rd, rx - mcr p14, 0, \rd, c1, c0, 0 - .endm - - .macro busyuart, rd, rx -1001: - mrc p14, 0, \rx, c0, c0, 0 - tst \rx, #2 - beq 1001b - - .endm - - .macro waituart, rd, rx - mov \rd, #0x2000000 -1001: - subs \rd, \rd, #1 - bmi 1002f - mrc p14, 0, \rx, c0, c0, 0 - tst \rx, #2 - bne 1001b -1002: - .endm - -#endif /* CONFIG_CPU_V6 */ - -#elif !defined(CONFIG_DEBUG_SEMIHOSTING) -#include <mach/debug-macro.S> -#endif /* CONFIG_DEBUG_ICEDCC */ - -#ifdef CONFIG_MMU - .macro addruart_current, rx, tmp1, tmp2 - addruart \tmp1, \tmp2, \rx - mrc p15, 0, \rx, c1, c0 - tst \rx, #1 - moveq \rx, \tmp1 - movne \rx, \tmp2 - .endm - -#else /* !CONFIG_MMU */ - .macro addruart_current, rx, tmp1, tmp2 - addruart \rx, \tmp1 - .endm - -#endif /* CONFIG_MMU */ - -/* - * Useful debugging routines - */ -ENTRY(printhex8) - mov r1, #8 - b printhex -ENDPROC(printhex8) - -ENTRY(printhex4) - mov r1, #4 - b printhex -ENDPROC(printhex4) - -ENTRY(printhex2) - mov r1, #2 -printhex: adr r2, hexbuf - add r3, r2, r1 - mov r1, #0 - strb r1, [r3] -1: and r1, r0, #15 - mov r0, r0, lsr #4 - cmp r1, #10 - addlt r1, r1, #'0' - addge r1, r1, #'a' - 10 - strb r1, [r3, #-1]! - teq r3, r2 - bne 1b - mov r0, r2 - b printascii -ENDPROC(printhex2) - -hexbuf: .space 16 - - .ltorg - -#ifndef CONFIG_DEBUG_SEMIHOSTING - -ENTRY(printascii) - addruart_current r3, r1, r2 - b 2f -1: waituart r2, r3 - senduart r1, r3 - busyuart r2, r3 - teq r1, #'\n' - moveq r1, #'\r' - beq 1b -2: teq r0, #0 - ldrneb r1, [r0], #1 - teqne r1, #0 - bne 1b - mov pc, lr -ENDPROC(printascii) - -ENTRY(printch) - addruart_current r3, r1, r2 - mov r1, r0 - mov r0, #0 - b 1b -ENDPROC(printch) - -#else - -ENTRY(printascii) - mov r1, r0 - mov r0, #0x04 @ SYS_WRITE0 - ARM( svc #0x123456 ) - THUMB( svc #0xab ) - mov pc, lr -ENDPROC(printascii) - -ENTRY(printch) - adr r1, hexbuf - strb r0, [r1] - mov r0, #0x03 @ SYS_WRITEC - ARM( svc #0x123456 ) - THUMB( svc #0xab ) - mov pc, lr -ENDPROC(printch) - -#endif diff --git a/ANDROID_3.4.5/arch/arm/kernel/devtree.c b/ANDROID_3.4.5/arch/arm/kernel/devtree.c deleted file mode 100644 index bee7f9d4..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/devtree.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * linux/arch/arm/kernel/devtree.c - * - * Copyright (C) 2009 Canonical Ltd. <jeremy.kerr@canonical.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/init.h> -#include <linux/export.h> -#include <linux/errno.h> -#include <linux/types.h> -#include <linux/bootmem.h> -#include <linux/memblock.h> -#include <linux/of.h> -#include <linux/of_fdt.h> -#include <linux/of_irq.h> -#include <linux/of_platform.h> - -#include <asm/setup.h> -#include <asm/page.h> -#include <asm/mach/arch.h> -#include <asm/mach-types.h> - -void __init early_init_dt_add_memory_arch(u64 base, u64 size) -{ - arm_add_memory(base, size); -} - -void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) -{ - return alloc_bootmem_align(size, align); -} - -void __init arm_dt_memblock_reserve(void) -{ - u64 *reserve_map, base, size; - - if (!initial_boot_params) - return; - - /* Reserve the dtb region */ - memblock_reserve(virt_to_phys(initial_boot_params), - be32_to_cpu(initial_boot_params->totalsize)); - - /* - * Process the reserve map. This will probably overlap the initrd - * and dtb locations which are already reserved, but overlaping - * doesn't hurt anything - */ - reserve_map = ((void*)initial_boot_params) + - be32_to_cpu(initial_boot_params->off_mem_rsvmap); - while (1) { - base = be64_to_cpup(reserve_map++); - size = be64_to_cpup(reserve_map++); - if (!size) - break; - memblock_reserve(base, size); - } -} - -/** - * setup_machine_fdt - Machine setup when an dtb was passed to the kernel - * @dt_phys: physical address of dt blob - * - * If a dtb was passed to the kernel in r2, then use it to choose the - * correct machine_desc and to setup the system. - */ -struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys) -{ - struct boot_param_header *devtree; - struct machine_desc *mdesc, *mdesc_best = NULL; - unsigned int score, mdesc_score = ~1; - unsigned long dt_root; - const char *model; - - if (!dt_phys) - return NULL; - - devtree = phys_to_virt(dt_phys); - - /* check device tree validity */ - if (be32_to_cpu(devtree->magic) != OF_DT_HEADER) - return NULL; - - /* Search the mdescs for the 'best' compatible value match */ - initial_boot_params = devtree; - dt_root = of_get_flat_dt_root(); - for_each_machine_desc(mdesc) { - score = of_flat_dt_match(dt_root, mdesc->dt_compat); - if (score > 0 && score < mdesc_score) { - mdesc_best = mdesc; - mdesc_score = score; - } - } - if (!mdesc_best) { - const char *prop; - long size; - - early_print("\nError: unrecognized/unsupported " - "device tree compatible list:\n[ "); - - prop = of_get_flat_dt_prop(dt_root, "compatible", &size); - while (size > 0) { - early_print("'%s' ", prop); - size -= strlen(prop) + 1; - prop += strlen(prop) + 1; - } - early_print("]\n\n"); - - dump_machine_table(); /* does not return */ - } - - model = of_get_flat_dt_prop(dt_root, "model", NULL); - if (!model) - model = of_get_flat_dt_prop(dt_root, "compatible", NULL); - if (!model) - model = "<unknown>"; - pr_info("Machine: %s, model: %s\n", mdesc_best->name, model); - - /* Retrieve various information from the /chosen node */ - of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line); - /* Initialize {size,address}-cells info */ - of_scan_flat_dt(early_init_dt_scan_root, NULL); - /* Setup memory, calling early_init_dt_add_memory_arch */ - of_scan_flat_dt(early_init_dt_scan_memory, NULL); - - /* Change machine number to match the mdesc we're using */ - __machine_arch_type = mdesc_best->nr; - - return mdesc_best; -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/dma-isa.c b/ANDROID_3.4.5/arch/arm/kernel/dma-isa.c deleted file mode 100644 index 360bb6d7..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/dma-isa.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * linux/arch/arm/kernel/dma-isa.c - * - * Copyright (C) 1999-2000 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * ISA DMA primitives - * Taken from various sources, including: - * linux/include/asm/dma.h: Defines for using and allocating dma channels. - * Written by Hennus Bergman, 1992. - * High DMA channel support & info by Hannu Savolainen and John Boyd, - * Nov. 1992. - * arch/arm/kernel/dma-ebsa285.c - * Copyright (C) 1998 Phil Blundell - */ -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/dma-mapping.h> -#include <linux/io.h> - -#include <asm/dma.h> -#include <asm/mach/dma.h> - -#define ISA_DMA_MASK 0 -#define ISA_DMA_MODE 1 -#define ISA_DMA_CLRFF 2 -#define ISA_DMA_PGHI 3 -#define ISA_DMA_PGLO 4 -#define ISA_DMA_ADDR 5 -#define ISA_DMA_COUNT 6 - -static unsigned int isa_dma_port[8][7] = { - /* MASK MODE CLRFF PAGE_HI PAGE_LO ADDR COUNT */ - { 0x0a, 0x0b, 0x0c, 0x487, 0x087, 0x00, 0x01 }, - { 0x0a, 0x0b, 0x0c, 0x483, 0x083, 0x02, 0x03 }, - { 0x0a, 0x0b, 0x0c, 0x481, 0x081, 0x04, 0x05 }, - { 0x0a, 0x0b, 0x0c, 0x482, 0x082, 0x06, 0x07 }, - { 0xd4, 0xd6, 0xd8, 0x000, 0x000, 0xc0, 0xc2 }, - { 0xd4, 0xd6, 0xd8, 0x48b, 0x08b, 0xc4, 0xc6 }, - { 0xd4, 0xd6, 0xd8, 0x489, 0x089, 0xc8, 0xca }, - { 0xd4, 0xd6, 0xd8, 0x48a, 0x08a, 0xcc, 0xce } -}; - -static int isa_get_dma_residue(unsigned int chan, dma_t *dma) -{ - unsigned int io_port = isa_dma_port[chan][ISA_DMA_COUNT]; - int count; - - count = 1 + inb(io_port); - count |= inb(io_port) << 8; - - return chan < 4 ? count : (count << 1); -} - -static void isa_enable_dma(unsigned int chan, dma_t *dma) -{ - if (dma->invalid) { - unsigned long address, length; - unsigned int mode; - enum dma_data_direction direction; - - mode = (chan & 3) | dma->dma_mode; - switch (dma->dma_mode & DMA_MODE_MASK) { - case DMA_MODE_READ: - direction = DMA_FROM_DEVICE; - break; - - case DMA_MODE_WRITE: - direction = DMA_TO_DEVICE; - break; - - case DMA_MODE_CASCADE: - direction = DMA_BIDIRECTIONAL; - break; - - default: - direction = DMA_NONE; - break; - } - - if (!dma->sg) { - /* - * Cope with ISA-style drivers which expect cache - * coherence. - */ - dma->sg = &dma->buf; - dma->sgcount = 1; - dma->buf.length = dma->count; - dma->buf.dma_address = dma_map_single(NULL, - dma->addr, dma->count, - direction); - } - - address = dma->buf.dma_address; - length = dma->buf.length - 1; - - outb(address >> 16, isa_dma_port[chan][ISA_DMA_PGLO]); - outb(address >> 24, isa_dma_port[chan][ISA_DMA_PGHI]); - - if (chan >= 4) { - address >>= 1; - length >>= 1; - } - - outb(0, isa_dma_port[chan][ISA_DMA_CLRFF]); - - outb(address, isa_dma_port[chan][ISA_DMA_ADDR]); - outb(address >> 8, isa_dma_port[chan][ISA_DMA_ADDR]); - - outb(length, isa_dma_port[chan][ISA_DMA_COUNT]); - outb(length >> 8, isa_dma_port[chan][ISA_DMA_COUNT]); - - outb(mode, isa_dma_port[chan][ISA_DMA_MODE]); - dma->invalid = 0; - } - outb(chan & 3, isa_dma_port[chan][ISA_DMA_MASK]); -} - -static void isa_disable_dma(unsigned int chan, dma_t *dma) -{ - outb(chan | 4, isa_dma_port[chan][ISA_DMA_MASK]); -} - -static struct dma_ops isa_dma_ops = { - .type = "ISA", - .enable = isa_enable_dma, - .disable = isa_disable_dma, - .residue = isa_get_dma_residue, -}; - -static struct resource dma_resources[] = { { - .name = "dma1", - .start = 0x0000, - .end = 0x000f -}, { - .name = "dma low page", - .start = 0x0080, - .end = 0x008f -}, { - .name = "dma2", - .start = 0x00c0, - .end = 0x00df -}, { - .name = "dma high page", - .start = 0x0480, - .end = 0x048f -} }; - -static dma_t isa_dma[8]; - -/* - * ISA DMA always starts at channel 0 - */ -void __init isa_init_dma(void) -{ - /* - * Try to autodetect presence of an ISA DMA controller. - * We do some minimal initialisation, and check that - * channel 0's DMA address registers are writeable. - */ - outb(0xff, 0x0d); - outb(0xff, 0xda); - - /* - * Write high and low address, and then read them back - * in the same order. - */ - outb(0x55, 0x00); - outb(0xaa, 0x00); - - if (inb(0) == 0x55 && inb(0) == 0xaa) { - unsigned int chan, i; - - for (chan = 0; chan < 8; chan++) { - isa_dma[chan].d_ops = &isa_dma_ops; - isa_disable_dma(chan, NULL); - } - - outb(0x40, 0x0b); - outb(0x41, 0x0b); - outb(0x42, 0x0b); - outb(0x43, 0x0b); - - outb(0xc0, 0xd6); - outb(0x41, 0xd6); - outb(0x42, 0xd6); - outb(0x43, 0xd6); - - outb(0, 0xd4); - - outb(0x10, 0x08); - outb(0x10, 0xd0); - - /* - * Is this correct? According to my documentation, it - * doesn't appear to be. It should be: - * outb(0x3f, 0x40b); outb(0x3f, 0x4d6); - */ - outb(0x30, 0x40b); - outb(0x31, 0x40b); - outb(0x32, 0x40b); - outb(0x33, 0x40b); - outb(0x31, 0x4d6); - outb(0x32, 0x4d6); - outb(0x33, 0x4d6); - - for (i = 0; i < ARRAY_SIZE(dma_resources); i++) - request_resource(&ioport_resource, dma_resources + i); - - for (chan = 0; chan < 8; chan++) { - int ret = isa_dma_add(chan, &isa_dma[chan]); - if (ret) - printk(KERN_ERR "ISADMA%u: unable to register: %d\n", - chan, ret); - } - - request_dma(DMA_ISA_CASCADE, "cascade"); - } -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/dma.c b/ANDROID_3.4.5/arch/arm/kernel/dma.c deleted file mode 100644 index 7b829d96..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/dma.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * linux/arch/arm/kernel/dma.c - * - * Copyright (C) 1995-2000 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Front-end to the DMA handling. This handles the allocation/freeing - * of DMA channels, and provides a unified interface to the machines - * DMA facilities. - */ -#include <linux/module.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/errno.h> -#include <linux/scatterlist.h> -#include <linux/seq_file.h> -#include <linux/proc_fs.h> - -#include <asm/dma.h> - -#include <asm/mach/dma.h> - -DEFINE_RAW_SPINLOCK(dma_spin_lock); -EXPORT_SYMBOL(dma_spin_lock); - -static dma_t *dma_chan[MAX_DMA_CHANNELS]; - -static inline dma_t *dma_channel(unsigned int chan) -{ - if (chan >= MAX_DMA_CHANNELS) - return NULL; - - return dma_chan[chan]; -} - -int __init isa_dma_add(unsigned int chan, dma_t *dma) -{ - if (!dma->d_ops) - return -EINVAL; - - sg_init_table(&dma->buf, 1); - - if (dma_chan[chan]) - return -EBUSY; - dma_chan[chan] = dma; - return 0; -} - -/* - * Request DMA channel - * - * On certain platforms, we have to allocate an interrupt as well... - */ -int request_dma(unsigned int chan, const char *device_id) -{ - dma_t *dma = dma_channel(chan); - int ret; - - if (!dma) - goto bad_dma; - - if (xchg(&dma->lock, 1) != 0) - goto busy; - - dma->device_id = device_id; - dma->active = 0; - dma->invalid = 1; - - ret = 0; - if (dma->d_ops->request) - ret = dma->d_ops->request(chan, dma); - - if (ret) - xchg(&dma->lock, 0); - - return ret; - -bad_dma: - printk(KERN_ERR "dma: trying to allocate DMA%d\n", chan); - return -EINVAL; - -busy: - return -EBUSY; -} -EXPORT_SYMBOL(request_dma); - -/* - * Free DMA channel - * - * On certain platforms, we have to free interrupt as well... - */ -void free_dma(unsigned int chan) -{ - dma_t *dma = dma_channel(chan); - - if (!dma) - goto bad_dma; - - if (dma->active) { - printk(KERN_ERR "dma%d: freeing active DMA\n", chan); - dma->d_ops->disable(chan, dma); - dma->active = 0; - } - - if (xchg(&dma->lock, 0) != 0) { - if (dma->d_ops->free) - dma->d_ops->free(chan, dma); - return; - } - - printk(KERN_ERR "dma%d: trying to free free DMA\n", chan); - return; - -bad_dma: - printk(KERN_ERR "dma: trying to free DMA%d\n", chan); -} -EXPORT_SYMBOL(free_dma); - -/* Set DMA Scatter-Gather list - */ -void set_dma_sg (unsigned int chan, struct scatterlist *sg, int nr_sg) -{ - dma_t *dma = dma_channel(chan); - - if (dma->active) - printk(KERN_ERR "dma%d: altering DMA SG while " - "DMA active\n", chan); - - dma->sg = sg; - dma->sgcount = nr_sg; - dma->invalid = 1; -} -EXPORT_SYMBOL(set_dma_sg); - -/* Set DMA address - * - * Copy address to the structure, and set the invalid bit - */ -void __set_dma_addr (unsigned int chan, void *addr) -{ - dma_t *dma = dma_channel(chan); - - if (dma->active) - printk(KERN_ERR "dma%d: altering DMA address while " - "DMA active\n", chan); - - dma->sg = NULL; - dma->addr = addr; - dma->invalid = 1; -} -EXPORT_SYMBOL(__set_dma_addr); - -/* Set DMA byte count - * - * Copy address to the structure, and set the invalid bit - */ -void set_dma_count (unsigned int chan, unsigned long count) -{ - dma_t *dma = dma_channel(chan); - - if (dma->active) - printk(KERN_ERR "dma%d: altering DMA count while " - "DMA active\n", chan); - - dma->sg = NULL; - dma->count = count; - dma->invalid = 1; -} -EXPORT_SYMBOL(set_dma_count); - -/* Set DMA direction mode - */ -void set_dma_mode (unsigned int chan, unsigned int mode) -{ - dma_t *dma = dma_channel(chan); - - if (dma->active) - printk(KERN_ERR "dma%d: altering DMA mode while " - "DMA active\n", chan); - - dma->dma_mode = mode; - dma->invalid = 1; -} -EXPORT_SYMBOL(set_dma_mode); - -/* Enable DMA channel - */ -void enable_dma (unsigned int chan) -{ - dma_t *dma = dma_channel(chan); - - if (!dma->lock) - goto free_dma; - - if (dma->active == 0) { - dma->active = 1; - dma->d_ops->enable(chan, dma); - } - return; - -free_dma: - printk(KERN_ERR "dma%d: trying to enable free DMA\n", chan); - BUG(); -} -EXPORT_SYMBOL(enable_dma); - -/* Disable DMA channel - */ -void disable_dma (unsigned int chan) -{ - dma_t *dma = dma_channel(chan); - - if (!dma->lock) - goto free_dma; - - if (dma->active == 1) { - dma->active = 0; - dma->d_ops->disable(chan, dma); - } - return; - -free_dma: - printk(KERN_ERR "dma%d: trying to disable free DMA\n", chan); - BUG(); -} -EXPORT_SYMBOL(disable_dma); - -/* - * Is the specified DMA channel active? - */ -int dma_channel_active(unsigned int chan) -{ - dma_t *dma = dma_channel(chan); - return dma->active; -} -EXPORT_SYMBOL(dma_channel_active); - -void set_dma_page(unsigned int chan, char pagenr) -{ - printk(KERN_ERR "dma%d: trying to set_dma_page\n", chan); -} -EXPORT_SYMBOL(set_dma_page); - -void set_dma_speed(unsigned int chan, int cycle_ns) -{ - dma_t *dma = dma_channel(chan); - int ret = 0; - - if (dma->d_ops->setspeed) - ret = dma->d_ops->setspeed(chan, dma, cycle_ns); - dma->speed = ret; -} -EXPORT_SYMBOL(set_dma_speed); - -int get_dma_residue(unsigned int chan) -{ - dma_t *dma = dma_channel(chan); - int ret = 0; - - if (dma->d_ops->residue) - ret = dma->d_ops->residue(chan, dma); - - return ret; -} -EXPORT_SYMBOL(get_dma_residue); - -#ifdef CONFIG_PROC_FS -static int proc_dma_show(struct seq_file *m, void *v) -{ - int i; - - for (i = 0 ; i < MAX_DMA_CHANNELS ; i++) { - dma_t *dma = dma_channel(i); - if (dma && dma->lock) - seq_printf(m, "%2d: %s\n", i, dma->device_id); - } - return 0; -} - -static int proc_dma_open(struct inode *inode, struct file *file) -{ - return single_open(file, proc_dma_show, NULL); -} - -static const struct file_operations proc_dma_operations = { - .open = proc_dma_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init proc_dma_init(void) -{ - proc_create("dma", 0, NULL, &proc_dma_operations); - return 0; -} - -__initcall(proc_dma_init); -#endif diff --git a/ANDROID_3.4.5/arch/arm/kernel/early_printk.c b/ANDROID_3.4.5/arch/arm/kernel/early_printk.c deleted file mode 100644 index 85aa2b29..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/early_printk.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * linux/arch/arm/kernel/early_printk.c - * - * Copyright (C) 2009 Sascha Hauer <s.hauer@pengutronix.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/kernel.h> -#include <linux/console.h> -#include <linux/init.h> - -extern void printch(int); - -static void early_write(const char *s, unsigned n) -{ - while (n-- > 0) { - if (*s == '\n') - printch('\r'); - printch(*s); - s++; - } -} - -static void early_console_write(struct console *con, const char *s, unsigned n) -{ - early_write(s, n); -} - -static struct console early_console = { - .name = "earlycon", - .write = early_console_write, - .flags = CON_PRINTBUFFER | CON_BOOT, - .index = -1, -}; - -asmlinkage void early_printk(const char *fmt, ...) -{ - char buf[512]; - int n; - va_list ap; - - va_start(ap, fmt); - n = vscnprintf(buf, sizeof(buf), fmt, ap); - early_write(buf, n); - va_end(ap); -} - -static int __init setup_early_printk(char *buf) -{ - register_console(&early_console); - return 0; -} - -early_param("earlyprintk", setup_early_printk); diff --git a/ANDROID_3.4.5/arch/arm/kernel/elf.c b/ANDROID_3.4.5/arch/arm/kernel/elf.c deleted file mode 100644 index d0d1e831..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/elf.c +++ /dev/null @@ -1,91 +0,0 @@ -#include <linux/export.h> -#include <linux/sched.h> -#include <linux/personality.h> -#include <linux/binfmts.h> -#include <linux/elf.h> -#include <asm/system_info.h> - -int elf_check_arch(const struct elf32_hdr *x) -{ - unsigned int eflags; - - /* Make sure it's an ARM executable */ - if (x->e_machine != EM_ARM) - return 0; - - /* Make sure the entry address is reasonable */ - if (x->e_entry & 1) { - if (!(elf_hwcap & HWCAP_THUMB)) - return 0; - } else if (x->e_entry & 3) - return 0; - - eflags = x->e_flags; - if ((eflags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN) { - unsigned int flt_fmt; - - /* APCS26 is only allowed if the CPU supports it */ - if ((eflags & EF_ARM_APCS_26) && !(elf_hwcap & HWCAP_26BIT)) - return 0; - - flt_fmt = eflags & (EF_ARM_VFP_FLOAT | EF_ARM_SOFT_FLOAT); - - /* VFP requires the supporting code */ - if (flt_fmt == EF_ARM_VFP_FLOAT && !(elf_hwcap & HWCAP_VFP)) - return 0; - } - return 1; -} -EXPORT_SYMBOL(elf_check_arch); - -void elf_set_personality(const struct elf32_hdr *x) -{ - unsigned int eflags = x->e_flags; - unsigned int personality = current->personality & ~PER_MASK; - - /* - * We only support Linux ELF executables, so always set the - * personality to LINUX. - */ - personality |= PER_LINUX; - - /* - * APCS-26 is only valid for OABI executables - */ - if ((eflags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN && - (eflags & EF_ARM_APCS_26)) - personality &= ~ADDR_LIMIT_32BIT; - else - personality |= ADDR_LIMIT_32BIT; - - set_personality(personality); - - /* - * Since the FPA coprocessor uses CP1 and CP2, and iWMMXt uses CP0 - * and CP1, we only enable access to the iWMMXt coprocessor if the - * binary is EABI or softfloat (and thus, guaranteed not to use - * FPA instructions.) - */ - if (elf_hwcap & HWCAP_IWMMXT && - eflags & (EF_ARM_EABI_MASK | EF_ARM_SOFT_FLOAT)) { - set_thread_flag(TIF_USING_IWMMXT); - } else { - clear_thread_flag(TIF_USING_IWMMXT); - } -} -EXPORT_SYMBOL(elf_set_personality); - -/* - * Set READ_IMPLIES_EXEC if: - * - the binary requires an executable stack - * - we're running on a CPU which doesn't support NX. - */ -int arm_elf_read_implies_exec(const struct elf32_hdr *x, int executable_stack) -{ - if (executable_stack != EXSTACK_DISABLE_X) - return 1; - if (cpu_architecture() < CPU_ARCH_ARMv6) - return 1; - return 0; -} -EXPORT_SYMBOL(arm_elf_read_implies_exec); diff --git a/ANDROID_3.4.5/arch/arm/kernel/entry-armv.S b/ANDROID_3.4.5/arch/arm/kernel/entry-armv.S deleted file mode 100644 index 7fd3ad04..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/entry-armv.S +++ /dev/null @@ -1,1162 +0,0 @@ -/* - * linux/arch/arm/kernel/entry-armv.S - * - * Copyright (C) 1996,1997,1998 Russell King. - * ARM700 fix by Matthew Godbolt (linux-user@willothewisp.demon.co.uk) - * nommu support by Hyok S. Choi (hyok.choi@samsung.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Low-level vector interface routines - * - * Note: there is a StrongARM bug in the STMIA rn, {regs}^ instruction - * that causes it to save wrong values... Be aware! - */ - -#include <asm/assembler.h> -#include <asm/memory.h> -#include <asm/glue-df.h> -#include <asm/glue-pf.h> -#include <asm/vfpmacros.h> -#ifndef CONFIG_MULTI_IRQ_HANDLER -#include <mach/entry-macro.S> -#endif -#include <asm/thread_notify.h> -#include <asm/unwind.h> -#include <asm/unistd.h> -#include <asm/tls.h> -#include <asm/system_info.h> - -#include "entry-header.S" -#include <asm/entry-macro-multi.S> - -/* - * Interrupt handling. - */ - .macro irq_handler -#ifdef CONFIG_MULTI_IRQ_HANDLER - ldr r1, =handle_arch_irq - mov r0, sp - adr lr, BSYM(9997f) - ldr pc, [r1] -#else - arch_irq_handler_default -#endif -9997: - .endm - - .macro pabt_helper - @ PABORT handler takes pt_regs in r2, fault address in r4 and psr in r5 -#ifdef MULTI_PABORT - ldr ip, .LCprocfns - mov lr, pc - ldr pc, [ip, #PROCESSOR_PABT_FUNC] -#else - bl CPU_PABORT_HANDLER -#endif - .endm - - .macro dabt_helper - - @ - @ Call the processor-specific abort handler: - @ - @ r2 - pt_regs - @ r4 - aborted context pc - @ r5 - aborted context psr - @ - @ The abort handler must return the aborted address in r0, and - @ the fault status register in r1. r9 must be preserved. - @ -#ifdef MULTI_DABORT - ldr ip, .LCprocfns - mov lr, pc - ldr pc, [ip, #PROCESSOR_DABT_FUNC] -#else - bl CPU_DABORT_HANDLER -#endif - .endm - -#ifdef CONFIG_KPROBES - .section .kprobes.text,"ax",%progbits -#else - .text -#endif - -/* - * Invalid mode handlers - */ - .macro inv_entry, reason - sub sp, sp, #S_FRAME_SIZE - ARM( stmib sp, {r1 - lr} ) - THUMB( stmia sp, {r0 - r12} ) - THUMB( str sp, [sp, #S_SP] ) - THUMB( str lr, [sp, #S_LR] ) - mov r1, #\reason - .endm - -__pabt_invalid: - inv_entry BAD_PREFETCH - b common_invalid -ENDPROC(__pabt_invalid) - -__dabt_invalid: - inv_entry BAD_DATA - b common_invalid -ENDPROC(__dabt_invalid) - -__irq_invalid: - inv_entry BAD_IRQ - b common_invalid -ENDPROC(__irq_invalid) - -__und_invalid: - inv_entry BAD_UNDEFINSTR - - @ - @ XXX fall through to common_invalid - @ - -@ -@ common_invalid - generic code for failed exception (re-entrant version of handlers) -@ -common_invalid: - zero_fp - - ldmia r0, {r4 - r6} - add r0, sp, #S_PC @ here for interlock avoidance - mov r7, #-1 @ "" "" "" "" - str r4, [sp] @ save preserved r0 - stmia r0, {r5 - r7} @ lr_<exception>, - @ cpsr_<exception>, "old_r0" - - mov r0, sp - b bad_mode -ENDPROC(__und_invalid) - -/* - * SVC mode handlers - */ - -#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) -#define SPFIX(code...) code -#else -#define SPFIX(code...) -#endif - - .macro svc_entry, stack_hole=0 - UNWIND(.fnstart ) - UNWIND(.save {r0 - pc} ) - sub sp, sp, #(S_FRAME_SIZE + \stack_hole - 4) -#ifdef CONFIG_THUMB2_KERNEL - SPFIX( str r0, [sp] ) @ temporarily saved - SPFIX( mov r0, sp ) - SPFIX( tst r0, #4 ) @ test original stack alignment - SPFIX( ldr r0, [sp] ) @ restored -#else - SPFIX( tst sp, #4 ) -#endif - SPFIX( subeq sp, sp, #4 ) - stmia sp, {r1 - r12} - - ldmia r0, {r3 - r5} - add r7, sp, #S_SP - 4 @ here for interlock avoidance - mov r6, #-1 @ "" "" "" "" - add r2, sp, #(S_FRAME_SIZE + \stack_hole - 4) - SPFIX( addeq r2, r2, #4 ) - str r3, [sp, #-4]! @ save the "real" r0 copied - @ from the exception stack - - mov r3, lr - - @ - @ We are now ready to fill in the remaining blanks on the stack: - @ - @ r2 - sp_svc - @ r3 - lr_svc - @ r4 - lr_<exception>, already fixed up for correct return/restart - @ r5 - spsr_<exception> - @ r6 - orig_r0 (see pt_regs definition in ptrace.h) - @ - stmia r7, {r2 - r6} - -#ifdef CONFIG_TRACE_IRQFLAGS - bl trace_hardirqs_off -#endif - .endm - - .align 5 -__dabt_svc: - svc_entry - mov r2, sp - dabt_helper - - @ - @ IRQs off again before pulling preserved data off the stack - @ - disable_irq_notrace - -#ifdef CONFIG_TRACE_IRQFLAGS - tst r5, #PSR_I_BIT - bleq trace_hardirqs_on - tst r5, #PSR_I_BIT - blne trace_hardirqs_off -#endif - svc_exit r5 @ return from exception - UNWIND(.fnend ) -ENDPROC(__dabt_svc) - - .align 5 -__irq_svc: - svc_entry - irq_handler - -#ifdef CONFIG_PREEMPT - get_thread_info tsk - ldr r8, [tsk, #TI_PREEMPT] @ get preempt count - ldr r0, [tsk, #TI_FLAGS] @ get flags - teq r8, #0 @ if preempt count != 0 - movne r0, #0 @ force flags to 0 - tst r0, #_TIF_NEED_RESCHED - blne svc_preempt -#endif - -#ifdef CONFIG_TRACE_IRQFLAGS - @ The parent context IRQs must have been enabled to get here in - @ the first place, so there's no point checking the PSR I bit. - bl trace_hardirqs_on -#endif - svc_exit r5 @ return from exception - UNWIND(.fnend ) -ENDPROC(__irq_svc) - - .ltorg - -#ifdef CONFIG_PREEMPT -svc_preempt: - mov r8, lr -1: bl preempt_schedule_irq @ irq en/disable is done inside - ldr r0, [tsk, #TI_FLAGS] @ get new tasks TI_FLAGS - tst r0, #_TIF_NEED_RESCHED - moveq pc, r8 @ go again - b 1b -#endif - - .align 5 -__und_svc: -#ifdef CONFIG_KPROBES - @ If a kprobe is about to simulate a "stmdb sp..." instruction, - @ it obviously needs free stack space which then will belong to - @ the saved context. - svc_entry 64 -#else - svc_entry -#endif - @ - @ call emulation code, which returns using r9 if it has emulated - @ the instruction, or the more conventional lr if we are to treat - @ this as a real undefined instruction - @ - @ r0 - instruction - @ -#ifndef CONFIG_THUMB2_KERNEL - ldr r0, [r4, #-4] -#else - ldrh r0, [r4, #-2] @ Thumb instruction at LR - 2 - cmp r0, #0xe800 @ 32-bit instruction if xx >= 0 - ldrhhs r9, [r4] @ bottom 16 bits - orrhs r0, r9, r0, lsl #16 -#endif - adr r9, BSYM(1f) - mov r2, r4 - bl call_fpe - - mov r0, sp @ struct pt_regs *regs - bl do_undefinstr - - @ - @ IRQs off again before pulling preserved data off the stack - @ -1: disable_irq_notrace - - @ - @ restore SPSR and restart the instruction - @ - ldr r5, [sp, #S_PSR] @ Get SVC cpsr -#ifdef CONFIG_TRACE_IRQFLAGS - tst r5, #PSR_I_BIT - bleq trace_hardirqs_on - tst r5, #PSR_I_BIT - blne trace_hardirqs_off -#endif - svc_exit r5 @ return from exception - UNWIND(.fnend ) -ENDPROC(__und_svc) - - .align 5 -__pabt_svc: - svc_entry - mov r2, sp @ regs - pabt_helper - - @ - @ IRQs off again before pulling preserved data off the stack - @ - disable_irq_notrace - -#ifdef CONFIG_TRACE_IRQFLAGS - tst r5, #PSR_I_BIT - bleq trace_hardirqs_on - tst r5, #PSR_I_BIT - blne trace_hardirqs_off -#endif - svc_exit r5 @ return from exception - UNWIND(.fnend ) -ENDPROC(__pabt_svc) - - .align 5 -.LCcralign: - .word cr_alignment -#ifdef MULTI_DABORT -.LCprocfns: - .word processor -#endif -.LCfp: - .word fp_enter - -/* - * User mode handlers - * - * EABI note: sp_svc is always 64-bit aligned here, so should S_FRAME_SIZE - */ - -#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7) -#error "sizeof(struct pt_regs) must be a multiple of 8" -#endif - - .macro usr_entry - UNWIND(.fnstart ) - UNWIND(.cantunwind ) @ don't unwind the user space - sub sp, sp, #S_FRAME_SIZE - ARM( stmib sp, {r1 - r12} ) - THUMB( stmia sp, {r0 - r12} ) - - ldmia r0, {r3 - r5} - add r0, sp, #S_PC @ here for interlock avoidance - mov r6, #-1 @ "" "" "" "" - - str r3, [sp] @ save the "real" r0 copied - @ from the exception stack - - @ - @ We are now ready to fill in the remaining blanks on the stack: - @ - @ r4 - lr_<exception>, already fixed up for correct return/restart - @ r5 - spsr_<exception> - @ r6 - orig_r0 (see pt_regs definition in ptrace.h) - @ - @ Also, separately save sp_usr and lr_usr - @ - stmia r0, {r4 - r6} - ARM( stmdb r0, {sp, lr}^ ) - THUMB( store_user_sp_lr r0, r1, S_SP - S_PC ) - - @ - @ Enable the alignment trap while in kernel mode - @ - alignment_trap r0 - - @ - @ Clear FP to mark the first stack frame - @ - zero_fp - -#ifdef CONFIG_IRQSOFF_TRACER - bl trace_hardirqs_off -#endif - .endm - - .macro kuser_cmpxchg_check -#if !defined(CONFIG_CPU_32v6K) && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) -#ifndef CONFIG_MMU -#warning "NPTL on non MMU needs fixing" -#else - @ Make sure our user space atomic helper is restarted - @ if it was interrupted in a critical region. Here we - @ perform a quick test inline since it should be false - @ 99.9999% of the time. The rest is done out of line. - cmp r4, #TASK_SIZE - blhs kuser_cmpxchg64_fixup -#endif -#endif - .endm - - .align 5 -__dabt_usr: - usr_entry - kuser_cmpxchg_check - mov r2, sp - dabt_helper - b ret_from_exception - UNWIND(.fnend ) -ENDPROC(__dabt_usr) - - .align 5 -__irq_usr: - usr_entry - kuser_cmpxchg_check - irq_handler - get_thread_info tsk - mov why, #0 - b ret_to_user_from_irq - UNWIND(.fnend ) -ENDPROC(__irq_usr) - - .ltorg - - .align 5 -__und_usr: - usr_entry - - mov r2, r4 - mov r3, r5 - - @ - @ fall through to the emulation code, which returns using r9 if - @ it has emulated the instruction, or the more conventional lr - @ if we are to treat this as a real undefined instruction - @ - @ r0 - instruction - @ - adr r9, BSYM(ret_from_exception) - adr lr, BSYM(__und_usr_unknown) - tst r3, #PSR_T_BIT @ Thumb mode? - itet eq @ explicit IT needed for the 1f label - subeq r4, r2, #4 @ ARM instr at LR - 4 - subne r4, r2, #2 @ Thumb instr at LR - 2 -1: ldreqt r0, [r4] -#ifdef CONFIG_CPU_ENDIAN_BE8 - reveq r0, r0 @ little endian instruction -#endif - beq call_fpe - @ Thumb instruction -#if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7 -/* - * Thumb-2 instruction handling. Note that because pre-v6 and >= v6 platforms - * can never be supported in a single kernel, this code is not applicable at - * all when __LINUX_ARM_ARCH__ < 6. This allows simplifying assumptions to be - * made about .arch directives. - */ -#if __LINUX_ARM_ARCH__ < 7 -/* If the target CPU may not be Thumb-2-capable, a run-time check is needed: */ -#define NEED_CPU_ARCHITECTURE - ldr r5, .LCcpu_architecture - ldr r5, [r5] - cmp r5, #CPU_ARCH_ARMv7 - blo __und_usr_unknown -/* - * The following code won't get run unless the running CPU really is v7, so - * coding round the lack of ldrht on older arches is pointless. Temporarily - * override the assembler target arch with the minimum required instead: - */ - .arch armv6t2 -#endif -2: - ARM( ldrht r5, [r4], #2 ) - THUMB( ldrht r5, [r4] ) - THUMB( add r4, r4, #2 ) - cmp r5, #0xe800 @ 32bit instruction if xx != 0 - blo __und_usr_unknown -3: ldrht r0, [r4] - add r2, r2, #2 @ r2 is PC + 2, make it PC + 4 - orr r0, r0, r5, lsl #16 - -#if __LINUX_ARM_ARCH__ < 7 -/* If the target arch was overridden, change it back: */ -#ifdef CONFIG_CPU_32v6K - .arch armv6k -#else - .arch armv6 -#endif -#endif /* __LINUX_ARM_ARCH__ < 7 */ -#else /* !(CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7) */ - b __und_usr_unknown -#endif - UNWIND(.fnend ) -ENDPROC(__und_usr) - - @ - @ fallthrough to call_fpe - @ - -/* - * The out of line fixup for the ldrt above. - */ - .pushsection .fixup, "ax" -4: mov pc, r9 - .popsection - .pushsection __ex_table,"a" - .long 1b, 4b -#if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7 - .long 2b, 4b - .long 3b, 4b -#endif - .popsection - -/* - * Check whether the instruction is a co-processor instruction. - * If yes, we need to call the relevant co-processor handler. - * - * Note that we don't do a full check here for the co-processor - * instructions; all instructions with bit 27 set are well - * defined. The only instructions that should fault are the - * co-processor instructions. However, we have to watch out - * for the ARM6/ARM7 SWI bug. - * - * NEON is a special case that has to be handled here. Not all - * NEON instructions are co-processor instructions, so we have - * to make a special case of checking for them. Plus, there's - * five groups of them, so we have a table of mask/opcode pairs - * to check against, and if any match then we branch off into the - * NEON handler code. - * - * Emulators may wish to make use of the following registers: - * r0 = instruction opcode. - * r2 = PC+4 - * r9 = normal "successful" return address - * r10 = this threads thread_info structure. - * lr = unrecognised instruction return address - */ - @ - @ Fall-through from Thumb-2 __und_usr - @ -#ifdef CONFIG_NEON - adr r6, .LCneon_thumb_opcodes - b 2f -#endif -call_fpe: -#ifdef CONFIG_NEON - adr r6, .LCneon_arm_opcodes -2: - ldr r7, [r6], #4 @ mask value - cmp r7, #0 @ end mask? - beq 1f - and r8, r0, r7 - ldr r7, [r6], #4 @ opcode bits matching in mask - cmp r8, r7 @ NEON instruction? - bne 2b - get_thread_info r10 - mov r7, #1 - strb r7, [r10, #TI_USED_CP + 10] @ mark CP#10 as used - strb r7, [r10, #TI_USED_CP + 11] @ mark CP#11 as used - b do_vfp @ let VFP handler handle this -1: -#endif - tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27 - tstne r0, #0x04000000 @ bit 26 set on both ARM and Thumb-2 -#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710) - and r8, r0, #0x0f000000 @ mask out op-code bits - teqne r8, #0x0f000000 @ SWI (ARM6/7 bug)? -#endif - moveq pc, lr - get_thread_info r10 @ get current thread - and r8, r0, #0x00000f00 @ mask out CP number - THUMB( lsr r8, r8, #8 ) - mov r7, #1 - add r6, r10, #TI_USED_CP - ARM( strb r7, [r6, r8, lsr #8] ) @ set appropriate used_cp[] - THUMB( strb r7, [r6, r8] ) @ set appropriate used_cp[] -#ifdef CONFIG_IWMMXT - @ Test if we need to give access to iWMMXt coprocessors - ldr r5, [r10, #TI_FLAGS] - rsbs r7, r8, #(1 << 8) @ CP 0 or 1 only - movcss r7, r5, lsr #(TIF_USING_IWMMXT + 1) - bcs iwmmxt_task_enable -#endif - ARM( add pc, pc, r8, lsr #6 ) - THUMB( lsl r8, r8, #2 ) - THUMB( add pc, r8 ) - nop - - movw_pc lr @ CP#0 - W(b) do_fpe @ CP#1 (FPE) - W(b) do_fpe @ CP#2 (FPE) - movw_pc lr @ CP#3 -#ifdef CONFIG_CRUNCH - b crunch_task_enable @ CP#4 (MaverickCrunch) - b crunch_task_enable @ CP#5 (MaverickCrunch) - b crunch_task_enable @ CP#6 (MaverickCrunch) -#else - movw_pc lr @ CP#4 - movw_pc lr @ CP#5 - movw_pc lr @ CP#6 -#endif - movw_pc lr @ CP#7 - movw_pc lr @ CP#8 - movw_pc lr @ CP#9 -#ifdef CONFIG_VFP - W(b) do_vfp @ CP#10 (VFP) - W(b) do_vfp @ CP#11 (VFP) -#else - movw_pc lr @ CP#10 (VFP) - movw_pc lr @ CP#11 (VFP) -#endif - movw_pc lr @ CP#12 - movw_pc lr @ CP#13 - movw_pc lr @ CP#14 (Debug) - movw_pc lr @ CP#15 (Control) - -#ifdef NEED_CPU_ARCHITECTURE - .align 2 -.LCcpu_architecture: - .word __cpu_architecture -#endif - -#ifdef CONFIG_NEON - .align 6 - -.LCneon_arm_opcodes: - .word 0xfe000000 @ mask - .word 0xf2000000 @ opcode - - .word 0xff100000 @ mask - .word 0xf4000000 @ opcode - - .word 0x00000000 @ mask - .word 0x00000000 @ opcode - -.LCneon_thumb_opcodes: - .word 0xef000000 @ mask - .word 0xef000000 @ opcode - - .word 0xff100000 @ mask - .word 0xf9000000 @ opcode - - .word 0x00000000 @ mask - .word 0x00000000 @ opcode -#endif - -do_fpe: - enable_irq - ldr r4, .LCfp - add r10, r10, #TI_FPSTATE @ r10 = workspace - ldr pc, [r4] @ Call FP module USR entry point - -/* - * The FP module is called with these registers set: - * r0 = instruction - * r2 = PC+4 - * r9 = normal "successful" return address - * r10 = FP workspace - * lr = unrecognised FP instruction return address - */ - - .pushsection .data -ENTRY(fp_enter) - .word no_fp - .popsection - -ENTRY(no_fp) - mov pc, lr -ENDPROC(no_fp) - -__und_usr_unknown: - enable_irq - mov r0, sp - adr lr, BSYM(ret_from_exception) - b do_undefinstr -ENDPROC(__und_usr_unknown) - - .align 5 -__pabt_usr: - usr_entry - mov r2, sp @ regs - pabt_helper - UNWIND(.fnend ) - /* fall through */ -/* - * This is the return code to user mode for abort handlers - */ -ENTRY(ret_from_exception) - UNWIND(.fnstart ) - UNWIND(.cantunwind ) - get_thread_info tsk - mov why, #0 - b ret_to_user - UNWIND(.fnend ) -ENDPROC(__pabt_usr) -ENDPROC(ret_from_exception) - -/* - * Register switch for ARMv3 and ARMv4 processors - * r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info - * previous and next are guaranteed not to be the same. - */ -ENTRY(__switch_to) - UNWIND(.fnstart ) - UNWIND(.cantunwind ) - add ip, r1, #TI_CPU_SAVE - ldr r3, [r2, #TI_TP_VALUE] - ARM( stmia ip!, {r4 - sl, fp, sp, lr} ) @ Store most regs on stack - THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack - THUMB( str sp, [ip], #4 ) - THUMB( str lr, [ip], #4 ) -#ifdef CONFIG_CPU_USE_DOMAINS - ldr r6, [r2, #TI_CPU_DOMAIN] -#endif - set_tls r3, r4, r5 -#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP) - ldr r7, [r2, #TI_TASK] - ldr r8, =__stack_chk_guard - ldr r7, [r7, #TSK_STACK_CANARY] -#endif -#ifdef CONFIG_CPU_USE_DOMAINS - mcr p15, 0, r6, c3, c0, 0 @ Set domain register -#endif - mov r5, r0 - add r4, r2, #TI_CPU_SAVE - ldr r0, =thread_notify_head - mov r1, #THREAD_NOTIFY_SWITCH - bl atomic_notifier_call_chain -#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP) - str r7, [r8] -#endif - THUMB( mov ip, r4 ) - mov r0, r5 - ARM( ldmia r4, {r4 - sl, fp, sp, pc} ) @ Load all regs saved previously - THUMB( ldmia ip!, {r4 - sl, fp} ) @ Load all regs saved previously - THUMB( ldr sp, [ip], #4 ) - THUMB( ldr pc, [ip] ) - UNWIND(.fnend ) -ENDPROC(__switch_to) - - __INIT - -/* - * User helpers. - * - * Each segment is 32-byte aligned and will be moved to the top of the high - * vector page. New segments (if ever needed) must be added in front of - * existing ones. This mechanism should be used only for things that are - * really small and justified, and not be abused freely. - * - * See Documentation/arm/kernel_user_helpers.txt for formal definitions. - */ - THUMB( .arm ) - - .macro usr_ret, reg -#ifdef CONFIG_ARM_THUMB - bx \reg -#else - mov pc, \reg -#endif - .endm - - .align 5 - .globl __kuser_helper_start -__kuser_helper_start: - -/* - * Due to the length of some sequences, __kuser_cmpxchg64 spans 2 regular - * kuser "slots", therefore 0xffff0f80 is not used as a valid entry point. - */ - -__kuser_cmpxchg64: @ 0xffff0f60 - -#if defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) - - /* - * Poor you. No fast solution possible... - * The kernel itself must perform the operation. - * A special ghost syscall is used for that (see traps.c). - */ - stmfd sp!, {r7, lr} - ldr r7, 1f @ it's 20 bits - swi __ARM_NR_cmpxchg64 - ldmfd sp!, {r7, pc} -1: .word __ARM_NR_cmpxchg64 - -#elif defined(CONFIG_CPU_32v6K) - - stmfd sp!, {r4, r5, r6, r7} - ldrd r4, r5, [r0] @ load old val - ldrd r6, r7, [r1] @ load new val - smp_dmb arm -1: ldrexd r0, r1, [r2] @ load current val - eors r3, r0, r4 @ compare with oldval (1) - eoreqs r3, r1, r5 @ compare with oldval (2) - strexdeq r3, r6, r7, [r2] @ store newval if eq - teqeq r3, #1 @ success? - beq 1b @ if no then retry - smp_dmb arm - rsbs r0, r3, #0 @ set returned val and C flag - ldmfd sp!, {r4, r5, r6, r7} - usr_ret lr - -#elif !defined(CONFIG_SMP) - -#ifdef CONFIG_MMU - - /* - * The only thing that can break atomicity in this cmpxchg64 - * implementation is either an IRQ or a data abort exception - * causing another process/thread to be scheduled in the middle of - * the critical sequence. The same strategy as for cmpxchg is used. - */ - stmfd sp!, {r4, r5, r6, lr} - ldmia r0, {r4, r5} @ load old val - ldmia r1, {r6, lr} @ load new val -1: ldmia r2, {r0, r1} @ load current val - eors r3, r0, r4 @ compare with oldval (1) - eoreqs r3, r1, r5 @ compare with oldval (2) -2: stmeqia r2, {r6, lr} @ store newval if eq - rsbs r0, r3, #0 @ set return val and C flag - ldmfd sp!, {r4, r5, r6, pc} - - .text -kuser_cmpxchg64_fixup: - @ Called from kuser_cmpxchg_fixup. - @ r4 = address of interrupted insn (must be preserved). - @ sp = saved regs. r7 and r8 are clobbered. - @ 1b = first critical insn, 2b = last critical insn. - @ If r4 >= 1b and r4 <= 2b then saved pc_usr is set to 1b. - mov r7, #0xffff0fff - sub r7, r7, #(0xffff0fff - (0xffff0f60 + (1b - __kuser_cmpxchg64))) - subs r8, r4, r7 - rsbcss r8, r8, #(2b - 1b) - strcs r7, [sp, #S_PC] -#if __LINUX_ARM_ARCH__ < 6 - bcc kuser_cmpxchg32_fixup -#endif - mov pc, lr - .previous - -#else -#warning "NPTL on non MMU needs fixing" - mov r0, #-1 - adds r0, r0, #0 - usr_ret lr -#endif - -#else -#error "incoherent kernel configuration" -#endif - - /* pad to next slot */ - .rept (16 - (. - __kuser_cmpxchg64)/4) - .word 0 - .endr - - .align 5 - -__kuser_memory_barrier: @ 0xffff0fa0 - smp_dmb arm - usr_ret lr - - .align 5 - -__kuser_cmpxchg: @ 0xffff0fc0 - -#if defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) - - /* - * Poor you. No fast solution possible... - * The kernel itself must perform the operation. - * A special ghost syscall is used for that (see traps.c). - */ - stmfd sp!, {r7, lr} - ldr r7, 1f @ it's 20 bits - swi __ARM_NR_cmpxchg - ldmfd sp!, {r7, pc} -1: .word __ARM_NR_cmpxchg - -#elif __LINUX_ARM_ARCH__ < 6 - -#ifdef CONFIG_MMU - - /* - * The only thing that can break atomicity in this cmpxchg - * implementation is either an IRQ or a data abort exception - * causing another process/thread to be scheduled in the middle - * of the critical sequence. To prevent this, code is added to - * the IRQ and data abort exception handlers to set the pc back - * to the beginning of the critical section if it is found to be - * within that critical section (see kuser_cmpxchg_fixup). - */ -1: ldr r3, [r2] @ load current val - subs r3, r3, r0 @ compare with oldval -2: streq r1, [r2] @ store newval if eq - rsbs r0, r3, #0 @ set return val and C flag - usr_ret lr - - .text -kuser_cmpxchg32_fixup: - @ Called from kuser_cmpxchg_check macro. - @ r4 = address of interrupted insn (must be preserved). - @ sp = saved regs. r7 and r8 are clobbered. - @ 1b = first critical insn, 2b = last critical insn. - @ If r4 >= 1b and r4 <= 2b then saved pc_usr is set to 1b. - mov r7, #0xffff0fff - sub r7, r7, #(0xffff0fff - (0xffff0fc0 + (1b - __kuser_cmpxchg))) - subs r8, r4, r7 - rsbcss r8, r8, #(2b - 1b) - strcs r7, [sp, #S_PC] - mov pc, lr - .previous - -#else -#warning "NPTL on non MMU needs fixing" - mov r0, #-1 - adds r0, r0, #0 - usr_ret lr -#endif - -#else - - smp_dmb arm -1: ldrex r3, [r2] - subs r3, r3, r0 - strexeq r3, r1, [r2] - teqeq r3, #1 - beq 1b - rsbs r0, r3, #0 - /* beware -- each __kuser slot must be 8 instructions max */ - ALT_SMP(b __kuser_memory_barrier) - ALT_UP(usr_ret lr) - -#endif - - .align 5 - -__kuser_get_tls: @ 0xffff0fe0 - ldr r0, [pc, #(16 - 8)] @ read TLS, set in kuser_get_tls_init - usr_ret lr - mrc p15, 0, r0, c13, c0, 3 @ 0xffff0fe8 hardware TLS code - .rep 4 - .word 0 @ 0xffff0ff0 software TLS value, then - .endr @ pad up to __kuser_helper_version - -__kuser_helper_version: @ 0xffff0ffc - .word ((__kuser_helper_end - __kuser_helper_start) >> 5) - - .globl __kuser_helper_end -__kuser_helper_end: - - THUMB( .thumb ) - -/* - * Vector stubs. - * - * This code is copied to 0xffff0200 so we can use branches in the - * vectors, rather than ldr's. Note that this code must not - * exceed 0x300 bytes. - * - * Common stub entry macro: - * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC - * - * SP points to a minimal amount of processor-private memory, the address - * of which is copied into r0 for the mode specific abort handler. - */ - .macro vector_stub, name, mode, correction=0 - .align 5 - -vector_\name: - .if \correction - sub lr, lr, #\correction - .endif - - @ - @ Save r0, lr_<exception> (parent PC) and spsr_<exception> - @ (parent CPSR) - @ - stmia sp, {r0, lr} @ save r0, lr - mrs lr, spsr - str lr, [sp, #8] @ save spsr - - @ - @ Prepare for SVC32 mode. IRQs remain disabled. - @ - mrs r0, cpsr - eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE) - msr spsr_cxsf, r0 - - @ - @ the branch table must immediately follow this code - @ - and lr, lr, #0x0f - THUMB( adr r0, 1f ) - THUMB( ldr lr, [r0, lr, lsl #2] ) - mov r0, sp - ARM( ldr lr, [pc, lr, lsl #2] ) - movs pc, lr @ branch to handler in SVC mode -ENDPROC(vector_\name) - - .align 2 - @ handler addresses follow this label -1: - .endm - - .globl __stubs_start -__stubs_start: -/* - * Interrupt dispatcher - */ - vector_stub irq, IRQ_MODE, 4 - - .long __irq_usr @ 0 (USR_26 / USR_32) - .long __irq_invalid @ 1 (FIQ_26 / FIQ_32) - .long __irq_invalid @ 2 (IRQ_26 / IRQ_32) - .long __irq_svc @ 3 (SVC_26 / SVC_32) - .long __irq_invalid @ 4 - .long __irq_invalid @ 5 - .long __irq_invalid @ 6 - .long __irq_invalid @ 7 - .long __irq_invalid @ 8 - .long __irq_invalid @ 9 - .long __irq_invalid @ a - .long __irq_invalid @ b - .long __irq_invalid @ c - .long __irq_invalid @ d - .long __irq_invalid @ e - .long __irq_invalid @ f - -/* - * Data abort dispatcher - * Enter in ABT mode, spsr = USR CPSR, lr = USR PC - */ - vector_stub dabt, ABT_MODE, 8 - - .long __dabt_usr @ 0 (USR_26 / USR_32) - .long __dabt_invalid @ 1 (FIQ_26 / FIQ_32) - .long __dabt_invalid @ 2 (IRQ_26 / IRQ_32) - .long __dabt_svc @ 3 (SVC_26 / SVC_32) - .long __dabt_invalid @ 4 - .long __dabt_invalid @ 5 - .long __dabt_invalid @ 6 - .long __dabt_invalid @ 7 - .long __dabt_invalid @ 8 - .long __dabt_invalid @ 9 - .long __dabt_invalid @ a - .long __dabt_invalid @ b - .long __dabt_invalid @ c - .long __dabt_invalid @ d - .long __dabt_invalid @ e - .long __dabt_invalid @ f - -/* - * Prefetch abort dispatcher - * Enter in ABT mode, spsr = USR CPSR, lr = USR PC - */ - vector_stub pabt, ABT_MODE, 4 - - .long __pabt_usr @ 0 (USR_26 / USR_32) - .long __pabt_invalid @ 1 (FIQ_26 / FIQ_32) - .long __pabt_invalid @ 2 (IRQ_26 / IRQ_32) - .long __pabt_svc @ 3 (SVC_26 / SVC_32) - .long __pabt_invalid @ 4 - .long __pabt_invalid @ 5 - .long __pabt_invalid @ 6 - .long __pabt_invalid @ 7 - .long __pabt_invalid @ 8 - .long __pabt_invalid @ 9 - .long __pabt_invalid @ a - .long __pabt_invalid @ b - .long __pabt_invalid @ c - .long __pabt_invalid @ d - .long __pabt_invalid @ e - .long __pabt_invalid @ f - -/* - * Undef instr entry dispatcher - * Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC - */ - vector_stub und, UND_MODE - - .long __und_usr @ 0 (USR_26 / USR_32) - .long __und_invalid @ 1 (FIQ_26 / FIQ_32) - .long __und_invalid @ 2 (IRQ_26 / IRQ_32) - .long __und_svc @ 3 (SVC_26 / SVC_32) - .long __und_invalid @ 4 - .long __und_invalid @ 5 - .long __und_invalid @ 6 - .long __und_invalid @ 7 - .long __und_invalid @ 8 - .long __und_invalid @ 9 - .long __und_invalid @ a - .long __und_invalid @ b - .long __und_invalid @ c - .long __und_invalid @ d - .long __und_invalid @ e - .long __und_invalid @ f - - .align 5 - -/*============================================================================= - * Undefined FIQs - *----------------------------------------------------------------------------- - * Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC - * MUST PRESERVE SVC SPSR, but need to switch to SVC mode to show our msg. - * Basically to switch modes, we *HAVE* to clobber one register... brain - * damage alert! I don't think that we can execute any code in here in any - * other mode than FIQ... Ok you can switch to another mode, but you can't - * get out of that mode without clobbering one register. - */ -vector_fiq: - subs pc, lr, #4 - -/*============================================================================= - * Address exception handler - *----------------------------------------------------------------------------- - * These aren't too critical. - * (they're not supposed to happen, and won't happen in 32-bit data mode). - */ - -vector_addrexcptn: - b vector_addrexcptn - -/* - * We group all the following data together to optimise - * for CPUs with separate I & D caches. - */ - .align 5 - -.LCvswi: - .word vector_swi - - .globl __stubs_end -__stubs_end: - - .equ stubs_offset, __vectors_start + 0x200 - __stubs_start - - .globl __vectors_start -__vectors_start: - ARM( swi SYS_ERROR0 ) - THUMB( svc #0 ) - THUMB( nop ) - W(b) vector_und + stubs_offset - W(ldr) pc, .LCvswi + stubs_offset - W(b) vector_pabt + stubs_offset - W(b) vector_dabt + stubs_offset - W(b) vector_addrexcptn + stubs_offset - W(b) vector_irq + stubs_offset - W(b) vector_fiq + stubs_offset - - .globl __vectors_end -__vectors_end: - - .data - - .globl cr_alignment - .globl cr_no_alignment -cr_alignment: - .space 4 -cr_no_alignment: - .space 4 - -#ifdef CONFIG_MULTI_IRQ_HANDLER - .globl handle_arch_irq -handle_arch_irq: - .space 4 -#endif diff --git a/ANDROID_3.4.5/arch/arm/kernel/entry-common.S b/ANDROID_3.4.5/arch/arm/kernel/entry-common.S deleted file mode 100644 index 54ee265d..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/entry-common.S +++ /dev/null @@ -1,656 +0,0 @@ -/* - * linux/arch/arm/kernel/entry-common.S - * - * Copyright (C) 2000 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <asm/unistd.h> -#include <asm/ftrace.h> -#include <asm/unwind.h> - -#ifdef CONFIG_NEED_RET_TO_USER -#include <mach/entry-macro.S> -#else - .macro arch_ret_to_user, tmp1, tmp2 - .endm -#endif - -#include "entry-header.S" - - - .align 5 -/* - * This is the fast syscall return path. We do as little as - * possible here, and this includes saving r0 back into the SVC - * stack. - */ -ret_fast_syscall: - UNWIND(.fnstart ) - UNWIND(.cantunwind ) - disable_irq @ disable interrupts - ldr r1, [tsk, #TI_FLAGS] - tst r1, #_TIF_WORK_MASK - bne fast_work_pending -#if defined(CONFIG_IRQSOFF_TRACER) - asm_trace_hardirqs_on -#endif - - /* perform architecture specific actions before user return */ - arch_ret_to_user r1, lr - - restore_user_regs fast = 1, offset = S_OFF - UNWIND(.fnend ) - -/* - * Ok, we need to do extra processing, enter the slow path. - */ -fast_work_pending: - str r0, [sp, #S_R0+S_OFF]! @ returned r0 -work_pending: - tst r1, #_TIF_NEED_RESCHED - bne work_resched - tst r1, #_TIF_SIGPENDING|_TIF_NOTIFY_RESUME - beq no_work_pending - mov r0, sp @ 'regs' - mov r2, why @ 'syscall' - tst r1, #_TIF_SIGPENDING @ delivering a signal? - movne why, #0 @ prevent further restarts - bl do_notify_resume - b ret_slow_syscall @ Check work again - -work_resched: - bl schedule -/* - * "slow" syscall return path. "why" tells us if this was a real syscall. - */ -ENTRY(ret_to_user) -ret_slow_syscall: - disable_irq @ disable interrupts -ENTRY(ret_to_user_from_irq) - ldr r1, [tsk, #TI_FLAGS] - tst r1, #_TIF_WORK_MASK - bne work_pending -no_work_pending: -#if defined(CONFIG_IRQSOFF_TRACER) - asm_trace_hardirqs_on -#endif - /* perform architecture specific actions before user return */ - arch_ret_to_user r1, lr - - restore_user_regs fast = 0, offset = 0 -ENDPROC(ret_to_user_from_irq) -ENDPROC(ret_to_user) - -/* - * This is how we return from a fork. - */ -ENTRY(ret_from_fork) - bl schedule_tail - get_thread_info tsk - ldr r1, [tsk, #TI_FLAGS] @ check for syscall tracing - mov why, #1 - tst r1, #_TIF_SYSCALL_WORK @ are we tracing syscalls? - beq ret_slow_syscall - mov r1, sp - mov r0, #1 @ trace exit [IP = 1] - bl syscall_trace - b ret_slow_syscall -ENDPROC(ret_from_fork) - - .equ NR_syscalls,0 -#define CALL(x) .equ NR_syscalls,NR_syscalls+1 -#include "calls.S" -#undef CALL -#define CALL(x) .long x - -#ifdef CONFIG_FUNCTION_TRACER -/* - * When compiling with -pg, gcc inserts a call to the mcount routine at the - * start of every function. In mcount, apart from the function's address (in - * lr), we need to get hold of the function's caller's address. - * - * Older GCCs (pre-4.4) inserted a call to a routine called mcount like this: - * - * bl mcount - * - * These versions have the limitation that in order for the mcount routine to - * be able to determine the function's caller's address, an APCS-style frame - * pointer (which is set up with something like the code below) is required. - * - * mov ip, sp - * push {fp, ip, lr, pc} - * sub fp, ip, #4 - * - * With EABI, these frame pointers are not available unless -mapcs-frame is - * specified, and if building as Thumb-2, not even then. - * - * Newer GCCs (4.4+) solve this problem by introducing a new version of mcount, - * with call sites like: - * - * push {lr} - * bl __gnu_mcount_nc - * - * With these compilers, frame pointers are not necessary. - * - * mcount can be thought of as a function called in the middle of a subroutine - * call. As such, it needs to be transparent for both the caller and the - * callee: the original lr needs to be restored when leaving mcount, and no - * registers should be clobbered. (In the __gnu_mcount_nc implementation, we - * clobber the ip register. This is OK because the ARM calling convention - * allows it to be clobbered in subroutines and doesn't use it to hold - * parameters.) - * - * When using dynamic ftrace, we patch out the mcount call by a "mov r0, r0" - * for the mcount case, and a "pop {lr}" for the __gnu_mcount_nc case (see - * arch/arm/kernel/ftrace.c). - */ - -#ifndef CONFIG_OLD_MCOUNT -#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4)) -#error Ftrace requires CONFIG_FRAME_POINTER=y with GCC older than 4.4.0. -#endif -#endif - -.macro mcount_adjust_addr rd, rn - bic \rd, \rn, #1 @ clear the Thumb bit if present - sub \rd, \rd, #MCOUNT_INSN_SIZE -.endm - -.macro __mcount suffix - mcount_enter - ldr r0, =ftrace_trace_function - ldr r2, [r0] - adr r0, .Lftrace_stub - cmp r0, r2 - bne 1f - -#ifdef CONFIG_FUNCTION_GRAPH_TRACER - ldr r1, =ftrace_graph_return - ldr r2, [r1] - cmp r0, r2 - bne ftrace_graph_caller\suffix - - ldr r1, =ftrace_graph_entry - ldr r2, [r1] - ldr r0, =ftrace_graph_entry_stub - cmp r0, r2 - bne ftrace_graph_caller\suffix -#endif - - mcount_exit - -1: mcount_get_lr r1 @ lr of instrumented func - mcount_adjust_addr r0, lr @ instrumented function - adr lr, BSYM(2f) - mov pc, r2 -2: mcount_exit -.endm - -.macro __ftrace_caller suffix - mcount_enter - - mcount_get_lr r1 @ lr of instrumented func - mcount_adjust_addr r0, lr @ instrumented function - - .globl ftrace_call\suffix -ftrace_call\suffix: - bl ftrace_stub - -#ifdef CONFIG_FUNCTION_GRAPH_TRACER - .globl ftrace_graph_call\suffix -ftrace_graph_call\suffix: - mov r0, r0 -#endif - - mcount_exit -.endm - -.macro __ftrace_graph_caller - sub r0, fp, #4 @ &lr of instrumented routine (&parent) -#ifdef CONFIG_DYNAMIC_FTRACE - @ called from __ftrace_caller, saved in mcount_enter - ldr r1, [sp, #16] @ instrumented routine (func) - mcount_adjust_addr r1, r1 -#else - @ called from __mcount, untouched in lr - mcount_adjust_addr r1, lr @ instrumented routine (func) -#endif - mov r2, fp @ frame pointer - bl prepare_ftrace_return - mcount_exit -.endm - -#ifdef CONFIG_OLD_MCOUNT -/* - * mcount - */ - -.macro mcount_enter - stmdb sp!, {r0-r3, lr} -.endm - -.macro mcount_get_lr reg - ldr \reg, [fp, #-4] -.endm - -.macro mcount_exit - ldr lr, [fp, #-4] - ldmia sp!, {r0-r3, pc} -.endm - -ENTRY(mcount) -#ifdef CONFIG_DYNAMIC_FTRACE - stmdb sp!, {lr} - ldr lr, [fp, #-4] - ldmia sp!, {pc} -#else - __mcount _old -#endif -ENDPROC(mcount) - -#ifdef CONFIG_DYNAMIC_FTRACE -ENTRY(ftrace_caller_old) - __ftrace_caller _old -ENDPROC(ftrace_caller_old) -#endif - -#ifdef CONFIG_FUNCTION_GRAPH_TRACER -ENTRY(ftrace_graph_caller_old) - __ftrace_graph_caller -ENDPROC(ftrace_graph_caller_old) -#endif - -.purgem mcount_enter -.purgem mcount_get_lr -.purgem mcount_exit -#endif - -/* - * __gnu_mcount_nc - */ - -.macro mcount_enter - stmdb sp!, {r0-r3, lr} -.endm - -.macro mcount_get_lr reg - ldr \reg, [sp, #20] -.endm - -.macro mcount_exit - ldmia sp!, {r0-r3, ip, lr} - mov pc, ip -.endm - -ENTRY(__gnu_mcount_nc) -#ifdef CONFIG_DYNAMIC_FTRACE - mov ip, lr - ldmia sp!, {lr} - mov pc, ip -#else - __mcount -#endif -ENDPROC(__gnu_mcount_nc) - -#ifdef CONFIG_DYNAMIC_FTRACE -ENTRY(ftrace_caller) - __ftrace_caller -ENDPROC(ftrace_caller) -#endif - -#ifdef CONFIG_FUNCTION_GRAPH_TRACER -ENTRY(ftrace_graph_caller) - __ftrace_graph_caller -ENDPROC(ftrace_graph_caller) -#endif - -.purgem mcount_enter -.purgem mcount_get_lr -.purgem mcount_exit - -#ifdef CONFIG_FUNCTION_GRAPH_TRACER - .globl return_to_handler -return_to_handler: - stmdb sp!, {r0-r3} - mov r0, fp @ frame pointer - bl ftrace_return_to_handler - mov lr, r0 @ r0 has real ret addr - ldmia sp!, {r0-r3} - mov pc, lr -#endif - -ENTRY(ftrace_stub) -.Lftrace_stub: - mov pc, lr -ENDPROC(ftrace_stub) - -#endif /* CONFIG_FUNCTION_TRACER */ - -/*============================================================================= - * SWI handler - *----------------------------------------------------------------------------- - */ - - /* If we're optimising for StrongARM the resulting code won't - run on an ARM7 and we can save a couple of instructions. - --pb */ -#ifdef CONFIG_CPU_ARM710 -#define A710(code...) code -.Larm710bug: - ldmia sp, {r0 - lr}^ @ Get calling r0 - lr - mov r0, r0 - add sp, sp, #S_FRAME_SIZE - subs pc, lr, #4 -#else -#define A710(code...) -#endif - - .align 5 -ENTRY(vector_swi) - sub sp, sp, #S_FRAME_SIZE - stmia sp, {r0 - r12} @ Calling r0 - r12 - ARM( add r8, sp, #S_PC ) - ARM( stmdb r8, {sp, lr}^ ) @ Calling sp, lr - THUMB( mov r8, sp ) - THUMB( store_user_sp_lr r8, r10, S_SP ) @ calling sp, lr - mrs r8, spsr @ called from non-FIQ mode, so ok. - str lr, [sp, #S_PC] @ Save calling PC - str r8, [sp, #S_PSR] @ Save CPSR - str r0, [sp, #S_OLD_R0] @ Save OLD_R0 - zero_fp - - /* - * Get the system call number. - */ - -#if defined(CONFIG_OABI_COMPAT) - - /* - * If we have CONFIG_OABI_COMPAT then we need to look at the swi - * value to determine if it is an EABI or an old ABI call. - */ -#ifdef CONFIG_ARM_THUMB - tst r8, #PSR_T_BIT - movne r10, #0 @ no thumb OABI emulation - ldreq r10, [lr, #-4] @ get SWI instruction -#else - ldr r10, [lr, #-4] @ get SWI instruction - A710( and ip, r10, #0x0f000000 @ check for SWI ) - A710( teq ip, #0x0f000000 ) - A710( bne .Larm710bug ) -#endif -#ifdef CONFIG_CPU_ENDIAN_BE8 - rev r10, r10 @ little endian instruction -#endif - -#elif defined(CONFIG_AEABI) - - /* - * Pure EABI user space always put syscall number into scno (r7). - */ - A710( ldr ip, [lr, #-4] @ get SWI instruction ) - A710( and ip, ip, #0x0f000000 @ check for SWI ) - A710( teq ip, #0x0f000000 ) - A710( bne .Larm710bug ) - -#elif defined(CONFIG_ARM_THUMB) - - /* Legacy ABI only, possibly thumb mode. */ - tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs - addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in - ldreq scno, [lr, #-4] - -#else - - /* Legacy ABI only. */ - ldr scno, [lr, #-4] @ get SWI instruction - A710( and ip, scno, #0x0f000000 @ check for SWI ) - A710( teq ip, #0x0f000000 ) - A710( bne .Larm710bug ) - -#endif - -#ifdef CONFIG_ALIGNMENT_TRAP - ldr ip, __cr_alignment - ldr ip, [ip] - mcr p15, 0, ip, c1, c0 @ update control register -#endif - enable_irq - - get_thread_info tsk - adr tbl, sys_call_table @ load syscall table pointer - -#if defined(CONFIG_OABI_COMPAT) - /* - * If the swi argument is zero, this is an EABI call and we do nothing. - * - * If this is an old ABI call, get the syscall number into scno and - * get the old ABI syscall table address. - */ - bics r10, r10, #0xff000000 - eorne scno, r10, #__NR_OABI_SYSCALL_BASE - ldrne tbl, =sys_oabi_call_table -#elif !defined(CONFIG_AEABI) - bic scno, scno, #0xff000000 @ mask off SWI op-code - eor scno, scno, #__NR_SYSCALL_BASE @ check OS number -#endif - - ldr r10, [tsk, #TI_FLAGS] @ check for syscall tracing - stmdb sp!, {r4, r5} @ push fifth and sixth args - -#ifdef CONFIG_SECCOMP - tst r10, #_TIF_SECCOMP - beq 1f - mov r0, scno - bl __secure_computing - add r0, sp, #S_R0 + S_OFF @ pointer to regs - ldmia r0, {r0 - r3} @ have to reload r0 - r3 -1: -#endif - - tst r10, #_TIF_SYSCALL_WORK @ are we tracing syscalls? - bne __sys_trace - - cmp scno, #NR_syscalls @ check upper syscall limit - adr lr, BSYM(ret_fast_syscall) @ return address - ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine - - add r1, sp, #S_OFF -2: mov why, #0 @ no longer a real syscall - cmp scno, #(__ARM_NR_BASE - __NR_SYSCALL_BASE) - eor r0, scno, #__NR_SYSCALL_BASE @ put OS number back - bcs arm_syscall - b sys_ni_syscall @ not private func -ENDPROC(vector_swi) - - /* - * This is the really slow path. We're going to be doing - * context switches, and waiting for our parent to respond. - */ -__sys_trace: - mov r2, scno - add r1, sp, #S_OFF - mov r0, #0 @ trace entry [IP = 0] - bl syscall_trace - - adr lr, BSYM(__sys_trace_return) @ return address - mov scno, r0 @ syscall number (possibly new) - add r1, sp, #S_R0 + S_OFF @ pointer to regs - cmp scno, #NR_syscalls @ check upper syscall limit - ldmccia r1, {r0 - r3} @ have to reload r0 - r3 - ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine - b 2b - -__sys_trace_return: - str r0, [sp, #S_R0 + S_OFF]! @ save returned r0 - mov r2, scno - mov r1, sp - mov r0, #1 @ trace exit [IP = 1] - bl syscall_trace - b ret_slow_syscall - - .align 5 -#ifdef CONFIG_ALIGNMENT_TRAP - .type __cr_alignment, #object -__cr_alignment: - .word cr_alignment -#endif - .ltorg - -/* - * This is the syscall table declaration for native ABI syscalls. - * With EABI a couple syscalls are obsolete and defined as sys_ni_syscall. - */ -#define ABI(native, compat) native -#ifdef CONFIG_AEABI -#define OBSOLETE(syscall) sys_ni_syscall -#else -#define OBSOLETE(syscall) syscall -#endif - - .type sys_call_table, #object -ENTRY(sys_call_table) -#include "calls.S" -#undef ABI -#undef OBSOLETE - -/*============================================================================ - * Special system call wrappers - */ -@ r0 = syscall number -@ r8 = syscall table -sys_syscall: - bic scno, r0, #__NR_OABI_SYSCALL_BASE - cmp scno, #__NR_syscall - __NR_SYSCALL_BASE - cmpne scno, #NR_syscalls @ check range - stmloia sp, {r5, r6} @ shuffle args - movlo r0, r1 - movlo r1, r2 - movlo r2, r3 - movlo r3, r4 - ldrlo pc, [tbl, scno, lsl #2] - b sys_ni_syscall -ENDPROC(sys_syscall) - -sys_fork_wrapper: - add r0, sp, #S_OFF - b sys_fork -ENDPROC(sys_fork_wrapper) - -sys_vfork_wrapper: - add r0, sp, #S_OFF - b sys_vfork -ENDPROC(sys_vfork_wrapper) - -sys_execve_wrapper: - add r3, sp, #S_OFF - b sys_execve -ENDPROC(sys_execve_wrapper) - -sys_clone_wrapper: - add ip, sp, #S_OFF - str ip, [sp, #4] - b sys_clone -ENDPROC(sys_clone_wrapper) - -sys_sigreturn_wrapper: - add r0, sp, #S_OFF - mov why, #0 @ prevent syscall restart handling - b sys_sigreturn -ENDPROC(sys_sigreturn_wrapper) - -sys_rt_sigreturn_wrapper: - add r0, sp, #S_OFF - mov why, #0 @ prevent syscall restart handling - b sys_rt_sigreturn -ENDPROC(sys_rt_sigreturn_wrapper) - -sys_sigaltstack_wrapper: - ldr r2, [sp, #S_OFF + S_SP] - b do_sigaltstack -ENDPROC(sys_sigaltstack_wrapper) - -sys_statfs64_wrapper: - teq r1, #88 - moveq r1, #84 - b sys_statfs64 -ENDPROC(sys_statfs64_wrapper) - -sys_fstatfs64_wrapper: - teq r1, #88 - moveq r1, #84 - b sys_fstatfs64 -ENDPROC(sys_fstatfs64_wrapper) - -/* - * Note: off_4k (r5) is always units of 4K. If we can't do the requested - * offset, we return EINVAL. - */ -sys_mmap2: -#if PAGE_SHIFT > 12 - tst r5, #PGOFF_MASK - moveq r5, r5, lsr #PAGE_SHIFT - 12 - streq r5, [sp, #4] - beq sys_mmap_pgoff - mov r0, #-EINVAL - mov pc, lr -#else - str r5, [sp, #4] - b sys_mmap_pgoff -#endif -ENDPROC(sys_mmap2) - -#ifdef CONFIG_OABI_COMPAT - -/* - * These are syscalls with argument register differences - */ - -sys_oabi_pread64: - stmia sp, {r3, r4} - b sys_pread64 -ENDPROC(sys_oabi_pread64) - -sys_oabi_pwrite64: - stmia sp, {r3, r4} - b sys_pwrite64 -ENDPROC(sys_oabi_pwrite64) - -sys_oabi_truncate64: - mov r3, r2 - mov r2, r1 - b sys_truncate64 -ENDPROC(sys_oabi_truncate64) - -sys_oabi_ftruncate64: - mov r3, r2 - mov r2, r1 - b sys_ftruncate64 -ENDPROC(sys_oabi_ftruncate64) - -sys_oabi_readahead: - str r3, [sp] - mov r3, r2 - mov r2, r1 - b sys_readahead -ENDPROC(sys_oabi_readahead) - -/* - * Let's declare a second syscall table for old ABI binaries - * using the compatibility syscall entries. - */ -#define ABI(native, compat) compat -#define OBSOLETE(syscall) syscall - - .type sys_oabi_call_table, #object -ENTRY(sys_oabi_call_table) -#include "calls.S" -#undef ABI -#undef OBSOLETE - -#endif - diff --git a/ANDROID_3.4.5/arch/arm/kernel/entry-header.S b/ANDROID_3.4.5/arch/arm/kernel/entry-header.S deleted file mode 100644 index 9a8531ea..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/entry-header.S +++ /dev/null @@ -1,179 +0,0 @@ -#include <linux/init.h> -#include <linux/linkage.h> - -#include <asm/assembler.h> -#include <asm/asm-offsets.h> -#include <asm/errno.h> -#include <asm/thread_info.h> - -@ Bad Abort numbers -@ ----------------- -@ -#define BAD_PREFETCH 0 -#define BAD_DATA 1 -#define BAD_ADDREXCPTN 2 -#define BAD_IRQ 3 -#define BAD_UNDEFINSTR 4 - -@ -@ Most of the stack format comes from struct pt_regs, but with -@ the addition of 8 bytes for storing syscall args 5 and 6. -@ This _must_ remain a multiple of 8 for EABI. -@ -#define S_OFF 8 - -/* - * The SWI code relies on the fact that R0 is at the bottom of the stack - * (due to slow/fast restore user regs). - */ -#if S_R0 != 0 -#error "Please fix" -#endif - - .macro zero_fp -#ifdef CONFIG_FRAME_POINTER - mov fp, #0 -#endif - .endm - - .macro alignment_trap, rtemp -#ifdef CONFIG_ALIGNMENT_TRAP - ldr \rtemp, .LCcralign - ldr \rtemp, [\rtemp] - mcr p15, 0, \rtemp, c1, c0 -#endif - .endm - - @ - @ Store/load the USER SP and LR registers by switching to the SYS - @ mode. Useful in Thumb-2 mode where "stm/ldm rd, {sp, lr}^" is not - @ available. Should only be called from SVC mode - @ - .macro store_user_sp_lr, rd, rtemp, offset = 0 - mrs \rtemp, cpsr - eor \rtemp, \rtemp, #(SVC_MODE ^ SYSTEM_MODE) - msr cpsr_c, \rtemp @ switch to the SYS mode - - str sp, [\rd, #\offset] @ save sp_usr - str lr, [\rd, #\offset + 4] @ save lr_usr - - eor \rtemp, \rtemp, #(SVC_MODE ^ SYSTEM_MODE) - msr cpsr_c, \rtemp @ switch back to the SVC mode - .endm - - .macro load_user_sp_lr, rd, rtemp, offset = 0 - mrs \rtemp, cpsr - eor \rtemp, \rtemp, #(SVC_MODE ^ SYSTEM_MODE) - msr cpsr_c, \rtemp @ switch to the SYS mode - - ldr sp, [\rd, #\offset] @ load sp_usr - ldr lr, [\rd, #\offset + 4] @ load lr_usr - - eor \rtemp, \rtemp, #(SVC_MODE ^ SYSTEM_MODE) - msr cpsr_c, \rtemp @ switch back to the SVC mode - .endm - -#ifndef CONFIG_THUMB2_KERNEL - .macro svc_exit, rpsr - msr spsr_cxsf, \rpsr -#if defined(CONFIG_CPU_V6) - ldr r0, [sp] - strex r1, r2, [sp] @ clear the exclusive monitor - ldmib sp, {r1 - pc}^ @ load r1 - pc, cpsr -#elif defined(CONFIG_CPU_32v6K) - clrex @ clear the exclusive monitor - ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr -#else - ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr -#endif - .endm - - .macro restore_user_regs, fast = 0, offset = 0 - ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr - ldr lr, [sp, #\offset + S_PC]! @ get pc - msr spsr_cxsf, r1 @ save in spsr_svc -#if defined(CONFIG_CPU_V6) - strex r1, r2, [sp] @ clear the exclusive monitor -#elif defined(CONFIG_CPU_32v6K) - clrex @ clear the exclusive monitor -#endif - .if \fast - ldmdb sp, {r1 - lr}^ @ get calling r1 - lr - .else - ldmdb sp, {r0 - lr}^ @ get calling r0 - lr - .endif - mov r0, r0 @ ARMv5T and earlier require a nop - @ after ldm {}^ - add sp, sp, #S_FRAME_SIZE - S_PC - movs pc, lr @ return & move spsr_svc into cpsr - .endm - - .macro get_thread_info, rd - mov \rd, sp, lsr #13 - mov \rd, \rd, lsl #13 - .endm - - @ - @ 32-bit wide "mov pc, reg" - @ - .macro movw_pc, reg - mov pc, \reg - .endm -#else /* CONFIG_THUMB2_KERNEL */ - .macro svc_exit, rpsr - ldr lr, [sp, #S_SP] @ top of the stack - ldrd r0, r1, [sp, #S_LR] @ calling lr and pc - clrex @ clear the exclusive monitor - stmdb lr!, {r0, r1, \rpsr} @ calling lr and rfe context - ldmia sp, {r0 - r12} - mov sp, lr - ldr lr, [sp], #4 - rfeia sp! - .endm - - .macro restore_user_regs, fast = 0, offset = 0 - clrex @ clear the exclusive monitor - mov r2, sp - load_user_sp_lr r2, r3, \offset + S_SP @ calling sp, lr - ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr - ldr lr, [sp, #\offset + S_PC] @ get pc - add sp, sp, #\offset + S_SP - msr spsr_cxsf, r1 @ save in spsr_svc - .if \fast - ldmdb sp, {r1 - r12} @ get calling r1 - r12 - .else - ldmdb sp, {r0 - r12} @ get calling r0 - r12 - .endif - add sp, sp, #S_FRAME_SIZE - S_SP - movs pc, lr @ return & move spsr_svc into cpsr - .endm - - .macro get_thread_info, rd - mov \rd, sp - lsr \rd, \rd, #13 - mov \rd, \rd, lsl #13 - .endm - - @ - @ 32-bit wide "mov pc, reg" - @ - .macro movw_pc, reg - mov pc, \reg - nop - .endm -#endif /* !CONFIG_THUMB2_KERNEL */ - -/* - * These are the registers used in the syscall handler, and allow us to - * have in theory up to 7 arguments to a function - r0 to r6. - * - * r7 is reserved for the system call number for thumb mode. - * - * Note that tbl == why is intentional. - * - * We must set at least "tsk" and "why" when calling ret_with_reschedule. - */ -scno .req r7 @ syscall number -tbl .req r8 @ syscall table pointer -why .req r8 @ Linux syscall (!= 0) -tsk .req r9 @ current thread_info diff --git a/ANDROID_3.4.5/arch/arm/kernel/etm.c b/ANDROID_3.4.5/arch/arm/kernel/etm.c deleted file mode 100644 index c5fb6c9f..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/etm.c +++ /dev/null @@ -1,1076 +0,0 @@ -/* - * linux/arch/arm/kernel/etm.c - * - * Driver for ARM's Embedded Trace Macrocell and Embedded Trace Buffer. - * - * Copyright (C) 2009 Nokia Corporation. - * Alexander Shishkin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/types.h> -#include <linux/io.h> -#include <linux/slab.h> -#include <linux/sysrq.h> -#include <linux/device.h> -#include <linux/clk.h> -#include <linux/amba/bus.h> -#include <linux/fs.h> -#include <linux/uaccess.h> -#include <linux/miscdevice.h> -#include <linux/vmalloc.h> -#include <linux/mutex.h> -#include <linux/module.h> -#include <asm/hardware/coresight.h> -#include <asm/sections.h> - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Alexander Shishkin"); - -/* - * ETM tracer state - */ -struct tracectx { - unsigned int etb_bufsz; - void __iomem *etb_regs; - void __iomem **etm_regs; - int etm_regs_count; - unsigned long flags; - int ncmppairs; - int etm_portsz; - int etm_contextid_size; - u32 etb_fc; - unsigned long range_start; - unsigned long range_end; - unsigned long data_range_start; - unsigned long data_range_end; - bool dump_initial_etb; - struct device *dev; - struct clk *emu_clk; - struct mutex mutex; -}; - -static struct tracectx tracer = { - .range_start = (unsigned long)_stext, - .range_end = (unsigned long)_etext, -}; - -static inline bool trace_isrunning(struct tracectx *t) -{ - return !!(t->flags & TRACER_RUNNING); -} - -static int etm_setup_address_range(struct tracectx *t, int id, int n, - unsigned long start, unsigned long end, int exclude, int data) -{ - u32 flags = ETMAAT_ARM | ETMAAT_IGNCONTEXTID | ETMAAT_IGNSECURITY | - ETMAAT_NOVALCMP; - - if (n < 1 || n > t->ncmppairs) - return -EINVAL; - - /* comparators and ranges are numbered starting with 1 as opposed - * to bits in a word */ - n--; - - if (data) - flags |= ETMAAT_DLOADSTORE; - else - flags |= ETMAAT_IEXEC; - - /* first comparator for the range */ - etm_writel(t, id, flags, ETMR_COMP_ACC_TYPE(n * 2)); - etm_writel(t, id, start, ETMR_COMP_VAL(n * 2)); - - /* second comparator is right next to it */ - etm_writel(t, id, flags, ETMR_COMP_ACC_TYPE(n * 2 + 1)); - etm_writel(t, id, end, ETMR_COMP_VAL(n * 2 + 1)); - - if (data) { - flags = exclude ? ETMVDC3_EXCLONLY : 0; - if (exclude) - n += 8; - etm_writel(t, id, flags | BIT(n), ETMR_VIEWDATACTRL3); - } else { - flags = exclude ? ETMTE_INCLEXCL : 0; - etm_writel(t, id, flags | (1 << n), ETMR_TRACEENCTRL); - } - - return 0; -} - -static int trace_start_etm(struct tracectx *t, int id) -{ - u32 v; - unsigned long timeout = TRACER_TIMEOUT; - - v = ETMCTRL_OPTS | ETMCTRL_PROGRAM | ETMCTRL_PORTSIZE(t->etm_portsz); - v |= ETMCTRL_CONTEXTIDSIZE(t->etm_contextid_size); - - if (t->flags & TRACER_CYCLE_ACC) - v |= ETMCTRL_CYCLEACCURATE; - - if (t->flags & TRACER_BRANCHOUTPUT) - v |= ETMCTRL_BRANCH_OUTPUT; - - if (t->flags & TRACER_TRACE_DATA) - v |= ETMCTRL_DATA_DO_ADDR; - - if (t->flags & TRACER_TIMESTAMP) - v |= ETMCTRL_TIMESTAMP_EN; - - if (t->flags & TRACER_RETURN_STACK) - v |= ETMCTRL_RETURN_STACK_EN; - - etm_unlock(t, id); - - etm_writel(t, id, v, ETMR_CTRL); - - while (!(etm_readl(t, id, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout) - ; - if (!timeout) { - dev_dbg(t->dev, "Waiting for progbit to assert timed out\n"); - etm_lock(t, id); - return -EFAULT; - } - - if (t->range_start || t->range_end) - etm_setup_address_range(t, id, 1, - t->range_start, t->range_end, 0, 0); - else - etm_writel(t, id, ETMTE_INCLEXCL, ETMR_TRACEENCTRL); - - etm_writel(t, id, 0, ETMR_TRACEENCTRL2); - etm_writel(t, id, 0, ETMR_TRACESSCTRL); - etm_writel(t, id, 0x6f, ETMR_TRACEENEVT); - - etm_writel(t, id, 0, ETMR_VIEWDATACTRL1); - etm_writel(t, id, 0, ETMR_VIEWDATACTRL2); - - if (t->data_range_start || t->data_range_end) - etm_setup_address_range(t, id, 2, t->data_range_start, - t->data_range_end, 0, 1); - else - etm_writel(t, id, ETMVDC3_EXCLONLY, ETMR_VIEWDATACTRL3); - - etm_writel(t, id, 0x6f, ETMR_VIEWDATAEVT); - - v &= ~ETMCTRL_PROGRAM; - v |= ETMCTRL_PORTSEL; - - etm_writel(t, id, v, ETMR_CTRL); - - timeout = TRACER_TIMEOUT; - while (etm_readl(t, id, ETMR_CTRL) & ETMCTRL_PROGRAM && --timeout) - ; - if (!timeout) { - dev_dbg(t->dev, "Waiting for progbit to deassert timed out\n"); - etm_lock(t, id); - return -EFAULT; - } - - etm_lock(t, id); - return 0; -} - -static int trace_start(struct tracectx *t) -{ - int ret; - int id; - u32 etb_fc = t->etb_fc; - - etb_unlock(t); - - t->dump_initial_etb = false; - etb_writel(t, 0, ETBR_WRITEADDR); - etb_writel(t, etb_fc, ETBR_FORMATTERCTRL); - etb_writel(t, 1, ETBR_CTRL); - - etb_lock(t); - - /* configure etm(s) */ - for (id = 0; id < t->etm_regs_count; id++) { - ret = trace_start_etm(t, id); - if (ret) - return ret; - } - - t->flags |= TRACER_RUNNING; - - return 0; -} - -static int trace_stop_etm(struct tracectx *t, int id) -{ - unsigned long timeout = TRACER_TIMEOUT; - - etm_unlock(t, id); - - etm_writel(t, id, 0x440, ETMR_CTRL); - while (!(etm_readl(t, id, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout) - ; - if (!timeout) { - dev_err(t->dev, - "etm%d: Waiting for progbit to assert timed out\n", - id); - etm_lock(t, id); - return -EFAULT; - } - - etm_lock(t, id); - return 0; -} - -static int trace_power_down_etm(struct tracectx *t, int id) -{ - unsigned long timeout = TRACER_TIMEOUT; - etm_unlock(t, id); - while (!(etm_readl(t, id, ETMR_STATUS) & ETMST_PROGBIT) && --timeout) - ; - if (!timeout) { - dev_err(t->dev, "etm%d: Waiting for status progbit to assert timed out\n", - id); - etm_lock(t, id); - return -EFAULT; - } - - etm_writel(t, id, 0x441, ETMR_CTRL); - - etm_lock(t, id); - return 0; -} - -static int trace_stop(struct tracectx *t) -{ - int id; - unsigned long timeout = TRACER_TIMEOUT; - u32 etb_fc = t->etb_fc; - - for (id = 0; id < t->etm_regs_count; id++) - trace_stop_etm(t, id); - - for (id = 0; id < t->etm_regs_count; id++) - trace_power_down_etm(t, id); - - etb_unlock(t); - if (etb_fc) { - etb_fc |= ETBFF_STOPFL; - etb_writel(t, t->etb_fc, ETBR_FORMATTERCTRL); - } - etb_writel(t, etb_fc | ETBFF_MANUAL_FLUSH, ETBR_FORMATTERCTRL); - - timeout = TRACER_TIMEOUT; - while (etb_readl(t, ETBR_FORMATTERCTRL) & - ETBFF_MANUAL_FLUSH && --timeout) - ; - if (!timeout) { - dev_dbg(t->dev, "Waiting for formatter flush to commence " - "timed out\n"); - etb_lock(t); - return -EFAULT; - } - - etb_writel(t, 0, ETBR_CTRL); - - etb_lock(t); - - t->flags &= ~TRACER_RUNNING; - - return 0; -} - -static int etb_getdatalen(struct tracectx *t) -{ - u32 v; - int wp; - - v = etb_readl(t, ETBR_STATUS); - - if (v & 1) - return t->etb_bufsz; - - wp = etb_readl(t, ETBR_WRITEADDR); - return wp; -} - -/* sysrq+v will always stop the running trace and leave it at that */ -static void etm_dump(void) -{ - struct tracectx *t = &tracer; - u32 first = 0; - int length; - - if (!t->etb_regs) { - printk(KERN_INFO "No tracing hardware found\n"); - return; - } - - if (trace_isrunning(t)) - trace_stop(t); - - etb_unlock(t); - - length = etb_getdatalen(t); - - if (length == t->etb_bufsz) - first = etb_readl(t, ETBR_WRITEADDR); - - etb_writel(t, first, ETBR_READADDR); - - printk(KERN_INFO "Trace buffer contents length: %d\n", length); - printk(KERN_INFO "--- ETB buffer begin ---\n"); - for (; length; length--) - printk("%08x", cpu_to_be32(etb_readl(t, ETBR_READMEM))); - printk(KERN_INFO "\n--- ETB buffer end ---\n"); - - etb_lock(t); -} - -static void sysrq_etm_dump(int key) -{ - if (!mutex_trylock(&tracer.mutex)) { - printk(KERN_INFO "Tracing hardware busy\n"); - return; - } - dev_dbg(tracer.dev, "Dumping ETB buffer\n"); - etm_dump(); - mutex_unlock(&tracer.mutex); -} - -static struct sysrq_key_op sysrq_etm_op = { - .handler = sysrq_etm_dump, - .help_msg = "ETM buffer dump", - .action_msg = "etm", -}; - -static int etb_open(struct inode *inode, struct file *file) -{ - if (!tracer.etb_regs) - return -ENODEV; - - file->private_data = &tracer; - - return nonseekable_open(inode, file); -} - -static ssize_t etb_read(struct file *file, char __user *data, - size_t len, loff_t *ppos) -{ - int total, i; - long length; - struct tracectx *t = file->private_data; - u32 first = 0; - u32 *buf; - int wpos; - int skip; - long wlength; - loff_t pos = *ppos; - - mutex_lock(&t->mutex); - - if (trace_isrunning(t)) { - length = 0; - goto out; - } - - etb_unlock(t); - - total = etb_getdatalen(t); - if (total == 0 && t->dump_initial_etb) - total = t->etb_bufsz; - if (total == t->etb_bufsz) - first = etb_readl(t, ETBR_WRITEADDR); - - if (pos > total * 4) { - skip = 0; - wpos = total; - } else { - skip = (int)pos % 4; - wpos = (int)pos / 4; - } - total -= wpos; - first = (first + wpos) % t->etb_bufsz; - - etb_writel(t, first, ETBR_READADDR); - - wlength = min(total, DIV_ROUND_UP(skip + (int)len, 4)); - length = min(total * 4 - skip, (int)len); - buf = vmalloc(wlength * 4); - - dev_dbg(t->dev, "ETB read %ld bytes to %lld from %ld words at %d\n", - length, pos, wlength, first); - dev_dbg(t->dev, "ETB buffer length: %d\n", total + wpos); - dev_dbg(t->dev, "ETB status reg: %x\n", etb_readl(t, ETBR_STATUS)); - for (i = 0; i < wlength; i++) - buf[i] = etb_readl(t, ETBR_READMEM); - - etb_lock(t); - - length -= copy_to_user(data, (u8 *)buf + skip, length); - vfree(buf); - *ppos = pos + length; - -out: - mutex_unlock(&t->mutex); - - return length; -} - -static int etb_release(struct inode *inode, struct file *file) -{ - /* there's nothing to do here, actually */ - return 0; -} - -static const struct file_operations etb_fops = { - .owner = THIS_MODULE, - .read = etb_read, - .open = etb_open, - .release = etb_release, - .llseek = no_llseek, -}; - -static struct miscdevice etb_miscdev = { - .name = "tracebuf", - .minor = 0, - .fops = &etb_fops, -}; - -static int __devinit etb_probe(struct amba_device *dev, const struct amba_id *id) -{ - struct tracectx *t = &tracer; - int ret = 0; - - ret = amba_request_regions(dev, NULL); - if (ret) - goto out; - - mutex_lock(&t->mutex); - t->etb_regs = ioremap_nocache(dev->res.start, resource_size(&dev->res)); - if (!t->etb_regs) { - ret = -ENOMEM; - goto out_release; - } - - t->dev = &dev->dev; - t->dump_initial_etb = true; - amba_set_drvdata(dev, t); - - etb_unlock(t); - t->etb_bufsz = etb_readl(t, ETBR_DEPTH); - dev_dbg(&dev->dev, "Size: %x\n", t->etb_bufsz); - - /* make sure trace capture is disabled */ - etb_writel(t, 0, ETBR_CTRL); - etb_writel(t, 0x1000, ETBR_FORMATTERCTRL); - etb_lock(t); - mutex_unlock(&t->mutex); - - etb_miscdev.parent = &dev->dev; - - ret = misc_register(&etb_miscdev); - if (ret) - goto out_unmap; - - /* Get optional clock. Currently used to select clock source on omap3 */ - t->emu_clk = clk_get(&dev->dev, "emu_src_ck"); - if (IS_ERR(t->emu_clk)) - dev_dbg(&dev->dev, "Failed to obtain emu_src_ck.\n"); - else - clk_enable(t->emu_clk); - - dev_dbg(&dev->dev, "ETB AMBA driver initialized.\n"); - -out: - return ret; - -out_unmap: - mutex_lock(&t->mutex); - amba_set_drvdata(dev, NULL); - iounmap(t->etb_regs); - t->etb_regs = NULL; - -out_release: - mutex_unlock(&t->mutex); - amba_release_regions(dev); - - return ret; -} - -static int etb_remove(struct amba_device *dev) -{ - struct tracectx *t = amba_get_drvdata(dev); - - amba_set_drvdata(dev, NULL); - - iounmap(t->etb_regs); - t->etb_regs = NULL; - - if (!IS_ERR(t->emu_clk)) { - clk_disable(t->emu_clk); - clk_put(t->emu_clk); - } - - amba_release_regions(dev); - - return 0; -} - -static struct amba_id etb_ids[] = { - { - .id = 0x0003b907, - .mask = 0x0007ffff, - }, - { 0, 0 }, -}; - -static struct amba_driver etb_driver = { - .drv = { - .name = "etb", - .owner = THIS_MODULE, - }, - .probe = etb_probe, - .remove = etb_remove, - .id_table = etb_ids, -}; - -/* use a sysfs file "trace_running" to start/stop tracing */ -static ssize_t trace_running_show(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - return sprintf(buf, "%x\n", trace_isrunning(&tracer)); -} - -static ssize_t trace_running_store(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, size_t n) -{ - unsigned int value; - int ret; - - if (sscanf(buf, "%u", &value) != 1) - return -EINVAL; - - mutex_lock(&tracer.mutex); - if (!tracer.etb_regs) - ret = -ENODEV; - else - ret = value ? trace_start(&tracer) : trace_stop(&tracer); - mutex_unlock(&tracer.mutex); - - return ret ? : n; -} - -static struct kobj_attribute trace_running_attr = - __ATTR(trace_running, 0644, trace_running_show, trace_running_store); - -static ssize_t trace_info_show(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - u32 etb_wa, etb_ra, etb_st, etb_fc, etm_ctrl, etm_st; - int datalen; - int id; - int ret; - - mutex_lock(&tracer.mutex); - if (tracer.etb_regs) { - etb_unlock(&tracer); - datalen = etb_getdatalen(&tracer); - etb_wa = etb_readl(&tracer, ETBR_WRITEADDR); - etb_ra = etb_readl(&tracer, ETBR_READADDR); - etb_st = etb_readl(&tracer, ETBR_STATUS); - etb_fc = etb_readl(&tracer, ETBR_FORMATTERCTRL); - etb_lock(&tracer); - } else { - etb_wa = etb_ra = etb_st = etb_fc = ~0; - datalen = -1; - } - - ret = sprintf(buf, "Trace buffer len: %d\nComparator pairs: %d\n" - "ETBR_WRITEADDR:\t%08x\n" - "ETBR_READADDR:\t%08x\n" - "ETBR_STATUS:\t%08x\n" - "ETBR_FORMATTERCTRL:\t%08x\n", - datalen, - tracer.ncmppairs, - etb_wa, - etb_ra, - etb_st, - etb_fc - ); - - for (id = 0; id < tracer.etm_regs_count; id++) { - etm_unlock(&tracer, id); - etm_ctrl = etm_readl(&tracer, id, ETMR_CTRL); - etm_st = etm_readl(&tracer, id, ETMR_STATUS); - etm_lock(&tracer, id); - ret += sprintf(buf + ret, "ETMR_CTRL:\t%08x\n" - "ETMR_STATUS:\t%08x\n", - etm_ctrl, - etm_st - ); - } - mutex_unlock(&tracer.mutex); - - return ret; -} - -static struct kobj_attribute trace_info_attr = - __ATTR(trace_info, 0444, trace_info_show, NULL); - -static ssize_t trace_mode_show(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d %d\n", - !!(tracer.flags & TRACER_CYCLE_ACC), - tracer.etm_portsz); -} - -static ssize_t trace_mode_store(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, size_t n) -{ - unsigned int cycacc, portsz; - - if (sscanf(buf, "%u %u", &cycacc, &portsz) != 2) - return -EINVAL; - - mutex_lock(&tracer.mutex); - if (cycacc) - tracer.flags |= TRACER_CYCLE_ACC; - else - tracer.flags &= ~TRACER_CYCLE_ACC; - - tracer.etm_portsz = portsz & 0x0f; - mutex_unlock(&tracer.mutex); - - return n; -} - -static struct kobj_attribute trace_mode_attr = - __ATTR(trace_mode, 0644, trace_mode_show, trace_mode_store); - -static ssize_t trace_contextid_size_show(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - /* 0: No context id tracing, 1: One byte, 2: Two bytes, 3: Four bytes */ - return sprintf(buf, "%d\n", (1 << tracer.etm_contextid_size) >> 1); -} - -static ssize_t trace_contextid_size_store(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, size_t n) -{ - unsigned int contextid_size; - - if (sscanf(buf, "%u", &contextid_size) != 1) - return -EINVAL; - - if (contextid_size == 3 || contextid_size > 4) - return -EINVAL; - - mutex_lock(&tracer.mutex); - tracer.etm_contextid_size = fls(contextid_size); - mutex_unlock(&tracer.mutex); - - return n; -} - -static struct kobj_attribute trace_contextid_size_attr = - __ATTR(trace_contextid_size, 0644, - trace_contextid_size_show, trace_contextid_size_store); - -static ssize_t trace_branch_output_show(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d\n", !!(tracer.flags & TRACER_BRANCHOUTPUT)); -} - -static ssize_t trace_branch_output_store(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, size_t n) -{ - unsigned int branch_output; - - if (sscanf(buf, "%u", &branch_output) != 1) - return -EINVAL; - - mutex_lock(&tracer.mutex); - if (branch_output) { - tracer.flags |= TRACER_BRANCHOUTPUT; - /* Branch broadcasting is incompatible with the return stack */ - tracer.flags &= ~TRACER_RETURN_STACK; - } else { - tracer.flags &= ~TRACER_BRANCHOUTPUT; - } - mutex_unlock(&tracer.mutex); - - return n; -} - -static struct kobj_attribute trace_branch_output_attr = - __ATTR(trace_branch_output, 0644, - trace_branch_output_show, trace_branch_output_store); - -static ssize_t trace_return_stack_show(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d\n", !!(tracer.flags & TRACER_RETURN_STACK)); -} - -static ssize_t trace_return_stack_store(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, size_t n) -{ - unsigned int return_stack; - - if (sscanf(buf, "%u", &return_stack) != 1) - return -EINVAL; - - mutex_lock(&tracer.mutex); - if (return_stack) { - tracer.flags |= TRACER_RETURN_STACK; - /* Return stack is incompatible with branch broadcasting */ - tracer.flags &= ~TRACER_BRANCHOUTPUT; - } else { - tracer.flags &= ~TRACER_RETURN_STACK; - } - mutex_unlock(&tracer.mutex); - - return n; -} - -static struct kobj_attribute trace_return_stack_attr = - __ATTR(trace_return_stack, 0644, - trace_return_stack_show, trace_return_stack_store); - -static ssize_t trace_timestamp_show(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d\n", !!(tracer.flags & TRACER_TIMESTAMP)); -} - -static ssize_t trace_timestamp_store(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, size_t n) -{ - unsigned int timestamp; - - if (sscanf(buf, "%u", ×tamp) != 1) - return -EINVAL; - - mutex_lock(&tracer.mutex); - if (timestamp) - tracer.flags |= TRACER_TIMESTAMP; - else - tracer.flags &= ~TRACER_TIMESTAMP; - mutex_unlock(&tracer.mutex); - - return n; -} - -static struct kobj_attribute trace_timestamp_attr = - __ATTR(trace_timestamp, 0644, - trace_timestamp_show, trace_timestamp_store); - -static ssize_t trace_range_show(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - return sprintf(buf, "%08lx %08lx\n", - tracer.range_start, tracer.range_end); -} - -static ssize_t trace_range_store(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, size_t n) -{ - unsigned long range_start, range_end; - - if (sscanf(buf, "%lx %lx", &range_start, &range_end) != 2) - return -EINVAL; - - mutex_lock(&tracer.mutex); - tracer.range_start = range_start; - tracer.range_end = range_end; - mutex_unlock(&tracer.mutex); - - return n; -} - - -static struct kobj_attribute trace_range_attr = - __ATTR(trace_range, 0644, trace_range_show, trace_range_store); - -static ssize_t trace_data_range_show(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - unsigned long range_start; - u64 range_end; - mutex_lock(&tracer.mutex); - range_start = tracer.data_range_start; - range_end = tracer.data_range_end; - if (!range_end && (tracer.flags & TRACER_TRACE_DATA)) - range_end = 0x100000000ULL; - mutex_unlock(&tracer.mutex); - return sprintf(buf, "%08lx %08llx\n", range_start, range_end); -} - -static ssize_t trace_data_range_store(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, size_t n) -{ - unsigned long range_start; - u64 range_end; - - if (sscanf(buf, "%lx %llx", &range_start, &range_end) != 2) - return -EINVAL; - - mutex_lock(&tracer.mutex); - tracer.data_range_start = range_start; - tracer.data_range_end = (unsigned long)range_end; - if (range_end) - tracer.flags |= TRACER_TRACE_DATA; - else - tracer.flags &= ~TRACER_TRACE_DATA; - mutex_unlock(&tracer.mutex); - - return n; -} - - -static struct kobj_attribute trace_data_range_attr = - __ATTR(trace_data_range, 0644, - trace_data_range_show, trace_data_range_store); - -static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id) -{ - struct tracectx *t = &tracer; - int ret = 0; - void __iomem **new_regs; - int new_count; - u32 etmccr; - u32 etmidr; - u32 etmccer = 0; - u8 etm_version = 0; - - mutex_lock(&t->mutex); - new_count = t->etm_regs_count + 1; - new_regs = krealloc(t->etm_regs, - sizeof(t->etm_regs[0]) * new_count, GFP_KERNEL); - - if (!new_regs) { - dev_dbg(&dev->dev, "Failed to allocate ETM register array\n"); - ret = -ENOMEM; - goto out; - } - t->etm_regs = new_regs; - - ret = amba_request_regions(dev, NULL); - if (ret) - goto out; - - t->etm_regs[t->etm_regs_count] = - ioremap_nocache(dev->res.start, resource_size(&dev->res)); - if (!t->etm_regs[t->etm_regs_count]) { - ret = -ENOMEM; - goto out_release; - } - - amba_set_drvdata(dev, t->etm_regs[t->etm_regs_count]); - - t->flags = TRACER_CYCLE_ACC | TRACER_TRACE_DATA | TRACER_BRANCHOUTPUT; - t->etm_portsz = 1; - t->etm_contextid_size = 3; - - etm_unlock(t, t->etm_regs_count); - (void)etm_readl(t, t->etm_regs_count, ETMMR_PDSR); - /* dummy first read */ - (void)etm_readl(&tracer, t->etm_regs_count, ETMMR_OSSRR); - - etmccr = etm_readl(t, t->etm_regs_count, ETMR_CONFCODE); - t->ncmppairs = etmccr & 0xf; - if (etmccr & ETMCCR_ETMIDR_PRESENT) { - etmidr = etm_readl(t, t->etm_regs_count, ETMR_ID); - etm_version = ETMIDR_VERSION(etmidr); - if (etm_version >= ETMIDR_VERSION_3_1) - etmccer = etm_readl(t, t->etm_regs_count, ETMR_CCE); - } - etm_writel(t, t->etm_regs_count, 0x441, ETMR_CTRL); - etm_writel(t, t->etm_regs_count, new_count, ETMR_TRACEIDR); - etm_lock(t, t->etm_regs_count); - - ret = sysfs_create_file(&dev->dev.kobj, - &trace_running_attr.attr); - if (ret) - goto out_unmap; - - /* failing to create any of these two is not fatal */ - ret = sysfs_create_file(&dev->dev.kobj, &trace_info_attr.attr); - if (ret) - dev_dbg(&dev->dev, "Failed to create trace_info in sysfs\n"); - - ret = sysfs_create_file(&dev->dev.kobj, &trace_mode_attr.attr); - if (ret) - dev_dbg(&dev->dev, "Failed to create trace_mode in sysfs\n"); - - ret = sysfs_create_file(&dev->dev.kobj, - &trace_contextid_size_attr.attr); - if (ret) - dev_dbg(&dev->dev, - "Failed to create trace_contextid_size in sysfs\n"); - - ret = sysfs_create_file(&dev->dev.kobj, - &trace_branch_output_attr.attr); - if (ret) - dev_dbg(&dev->dev, - "Failed to create trace_branch_output in sysfs\n"); - - if (etmccer & ETMCCER_RETURN_STACK_IMPLEMENTED) { - ret = sysfs_create_file(&dev->dev.kobj, - &trace_return_stack_attr.attr); - if (ret) - dev_dbg(&dev->dev, - "Failed to create trace_return_stack in sysfs\n"); - } - - if (etmccer & ETMCCER_TIMESTAMPING_IMPLEMENTED) { - ret = sysfs_create_file(&dev->dev.kobj, - &trace_timestamp_attr.attr); - if (ret) - dev_dbg(&dev->dev, - "Failed to create trace_timestamp in sysfs\n"); - } - - ret = sysfs_create_file(&dev->dev.kobj, &trace_range_attr.attr); - if (ret) - dev_dbg(&dev->dev, "Failed to create trace_range in sysfs\n"); - - if (etm_version < ETMIDR_VERSION_PFT_1_0) { - ret = sysfs_create_file(&dev->dev.kobj, - &trace_data_range_attr.attr); - if (ret) - dev_dbg(&dev->dev, - "Failed to create trace_data_range in sysfs\n"); - } else { - tracer.flags &= ~TRACER_TRACE_DATA; - } - - dev_dbg(&dev->dev, "ETM AMBA driver initialized.\n"); - - /* Enable formatter if there are multiple trace sources */ - if (new_count > 1) - t->etb_fc = ETBFF_ENFCONT | ETBFF_ENFTC; - - t->etm_regs_count = new_count; - -out: - mutex_unlock(&t->mutex); - return ret; - -out_unmap: - amba_set_drvdata(dev, NULL); - iounmap(t->etm_regs[t->etm_regs_count]); - -out_release: - amba_release_regions(dev); - - mutex_unlock(&t->mutex); - return ret; -} - -static int etm_remove(struct amba_device *dev) -{ - int i; - struct tracectx *t = &tracer; - void __iomem *etm_regs = amba_get_drvdata(dev); - - sysfs_remove_file(&dev->dev.kobj, &trace_running_attr.attr); - sysfs_remove_file(&dev->dev.kobj, &trace_info_attr.attr); - sysfs_remove_file(&dev->dev.kobj, &trace_mode_attr.attr); - sysfs_remove_file(&dev->dev.kobj, &trace_range_attr.attr); - sysfs_remove_file(&dev->dev.kobj, &trace_data_range_attr.attr); - - amba_set_drvdata(dev, NULL); - - mutex_lock(&t->mutex); - for (i = 0; i < t->etm_regs_count; i++) - if (t->etm_regs[i] == etm_regs) - break; - for (; i < t->etm_regs_count - 1; i++) - t->etm_regs[i] = t->etm_regs[i + 1]; - t->etm_regs_count--; - if (!t->etm_regs_count) { - kfree(t->etm_regs); - t->etm_regs = NULL; - } - mutex_unlock(&t->mutex); - - iounmap(etm_regs); - amba_release_regions(dev); - - return 0; -} - -static struct amba_id etm_ids[] = { - { - .id = 0x0003b921, - .mask = 0x0007ffff, - }, - { - .id = 0x0003b950, - .mask = 0x0007ffff, - }, - { 0, 0 }, -}; - -static struct amba_driver etm_driver = { - .drv = { - .name = "etm", - .owner = THIS_MODULE, - }, - .probe = etm_probe, - .remove = etm_remove, - .id_table = etm_ids, -}; - -static int __init etm_init(void) -{ - int retval; - - mutex_init(&tracer.mutex); - - retval = amba_driver_register(&etb_driver); - if (retval) { - printk(KERN_ERR "Failed to register etb\n"); - return retval; - } - - retval = amba_driver_register(&etm_driver); - if (retval) { - amba_driver_unregister(&etb_driver); - printk(KERN_ERR "Failed to probe etm\n"); - return retval; - } - - /* not being able to install this handler is not fatal */ - (void)register_sysrq_key('v', &sysrq_etm_op); - - return 0; -} - -device_initcall(etm_init); - diff --git a/ANDROID_3.4.5/arch/arm/kernel/fiq.c b/ANDROID_3.4.5/arch/arm/kernel/fiq.c deleted file mode 100644 index c32f8456..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/fiq.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * linux/arch/arm/kernel/fiq.c - * - * Copyright (C) 1998 Russell King - * Copyright (C) 1998, 1999 Phil Blundell - * - * FIQ support written by Philip Blundell <philb@gnu.org>, 1998. - * - * FIQ support re-written by Russell King to be more generic - * - * We now properly support a method by which the FIQ handlers can - * be stacked onto the vector. We still do not support sharing - * the FIQ vector itself. - * - * Operation is as follows: - * 1. Owner A claims FIQ: - * - default_fiq relinquishes control. - * 2. Owner A: - * - inserts code. - * - sets any registers, - * - enables FIQ. - * 3. Owner B claims FIQ: - * - if owner A has a relinquish function. - * - disable FIQs. - * - saves any registers. - * - returns zero. - * 4. Owner B: - * - inserts code. - * - sets any registers, - * - enables FIQ. - * 5. Owner B releases FIQ: - * - Owner A is asked to reacquire FIQ: - * - inserts code. - * - restores saved registers. - * - enables FIQ. - * 6. Goto 3 - */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/seq_file.h> - -#include <asm/cacheflush.h> -#include <asm/cp15.h> -#include <asm/fiq.h> -#include <asm/irq.h> -#include <asm/traps.h> - -static unsigned long no_fiq_insn; - -/* Default reacquire function - * - we always relinquish FIQ control - * - we always reacquire FIQ control - */ -static int fiq_def_op(void *ref, int relinquish) -{ - if (!relinquish) - set_fiq_handler(&no_fiq_insn, sizeof(no_fiq_insn)); - - return 0; -} - -static struct fiq_handler default_owner = { - .name = "default", - .fiq_op = fiq_def_op, -}; - -static struct fiq_handler *current_fiq = &default_owner; - -int show_fiq_list(struct seq_file *p, int prec) -{ - if (current_fiq != &default_owner) - seq_printf(p, "%*s: %s\n", prec, "FIQ", - current_fiq->name); - - return 0; -} - -void set_fiq_handler(void *start, unsigned int length) -{ -#if defined(CONFIG_CPU_USE_DOMAINS) - memcpy((void *)0xffff001c, start, length); -#else - memcpy(vectors_page + 0x1c, start, length); -#endif - flush_icache_range(0xffff001c, 0xffff001c + length); - if (!vectors_high()) - flush_icache_range(0x1c, 0x1c + length); -} - -int claim_fiq(struct fiq_handler *f) -{ - int ret = 0; - - if (current_fiq) { - ret = -EBUSY; - - if (current_fiq->fiq_op != NULL) - ret = current_fiq->fiq_op(current_fiq->dev_id, 1); - } - - if (!ret) { - f->next = current_fiq; - current_fiq = f; - } - - return ret; -} - -void release_fiq(struct fiq_handler *f) -{ - if (current_fiq != f) { - printk(KERN_ERR "%s FIQ trying to release %s FIQ\n", - f->name, current_fiq->name); - dump_stack(); - return; - } - - do - current_fiq = current_fiq->next; - while (current_fiq->fiq_op(current_fiq->dev_id, 0)); -} - -void enable_fiq(int fiq) -{ - enable_irq(fiq + FIQ_START); -} - -void disable_fiq(int fiq) -{ - disable_irq(fiq + FIQ_START); -} - -EXPORT_SYMBOL(set_fiq_handler); -EXPORT_SYMBOL(__set_fiq_regs); /* defined in fiqasm.S */ -EXPORT_SYMBOL(__get_fiq_regs); /* defined in fiqasm.S */ -EXPORT_SYMBOL(claim_fiq); -EXPORT_SYMBOL(release_fiq); -EXPORT_SYMBOL(enable_fiq); -EXPORT_SYMBOL(disable_fiq); - -void __init init_FIQ(void) -{ - no_fiq_insn = *(unsigned long *)0xffff001c; -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/fiqasm.S b/ANDROID_3.4.5/arch/arm/kernel/fiqasm.S deleted file mode 100644 index 207f9d65..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/fiqasm.S +++ /dev/null @@ -1,49 +0,0 @@ -/* - * linux/arch/arm/kernel/fiqasm.S - * - * Derived from code originally in linux/arch/arm/kernel/fiq.c: - * - * Copyright (C) 1998 Russell King - * Copyright (C) 1998, 1999 Phil Blundell - * Copyright (C) 2011, Linaro Limited - * - * FIQ support written by Philip Blundell <philb@gnu.org>, 1998. - * - * FIQ support re-written by Russell King to be more generic - * - * v7/Thumb-2 compatibility modifications by Linaro Limited, 2011. - */ - -#include <linux/linkage.h> -#include <asm/assembler.h> - -/* - * Taking an interrupt in FIQ mode is death, so both these functions - * disable irqs for the duration. - */ - -ENTRY(__set_fiq_regs) - mov r2, #PSR_I_BIT | PSR_F_BIT | FIQ_MODE - mrs r1, cpsr - msr cpsr_c, r2 @ select FIQ mode - mov r0, r0 @ avoid hazard prior to ARMv4 - ldmia r0!, {r8 - r12} - ldr sp, [r0], #4 - ldr lr, [r0] - msr cpsr_c, r1 @ return to SVC mode - mov r0, r0 @ avoid hazard prior to ARMv4 - mov pc, lr -ENDPROC(__set_fiq_regs) - -ENTRY(__get_fiq_regs) - mov r2, #PSR_I_BIT | PSR_F_BIT | FIQ_MODE - mrs r1, cpsr - msr cpsr_c, r2 @ select FIQ mode - mov r0, r0 @ avoid hazard prior to ARMv4 - stmia r0!, {r8 - r12} - str sp, [r0], #4 - str lr, [r0] - msr cpsr_c, r1 @ return to SVC mode - mov r0, r0 @ avoid hazard prior to ARMv4 - mov pc, lr -ENDPROC(__get_fiq_regs) diff --git a/ANDROID_3.4.5/arch/arm/kernel/ftrace.c b/ANDROID_3.4.5/arch/arm/kernel/ftrace.c deleted file mode 100644 index 6a740a93..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/ftrace.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Dynamic function tracing support. - * - * Copyright (C) 2008 Abhishek Sagar <sagar.abhishek@gmail.com> - * Copyright (C) 2010 Rabin Vincent <rabin@rab.in> - * - * For licencing details, see COPYING. - * - * Defines low-level handling of mcount calls when the kernel - * is compiled with the -pg flag. When using dynamic ftrace, the - * mcount call-sites get patched with NOP till they are enabled. - * All code mutation routines here are called under stop_machine(). - */ - -#include <linux/ftrace.h> -#include <linux/module.h> -#include <linux/uaccess.h> - -#include <asm/cacheflush.h> -#include <asm/opcodes.h> -#include <asm/ftrace.h> - -#include "insn.h" - -#ifdef CONFIG_THUMB2_KERNEL -#define NOP 0xf85deb04 /* pop.w {lr} */ -#else -#define NOP 0xe8bd4000 /* pop {lr} */ -#endif - -#ifdef CONFIG_DYNAMIC_FTRACE -#ifdef CONFIG_OLD_MCOUNT -#define OLD_MCOUNT_ADDR ((unsigned long) mcount) -#define OLD_FTRACE_ADDR ((unsigned long) ftrace_caller_old) - -#define OLD_NOP 0xe1a00000 /* mov r0, r0 */ - -static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec) -{ - return rec->arch.old_mcount ? OLD_NOP : NOP; -} - -static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr) -{ - if (!rec->arch.old_mcount) - return addr; - - if (addr == MCOUNT_ADDR) - addr = OLD_MCOUNT_ADDR; - else if (addr == FTRACE_ADDR) - addr = OLD_FTRACE_ADDR; - - return addr; -} -#else -static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec) -{ - return NOP; -} - -static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr) -{ - return addr; -} -#endif - -int ftrace_arch_code_modify_prepare(void) -{ - set_kernel_text_rw(); - set_all_modules_text_rw(); - return 0; -} - -int ftrace_arch_code_modify_post_process(void) -{ - set_all_modules_text_ro(); - set_kernel_text_ro(); - return 0; -} - -static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr) -{ - return arm_gen_branch_link(pc, addr); -} - -static int ftrace_modify_code(unsigned long pc, unsigned long old, - unsigned long new, bool validate) -{ - unsigned long replaced; - - if (IS_ENABLED(CONFIG_THUMB2_KERNEL)) { - old = __opcode_to_mem_thumb32(old); - new = __opcode_to_mem_thumb32(new); - } else { - old = __opcode_to_mem_arm(old); - new = __opcode_to_mem_arm(new); - } - - if (validate) { - if (probe_kernel_read(&replaced, (void *)pc, MCOUNT_INSN_SIZE)) - return -EFAULT; - - if (replaced != old) - return -EINVAL; - } - - if (probe_kernel_write((void *)pc, &new, MCOUNT_INSN_SIZE)) - return -EPERM; - - flush_icache_range(pc, pc + MCOUNT_INSN_SIZE); - - return 0; -} - -int ftrace_update_ftrace_func(ftrace_func_t func) -{ - unsigned long pc; - unsigned long new; - int ret; - - pc = (unsigned long)&ftrace_call; - new = ftrace_call_replace(pc, (unsigned long)func); - - ret = ftrace_modify_code(pc, 0, new, false); - -#ifdef CONFIG_OLD_MCOUNT - if (!ret) { - pc = (unsigned long)&ftrace_call_old; - new = ftrace_call_replace(pc, (unsigned long)func); - - ret = ftrace_modify_code(pc, 0, new, false); - } -#endif - - return ret; -} - -int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) -{ - unsigned long new, old; - unsigned long ip = rec->ip; - - old = ftrace_nop_replace(rec); - new = ftrace_call_replace(ip, adjust_address(rec, addr)); - - return ftrace_modify_code(rec->ip, old, new, true); -} - -int ftrace_make_nop(struct module *mod, - struct dyn_ftrace *rec, unsigned long addr) -{ - unsigned long ip = rec->ip; - unsigned long old; - unsigned long new; - int ret; - - old = ftrace_call_replace(ip, adjust_address(rec, addr)); - new = ftrace_nop_replace(rec); - ret = ftrace_modify_code(ip, old, new, true); - -#ifdef CONFIG_OLD_MCOUNT - if (ret == -EINVAL && addr == MCOUNT_ADDR) { - rec->arch.old_mcount = true; - - old = ftrace_call_replace(ip, adjust_address(rec, addr)); - new = ftrace_nop_replace(rec); - ret = ftrace_modify_code(ip, old, new, true); - } -#endif - - return ret; -} - -int __init ftrace_dyn_arch_init(void *data) -{ - *(unsigned long *)data = 0; - - return 0; -} -#endif /* CONFIG_DYNAMIC_FTRACE */ - -#ifdef CONFIG_FUNCTION_GRAPH_TRACER -void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, - unsigned long frame_pointer) -{ - unsigned long return_hooker = (unsigned long) &return_to_handler; - struct ftrace_graph_ent trace; - unsigned long old; - int err; - - if (unlikely(atomic_read(¤t->tracing_graph_pause))) - return; - - old = *parent; - *parent = return_hooker; - - trace.func = self_addr; - trace.depth = current->curr_ret_stack + 1; - - /* Only trace if the calling function expects to */ - if (!ftrace_graph_entry(&trace)) { - *parent = old; - return; - } - - err = ftrace_push_return_trace(old, self_addr, &trace.depth, - frame_pointer); - if (err == -EBUSY) { - *parent = old; - return; - } -} - -#ifdef CONFIG_DYNAMIC_FTRACE -extern unsigned long ftrace_graph_call; -extern unsigned long ftrace_graph_call_old; -extern void ftrace_graph_caller_old(void); - -static int __ftrace_modify_caller(unsigned long *callsite, - void (*func) (void), bool enable) -{ - unsigned long caller_fn = (unsigned long) func; - unsigned long pc = (unsigned long) callsite; - unsigned long branch = arm_gen_branch(pc, caller_fn); - unsigned long nop = 0xe1a00000; /* mov r0, r0 */ - unsigned long old = enable ? nop : branch; - unsigned long new = enable ? branch : nop; - - return ftrace_modify_code(pc, old, new, true); -} - -static int ftrace_modify_graph_caller(bool enable) -{ - int ret; - - ret = __ftrace_modify_caller(&ftrace_graph_call, - ftrace_graph_caller, - enable); - -#ifdef CONFIG_OLD_MCOUNT - if (!ret) - ret = __ftrace_modify_caller(&ftrace_graph_call_old, - ftrace_graph_caller_old, - enable); -#endif - - return ret; -} - -int ftrace_enable_ftrace_graph_caller(void) -{ - return ftrace_modify_graph_caller(true); -} - -int ftrace_disable_ftrace_graph_caller(void) -{ - return ftrace_modify_graph_caller(false); -} -#endif /* CONFIG_DYNAMIC_FTRACE */ -#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ diff --git a/ANDROID_3.4.5/arch/arm/kernel/head-common.S b/ANDROID_3.4.5/arch/arm/kernel/head-common.S deleted file mode 100644 index 854bd223..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/head-common.S +++ /dev/null @@ -1,204 +0,0 @@ -/* - * linux/arch/arm/kernel/head-common.S - * - * Copyright (C) 1994-2002 Russell King - * Copyright (c) 2003 ARM Limited - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#define ATAG_CORE 0x54410001 -#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2) -#define ATAG_CORE_SIZE_EMPTY ((2*4) >> 2) - -#ifdef CONFIG_CPU_BIG_ENDIAN -#define OF_DT_MAGIC 0xd00dfeed -#else -#define OF_DT_MAGIC 0xedfe0dd0 /* 0xd00dfeed in big-endian */ -#endif - -/* - * Exception handling. Something went wrong and we can't proceed. We - * ought to tell the user, but since we don't have any guarantee that - * we're even running on the right architecture, we do virtually nothing. - * - * If CONFIG_DEBUG_LL is set we try to print out something about the error - * and hope for the best (useful if bootloader fails to pass a proper - * machine ID for example). - */ - __HEAD - -/* Determine validity of the r2 atags pointer. The heuristic requires - * that the pointer be aligned, in the first 16k of physical RAM and - * that the ATAG_CORE marker is first and present. If CONFIG_OF_FLATTREE - * is selected, then it will also accept a dtb pointer. Future revisions - * of this function may be more lenient with the physical address and - * may also be able to move the ATAGS block if necessary. - * - * Returns: - * r2 either valid atags pointer, valid dtb pointer, or zero - * r5, r6 corrupted - */ -__vet_atags: - tst r2, #0x3 @ aligned? - bne 1f - - ldr r5, [r2, #0] -#ifdef CONFIG_OF_FLATTREE - ldr r6, =OF_DT_MAGIC @ is it a DTB? - cmp r5, r6 - beq 2f -#endif - cmp r5, #ATAG_CORE_SIZE @ is first tag ATAG_CORE? - cmpne r5, #ATAG_CORE_SIZE_EMPTY - bne 1f - ldr r5, [r2, #4] - ldr r6, =ATAG_CORE - cmp r5, r6 - bne 1f - -2: mov pc, lr @ atag/dtb pointer is ok - -1: mov r2, #0 - mov pc, lr -ENDPROC(__vet_atags) - -/* - * The following fragment of code is executed with the MMU on in MMU mode, - * and uses absolute addresses; this is not position independent. - * - * r0 = cp#15 control register - * r1 = machine ID - * r2 = atags/dtb pointer - * r9 = processor ID - */ - __INIT -__mmap_switched: - adr r3, __mmap_switched_data - - ldmia r3!, {r4, r5, r6, r7} - cmp r4, r5 @ Copy data segment if needed -1: cmpne r5, r6 - ldrne fp, [r4], #4 - strne fp, [r5], #4 - bne 1b - - mov fp, #0 @ Clear BSS (and zero fp) -1: cmp r6, r7 - strcc fp, [r6],#4 - bcc 1b - - ARM( ldmia r3, {r4, r5, r6, r7, sp}) - THUMB( ldmia r3, {r4, r5, r6, r7} ) - THUMB( ldr sp, [r3, #16] ) - str r9, [r4] @ Save processor ID - str r1, [r5] @ Save machine type - str r2, [r6] @ Save atags pointer - bic r4, r0, #CR_A @ Clear 'A' bit - stmia r7, {r0, r4} @ Save control register values - b start_kernel -ENDPROC(__mmap_switched) - - .align 2 - .type __mmap_switched_data, %object -__mmap_switched_data: - .long __data_loc @ r4 - .long _sdata @ r5 - .long __bss_start @ r6 - .long _end @ r7 - .long processor_id @ r4 - .long __machine_arch_type @ r5 - .long __atags_pointer @ r6 - .long cr_alignment @ r7 - .long init_thread_union + THREAD_START_SP @ sp - .size __mmap_switched_data, . - __mmap_switched_data - -/* - * This provides a C-API version of __lookup_processor_type - */ -ENTRY(lookup_processor_type) - stmfd sp!, {r4 - r6, r9, lr} - mov r9, r0 - bl __lookup_processor_type - mov r0, r5 - ldmfd sp!, {r4 - r6, r9, pc} -ENDPROC(lookup_processor_type) - -/* - * Read processor ID register (CP#15, CR0), and look up in the linker-built - * supported processor list. Note that we can't use the absolute addresses - * for the __proc_info lists since we aren't running with the MMU on - * (and therefore, we are not in the correct address space). We have to - * calculate the offset. - * - * r9 = cpuid - * Returns: - * r3, r4, r6 corrupted - * r5 = proc_info pointer in physical address space - * r9 = cpuid (preserved) - */ - __CPUINIT -__lookup_processor_type: - adr r3, __lookup_processor_type_data - ldmia r3, {r4 - r6} - sub r3, r3, r4 @ get offset between virt&phys - add r5, r5, r3 @ convert virt addresses to - add r6, r6, r3 @ physical address space -1: ldmia r5, {r3, r4} @ value, mask - and r4, r4, r9 @ mask wanted bits - teq r3, r4 - beq 2f - add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list) - cmp r5, r6 - blo 1b - mov r5, #0 @ unknown processor -2: mov pc, lr -ENDPROC(__lookup_processor_type) - -/* - * Look in <asm/procinfo.h> for information about the __proc_info structure. - */ - .align 2 - .type __lookup_processor_type_data, %object -__lookup_processor_type_data: - .long . - .long __proc_info_begin - .long __proc_info_end - .size __lookup_processor_type_data, . - __lookup_processor_type_data - -__error_p: -#ifdef CONFIG_DEBUG_LL - adr r0, str_p1 - bl printascii - mov r0, r9 - bl printhex8 - adr r0, str_p2 - bl printascii - b __error -str_p1: .asciz "\nError: unrecognized/unsupported processor variant (0x" -str_p2: .asciz ").\n" - .align -#endif -ENDPROC(__error_p) - -__error: -#ifdef CONFIG_ARCH_RPC -/* - * Turn the screen red on a error - RiscPC only. - */ - mov r0, #0x02000000 - mov r3, #0x11 - orr r3, r3, r3, lsl #8 - orr r3, r3, r3, lsl #16 - str r3, [r0], #4 - str r3, [r0], #4 - str r3, [r0], #4 - str r3, [r0], #4 -#endif -1: mov r0, r0 - b 1b -ENDPROC(__error) diff --git a/ANDROID_3.4.5/arch/arm/kernel/head-nommu.S b/ANDROID_3.4.5/arch/arm/kernel/head-nommu.S deleted file mode 100644 index 278cfc14..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/head-nommu.S +++ /dev/null @@ -1,98 +0,0 @@ -/* - * linux/arch/arm/kernel/head-nommu.S - * - * Copyright (C) 1994-2002 Russell King - * Copyright (C) 2003-2006 Hyok S. Choi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Common kernel startup code (non-paged MM) - * - */ -#include <linux/linkage.h> -#include <linux/init.h> - -#include <asm/assembler.h> -#include <asm/ptrace.h> -#include <asm/asm-offsets.h> -#include <asm/cp15.h> -#include <asm/thread_info.h> - -/* - * Kernel startup entry point. - * --------------------------- - * - * This is normally called from the decompressor code. The requirements - * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0, - * r1 = machine nr. - * - * See linux/arch/arm/tools/mach-types for the complete list of machine - * numbers for r1. - * - */ - .arm - - __HEAD -ENTRY(stext) - - THUMB( adr r9, BSYM(1f) ) @ Kernel is always entered in ARM. - THUMB( bx r9 ) @ If this is a Thumb-2 kernel, - THUMB( .thumb ) @ switch to Thumb now. - THUMB(1: ) - - setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode - @ and irqs disabled -#ifndef CONFIG_CPU_CP15 - ldr r9, =CONFIG_PROCESSOR_ID -#else - mrc p15, 0, r9, c0, c0 @ get processor id -#endif - bl __lookup_processor_type @ r5=procinfo r9=cpuid - movs r10, r5 @ invalid processor (r5=0)? - beq __error_p @ yes, error 'p' - - adr lr, BSYM(__after_proc_init) @ return (PIC) address - ARM( add pc, r10, #PROCINFO_INITFUNC ) - THUMB( add r12, r10, #PROCINFO_INITFUNC ) - THUMB( mov pc, r12 ) -ENDPROC(stext) - -/* - * Set the Control Register and Read the process ID. - */ -__after_proc_init: -#ifdef CONFIG_CPU_CP15 - /* - * CP15 system control register value returned in r0 from - * the CPU init function. - */ -#ifdef CONFIG_ALIGNMENT_TRAP - orr r0, r0, #CR_A -#else - bic r0, r0, #CR_A -#endif -#ifdef CONFIG_CPU_DCACHE_DISABLE - bic r0, r0, #CR_C -#endif -#ifdef CONFIG_CPU_BPREDICT_DISABLE - bic r0, r0, #CR_Z -#endif -#ifdef CONFIG_CPU_ICACHE_DISABLE - bic r0, r0, #CR_I -#endif -#ifdef CONFIG_CPU_HIGH_VECTOR - orr r0, r0, #CR_V -#else - bic r0, r0, #CR_V -#endif - mcr p15, 0, r0, c1, c0, 0 @ write control reg -#endif /* CONFIG_CPU_CP15 */ - - b __mmap_switched @ clear the BSS and jump - @ to start_kernel -ENDPROC(__after_proc_init) - .ltorg - -#include "head-common.S" diff --git a/ANDROID_3.4.5/arch/arm/kernel/head.S b/ANDROID_3.4.5/arch/arm/kernel/head.S deleted file mode 100644 index 3bf0c7f8..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/head.S +++ /dev/null @@ -1,622 +0,0 @@ -/* - * linux/arch/arm/kernel/head.S - * - * Copyright (C) 1994-2002 Russell King - * Copyright (c) 2003 ARM Limited - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Kernel startup code for all 32-bit CPUs - */ -#include <linux/linkage.h> -#include <linux/init.h> - -#include <asm/assembler.h> -#include <asm/cp15.h> -#include <asm/domain.h> -#include <asm/ptrace.h> -#include <asm/asm-offsets.h> -#include <asm/memory.h> -#include <asm/thread_info.h> -#include <asm/pgtable.h> - -#ifdef CONFIG_DEBUG_LL -#include <mach/debug-macro.S> -#endif - -/* - * swapper_pg_dir is the virtual address of the initial page table. - * We place the page tables 16K below KERNEL_RAM_VADDR. Therefore, we must - * make sure that KERNEL_RAM_VADDR is correctly set. Currently, we expect - * the least significant 16 bits to be 0x8000, but we could probably - * relax this restriction to KERNEL_RAM_VADDR >= PAGE_OFFSET + 0x4000. - */ -#define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) -#if (KERNEL_RAM_VADDR & 0xffff) != 0x8000 -#error KERNEL_RAM_VADDR must start at 0xXXXX8000 -#endif - -#ifdef CONFIG_ARM_LPAE - /* LPAE requires an additional page for the PGD */ -#define PG_DIR_SIZE 0x5000 -#define PMD_ORDER 3 -#else -#define PG_DIR_SIZE 0x4000 -#define PMD_ORDER 2 -#endif - - .globl swapper_pg_dir - .equ swapper_pg_dir, KERNEL_RAM_VADDR - PG_DIR_SIZE - - .macro pgtbl, rd, phys - add \rd, \phys, #TEXT_OFFSET - PG_DIR_SIZE - .endm - -#ifdef CONFIG_XIP_KERNEL -#define KERNEL_START XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) -#define KERNEL_END _edata_loc -#else -#define KERNEL_START KERNEL_RAM_VADDR -#define KERNEL_END _end -#endif - -/* - * Kernel startup entry point. - * --------------------------- - * - * This is normally called from the decompressor code. The requirements - * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0, - * r1 = machine nr, r2 = atags or dtb pointer. - * - * This code is mostly position independent, so if you link the kernel at - * 0xc0008000, you call this at __pa(0xc0008000). - * - * See linux/arch/arm/tools/mach-types for the complete list of machine - * numbers for r1. - * - * We're trying to keep crap to a minimum; DO NOT add any machine specific - * crap here - that's what the boot loader (or in extreme, well justified - * circumstances, zImage) is for. - */ - .arm - - __HEAD -ENTRY(stext) - - THUMB( adr r9, BSYM(1f) ) @ Kernel is always entered in ARM. - THUMB( bx r9 ) @ If this is a Thumb-2 kernel, - THUMB( .thumb ) @ switch to Thumb now. - THUMB(1: ) - - setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode - @ and irqs disabled - mrc p15, 0, r9, c0, c0 @ get processor id - bl __lookup_processor_type @ r5=procinfo r9=cpuid - movs r10, r5 @ invalid processor (r5=0)? - THUMB( it eq ) @ force fixup-able long branch encoding - beq __error_p @ yes, error 'p' - -#ifdef CONFIG_ARM_LPAE - mrc p15, 0, r3, c0, c1, 4 @ read ID_MMFR0 - and r3, r3, #0xf @ extract VMSA support - cmp r3, #5 @ long-descriptor translation table format? - THUMB( it lo ) @ force fixup-able long branch encoding - blo __error_p @ only classic page table format -#endif - -#ifndef CONFIG_XIP_KERNEL - adr r3, 2f - ldmia r3, {r4, r8} - sub r4, r3, r4 @ (PHYS_OFFSET - PAGE_OFFSET) - add r8, r8, r4 @ PHYS_OFFSET -#else - ldr r8, =PHYS_OFFSET @ always constant in this case -#endif - - /* - * r1 = machine no, r2 = atags or dtb, - * r8 = phys_offset, r9 = cpuid, r10 = procinfo - */ - bl __vet_atags -#ifdef CONFIG_SMP_ON_UP - bl __fixup_smp -#endif -#ifdef CONFIG_ARM_PATCH_PHYS_VIRT - bl __fixup_pv_table -#endif - bl __create_page_tables - - /* - * The following calls CPU specific code in a position independent - * manner. See arch/arm/mm/proc-*.S for details. r10 = base of - * xxx_proc_info structure selected by __lookup_processor_type - * above. On return, the CPU will be ready for the MMU to be - * turned on, and r0 will hold the CPU control register value. - */ - ldr r13, =__mmap_switched @ address to jump to after - @ mmu has been enabled - adr lr, BSYM(1f) @ return (PIC) address - mov r8, r4 @ set TTBR1 to swapper_pg_dir - ARM( add pc, r10, #PROCINFO_INITFUNC ) - THUMB( add r12, r10, #PROCINFO_INITFUNC ) - THUMB( mov pc, r12 ) -1: b __enable_mmu -ENDPROC(stext) - .ltorg -#ifndef CONFIG_XIP_KERNEL -2: .long . - .long PAGE_OFFSET -#endif - -/* - * Setup the initial page tables. We only setup the barest - * amount which are required to get the kernel running, which - * generally means mapping in the kernel code. - * - * r8 = phys_offset, r9 = cpuid, r10 = procinfo - * - * Returns: - * r0, r3, r5-r7 corrupted - * r4 = physical page table address - */ -__create_page_tables: - pgtbl r4, r8 @ page table address - - /* - * Clear the swapper page table - */ - mov r0, r4 - mov r3, #0 - add r6, r0, #PG_DIR_SIZE -1: str r3, [r0], #4 - str r3, [r0], #4 - str r3, [r0], #4 - str r3, [r0], #4 - teq r0, r6 - bne 1b - -#ifdef CONFIG_ARM_LPAE - /* - * Build the PGD table (first level) to point to the PMD table. A PGD - * entry is 64-bit wide. - */ - mov r0, r4 - add r3, r4, #0x1000 @ first PMD table address - orr r3, r3, #3 @ PGD block type - mov r6, #4 @ PTRS_PER_PGD - mov r7, #1 << (55 - 32) @ L_PGD_SWAPPER -1: str r3, [r0], #4 @ set bottom PGD entry bits - str r7, [r0], #4 @ set top PGD entry bits - add r3, r3, #0x1000 @ next PMD table - subs r6, r6, #1 - bne 1b - - add r4, r4, #0x1000 @ point to the PMD tables -#endif - - ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags - - /* - * Create identity mapping to cater for __enable_mmu. - * This identity mapping will be removed by paging_init(). - */ - adr r0, __turn_mmu_on_loc - ldmia r0, {r3, r5, r6} - sub r0, r0, r3 @ virt->phys offset - add r5, r5, r0 @ phys __turn_mmu_on - add r6, r6, r0 @ phys __turn_mmu_on_end - mov r5, r5, lsr #SECTION_SHIFT - mov r6, r6, lsr #SECTION_SHIFT - -1: orr r3, r7, r5, lsl #SECTION_SHIFT @ flags + kernel base - str r3, [r4, r5, lsl #PMD_ORDER] @ identity mapping - cmp r5, r6 - addlo r5, r5, #1 @ next section - blo 1b - - /* - * Now setup the pagetables for our kernel direct - * mapped region. - */ - mov r3, pc - mov r3, r3, lsr #SECTION_SHIFT - orr r3, r7, r3, lsl #SECTION_SHIFT - add r0, r4, #(KERNEL_START & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER) - str r3, [r0, #((KERNEL_START & 0x00f00000) >> SECTION_SHIFT) << PMD_ORDER]! - ldr r6, =(KERNEL_END - 1) - add r0, r0, #1 << PMD_ORDER - add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER) -1: cmp r0, r6 - add r3, r3, #1 << SECTION_SHIFT - strls r3, [r0], #1 << PMD_ORDER - bls 1b - -#ifdef CONFIG_XIP_KERNEL - /* - * Map some ram to cover our .data and .bss areas. - */ - add r3, r8, #TEXT_OFFSET - orr r3, r3, r7 - add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER) - str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> (SECTION_SHIFT - PMD_ORDER)]! - ldr r6, =(_end - 1) - add r0, r0, #4 - add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER) -1: cmp r0, r6 - add r3, r3, #1 << 20 - strls r3, [r0], #4 - bls 1b -#endif - - /* - * Then map boot params address in r2 or the first 1MB (2MB with LPAE) - * of ram if boot params address is not specified. - */ - mov r0, r2, lsr #SECTION_SHIFT - movs r0, r0, lsl #SECTION_SHIFT - moveq r0, r8 - sub r3, r0, r8 - add r3, r3, #PAGE_OFFSET - add r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER) - orr r6, r7, r0 - str r6, [r3] - -#ifdef CONFIG_DEBUG_LL -#if !defined(CONFIG_DEBUG_ICEDCC) && !defined(CONFIG_DEBUG_SEMIHOSTING) - /* - * Map in IO space for serial debugging. - * This allows debug messages to be output - * via a serial console before paging_init. - */ - addruart r7, r3, r0 - - mov r3, r3, lsr #SECTION_SHIFT - mov r3, r3, lsl #PMD_ORDER - - add r0, r4, r3 - rsb r3, r3, #0x4000 @ PTRS_PER_PGD*sizeof(long) - cmp r3, #0x0800 @ limit to 512MB - movhi r3, #0x0800 - add r6, r0, r3 - mov r3, r7, lsr #SECTION_SHIFT - ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags - orr r3, r7, r3, lsl #SECTION_SHIFT -#ifdef CONFIG_ARM_LPAE - mov r7, #1 << (54 - 32) @ XN -#else - orr r3, r3, #PMD_SECT_XN -#endif -1: str r3, [r0], #4 -#ifdef CONFIG_ARM_LPAE - str r7, [r0], #4 -#endif - add r3, r3, #1 << SECTION_SHIFT - cmp r0, r6 - blo 1b - -#else /* CONFIG_DEBUG_ICEDCC || CONFIG_DEBUG_SEMIHOSTING */ - /* we don't need any serial debugging mappings */ - ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags -#endif - -#if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS) - /* - * If we're using the NetWinder or CATS, we also need to map - * in the 16550-type serial port for the debug messages - */ - add r0, r4, #0xff000000 >> (SECTION_SHIFT - PMD_ORDER) - orr r3, r7, #0x7c000000 - str r3, [r0] -#endif -#ifdef CONFIG_ARCH_RPC - /* - * Map in screen at 0x02000000 & SCREEN2_BASE - * Similar reasons here - for debug. This is - * only for Acorn RiscPC architectures. - */ - add r0, r4, #0x02000000 >> (SECTION_SHIFT - PMD_ORDER) - orr r3, r7, #0x02000000 - str r3, [r0] - add r0, r4, #0xd8000000 >> (SECTION_SHIFT - PMD_ORDER) - str r3, [r0] -#endif -#endif -#ifdef CONFIG_ARM_LPAE - sub r4, r4, #0x1000 @ point to the PGD table -#endif - mov pc, lr -ENDPROC(__create_page_tables) - .ltorg - .align -__turn_mmu_on_loc: - .long . - .long __turn_mmu_on - .long __turn_mmu_on_end - -#if defined(CONFIG_SMP) - __CPUINIT -ENTRY(secondary_startup) - /* - * Common entry point for secondary CPUs. - * - * Ensure that we're in SVC mode, and IRQs are disabled. Lookup - * the processor type - there is no need to check the machine type - * as it has already been validated by the primary processor. - */ - setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 - mrc p15, 0, r9, c0, c0 @ get processor id - bl __lookup_processor_type - movs r10, r5 @ invalid processor? - moveq r0, #'p' @ yes, error 'p' - THUMB( it eq ) @ force fixup-able long branch encoding - beq __error_p - - /* - * Use the page tables supplied from __cpu_up. - */ - adr r4, __secondary_data - ldmia r4, {r5, r7, r12} @ address to jump to after - sub lr, r4, r5 @ mmu has been enabled - ldr r4, [r7, lr] @ get secondary_data.pgdir - add r7, r7, #4 - ldr r8, [r7, lr] @ get secondary_data.swapper_pg_dir - adr lr, BSYM(__enable_mmu) @ return address - mov r13, r12 @ __secondary_switched address - ARM( add pc, r10, #PROCINFO_INITFUNC ) @ initialise processor - @ (return control reg) - THUMB( add r12, r10, #PROCINFO_INITFUNC ) - THUMB( mov pc, r12 ) -ENDPROC(secondary_startup) - - /* - * r6 = &secondary_data - */ -ENTRY(__secondary_switched) - ldr sp, [r7, #4] @ get secondary_data.stack - mov fp, #0 - b secondary_start_kernel -ENDPROC(__secondary_switched) - - .align - - .type __secondary_data, %object -__secondary_data: - .long . - .long secondary_data - .long __secondary_switched -#endif /* defined(CONFIG_SMP) */ - - - -/* - * Setup common bits before finally enabling the MMU. Essentially - * this is just loading the page table pointer and domain access - * registers. - * - * r0 = cp#15 control register - * r1 = machine ID - * r2 = atags or dtb pointer - * r4 = page table pointer - * r9 = processor ID - * r13 = *virtual* address to jump to upon completion - */ -__enable_mmu: -#if defined(CONFIG_ALIGNMENT_TRAP) && __LINUX_ARM_ARCH__ < 6 - orr r0, r0, #CR_A -#else - bic r0, r0, #CR_A -#endif -#ifdef CONFIG_CPU_DCACHE_DISABLE - bic r0, r0, #CR_C -#endif -#ifdef CONFIG_CPU_BPREDICT_DISABLE - bic r0, r0, #CR_Z -#endif -#ifdef CONFIG_CPU_ICACHE_DISABLE - bic r0, r0, #CR_I -#endif -#ifdef CONFIG_ARM_LPAE - mov r5, #0 - mcrr p15, 0, r4, r5, c2 @ load TTBR0 -#else - mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \ - domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ - domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \ - domain_val(DOMAIN_IO, DOMAIN_CLIENT)) - mcr p15, 0, r5, c3, c0, 0 @ load domain access register - mcr p15, 0, r4, c2, c0, 0 @ load page table pointer -#endif - b __turn_mmu_on -ENDPROC(__enable_mmu) - -/* - * Enable the MMU. This completely changes the structure of the visible - * memory space. You will not be able to trace execution through this. - * If you have an enquiry about this, *please* check the linux-arm-kernel - * mailing list archives BEFORE sending another post to the list. - * - * r0 = cp#15 control register - * r1 = machine ID - * r2 = atags or dtb pointer - * r9 = processor ID - * r13 = *virtual* address to jump to upon completion - * - * other registers depend on the function called upon completion - */ - .align 5 - .pushsection .idmap.text, "ax" -ENTRY(__turn_mmu_on) - mov r0, r0 - instr_sync - mcr p15, 0, r0, c1, c0, 0 @ write control reg - mrc p15, 0, r3, c0, c0, 0 @ read id reg - instr_sync - mov r3, r3 - mov r3, r13 - mov pc, r3 -__turn_mmu_on_end: -ENDPROC(__turn_mmu_on) - .popsection - - -#ifdef CONFIG_SMP_ON_UP - __INIT -__fixup_smp: - and r3, r9, #0x000f0000 @ architecture version - teq r3, #0x000f0000 @ CPU ID supported? - bne __fixup_smp_on_up @ no, assume UP - - bic r3, r9, #0x00ff0000 - bic r3, r3, #0x0000000f @ mask 0xff00fff0 - mov r4, #0x41000000 - orr r4, r4, #0x0000b000 - orr r4, r4, #0x00000020 @ val 0x4100b020 - teq r3, r4 @ ARM 11MPCore? - moveq pc, lr @ yes, assume SMP - - mrc p15, 0, r0, c0, c0, 5 @ read MPIDR - and r0, r0, #0xc0000000 @ multiprocessing extensions and - teq r0, #0x80000000 @ not part of a uniprocessor system? - moveq pc, lr @ yes, assume SMP - -__fixup_smp_on_up: - adr r0, 1f - ldmia r0, {r3 - r5} - sub r3, r0, r3 - add r4, r4, r3 - add r5, r5, r3 - b __do_fixup_smp_on_up -ENDPROC(__fixup_smp) - - .align -1: .word . - .word __smpalt_begin - .word __smpalt_end - - .pushsection .data - .globl smp_on_up -smp_on_up: - ALT_SMP(.long 1) - ALT_UP(.long 0) - .popsection -#endif - - .text -__do_fixup_smp_on_up: - cmp r4, r5 - movhs pc, lr - ldmia r4!, {r0, r6} - ARM( str r6, [r0, r3] ) - THUMB( add r0, r0, r3 ) -#ifdef __ARMEB__ - THUMB( mov r6, r6, ror #16 ) @ Convert word order for big-endian. -#endif - THUMB( strh r6, [r0], #2 ) @ For Thumb-2, store as two halfwords - THUMB( mov r6, r6, lsr #16 ) @ to be robust against misaligned r3. - THUMB( strh r6, [r0] ) - b __do_fixup_smp_on_up -ENDPROC(__do_fixup_smp_on_up) - -ENTRY(fixup_smp) - stmfd sp!, {r4 - r6, lr} - mov r4, r0 - add r5, r0, r1 - mov r3, #0 - bl __do_fixup_smp_on_up - ldmfd sp!, {r4 - r6, pc} -ENDPROC(fixup_smp) - -#ifdef CONFIG_ARM_PATCH_PHYS_VIRT - -/* __fixup_pv_table - patch the stub instructions with the delta between - * PHYS_OFFSET and PAGE_OFFSET, which is assumed to be 16MiB aligned and - * can be expressed by an immediate shifter operand. The stub instruction - * has a form of '(add|sub) rd, rn, #imm'. - */ - __HEAD -__fixup_pv_table: - adr r0, 1f - ldmia r0, {r3-r5, r7} - sub r3, r0, r3 @ PHYS_OFFSET - PAGE_OFFSET - add r4, r4, r3 @ adjust table start address - add r5, r5, r3 @ adjust table end address - add r7, r7, r3 @ adjust __pv_phys_offset address - str r8, [r7] @ save computed PHYS_OFFSET to __pv_phys_offset - mov r6, r3, lsr #24 @ constant for add/sub instructions - teq r3, r6, lsl #24 @ must be 16MiB aligned -THUMB( it ne @ cross section branch ) - bne __error - str r6, [r7, #4] @ save to __pv_offset - b __fixup_a_pv_table -ENDPROC(__fixup_pv_table) - - .align -1: .long . - .long __pv_table_begin - .long __pv_table_end -2: .long __pv_phys_offset - - .text -__fixup_a_pv_table: -#ifdef CONFIG_THUMB2_KERNEL - lsls r6, #24 - beq 2f - clz r7, r6 - lsr r6, #24 - lsl r6, r7 - bic r6, #0x0080 - lsrs r7, #1 - orrcs r6, #0x0080 - orr r6, r6, r7, lsl #12 - orr r6, #0x4000 - b 2f -1: add r7, r3 - ldrh ip, [r7, #2] - and ip, 0x8f00 - orr ip, r6 @ mask in offset bits 31-24 - strh ip, [r7, #2] -2: cmp r4, r5 - ldrcc r7, [r4], #4 @ use branch for delay slot - bcc 1b - bx lr -#else - b 2f -1: ldr ip, [r7, r3] - bic ip, ip, #0x000000ff - orr ip, ip, r6 @ mask in offset bits 31-24 - str ip, [r7, r3] -2: cmp r4, r5 - ldrcc r7, [r4], #4 @ use branch for delay slot - bcc 1b - mov pc, lr -#endif -ENDPROC(__fixup_a_pv_table) - -ENTRY(fixup_pv_table) - stmfd sp!, {r4 - r7, lr} - ldr r2, 2f @ get address of __pv_phys_offset - mov r3, #0 @ no offset - mov r4, r0 @ r0 = table start - add r5, r0, r1 @ r1 = table size - ldr r6, [r2, #4] @ get __pv_offset - bl __fixup_a_pv_table - ldmfd sp!, {r4 - r7, pc} -ENDPROC(fixup_pv_table) - - .align -2: .long __pv_phys_offset - - .data - .globl __pv_phys_offset - .type __pv_phys_offset, %object -__pv_phys_offset: - .long 0 - .size __pv_phys_offset, . - __pv_phys_offset -__pv_offset: - .long 0 -#endif - -#include "head-common.S" diff --git a/ANDROID_3.4.5/arch/arm/kernel/hibernate.c b/ANDROID_3.4.5/arch/arm/kernel/hibernate.c deleted file mode 100755 index 4aa1dc98..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/hibernate.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Hibernation support specific for ARM - * - * Derived from work on ARM hibernation support by: - * - * Ubuntu project, hibernation support for mach-dove - * Copyright (C) 2010 Nokia Corporation (Hiroshi Doyu) - * Copyright (C) 2010 Texas Instruments, Inc. (Teerth Reddy et al.) - * https://lkml.org/lkml/2010/6/18/4 - * https://lists.linux-foundation.org/pipermail/linux-pm/2010-June/027422.html - * https://patchwork.kernel.org/patch/96442/ - * - * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl> - * - * License terms: GNU General Public License (GPL) version 2 - */ -/* - from patch - ARM hibernation / suspend-to-disk - https://github.com/russdill/linux/commit/498079e0d06d2c0bd575ab4114d16b09e1ff3111 - add by roger. -*/ -#include <linux/mm.h> -#include <linux/suspend.h> -#include <asm/tlbflush.h> -#include <asm/cacheflush.h> -#include <asm/system_misc.h> -#include <linux/slab.h> -#include <linux/crc32.h> -#include <asm/idmap.h> -#include <asm/suspend.h> - -#define _PRINT_PAGE_CRC_ 1//also need to define in kernel/power/power.h -#undef _PRINT_PAGE_CRC_ - -extern const void __nosave_begin, __nosave_end; -extern void cpu_resume(void); -extern void cpu_resume_restore_nosave(void); - -u32 __nosave_backup_phys; //__nosave data backup here. -u32 __nosave_begin_phys; //__nosave data orginal location begin from here. -u32 __nosave_end_phys; //__nosave data orginal location end from here. - -void swsusp_arch_add_info(char *archdata, size_t size) -{ - *(u32 *) archdata = virt_to_phys(cpu_resume); - printk("\n phyaddr of cpu_resume : 0x%x \n", virt_to_phys(cpu_resume)); - *(((u32 *)archdata) + 1) = __nosave_backup_phys; - *(((u32 *)archdata) + 2) = __nosave_begin_phys; - *(((u32 *)archdata) + 3) = __nosave_end_phys; -/* - Save and check idmap_pgd. - When using Kernel restoring method, the "restoring kernel" should has the same - idmap_pgd as the "restored kernel". - If not, the mmu table may be corrupted during the restoration, - which may cause data abort (MMU translation fail). -*/ - *(((u32 *)archdata) + 4) = (u32)idmap_pgd; -} - -int pfn_is_nosave(unsigned long pfn) -{ - unsigned long nosave_begin_pfn = - __pa_symbol(&__nosave_begin) >> PAGE_SHIFT; - unsigned long nosave_end_pfn = - PAGE_ALIGN(__pa_symbol(&__nosave_end)) >> PAGE_SHIFT; - - return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn); -} - -void notrace save_processor_state(void) -{ - WARN_ON(num_online_cpus() != 1); - flush_thread(); - local_fiq_disable(); -} - -void notrace restore_processor_state(void) -{ - local_fiq_enable(); -} - -/* - * Snapshot kernel memory and reset the system. - * After resume, the hibernation snapshot is written out. - */ -static int notrace __swsusp_arch_save_image(unsigned long unused) -{ - extern int swsusp_save(void); - int ret; - - ret = swsusp_save(); - if (ret == 0) - soft_restart(virt_to_phys(cpu_resume)); - return ret; -} - -/* - * Save the current CPU state before suspend / poweroff. - */ -int notrace swsusp_arch_suspend(void) -{ - return cpu_suspend(0, __swsusp_arch_save_image); -} - -/* - * The framework loads the hibernation image into a linked list anchored - * at restore_pblist, for swsusp_arch_resume() to copy back to the proper - * destinations. - * - * To make this work if resume is triggered from initramfs, the - * pagetables need to be switched to allow writes to kernel mem. - */ -static void notrace __swsusp_arch_restore_image(void *unused) -{ - extern struct pbe *restore_pblist; - struct pbe *pbe; -#ifdef _PRINT_PAGE_CRC_// add by roger. - unsigned long crc_le; - unsigned char *virt_addr; - unsigned long pfn; -#endif - - - cpu_switch_mm(idmap_pgd, &init_mm); - for (pbe = restore_pblist; pbe; pbe = pbe->next){ - copy_page(pbe->orig_address, pbe->address); - #ifdef _PRINT_PAGE_CRC_ - virt_addr = pbe->orig_address; - pfn = page_to_pfn(virt_to_page(virt_addr)); - crc_le = crc32_le(0, virt_addr, PAGE_SIZE); - printk("pfn:%lu:phy_addr:0x%x:crc:%lu:virt_addr:0x%x\n", - pfn, pfn*PAGE_SIZE, crc_le, virt_addr); - #endif - } - soft_restart_noirq(virt_to_phys(cpu_resume)); -} - -static u8 __swsusp_resume_stk[PAGE_SIZE/2] __nosavedata; - -/* - * Resume from the hibernation image. - * Due to the kernel heap / data restore, stack contents change underneath - * and that would make function calls impossible; switch to a temporary - * stack within the nosave region to avoid that problem. - */ -int __naked swsusp_arch_resume(void) -{ - extern void call_with_stack(void (*fn)(void *), void *arg, void *sp); - - cpu_init(); /* get a clean PSR */ - call_with_stack(__swsusp_arch_restore_image, 0, - __swsusp_resume_stk + sizeof(__swsusp_resume_stk)); - - return 0; -} - -static int __init swsusp_arch_init(void) -{ - char *backup; - size_t len; - len = &__nosave_end - &__nosave_begin; - backup = kmalloc(len, GFP_KERNEL); - if (backup) { - printk("%s: Backed up %d byte nosave region\n", __func__, len); - memcpy(backup, &__nosave_begin, len); - } - - __nosave_backup_phys = virt_to_phys(backup); - __nosave_begin_phys = virt_to_phys(&__nosave_begin); - __nosave_end_phys = virt_to_phys(&__nosave_end); - printk("__nosave_backup_phys=0x%x\n",__nosave_backup_phys); - printk("__nosave_begin_phys=0x%x\n",__nosave_begin_phys); - printk("__nosave_end_phys=0x%x\n",__nosave_end_phys); - return 0; -} -late_initcall(swsusp_arch_init); diff --git a/ANDROID_3.4.5/arch/arm/kernel/hw_breakpoint.c b/ANDROID_3.4.5/arch/arm/kernel/hw_breakpoint.c deleted file mode 100644 index ba386bd9..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/hw_breakpoint.c +++ /dev/null @@ -1,1040 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Copyright (C) 2009, 2010 ARM Limited - * - * Author: Will Deacon <will.deacon@arm.com> - */ - -/* - * HW_breakpoint: a unified kernel/user-space hardware breakpoint facility, - * using the CPU's debug registers. - */ -#define pr_fmt(fmt) "hw-breakpoint: " fmt - -#include <linux/errno.h> -#include <linux/hardirq.h> -#include <linux/perf_event.h> -#include <linux/hw_breakpoint.h> -#include <linux/smp.h> - -#include <asm/cacheflush.h> -#include <asm/cputype.h> -#include <asm/current.h> -#include <asm/hw_breakpoint.h> -#include <asm/kdebug.h> -#include <asm/traps.h> - -/* Breakpoint currently in use for each BRP. */ -static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]); - -/* Watchpoint currently in use for each WRP. */ -static DEFINE_PER_CPU(struct perf_event *, wp_on_reg[ARM_MAX_WRP]); - -/* Number of BRP/WRP registers on this CPU. */ -static int core_num_brps; -static int core_num_wrps; - -/* Debug architecture version. */ -static u8 debug_arch; - -/* Maximum supported watchpoint length. */ -static u8 max_watchpoint_len; - -#define READ_WB_REG_CASE(OP2, M, VAL) \ - case ((OP2 << 4) + M): \ - ARM_DBG_READ(c ## M, OP2, VAL); \ - break - -#define WRITE_WB_REG_CASE(OP2, M, VAL) \ - case ((OP2 << 4) + M): \ - ARM_DBG_WRITE(c ## M, OP2, VAL);\ - break - -#define GEN_READ_WB_REG_CASES(OP2, VAL) \ - READ_WB_REG_CASE(OP2, 0, VAL); \ - READ_WB_REG_CASE(OP2, 1, VAL); \ - READ_WB_REG_CASE(OP2, 2, VAL); \ - READ_WB_REG_CASE(OP2, 3, VAL); \ - READ_WB_REG_CASE(OP2, 4, VAL); \ - READ_WB_REG_CASE(OP2, 5, VAL); \ - READ_WB_REG_CASE(OP2, 6, VAL); \ - READ_WB_REG_CASE(OP2, 7, VAL); \ - READ_WB_REG_CASE(OP2, 8, VAL); \ - READ_WB_REG_CASE(OP2, 9, VAL); \ - READ_WB_REG_CASE(OP2, 10, VAL); \ - READ_WB_REG_CASE(OP2, 11, VAL); \ - READ_WB_REG_CASE(OP2, 12, VAL); \ - READ_WB_REG_CASE(OP2, 13, VAL); \ - READ_WB_REG_CASE(OP2, 14, VAL); \ - READ_WB_REG_CASE(OP2, 15, VAL) - -#define GEN_WRITE_WB_REG_CASES(OP2, VAL) \ - WRITE_WB_REG_CASE(OP2, 0, VAL); \ - WRITE_WB_REG_CASE(OP2, 1, VAL); \ - WRITE_WB_REG_CASE(OP2, 2, VAL); \ - WRITE_WB_REG_CASE(OP2, 3, VAL); \ - WRITE_WB_REG_CASE(OP2, 4, VAL); \ - WRITE_WB_REG_CASE(OP2, 5, VAL); \ - WRITE_WB_REG_CASE(OP2, 6, VAL); \ - WRITE_WB_REG_CASE(OP2, 7, VAL); \ - WRITE_WB_REG_CASE(OP2, 8, VAL); \ - WRITE_WB_REG_CASE(OP2, 9, VAL); \ - WRITE_WB_REG_CASE(OP2, 10, VAL); \ - WRITE_WB_REG_CASE(OP2, 11, VAL); \ - WRITE_WB_REG_CASE(OP2, 12, VAL); \ - WRITE_WB_REG_CASE(OP2, 13, VAL); \ - WRITE_WB_REG_CASE(OP2, 14, VAL); \ - WRITE_WB_REG_CASE(OP2, 15, VAL) - -static u32 read_wb_reg(int n) -{ - u32 val = 0; - - switch (n) { - GEN_READ_WB_REG_CASES(ARM_OP2_BVR, val); - GEN_READ_WB_REG_CASES(ARM_OP2_BCR, val); - GEN_READ_WB_REG_CASES(ARM_OP2_WVR, val); - GEN_READ_WB_REG_CASES(ARM_OP2_WCR, val); - default: - pr_warning("attempt to read from unknown breakpoint " - "register %d\n", n); - } - - return val; -} - -static void write_wb_reg(int n, u32 val) -{ - switch (n) { - GEN_WRITE_WB_REG_CASES(ARM_OP2_BVR, val); - GEN_WRITE_WB_REG_CASES(ARM_OP2_BCR, val); - GEN_WRITE_WB_REG_CASES(ARM_OP2_WVR, val); - GEN_WRITE_WB_REG_CASES(ARM_OP2_WCR, val); - default: - pr_warning("attempt to write to unknown breakpoint " - "register %d\n", n); - } - isb(); -} - -/* Determine debug architecture. */ -static u8 get_debug_arch(void) -{ - u32 didr; - - /* Do we implement the extended CPUID interface? */ - if (((read_cpuid_id() >> 16) & 0xf) != 0xf) { - pr_warning("CPUID feature registers not supported. " - "Assuming v6 debug is present.\n"); - return ARM_DEBUG_ARCH_V6; - } - - ARM_DBG_READ(c0, 0, didr); - return (didr >> 16) & 0xf; -} - -u8 arch_get_debug_arch(void) -{ - return debug_arch; -} - -static int debug_arch_supported(void) -{ - u8 arch = get_debug_arch(); - - /* We don't support the memory-mapped interface. */ - return (arch >= ARM_DEBUG_ARCH_V6 && arch <= ARM_DEBUG_ARCH_V7_ECP14) || - arch >= ARM_DEBUG_ARCH_V7_1; -} - -/* Determine number of WRP registers available. */ -static int get_num_wrp_resources(void) -{ - u32 didr; - ARM_DBG_READ(c0, 0, didr); - return ((didr >> 28) & 0xf) + 1; -} - -/* Determine number of BRP registers available. */ -static int get_num_brp_resources(void) -{ - u32 didr; - ARM_DBG_READ(c0, 0, didr); - return ((didr >> 24) & 0xf) + 1; -} - -/* Does this core support mismatch breakpoints? */ -static int core_has_mismatch_brps(void) -{ - return (get_debug_arch() >= ARM_DEBUG_ARCH_V7_ECP14 && - get_num_brp_resources() > 1); -} - -/* Determine number of usable WRPs available. */ -static int get_num_wrps(void) -{ - /* - * On debug architectures prior to 7.1, when a watchpoint fires, the - * only way to work out which watchpoint it was is by disassembling - * the faulting instruction and working out the address of the memory - * access. - * - * Furthermore, we can only do this if the watchpoint was precise - * since imprecise watchpoints prevent us from calculating register - * based addresses. - * - * Providing we have more than 1 breakpoint register, we only report - * a single watchpoint register for the time being. This way, we always - * know which watchpoint fired. In the future we can either add a - * disassembler and address generation emulator, or we can insert a - * check to see if the DFAR is set on watchpoint exception entry - * [the ARM ARM states that the DFAR is UNKNOWN, but experience shows - * that it is set on some implementations]. - */ - if (get_debug_arch() < ARM_DEBUG_ARCH_V7_1) - return 1; - - return get_num_wrp_resources(); -} - -/* Determine number of usable BRPs available. */ -static int get_num_brps(void) -{ - int brps = get_num_brp_resources(); - return core_has_mismatch_brps() ? brps - 1 : brps; -} - -/* - * In order to access the breakpoint/watchpoint control registers, - * we must be running in debug monitor mode. Unfortunately, we can - * be put into halting debug mode at any time by an external debugger - * but there is nothing we can do to prevent that. - */ -static int enable_monitor_mode(void) -{ - u32 dscr; - int ret = 0; - - ARM_DBG_READ(c1, 0, dscr); - - /* Ensure that halting mode is disabled. */ - if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN, - "halting debug mode enabled. Unable to access hardware resources.\n")) { - ret = -EPERM; - goto out; - } - - /* If monitor mode is already enabled, just return. */ - if (dscr & ARM_DSCR_MDBGEN) - goto out; - - /* Write to the corresponding DSCR. */ - switch (get_debug_arch()) { - case ARM_DEBUG_ARCH_V6: - case ARM_DEBUG_ARCH_V6_1: - ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN)); - break; - case ARM_DEBUG_ARCH_V7_ECP14: - case ARM_DEBUG_ARCH_V7_1: - ARM_DBG_WRITE(c2, 2, (dscr | ARM_DSCR_MDBGEN)); - break; - default: - ret = -ENODEV; - goto out; - } - - /* Check that the write made it through. */ - ARM_DBG_READ(c1, 0, dscr); - if (!(dscr & ARM_DSCR_MDBGEN)) - ret = -EPERM; - -out: - return ret; -} - -int hw_breakpoint_slots(int type) -{ - if (!debug_arch_supported()) - return 0; - - /* - * We can be called early, so don't rely on - * our static variables being initialised. - */ - switch (type) { - case TYPE_INST: - return get_num_brps(); - case TYPE_DATA: - return get_num_wrps(); - default: - pr_warning("unknown slot type: %d\n", type); - return 0; - } -} - -/* - * Check if 8-bit byte-address select is available. - * This clobbers WRP 0. - */ -static u8 get_max_wp_len(void) -{ - u32 ctrl_reg; - struct arch_hw_breakpoint_ctrl ctrl; - u8 size = 4; - - if (debug_arch < ARM_DEBUG_ARCH_V7_ECP14) - goto out; - - memset(&ctrl, 0, sizeof(ctrl)); - ctrl.len = ARM_BREAKPOINT_LEN_8; - ctrl_reg = encode_ctrl_reg(ctrl); - - write_wb_reg(ARM_BASE_WVR, 0); - write_wb_reg(ARM_BASE_WCR, ctrl_reg); - if ((read_wb_reg(ARM_BASE_WCR) & ctrl_reg) == ctrl_reg) - size = 8; - -out: - return size; -} - -u8 arch_get_max_wp_len(void) -{ - return max_watchpoint_len; -} - -/* - * Install a perf counter breakpoint. - */ -int arch_install_hw_breakpoint(struct perf_event *bp) -{ - struct arch_hw_breakpoint *info = counter_arch_bp(bp); - struct perf_event **slot, **slots; - int i, max_slots, ctrl_base, val_base, ret = 0; - u32 addr, ctrl; - - /* Ensure that we are in monitor mode and halting mode is disabled. */ - ret = enable_monitor_mode(); - if (ret) - goto out; - - addr = info->address; - ctrl = encode_ctrl_reg(info->ctrl) | 0x1; - - if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) { - /* Breakpoint */ - ctrl_base = ARM_BASE_BCR; - val_base = ARM_BASE_BVR; - slots = (struct perf_event **)__get_cpu_var(bp_on_reg); - max_slots = core_num_brps; - } else { - /* Watchpoint */ - ctrl_base = ARM_BASE_WCR; - val_base = ARM_BASE_WVR; - slots = (struct perf_event **)__get_cpu_var(wp_on_reg); - max_slots = core_num_wrps; - } - - for (i = 0; i < max_slots; ++i) { - slot = &slots[i]; - - if (!*slot) { - *slot = bp; - break; - } - } - - if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n")) { - ret = -EBUSY; - goto out; - } - - /* Override the breakpoint data with the step data. */ - if (info->step_ctrl.enabled) { - addr = info->trigger & ~0x3; - ctrl = encode_ctrl_reg(info->step_ctrl); - if (info->ctrl.type != ARM_BREAKPOINT_EXECUTE) { - i = 0; - ctrl_base = ARM_BASE_BCR + core_num_brps; - val_base = ARM_BASE_BVR + core_num_brps; - } - } - - /* Setup the address register. */ - write_wb_reg(val_base + i, addr); - - /* Setup the control register. */ - write_wb_reg(ctrl_base + i, ctrl); - -out: - return ret; -} - -void arch_uninstall_hw_breakpoint(struct perf_event *bp) -{ - struct arch_hw_breakpoint *info = counter_arch_bp(bp); - struct perf_event **slot, **slots; - int i, max_slots, base; - - if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) { - /* Breakpoint */ - base = ARM_BASE_BCR; - slots = (struct perf_event **)__get_cpu_var(bp_on_reg); - max_slots = core_num_brps; - } else { - /* Watchpoint */ - base = ARM_BASE_WCR; - slots = (struct perf_event **)__get_cpu_var(wp_on_reg); - max_slots = core_num_wrps; - } - - /* Remove the breakpoint. */ - for (i = 0; i < max_slots; ++i) { - slot = &slots[i]; - - if (*slot == bp) { - *slot = NULL; - break; - } - } - - if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n")) - return; - - /* Ensure that we disable the mismatch breakpoint. */ - if (info->ctrl.type != ARM_BREAKPOINT_EXECUTE && - info->step_ctrl.enabled) { - i = 0; - base = ARM_BASE_BCR + core_num_brps; - } - - /* Reset the control register. */ - write_wb_reg(base + i, 0); -} - -static int get_hbp_len(u8 hbp_len) -{ - unsigned int len_in_bytes = 0; - - switch (hbp_len) { - case ARM_BREAKPOINT_LEN_1: - len_in_bytes = 1; - break; - case ARM_BREAKPOINT_LEN_2: - len_in_bytes = 2; - break; - case ARM_BREAKPOINT_LEN_4: - len_in_bytes = 4; - break; - case ARM_BREAKPOINT_LEN_8: - len_in_bytes = 8; - break; - } - - return len_in_bytes; -} - -/* - * Check whether bp virtual address is in kernel space. - */ -int arch_check_bp_in_kernelspace(struct perf_event *bp) -{ - unsigned int len; - unsigned long va; - struct arch_hw_breakpoint *info = counter_arch_bp(bp); - - va = info->address; - len = get_hbp_len(info->ctrl.len); - - return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE); -} - -/* - * Extract generic type and length encodings from an arch_hw_breakpoint_ctrl. - * Hopefully this will disappear when ptrace can bypass the conversion - * to generic breakpoint descriptions. - */ -int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl, - int *gen_len, int *gen_type) -{ - /* Type */ - switch (ctrl.type) { - case ARM_BREAKPOINT_EXECUTE: - *gen_type = HW_BREAKPOINT_X; - break; - case ARM_BREAKPOINT_LOAD: - *gen_type = HW_BREAKPOINT_R; - break; - case ARM_BREAKPOINT_STORE: - *gen_type = HW_BREAKPOINT_W; - break; - case ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE: - *gen_type = HW_BREAKPOINT_RW; - break; - default: - return -EINVAL; - } - - /* Len */ - switch (ctrl.len) { - case ARM_BREAKPOINT_LEN_1: - *gen_len = HW_BREAKPOINT_LEN_1; - break; - case ARM_BREAKPOINT_LEN_2: - *gen_len = HW_BREAKPOINT_LEN_2; - break; - case ARM_BREAKPOINT_LEN_4: - *gen_len = HW_BREAKPOINT_LEN_4; - break; - case ARM_BREAKPOINT_LEN_8: - *gen_len = HW_BREAKPOINT_LEN_8; - break; - default: - return -EINVAL; - } - - return 0; -} - -/* - * Construct an arch_hw_breakpoint from a perf_event. - */ -static int arch_build_bp_info(struct perf_event *bp) -{ - struct arch_hw_breakpoint *info = counter_arch_bp(bp); - - /* Type */ - switch (bp->attr.bp_type) { - case HW_BREAKPOINT_X: - info->ctrl.type = ARM_BREAKPOINT_EXECUTE; - break; - case HW_BREAKPOINT_R: - info->ctrl.type = ARM_BREAKPOINT_LOAD; - break; - case HW_BREAKPOINT_W: - info->ctrl.type = ARM_BREAKPOINT_STORE; - break; - case HW_BREAKPOINT_RW: - info->ctrl.type = ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE; - break; - default: - return -EINVAL; - } - - /* Len */ - switch (bp->attr.bp_len) { - case HW_BREAKPOINT_LEN_1: - info->ctrl.len = ARM_BREAKPOINT_LEN_1; - break; - case HW_BREAKPOINT_LEN_2: - info->ctrl.len = ARM_BREAKPOINT_LEN_2; - break; - case HW_BREAKPOINT_LEN_4: - info->ctrl.len = ARM_BREAKPOINT_LEN_4; - break; - case HW_BREAKPOINT_LEN_8: - info->ctrl.len = ARM_BREAKPOINT_LEN_8; - if ((info->ctrl.type != ARM_BREAKPOINT_EXECUTE) - && max_watchpoint_len >= 8) - break; - default: - return -EINVAL; - } - - /* - * Breakpoints must be of length 2 (thumb) or 4 (ARM) bytes. - * Watchpoints can be of length 1, 2, 4 or 8 bytes if supported - * by the hardware and must be aligned to the appropriate number of - * bytes. - */ - if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE && - info->ctrl.len != ARM_BREAKPOINT_LEN_2 && - info->ctrl.len != ARM_BREAKPOINT_LEN_4) - return -EINVAL; - - /* Address */ - info->address = bp->attr.bp_addr; - - /* Privilege */ - info->ctrl.privilege = ARM_BREAKPOINT_USER; - if (arch_check_bp_in_kernelspace(bp)) - info->ctrl.privilege |= ARM_BREAKPOINT_PRIV; - - /* Enabled? */ - info->ctrl.enabled = !bp->attr.disabled; - - /* Mismatch */ - info->ctrl.mismatch = 0; - - return 0; -} - -/* - * Validate the arch-specific HW Breakpoint register settings. - */ -int arch_validate_hwbkpt_settings(struct perf_event *bp) -{ - struct arch_hw_breakpoint *info = counter_arch_bp(bp); - int ret = 0; - u32 offset, alignment_mask = 0x3; - - /* Build the arch_hw_breakpoint. */ - ret = arch_build_bp_info(bp); - if (ret) - goto out; - - /* Check address alignment. */ - if (info->ctrl.len == ARM_BREAKPOINT_LEN_8) - alignment_mask = 0x7; - offset = info->address & alignment_mask; - switch (offset) { - case 0: - /* Aligned */ - break; - case 1: - /* Allow single byte watchpoint. */ - if (info->ctrl.len == ARM_BREAKPOINT_LEN_1) - break; - case 2: - /* Allow halfword watchpoints and breakpoints. */ - if (info->ctrl.len == ARM_BREAKPOINT_LEN_2) - break; - default: - ret = -EINVAL; - goto out; - } - - info->address &= ~alignment_mask; - info->ctrl.len <<= offset; - - /* - * Currently we rely on an overflow handler to take - * care of single-stepping the breakpoint when it fires. - * In the case of userspace breakpoints on a core with V7 debug, - * we can use the mismatch feature as a poor-man's hardware - * single-step, but this only works for per-task breakpoints. - */ - if (!bp->overflow_handler && (arch_check_bp_in_kernelspace(bp) || - !core_has_mismatch_brps() || !bp->hw.bp_target)) { - pr_warning("overflow handler required but none found\n"); - ret = -EINVAL; - } -out: - return ret; -} - -/* - * Enable/disable single-stepping over the breakpoint bp at address addr. - */ -static void enable_single_step(struct perf_event *bp, u32 addr) -{ - struct arch_hw_breakpoint *info = counter_arch_bp(bp); - - arch_uninstall_hw_breakpoint(bp); - info->step_ctrl.mismatch = 1; - info->step_ctrl.len = ARM_BREAKPOINT_LEN_4; - info->step_ctrl.type = ARM_BREAKPOINT_EXECUTE; - info->step_ctrl.privilege = info->ctrl.privilege; - info->step_ctrl.enabled = 1; - info->trigger = addr; - arch_install_hw_breakpoint(bp); -} - -static void disable_single_step(struct perf_event *bp) -{ - arch_uninstall_hw_breakpoint(bp); - counter_arch_bp(bp)->step_ctrl.enabled = 0; - arch_install_hw_breakpoint(bp); -} - -static void watchpoint_handler(unsigned long addr, unsigned int fsr, - struct pt_regs *regs) -{ - int i, access; - u32 val, ctrl_reg, alignment_mask; - struct perf_event *wp, **slots; - struct arch_hw_breakpoint *info; - struct arch_hw_breakpoint_ctrl ctrl; - - slots = (struct perf_event **)__get_cpu_var(wp_on_reg); - - for (i = 0; i < core_num_wrps; ++i) { - rcu_read_lock(); - - wp = slots[i]; - - if (wp == NULL) - goto unlock; - - info = counter_arch_bp(wp); - /* - * The DFAR is an unknown value on debug architectures prior - * to 7.1. Since we only allow a single watchpoint on these - * older CPUs, we can set the trigger to the lowest possible - * faulting address. - */ - if (debug_arch < ARM_DEBUG_ARCH_V7_1) { - BUG_ON(i > 0); - info->trigger = wp->attr.bp_addr; - } else { - if (info->ctrl.len == ARM_BREAKPOINT_LEN_8) - alignment_mask = 0x7; - else - alignment_mask = 0x3; - - /* Check if the watchpoint value matches. */ - val = read_wb_reg(ARM_BASE_WVR + i); - if (val != (addr & ~alignment_mask)) - goto unlock; - - /* Possible match, check the byte address select. */ - ctrl_reg = read_wb_reg(ARM_BASE_WCR + i); - decode_ctrl_reg(ctrl_reg, &ctrl); - if (!((1 << (addr & alignment_mask)) & ctrl.len)) - goto unlock; - - /* Check that the access type matches. */ - access = (fsr & ARM_FSR_ACCESS_MASK) ? HW_BREAKPOINT_W : - HW_BREAKPOINT_R; - if (!(access & hw_breakpoint_type(wp))) - goto unlock; - - /* We have a winner. */ - info->trigger = addr; - } - - pr_debug("watchpoint fired: address = 0x%x\n", info->trigger); - perf_bp_event(wp, regs); - - /* - * If no overflow handler is present, insert a temporary - * mismatch breakpoint so we can single-step over the - * watchpoint trigger. - */ - if (!wp->overflow_handler) - enable_single_step(wp, instruction_pointer(regs)); - -unlock: - rcu_read_unlock(); - } -} - -static void watchpoint_single_step_handler(unsigned long pc) -{ - int i; - struct perf_event *wp, **slots; - struct arch_hw_breakpoint *info; - - slots = (struct perf_event **)__get_cpu_var(wp_on_reg); - - for (i = 0; i < core_num_wrps; ++i) { - rcu_read_lock(); - - wp = slots[i]; - - if (wp == NULL) - goto unlock; - - info = counter_arch_bp(wp); - if (!info->step_ctrl.enabled) - goto unlock; - - /* - * Restore the original watchpoint if we've completed the - * single-step. - */ - if (info->trigger != pc) - disable_single_step(wp); - -unlock: - rcu_read_unlock(); - } -} - -static void breakpoint_handler(unsigned long unknown, struct pt_regs *regs) -{ - int i; - u32 ctrl_reg, val, addr; - struct perf_event *bp, **slots; - struct arch_hw_breakpoint *info; - struct arch_hw_breakpoint_ctrl ctrl; - - slots = (struct perf_event **)__get_cpu_var(bp_on_reg); - - /* The exception entry code places the amended lr in the PC. */ - addr = regs->ARM_pc; - - /* Check the currently installed breakpoints first. */ - for (i = 0; i < core_num_brps; ++i) { - rcu_read_lock(); - - bp = slots[i]; - - if (bp == NULL) - goto unlock; - - info = counter_arch_bp(bp); - - /* Check if the breakpoint value matches. */ - val = read_wb_reg(ARM_BASE_BVR + i); - if (val != (addr & ~0x3)) - goto mismatch; - - /* Possible match, check the byte address select to confirm. */ - ctrl_reg = read_wb_reg(ARM_BASE_BCR + i); - decode_ctrl_reg(ctrl_reg, &ctrl); - if ((1 << (addr & 0x3)) & ctrl.len) { - info->trigger = addr; - pr_debug("breakpoint fired: address = 0x%x\n", addr); - perf_bp_event(bp, regs); - if (!bp->overflow_handler) - enable_single_step(bp, addr); - goto unlock; - } - -mismatch: - /* If we're stepping a breakpoint, it can now be restored. */ - if (info->step_ctrl.enabled) - disable_single_step(bp); -unlock: - rcu_read_unlock(); - } - - /* Handle any pending watchpoint single-step breakpoints. */ - watchpoint_single_step_handler(addr); -} - -/* - * Called from either the Data Abort Handler [watchpoint] or the - * Prefetch Abort Handler [breakpoint] with interrupts disabled. - */ -static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr, - struct pt_regs *regs) -{ - int ret = 0; - u32 dscr; - - preempt_disable(); - - if (interrupts_enabled(regs)) - local_irq_enable(); - - /* We only handle watchpoints and hardware breakpoints. */ - ARM_DBG_READ(c1, 0, dscr); - - /* Perform perf callbacks. */ - switch (ARM_DSCR_MOE(dscr)) { - case ARM_ENTRY_BREAKPOINT: - breakpoint_handler(addr, regs); - break; - case ARM_ENTRY_ASYNC_WATCHPOINT: - WARN(1, "Asynchronous watchpoint exception taken. Debugging results may be unreliable\n"); - case ARM_ENTRY_SYNC_WATCHPOINT: - watchpoint_handler(addr, fsr, regs); - break; - default: - ret = 1; /* Unhandled fault. */ - } - - preempt_enable(); - - return ret; -} - -/* - * One-time initialisation. - */ -static cpumask_t debug_err_mask; - -static int debug_reg_trap(struct pt_regs *regs, unsigned int instr) -{ - int cpu = smp_processor_id(); - - pr_warning("Debug register access (0x%x) caused undefined instruction on CPU %d\n", - instr, cpu); - - /* Set the error flag for this CPU and skip the faulting instruction. */ - cpumask_set_cpu(cpu, &debug_err_mask); - instruction_pointer(regs) += 4; - return 0; -} - -static struct undef_hook debug_reg_hook = { - .instr_mask = 0x0fe80f10, - .instr_val = 0x0e000e10, - .fn = debug_reg_trap, -}; - -static void reset_ctrl_regs(void *unused) -{ - int i, raw_num_brps, err = 0, cpu = smp_processor_id(); - u32 dbg_power; - - /* - * v7 debug contains save and restore registers so that debug state - * can be maintained across low-power modes without leaving the debug - * logic powered up. It is IMPLEMENTATION DEFINED whether we can access - * the debug registers out of reset, so we must unlock the OS Lock - * Access Register to avoid taking undefined instruction exceptions - * later on. - */ - switch (debug_arch) { - case ARM_DEBUG_ARCH_V6: - case ARM_DEBUG_ARCH_V6_1: - /* ARMv6 cores just need to reset the registers. */ - goto reset_regs; - case ARM_DEBUG_ARCH_V7_ECP14: - /* - * Ensure sticky power-down is clear (i.e. debug logic is - * powered up). - */ - asm volatile("mrc p14, 0, %0, c1, c5, 4" : "=r" (dbg_power)); - if ((dbg_power & 0x1) == 0) - err = -EPERM; - break; - case ARM_DEBUG_ARCH_V7_1: - /* - * Ensure the OS double lock is clear. - */ - asm volatile("mrc p14, 0, %0, c1, c3, 4" : "=r" (dbg_power)); - if ((dbg_power & 0x1) == 1) - err = -EPERM; - break; - } - - if (err) { - pr_warning("CPU %d debug is powered down!\n", cpu); - cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu)); - return; - } - - /* - * Unconditionally clear the lock by writing a value - * other than 0xC5ACCE55 to the access register. - */ - asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0)); - isb(); - - /* - * Clear any configured vector-catch events before - * enabling monitor mode. - */ - asm volatile("mcr p14, 0, %0, c0, c7, 0" : : "r" (0)); - isb(); - -reset_regs: - if (enable_monitor_mode()) - return; - - /* We must also reset any reserved registers. */ - raw_num_brps = get_num_brp_resources(); - for (i = 0; i < raw_num_brps; ++i) { - write_wb_reg(ARM_BASE_BCR + i, 0UL); - write_wb_reg(ARM_BASE_BVR + i, 0UL); - } - - for (i = 0; i < core_num_wrps; ++i) { - write_wb_reg(ARM_BASE_WCR + i, 0UL); - write_wb_reg(ARM_BASE_WVR + i, 0UL); - } -} - -static int __cpuinit dbg_reset_notify(struct notifier_block *self, - unsigned long action, void *cpu) -{ - if (action == CPU_ONLINE) - smp_call_function_single((int)cpu, reset_ctrl_regs, NULL, 1); - - return NOTIFY_OK; -} - -static struct notifier_block __cpuinitdata dbg_reset_nb = { - .notifier_call = dbg_reset_notify, -}; - -static int __init arch_hw_breakpoint_init(void) -{ - u32 dscr; - - debug_arch = get_debug_arch(); - - if (!debug_arch_supported()) { - pr_info("debug architecture 0x%x unsupported.\n", debug_arch); - return 0; - } - - /* Determine how many BRPs/WRPs are available. */ - core_num_brps = get_num_brps(); - core_num_wrps = get_num_wrps(); - - /* - * We need to tread carefully here because DBGSWENABLE may be - * driven low on this core and there isn't an architected way to - * determine that. - */ - register_undef_hook(&debug_reg_hook); - - /* - * Reset the breakpoint resources. We assume that a halting - * debugger will leave the world in a nice state for us. - */ - on_each_cpu(reset_ctrl_regs, NULL, 1); - unregister_undef_hook(&debug_reg_hook); - if (!cpumask_empty(&debug_err_mask)) { - core_num_brps = 0; - core_num_wrps = 0; - return 0; - } - - pr_info("found %d " "%s" "breakpoint and %d watchpoint registers.\n", - core_num_brps, core_has_mismatch_brps() ? "(+1 reserved) " : - "", core_num_wrps); - - ARM_DBG_READ(c1, 0, dscr); - if (dscr & ARM_DSCR_HDBGEN) { - max_watchpoint_len = 4; - pr_warning("halting debug mode enabled. Assuming maximum watchpoint size of %u bytes.\n", - max_watchpoint_len); - } else { - /* Work out the maximum supported watchpoint length. */ - max_watchpoint_len = get_max_wp_len(); - pr_info("maximum watchpoint size is %u bytes.\n", - max_watchpoint_len); - } - - /* Register debug fault handler. */ - hook_fault_code(FAULT_CODE_DEBUG, hw_breakpoint_pending, SIGTRAP, - TRAP_HWBKPT, "watchpoint debug exception"); - hook_ifault_code(FAULT_CODE_DEBUG, hw_breakpoint_pending, SIGTRAP, - TRAP_HWBKPT, "breakpoint debug exception"); - - /* Register hotplug notifier. */ - register_cpu_notifier(&dbg_reset_nb); - return 0; -} -arch_initcall(arch_hw_breakpoint_init); - -void hw_breakpoint_pmu_read(struct perf_event *bp) -{ -} - -/* - * Dummy function to register with die_notifier. - */ -int hw_breakpoint_exceptions_notify(struct notifier_block *unused, - unsigned long val, void *data) -{ - return NOTIFY_DONE; -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/init_task.c b/ANDROID_3.4.5/arch/arm/kernel/init_task.c deleted file mode 100644 index e7cbb50d..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/init_task.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * linux/arch/arm/kernel/init_task.c - */ -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/init_task.h> -#include <linux/mqueue.h> -#include <linux/uaccess.h> - -#include <asm/pgtable.h> - -static struct signal_struct init_signals = INIT_SIGNALS(init_signals); -static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -/* - * Initial thread structure. - * - * We need to make sure that this is 8192-byte aligned due to the - * way process stacks are handled. This is done by making sure - * the linker maps this in the .text segment right after head.S, - * and making head.S ensure the proper alignment. - * - * The things we do for performance.. - */ -union thread_union init_thread_union __init_task_data = - { INIT_THREAD_INFO(init_task) }; - -/* - * Initial task structure. - * - * All other task structs will be allocated on slabs in fork.c - */ -struct task_struct init_task = INIT_TASK(init_task); - -EXPORT_SYMBOL(init_task); diff --git a/ANDROID_3.4.5/arch/arm/kernel/insn.c b/ANDROID_3.4.5/arch/arm/kernel/insn.c deleted file mode 100644 index b760340b..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/insn.c +++ /dev/null @@ -1,62 +0,0 @@ -#include <linux/bug.h> -#include <linux/kernel.h> -#include <asm/opcodes.h> - -static unsigned long -__arm_gen_branch_thumb2(unsigned long pc, unsigned long addr, bool link) -{ - unsigned long s, j1, j2, i1, i2, imm10, imm11; - unsigned long first, second; - long offset; - - offset = (long)addr - (long)(pc + 4); - if (offset < -16777216 || offset > 16777214) { - WARN_ON_ONCE(1); - return 0; - } - - s = (offset >> 24) & 0x1; - i1 = (offset >> 23) & 0x1; - i2 = (offset >> 22) & 0x1; - imm10 = (offset >> 12) & 0x3ff; - imm11 = (offset >> 1) & 0x7ff; - - j1 = (!i1) ^ s; - j2 = (!i2) ^ s; - - first = 0xf000 | (s << 10) | imm10; - second = 0x9000 | (j1 << 13) | (j2 << 11) | imm11; - if (link) - second |= 1 << 14; - - return __opcode_thumb32_compose(first, second); -} - -static unsigned long -__arm_gen_branch_arm(unsigned long pc, unsigned long addr, bool link) -{ - unsigned long opcode = 0xea000000; - long offset; - - if (link) - opcode |= 1 << 24; - - offset = (long)addr - (long)(pc + 8); - if (unlikely(offset < -33554432 || offset > 33554428)) { - WARN_ON_ONCE(1); - return 0; - } - - offset = (offset >> 2) & 0x00ffffff; - - return opcode | offset; -} - -unsigned long -__arm_gen_branch(unsigned long pc, unsigned long addr, bool link) -{ - if (IS_ENABLED(CONFIG_THUMB2_KERNEL)) - return __arm_gen_branch_thumb2(pc, addr, link); - else - return __arm_gen_branch_arm(pc, addr, link); -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/insn.h b/ANDROID_3.4.5/arch/arm/kernel/insn.h deleted file mode 100644 index e96065da..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/insn.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __ASM_ARM_INSN_H -#define __ASM_ARM_INSN_H - -static inline unsigned long -arm_gen_nop(void) -{ -#ifdef CONFIG_THUMB2_KERNEL - return 0xf3af8000; /* nop.w */ -#else - return 0xe1a00000; /* mov r0, r0 */ -#endif -} - -unsigned long -__arm_gen_branch(unsigned long pc, unsigned long addr, bool link); - -static inline unsigned long -arm_gen_branch(unsigned long pc, unsigned long addr) -{ - return __arm_gen_branch(pc, addr, false); -} - -static inline unsigned long -arm_gen_branch_link(unsigned long pc, unsigned long addr) -{ - return __arm_gen_branch(pc, addr, true); -} - -#endif diff --git a/ANDROID_3.4.5/arch/arm/kernel/io.c b/ANDROID_3.4.5/arch/arm/kernel/io.c deleted file mode 100644 index ba8f0559..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/io.c +++ /dev/null @@ -1,76 +0,0 @@ -#include <linux/export.h> -#include <linux/types.h> -#include <linux/io.h> - -/* - * Copy data from IO memory space to "real" memory space. - * This needs to be optimized. - */ -void _memcpy_fromio(void *to, const volatile void __iomem *from, size_t count) -{ - unsigned char *t = to; - while (count) { - count--; - *t = readb(from); - t++; - from++; - } -} - -/* - * Copy data from "real" memory space to IO memory space. - * This needs to be optimized. - */ -void _memcpy_toio(volatile void __iomem *to, const void *from, size_t count) -{ - /*const unsigned char *f = from; - while (count) { - count--; - writeb(*f, to); - f++; - to++; - }*/ - /*Dannierchen update for 4 byte data memory cpy*/ - void *vdest = (void __force *) to; - - //__asm__ __volatile__ ("sync" : : : "memory"); - while(count && ((((unsigned long)vdest)&3) || (((unsigned long)from)&3))) { - *((volatile u8 *)vdest) = *((u8 *)from); - from++; - vdest++; - count--; - /*printk("start sf_write(vdest:0x%x, from:0x%x )\n", vdest, from);*/ - } - while(count >= 4) { - *((volatile u32 *)vdest) = *((volatile u32 *)from); - from += 4; - vdest += 4; - count-=4; - } - while(count) { - *((volatile u8 *)vdest) = *((u8 *)from); - from++; - vdest++; - count--; - /*printk("end sf_write(vdest:0x%x, from:0x%x )\n", vdest, from);*/ - } - //__asm__ __volatile__ ("sync" : : : "memory"); - -} - -/* - * "memset" on IO memory space. - * This needs to be optimized. - */ -void _memset_io(volatile void __iomem *dst, int c, size_t count) -{ - while (count) { - count--; - writeb(c, dst); - dst++; - } -} - -EXPORT_SYMBOL(_memcpy_fromio); -EXPORT_SYMBOL(_memcpy_toio); -EXPORT_SYMBOL(_memset_io); diff --git a/ANDROID_3.4.5/arch/arm/kernel/irq.c b/ANDROID_3.4.5/arch/arm/kernel/irq.c deleted file mode 100644 index 8349d4e9..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/irq.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * linux/arch/arm/kernel/irq.c - * - * Copyright (C) 1992 Linus Torvalds - * Modifications for ARM processor Copyright (C) 1995-2000 Russell King. - * - * Support for Dynamic Tick Timer Copyright (C) 2004-2005 Nokia Corporation. - * Dynamic Tick Timer written by Tony Lindgren <tony@atomide.com> and - * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This file contains the code used by various IRQ handling routines: - * asking for different IRQ's should be done through these routines - * instead of just grabbing them. Thus setups with different IRQ numbers - * shouldn't result in any weird surprises, and installing new handlers - * should be easier. - * - * IRQ's are in fact implemented a bit like signal handlers for the kernel. - * Naturally it's not a 1:1 relation, but there are similarities. - */ -#include <linux/kernel_stat.h> -#include <linux/signal.h> -#include <linux/ioport.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/random.h> -#include <linux/smp.h> -#include <linux/init.h> -#include <linux/seq_file.h> -#include <linux/errno.h> -#include <linux/list.h> -#include <linux/kallsyms.h> -#include <linux/proc_fs.h> - -#include <asm/exception.h> -#include <asm/mach/arch.h> -#include <asm/mach/irq.h> -#include <asm/mach/time.h> - -/* - * No architecture-specific irq_finish function defined in arm/arch/irqs.h. - */ -#ifndef irq_finish -#define irq_finish(irq) do { } while (0) -#endif - -unsigned long irq_err_count; - -int arch_show_interrupts(struct seq_file *p, int prec) -{ -#ifdef CONFIG_FIQ - show_fiq_list(p, prec); -#endif -#ifdef CONFIG_SMP - show_ipi_list(p, prec); -#endif - seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count); - return 0; -} - -/* - * handle_IRQ handles all hardware IRQ's. Decoded IRQs should - * not come via this function. Instead, they should provide their - * own 'handler'. Used by platform code implementing C-based 1st - * level decoding. - */ -void handle_IRQ(unsigned int irq, struct pt_regs *regs) -{ - struct pt_regs *old_regs = set_irq_regs(regs); - - irq_enter(); - - /* - * Some hardware gives randomly wrong interrupts. Rather - * than crashing, do something sensible. - */ - if (unlikely(irq >= nr_irqs)) { - if (printk_ratelimit()) - printk(KERN_WARNING "Bad IRQ%u\n", irq); - ack_bad_irq(irq); - } else { - generic_handle_irq(irq); - } - - /* AT91 specific workaround */ - irq_finish(irq); - - irq_exit(); - set_irq_regs(old_regs); -} - -/* - * asm_do_IRQ is the interface to be used from assembly code. - */ -asmlinkage void __exception_irq_entry -asm_do_IRQ(unsigned int irq, struct pt_regs *regs) -{ - handle_IRQ(irq, regs); -} - -void set_irq_flags(unsigned int irq, unsigned int iflags) -{ - unsigned long clr = 0, set = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; - - if (irq >= nr_irqs) { - printk(KERN_ERR "Trying to set irq flags for IRQ%d\n", irq); - return; - } - - if (iflags & IRQF_VALID) - clr |= IRQ_NOREQUEST; - if (iflags & IRQF_PROBE) - clr |= IRQ_NOPROBE; - if (!(iflags & IRQF_NOAUTOEN)) - clr |= IRQ_NOAUTOEN; - /* Order is clear bits in "clr" then set bits in "set" */ - irq_modify_status(irq, clr, set & ~clr); -} - -void __init init_IRQ(void) -{ - machine_desc->init_irq(); -} - -#ifdef CONFIG_SPARSE_IRQ -int __init arch_probe_nr_irqs(void) -{ - nr_irqs = machine_desc->nr_irqs ? machine_desc->nr_irqs : NR_IRQS; - return nr_irqs; -} -#endif - -#ifdef CONFIG_HOTPLUG_CPU - -static bool migrate_one_irq(struct irq_desc *desc) -{ - struct irq_data *d = irq_desc_get_irq_data(desc); - const struct cpumask *affinity = d->affinity; - struct irq_chip *c; - bool ret = false; - - /* - * If this is a per-CPU interrupt, or the affinity does not - * include this CPU, then we have nothing to do. - */ - if (irqd_is_per_cpu(d) || !cpumask_test_cpu(smp_processor_id(), affinity)) - return false; - - if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) { - affinity = cpu_online_mask; - ret = true; - } - - c = irq_data_get_irq_chip(d); - if (!c->irq_set_affinity) - pr_debug("IRQ%u: unable to set affinity\n", d->irq); - else if (c->irq_set_affinity(d, affinity, true) == IRQ_SET_MASK_OK && ret) - cpumask_copy(d->affinity, affinity); - - return ret; -} - -/* - * The current CPU has been marked offline. Migrate IRQs off this CPU. - * If the affinity settings do not allow other CPUs, force them onto any - * available CPU. - * - * Note: we must iterate over all IRQs, whether they have an attached - * action structure or not, as we need to get chained interrupts too. - */ -void migrate_irqs(void) -{ - unsigned int i; - struct irq_desc *desc; - unsigned long flags; - - local_irq_save(flags); - - for_each_irq_desc(i, desc) { - bool affinity_broken; - - raw_spin_lock(&desc->lock); - affinity_broken = migrate_one_irq(desc); - raw_spin_unlock(&desc->lock); - - if (affinity_broken && printk_ratelimit()) - pr_warning("IRQ%u no longer affine to CPU%u\n", i, - smp_processor_id()); - } - - local_irq_restore(flags); -} -#endif /* CONFIG_HOTPLUG_CPU */ diff --git a/ANDROID_3.4.5/arch/arm/kernel/isa.c b/ANDROID_3.4.5/arch/arm/kernel/isa.c deleted file mode 100644 index 34648591..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/isa.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * linux/arch/arm/kernel/isa.c - * - * Copyright (C) 1999 Phil Blundell - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * ISA shared memory and I/O port support, and is required to support - * iopl, inb, outb and friends in userspace via glibc emulation. - */ -#include <linux/stddef.h> -#include <linux/types.h> -#include <linux/fs.h> -#include <linux/sysctl.h> -#include <linux/init.h> -#include <linux/io.h> - -static unsigned int isa_membase, isa_portbase, isa_portshift; - -static ctl_table ctl_isa_vars[4] = { - { - .procname = "membase", - .data = &isa_membase, - .maxlen = sizeof(isa_membase), - .mode = 0444, - .proc_handler = proc_dointvec, - }, { - .procname = "portbase", - .data = &isa_portbase, - .maxlen = sizeof(isa_portbase), - .mode = 0444, - .proc_handler = proc_dointvec, - }, { - .procname = "portshift", - .data = &isa_portshift, - .maxlen = sizeof(isa_portshift), - .mode = 0444, - .proc_handler = proc_dointvec, - }, {} -}; - -static struct ctl_table_header *isa_sysctl_header; - -static ctl_table ctl_isa[2] = { - { - .procname = "isa", - .mode = 0555, - .child = ctl_isa_vars, - }, {} -}; - -static ctl_table ctl_bus[2] = { - { - .procname = "bus", - .mode = 0555, - .child = ctl_isa, - }, {} -}; - -void __init -register_isa_ports(unsigned int membase, unsigned int portbase, unsigned int portshift) -{ - isa_membase = membase; - isa_portbase = portbase; - isa_portshift = portshift; - isa_sysctl_header = register_sysctl_table(ctl_bus); -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/iwmmxt.S b/ANDROID_3.4.5/arch/arm/kernel/iwmmxt.S deleted file mode 100644 index a0878382..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/iwmmxt.S +++ /dev/null @@ -1,346 +0,0 @@ -/* - * linux/arch/arm/kernel/iwmmxt.S - * - * XScale iWMMXt (Concan) context switching and handling - * - * Initial code: - * Copyright (c) 2003, Intel Corporation - * - * Full lazy switching support, optimizations and more, by Nicolas Pitre -* Copyright (c) 2003-2004, MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/linkage.h> -#include <asm/ptrace.h> -#include <asm/thread_info.h> -#include <asm/asm-offsets.h> - -#if defined(CONFIG_CPU_PJ4) -#define PJ4(code...) code -#define XSC(code...) -#else -#define PJ4(code...) -#define XSC(code...) code -#endif - -#define MMX_WR0 (0x00) -#define MMX_WR1 (0x08) -#define MMX_WR2 (0x10) -#define MMX_WR3 (0x18) -#define MMX_WR4 (0x20) -#define MMX_WR5 (0x28) -#define MMX_WR6 (0x30) -#define MMX_WR7 (0x38) -#define MMX_WR8 (0x40) -#define MMX_WR9 (0x48) -#define MMX_WR10 (0x50) -#define MMX_WR11 (0x58) -#define MMX_WR12 (0x60) -#define MMX_WR13 (0x68) -#define MMX_WR14 (0x70) -#define MMX_WR15 (0x78) -#define MMX_WCSSF (0x80) -#define MMX_WCASF (0x84) -#define MMX_WCGR0 (0x88) -#define MMX_WCGR1 (0x8C) -#define MMX_WCGR2 (0x90) -#define MMX_WCGR3 (0x94) - -#define MMX_SIZE (0x98) - - .text - -/* - * Lazy switching of Concan coprocessor context - * - * r10 = struct thread_info pointer - * r9 = ret_from_exception - * lr = undefined instr exit - * - * called from prefetch exception handler with interrupts disabled - */ - -ENTRY(iwmmxt_task_enable) - - XSC(mrc p15, 0, r2, c15, c1, 0) - PJ4(mrc p15, 0, r2, c1, c0, 2) - @ CP0 and CP1 accessible? - XSC(tst r2, #0x3) - PJ4(tst r2, #0xf) - movne pc, lr @ if so no business here - @ enable access to CP0 and CP1 - XSC(orr r2, r2, #0x3) - XSC(mcr p15, 0, r2, c15, c1, 0) - PJ4(orr r2, r2, #0xf) - PJ4(mcr p15, 0, r2, c1, c0, 2) - - ldr r3, =concan_owner - add r0, r10, #TI_IWMMXT_STATE @ get task Concan save area - ldr r2, [sp, #60] @ current task pc value - ldr r1, [r3] @ get current Concan owner - str r0, [r3] @ this task now owns Concan regs - sub r2, r2, #4 @ adjust pc back - str r2, [sp, #60] - - mrc p15, 0, r2, c2, c0, 0 - mov r2, r2 @ cpwait - - teq r1, #0 @ test for last ownership - mov lr, r9 @ normal exit from exception - beq concan_load @ no owner, skip save - -concan_save: - - tmrc r2, wCon - - @ CUP? wCx - tst r2, #0x1 - beq 1f - -concan_dump: - - wstrw wCSSF, [r1, #MMX_WCSSF] - wstrw wCASF, [r1, #MMX_WCASF] - wstrw wCGR0, [r1, #MMX_WCGR0] - wstrw wCGR1, [r1, #MMX_WCGR1] - wstrw wCGR2, [r1, #MMX_WCGR2] - wstrw wCGR3, [r1, #MMX_WCGR3] - -1: @ MUP? wRn - tst r2, #0x2 - beq 2f - - wstrd wR0, [r1, #MMX_WR0] - wstrd wR1, [r1, #MMX_WR1] - wstrd wR2, [r1, #MMX_WR2] - wstrd wR3, [r1, #MMX_WR3] - wstrd wR4, [r1, #MMX_WR4] - wstrd wR5, [r1, #MMX_WR5] - wstrd wR6, [r1, #MMX_WR6] - wstrd wR7, [r1, #MMX_WR7] - wstrd wR8, [r1, #MMX_WR8] - wstrd wR9, [r1, #MMX_WR9] - wstrd wR10, [r1, #MMX_WR10] - wstrd wR11, [r1, #MMX_WR11] - wstrd wR12, [r1, #MMX_WR12] - wstrd wR13, [r1, #MMX_WR13] - wstrd wR14, [r1, #MMX_WR14] - wstrd wR15, [r1, #MMX_WR15] - -2: teq r0, #0 @ anything to load? - moveq pc, lr - -concan_load: - - @ Load wRn - wldrd wR0, [r0, #MMX_WR0] - wldrd wR1, [r0, #MMX_WR1] - wldrd wR2, [r0, #MMX_WR2] - wldrd wR3, [r0, #MMX_WR3] - wldrd wR4, [r0, #MMX_WR4] - wldrd wR5, [r0, #MMX_WR5] - wldrd wR6, [r0, #MMX_WR6] - wldrd wR7, [r0, #MMX_WR7] - wldrd wR8, [r0, #MMX_WR8] - wldrd wR9, [r0, #MMX_WR9] - wldrd wR10, [r0, #MMX_WR10] - wldrd wR11, [r0, #MMX_WR11] - wldrd wR12, [r0, #MMX_WR12] - wldrd wR13, [r0, #MMX_WR13] - wldrd wR14, [r0, #MMX_WR14] - wldrd wR15, [r0, #MMX_WR15] - - @ Load wCx - wldrw wCSSF, [r0, #MMX_WCSSF] - wldrw wCASF, [r0, #MMX_WCASF] - wldrw wCGR0, [r0, #MMX_WCGR0] - wldrw wCGR1, [r0, #MMX_WCGR1] - wldrw wCGR2, [r0, #MMX_WCGR2] - wldrw wCGR3, [r0, #MMX_WCGR3] - - @ clear CUP/MUP (only if r1 != 0) - teq r1, #0 - mov r2, #0 - moveq pc, lr - tmcr wCon, r2 - mov pc, lr - -/* - * Back up Concan regs to save area and disable access to them - * (mainly for gdb or sleep mode usage) - * - * r0 = struct thread_info pointer of target task or NULL for any - */ - -ENTRY(iwmmxt_task_disable) - - stmfd sp!, {r4, lr} - - mrs ip, cpsr - orr r2, ip, #PSR_I_BIT @ disable interrupts - msr cpsr_c, r2 - - ldr r3, =concan_owner - add r2, r0, #TI_IWMMXT_STATE @ get task Concan save area - ldr r1, [r3] @ get current Concan owner - teq r1, #0 @ any current owner? - beq 1f @ no: quit - teq r0, #0 @ any owner? - teqne r1, r2 @ or specified one? - bne 1f @ no: quit - - @ enable access to CP0 and CP1 - XSC(mrc p15, 0, r4, c15, c1, 0) - XSC(orr r4, r4, #0x3) - XSC(mcr p15, 0, r4, c15, c1, 0) - PJ4(mrc p15, 0, r4, c1, c0, 2) - PJ4(orr r4, r4, #0xf) - PJ4(mcr p15, 0, r4, c1, c0, 2) - - mov r0, #0 @ nothing to load - str r0, [r3] @ no more current owner - mrc p15, 0, r2, c2, c0, 0 - mov r2, r2 @ cpwait - bl concan_save - - @ disable access to CP0 and CP1 - XSC(bic r4, r4, #0x3) - XSC(mcr p15, 0, r4, c15, c1, 0) - PJ4(bic r4, r4, #0xf) - PJ4(mcr p15, 0, r4, c1, c0, 2) - - mrc p15, 0, r2, c2, c0, 0 - mov r2, r2 @ cpwait - -1: msr cpsr_c, ip @ restore interrupt mode - ldmfd sp!, {r4, pc} - -/* - * Copy Concan state to given memory address - * - * r0 = struct thread_info pointer of target task - * r1 = memory address where to store Concan state - * - * this is called mainly in the creation of signal stack frames - */ - -ENTRY(iwmmxt_task_copy) - - mrs ip, cpsr - orr r2, ip, #PSR_I_BIT @ disable interrupts - msr cpsr_c, r2 - - ldr r3, =concan_owner - add r2, r0, #TI_IWMMXT_STATE @ get task Concan save area - ldr r3, [r3] @ get current Concan owner - teq r2, r3 @ does this task own it... - beq 1f - - @ current Concan values are in the task save area - msr cpsr_c, ip @ restore interrupt mode - mov r0, r1 - mov r1, r2 - mov r2, #MMX_SIZE - b memcpy - -1: @ this task owns Concan regs -- grab a copy from there - mov r0, #0 @ nothing to load - mov r2, #3 @ save all regs - mov r3, lr @ preserve return address - bl concan_dump - msr cpsr_c, ip @ restore interrupt mode - mov pc, r3 - -/* - * Restore Concan state from given memory address - * - * r0 = struct thread_info pointer of target task - * r1 = memory address where to get Concan state from - * - * this is used to restore Concan state when unwinding a signal stack frame - */ - -ENTRY(iwmmxt_task_restore) - - mrs ip, cpsr - orr r2, ip, #PSR_I_BIT @ disable interrupts - msr cpsr_c, r2 - - ldr r3, =concan_owner - add r2, r0, #TI_IWMMXT_STATE @ get task Concan save area - ldr r3, [r3] @ get current Concan owner - bic r2, r2, #0x7 @ 64-bit alignment - teq r2, r3 @ does this task own it... - beq 1f - - @ this task doesn't own Concan regs -- use its save area - msr cpsr_c, ip @ restore interrupt mode - mov r0, r2 - mov r2, #MMX_SIZE - b memcpy - -1: @ this task owns Concan regs -- load them directly - mov r0, r1 - mov r1, #0 @ don't clear CUP/MUP - mov r3, lr @ preserve return address - bl concan_load - msr cpsr_c, ip @ restore interrupt mode - mov pc, r3 - -/* - * Concan handling on task switch - * - * r0 = next thread_info pointer - * - * Called only from the iwmmxt notifier with task preemption disabled. - */ -ENTRY(iwmmxt_task_switch) - - XSC(mrc p15, 0, r1, c15, c1, 0) - PJ4(mrc p15, 0, r1, c1, c0, 2) - @ CP0 and CP1 accessible? - XSC(tst r1, #0x3) - PJ4(tst r1, #0xf) - bne 1f @ yes: block them for next task - - ldr r2, =concan_owner - add r3, r0, #TI_IWMMXT_STATE @ get next task Concan save area - ldr r2, [r2] @ get current Concan owner - teq r2, r3 @ next task owns it? - movne pc, lr @ no: leave Concan disabled - -1: @ flip Concan access - XSC(eor r1, r1, #0x3) - XSC(mcr p15, 0, r1, c15, c1, 0) - PJ4(eor r1, r1, #0xf) - PJ4(mcr p15, 0, r1, c1, c0, 2) - - mrc p15, 0, r1, c2, c0, 0 - sub pc, lr, r1, lsr #32 @ cpwait and return - -/* - * Remove Concan ownership of given task - * - * r0 = struct thread_info pointer - */ -ENTRY(iwmmxt_task_release) - - mrs r2, cpsr - orr ip, r2, #PSR_I_BIT @ disable interrupts - msr cpsr_c, ip - ldr r3, =concan_owner - add r0, r0, #TI_IWMMXT_STATE @ get task Concan save area - ldr r1, [r3] @ get current Concan owner - eors r0, r0, r1 @ if equal... - streq r0, [r3] @ then clear ownership - msr cpsr_c, r2 @ restore interrupts - mov pc, lr - - .data -concan_owner: - .word 0 - diff --git a/ANDROID_3.4.5/arch/arm/kernel/jump_label.c b/ANDROID_3.4.5/arch/arm/kernel/jump_label.c deleted file mode 100644 index 4ce4f789..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/jump_label.c +++ /dev/null @@ -1,39 +0,0 @@ -#include <linux/kernel.h> -#include <linux/jump_label.h> - -#include "insn.h" -#include "patch.h" - -#ifdef HAVE_JUMP_LABEL - -static void __arch_jump_label_transform(struct jump_entry *entry, - enum jump_label_type type, - bool is_static) -{ - void *addr = (void *)entry->code; - unsigned int insn; - - if (type == JUMP_LABEL_ENABLE) - insn = arm_gen_branch(entry->code, entry->target); - else - insn = arm_gen_nop(); - - if (is_static) - __patch_text(addr, insn); - else - patch_text(addr, insn); -} - -void arch_jump_label_transform(struct jump_entry *entry, - enum jump_label_type type) -{ - __arch_jump_label_transform(entry, type, false); -} - -void arch_jump_label_transform_static(struct jump_entry *entry, - enum jump_label_type type) -{ - __arch_jump_label_transform(entry, type, true); -} - -#endif diff --git a/ANDROID_3.4.5/arch/arm/kernel/kgdb.c b/ANDROID_3.4.5/arch/arm/kernel/kgdb.c deleted file mode 100644 index 778c2f70..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/kgdb.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - * arch/arm/kernel/kgdb.c - * - * ARM KGDB support - * - * Copyright (c) 2002-2004 MontaVista Software, Inc - * Copyright (c) 2008 Wind River Systems, Inc. - * - * Authors: George Davis <davis_g@mvista.com> - * Deepak Saxena <dsaxena@plexity.net> - */ -#include <linux/irq.h> -#include <linux/kdebug.h> -#include <linux/kgdb.h> -#include <asm/traps.h> - -struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = -{ - { "r0", 4, offsetof(struct pt_regs, ARM_r0)}, - { "r1", 4, offsetof(struct pt_regs, ARM_r1)}, - { "r2", 4, offsetof(struct pt_regs, ARM_r2)}, - { "r3", 4, offsetof(struct pt_regs, ARM_r3)}, - { "r4", 4, offsetof(struct pt_regs, ARM_r4)}, - { "r5", 4, offsetof(struct pt_regs, ARM_r5)}, - { "r6", 4, offsetof(struct pt_regs, ARM_r6)}, - { "r7", 4, offsetof(struct pt_regs, ARM_r7)}, - { "r8", 4, offsetof(struct pt_regs, ARM_r8)}, - { "r9", 4, offsetof(struct pt_regs, ARM_r9)}, - { "r10", 4, offsetof(struct pt_regs, ARM_r10)}, - { "fp", 4, offsetof(struct pt_regs, ARM_fp)}, - { "ip", 4, offsetof(struct pt_regs, ARM_ip)}, - { "sp", 4, offsetof(struct pt_regs, ARM_sp)}, - { "lr", 4, offsetof(struct pt_regs, ARM_lr)}, - { "pc", 4, offsetof(struct pt_regs, ARM_pc)}, - { "f0", 12, -1 }, - { "f1", 12, -1 }, - { "f2", 12, -1 }, - { "f3", 12, -1 }, - { "f4", 12, -1 }, - { "f5", 12, -1 }, - { "f6", 12, -1 }, - { "f7", 12, -1 }, - { "fps", 4, -1 }, - { "cpsr", 4, offsetof(struct pt_regs, ARM_cpsr)}, -}; - -char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs) -{ - if (regno >= DBG_MAX_REG_NUM || regno < 0) - return NULL; - - if (dbg_reg_def[regno].offset != -1) - memcpy(mem, (void *)regs + dbg_reg_def[regno].offset, - dbg_reg_def[regno].size); - else - memset(mem, 0, dbg_reg_def[regno].size); - return dbg_reg_def[regno].name; -} - -int dbg_set_reg(int regno, void *mem, struct pt_regs *regs) -{ - if (regno >= DBG_MAX_REG_NUM || regno < 0) - return -EINVAL; - - if (dbg_reg_def[regno].offset != -1) - memcpy((void *)regs + dbg_reg_def[regno].offset, mem, - dbg_reg_def[regno].size); - return 0; -} - -void -sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task) -{ - struct pt_regs *thread_regs; - int regno; - - /* Just making sure... */ - if (task == NULL) - return; - - /* Initialize to zero */ - for (regno = 0; regno < GDB_MAX_REGS; regno++) - gdb_regs[regno] = 0; - - /* Otherwise, we have only some registers from switch_to() */ - thread_regs = task_pt_regs(task); - gdb_regs[_R0] = thread_regs->ARM_r0; - gdb_regs[_R1] = thread_regs->ARM_r1; - gdb_regs[_R2] = thread_regs->ARM_r2; - gdb_regs[_R3] = thread_regs->ARM_r3; - gdb_regs[_R4] = thread_regs->ARM_r4; - gdb_regs[_R5] = thread_regs->ARM_r5; - gdb_regs[_R6] = thread_regs->ARM_r6; - gdb_regs[_R7] = thread_regs->ARM_r7; - gdb_regs[_R8] = thread_regs->ARM_r8; - gdb_regs[_R9] = thread_regs->ARM_r9; - gdb_regs[_R10] = thread_regs->ARM_r10; - gdb_regs[_FP] = thread_regs->ARM_fp; - gdb_regs[_IP] = thread_regs->ARM_ip; - gdb_regs[_SPT] = thread_regs->ARM_sp; - gdb_regs[_LR] = thread_regs->ARM_lr; - gdb_regs[_PC] = thread_regs->ARM_pc; - gdb_regs[_CPSR] = thread_regs->ARM_cpsr; -} - -void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) -{ - regs->ARM_pc = pc; -} - -static int compiled_break; - -int kgdb_arch_handle_exception(int exception_vector, int signo, - int err_code, char *remcom_in_buffer, - char *remcom_out_buffer, - struct pt_regs *linux_regs) -{ - unsigned long addr; - char *ptr; - - switch (remcom_in_buffer[0]) { - case 'D': - case 'k': - case 'c': - /* - * Try to read optional parameter, pc unchanged if no parm. - * If this was a compiled breakpoint, we need to move - * to the next instruction or we will just breakpoint - * over and over again. - */ - ptr = &remcom_in_buffer[1]; - if (kgdb_hex2long(&ptr, &addr)) - linux_regs->ARM_pc = addr; - else if (compiled_break == 1) - linux_regs->ARM_pc += 4; - - compiled_break = 0; - - return 0; - } - - return -1; -} - -static int kgdb_brk_fn(struct pt_regs *regs, unsigned int instr) -{ - kgdb_handle_exception(1, SIGTRAP, 0, regs); - - return 0; -} - -static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int instr) -{ - compiled_break = 1; - kgdb_handle_exception(1, SIGTRAP, 0, regs); - - return 0; -} - -static struct undef_hook kgdb_brkpt_hook = { - .instr_mask = 0xffffffff, - .instr_val = KGDB_BREAKINST, - .fn = kgdb_brk_fn -}; - -static struct undef_hook kgdb_compiled_brkpt_hook = { - .instr_mask = 0xffffffff, - .instr_val = KGDB_COMPILED_BREAK, - .fn = kgdb_compiled_brk_fn -}; - -static void kgdb_call_nmi_hook(void *ignored) -{ - kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs()); -} - -void kgdb_roundup_cpus(unsigned long flags) -{ - local_irq_enable(); - smp_call_function(kgdb_call_nmi_hook, NULL, 0); - local_irq_disable(); -} - -static int __kgdb_notify(struct die_args *args, unsigned long cmd) -{ - struct pt_regs *regs = args->regs; - - if (kgdb_handle_exception(1, args->signr, cmd, regs)) - return NOTIFY_DONE; - return NOTIFY_STOP; -} -static int -kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr) -{ - unsigned long flags; - int ret; - - local_irq_save(flags); - ret = __kgdb_notify(ptr, cmd); - local_irq_restore(flags); - - return ret; -} - -static struct notifier_block kgdb_notifier = { - .notifier_call = kgdb_notify, - .priority = -INT_MAX, -}; - - -/** - * kgdb_arch_init - Perform any architecture specific initalization. - * - * This function will handle the initalization of any architecture - * specific callbacks. - */ -int kgdb_arch_init(void) -{ - int ret = register_die_notifier(&kgdb_notifier); - - if (ret != 0) - return ret; - - register_undef_hook(&kgdb_brkpt_hook); - register_undef_hook(&kgdb_compiled_brkpt_hook); - - return 0; -} - -/** - * kgdb_arch_exit - Perform any architecture specific uninitalization. - * - * This function will handle the uninitalization of any architecture - * specific callbacks, for dynamic registration and unregistration. - */ -void kgdb_arch_exit(void) -{ - unregister_undef_hook(&kgdb_brkpt_hook); - unregister_undef_hook(&kgdb_compiled_brkpt_hook); - unregister_die_notifier(&kgdb_notifier); -} - -/* - * Register our undef instruction hooks with ARM undef core. - * We regsiter a hook specifically looking for the KGB break inst - * and we handle the normal undef case within the do_undefinstr - * handler. - */ -struct kgdb_arch arch_kgdb_ops = { -#ifndef __ARMEB__ - .gdb_bpt_instr = {0xfe, 0xde, 0xff, 0xe7} -#else /* ! __ARMEB__ */ - .gdb_bpt_instr = {0xe7, 0xff, 0xde, 0xfe} -#endif -}; diff --git a/ANDROID_3.4.5/arch/arm/kernel/kprobes-arm.c b/ANDROID_3.4.5/arch/arm/kernel/kprobes-arm.c deleted file mode 100644 index 8a30c89d..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/kprobes-arm.c +++ /dev/null @@ -1,1005 +0,0 @@ -/* - * arch/arm/kernel/kprobes-decode.c - * - * Copyright (C) 2006, 2007 Motorola Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ - -/* - * We do not have hardware single-stepping on ARM, This - * effort is further complicated by the ARM not having a - * "next PC" register. Instructions that change the PC - * can't be safely single-stepped in a MP environment, so - * we have a lot of work to do: - * - * In the prepare phase: - * *) If it is an instruction that does anything - * with the CPU mode, we reject it for a kprobe. - * (This is out of laziness rather than need. The - * instructions could be simulated.) - * - * *) Otherwise, decode the instruction rewriting its - * registers to take fixed, ordered registers and - * setting a handler for it to run the instruction. - * - * In the execution phase by an instruction's handler: - * - * *) If the PC is written to by the instruction, the - * instruction must be fully simulated in software. - * - * *) Otherwise, a modified form of the instruction is - * directly executed. Its handler calls the - * instruction in insn[0]. In insn[1] is a - * "mov pc, lr" to return. - * - * Before calling, load up the reordered registers - * from the original instruction's registers. If one - * of the original input registers is the PC, compute - * and adjust the appropriate input register. - * - * After call completes, copy the output registers to - * the original instruction's original registers. - * - * We don't use a real breakpoint instruction since that - * would have us in the kernel go from SVC mode to SVC - * mode losing the link register. Instead we use an - * undefined instruction. To simplify processing, the - * undefined instruction used for kprobes must be reserved - * exclusively for kprobes use. - * - * TODO: ifdef out some instruction decoding based on architecture. - */ - -#include <linux/kernel.h> -#include <linux/kprobes.h> -#include <linux/module.h> - -#include "kprobes.h" - -#define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit))))) - -#define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25) - -#if __LINUX_ARM_ARCH__ >= 6 -#define BLX(reg) "blx "reg" \n\t" -#else -#define BLX(reg) "mov lr, pc \n\t" \ - "mov pc, "reg" \n\t" -#endif - -/* - * To avoid the complications of mimicing single-stepping on a - * processor without a Next-PC or a single-step mode, and to - * avoid having to deal with the side-effects of boosting, we - * simulate or emulate (almost) all ARM instructions. - * - * "Simulation" is where the instruction's behavior is duplicated in - * C code. "Emulation" is where the original instruction is rewritten - * and executed, often by altering its registers. - * - * By having all behavior of the kprobe'd instruction completed before - * returning from the kprobe_handler(), all locks (scheduler and - * interrupt) can safely be released. There is no need for secondary - * breakpoints, no race with MP or preemptable kernels, nor having to - * clean up resources counts at a later time impacting overall system - * performance. By rewriting the instruction, only the minimum registers - * need to be loaded and saved back optimizing performance. - * - * Calling the insnslot_*_rwflags version of a function doesn't hurt - * anything even when the CPSR flags aren't updated by the - * instruction. It's just a little slower in return for saving - * a little space by not having a duplicate function that doesn't - * update the flags. (The same optimization can be said for - * instructions that do or don't perform register writeback) - * Also, instructions can either read the flags, only write the - * flags, or read and write the flags. To save combinations - * rather than for sheer performance, flag functions just assume - * read and write of flags. - */ - -static void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - long iaddr = (long)p->addr; - int disp = branch_displacement(insn); - - if (insn & (1 << 24)) - regs->ARM_lr = iaddr + 4; - - regs->ARM_pc = iaddr + 8 + disp; -} - -static void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - long iaddr = (long)p->addr; - int disp = branch_displacement(insn); - - regs->ARM_lr = iaddr + 4; - regs->ARM_pc = iaddr + 8 + disp + ((insn >> 23) & 0x2); - regs->ARM_cpsr |= PSR_T_BIT; -} - -static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - int rm = insn & 0xf; - long rmv = regs->uregs[rm]; - - if (insn & (1 << 5)) - regs->ARM_lr = (long)p->addr + 4; - - regs->ARM_pc = rmv & ~0x1; - regs->ARM_cpsr &= ~PSR_T_BIT; - if (rmv & 0x1) - regs->ARM_cpsr |= PSR_T_BIT; -} - -static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - int rd = (insn >> 12) & 0xf; - unsigned long mask = 0xf8ff03df; /* Mask out execution state */ - regs->uregs[rd] = regs->ARM_cpsr & mask; -} - -static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs) -{ - regs->uregs[12] = regs->uregs[13]; -} - -static void __kprobes -emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - unsigned long pc = (unsigned long)p->addr + 8; - int rt = (insn >> 12) & 0xf; - int rn = (insn >> 16) & 0xf; - int rm = insn & 0xf; - - register unsigned long rtv asm("r0") = regs->uregs[rt]; - register unsigned long rt2v asm("r1") = regs->uregs[rt+1]; - register unsigned long rnv asm("r2") = (rn == 15) ? pc - : regs->uregs[rn]; - register unsigned long rmv asm("r3") = regs->uregs[rm]; - - __asm__ __volatile__ ( - BLX("%[fn]") - : "=r" (rtv), "=r" (rt2v), "=r" (rnv) - : "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv), - [fn] "r" (p->ainsn.insn_fn) - : "lr", "memory", "cc" - ); - - regs->uregs[rt] = rtv; - regs->uregs[rt+1] = rt2v; - if (is_writeback(insn)) - regs->uregs[rn] = rnv; -} - -static void __kprobes -emulate_ldr(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - unsigned long pc = (unsigned long)p->addr + 8; - int rt = (insn >> 12) & 0xf; - int rn = (insn >> 16) & 0xf; - int rm = insn & 0xf; - - register unsigned long rtv asm("r0"); - register unsigned long rnv asm("r2") = (rn == 15) ? pc - : regs->uregs[rn]; - register unsigned long rmv asm("r3") = regs->uregs[rm]; - - __asm__ __volatile__ ( - BLX("%[fn]") - : "=r" (rtv), "=r" (rnv) - : "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn) - : "lr", "memory", "cc" - ); - - if (rt == 15) - load_write_pc(rtv, regs); - else - regs->uregs[rt] = rtv; - - if (is_writeback(insn)) - regs->uregs[rn] = rnv; -} - -static void __kprobes -emulate_str(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - unsigned long rtpc = (unsigned long)p->addr + str_pc_offset; - unsigned long rnpc = (unsigned long)p->addr + 8; - int rt = (insn >> 12) & 0xf; - int rn = (insn >> 16) & 0xf; - int rm = insn & 0xf; - - register unsigned long rtv asm("r0") = (rt == 15) ? rtpc - : regs->uregs[rt]; - register unsigned long rnv asm("r2") = (rn == 15) ? rnpc - : regs->uregs[rn]; - register unsigned long rmv asm("r3") = regs->uregs[rm]; - - __asm__ __volatile__ ( - BLX("%[fn]") - : "=r" (rnv) - : "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn) - : "lr", "memory", "cc" - ); - - if (is_writeback(insn)) - regs->uregs[rn] = rnv; -} - -static void __kprobes -emulate_rd12rn16rm0rs8_rwflags(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - unsigned long pc = (unsigned long)p->addr + 8; - int rd = (insn >> 12) & 0xf; - int rn = (insn >> 16) & 0xf; - int rm = insn & 0xf; - int rs = (insn >> 8) & 0xf; - - register unsigned long rdv asm("r0") = regs->uregs[rd]; - register unsigned long rnv asm("r2") = (rn == 15) ? pc - : regs->uregs[rn]; - register unsigned long rmv asm("r3") = (rm == 15) ? pc - : regs->uregs[rm]; - register unsigned long rsv asm("r1") = regs->uregs[rs]; - unsigned long cpsr = regs->ARM_cpsr; - - __asm__ __volatile__ ( - "msr cpsr_fs, %[cpsr] \n\t" - BLX("%[fn]") - "mrs %[cpsr], cpsr \n\t" - : "=r" (rdv), [cpsr] "=r" (cpsr) - : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv), - "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) - : "lr", "memory", "cc" - ); - - if (rd == 15) - alu_write_pc(rdv, regs); - else - regs->uregs[rd] = rdv; - regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); -} - -static void __kprobes -emulate_rd12rn16rm0_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - int rd = (insn >> 12) & 0xf; - int rn = (insn >> 16) & 0xf; - int rm = insn & 0xf; - - register unsigned long rdv asm("r0") = regs->uregs[rd]; - register unsigned long rnv asm("r2") = regs->uregs[rn]; - register unsigned long rmv asm("r3") = regs->uregs[rm]; - unsigned long cpsr = regs->ARM_cpsr; - - __asm__ __volatile__ ( - "msr cpsr_fs, %[cpsr] \n\t" - BLX("%[fn]") - "mrs %[cpsr], cpsr \n\t" - : "=r" (rdv), [cpsr] "=r" (cpsr) - : "0" (rdv), "r" (rnv), "r" (rmv), - "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) - : "lr", "memory", "cc" - ); - - regs->uregs[rd] = rdv; - regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); -} - -static void __kprobes -emulate_rd16rn12rm0rs8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - int rd = (insn >> 16) & 0xf; - int rn = (insn >> 12) & 0xf; - int rm = insn & 0xf; - int rs = (insn >> 8) & 0xf; - - register unsigned long rdv asm("r2") = regs->uregs[rd]; - register unsigned long rnv asm("r0") = regs->uregs[rn]; - register unsigned long rmv asm("r3") = regs->uregs[rm]; - register unsigned long rsv asm("r1") = regs->uregs[rs]; - unsigned long cpsr = regs->ARM_cpsr; - - __asm__ __volatile__ ( - "msr cpsr_fs, %[cpsr] \n\t" - BLX("%[fn]") - "mrs %[cpsr], cpsr \n\t" - : "=r" (rdv), [cpsr] "=r" (cpsr) - : "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv), - "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) - : "lr", "memory", "cc" - ); - - regs->uregs[rd] = rdv; - regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); -} - -static void __kprobes -emulate_rd12rm0_noflags_nopc(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - int rd = (insn >> 12) & 0xf; - int rm = insn & 0xf; - - register unsigned long rdv asm("r0") = regs->uregs[rd]; - register unsigned long rmv asm("r3") = regs->uregs[rm]; - - __asm__ __volatile__ ( - BLX("%[fn]") - : "=r" (rdv) - : "0" (rdv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn) - : "lr", "memory", "cc" - ); - - regs->uregs[rd] = rdv; -} - -static void __kprobes -emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - int rdlo = (insn >> 12) & 0xf; - int rdhi = (insn >> 16) & 0xf; - int rn = insn & 0xf; - int rm = (insn >> 8) & 0xf; - - register unsigned long rdlov asm("r0") = regs->uregs[rdlo]; - register unsigned long rdhiv asm("r2") = regs->uregs[rdhi]; - register unsigned long rnv asm("r3") = regs->uregs[rn]; - register unsigned long rmv asm("r1") = regs->uregs[rm]; - unsigned long cpsr = regs->ARM_cpsr; - - __asm__ __volatile__ ( - "msr cpsr_fs, %[cpsr] \n\t" - BLX("%[fn]") - "mrs %[cpsr], cpsr \n\t" - : "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr) - : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv), - "2" (cpsr), [fn] "r" (p->ainsn.insn_fn) - : "lr", "memory", "cc" - ); - - regs->uregs[rdlo] = rdlov; - regs->uregs[rdhi] = rdhiv; - regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); -} - -/* - * For the instruction masking and comparisons in all the "space_*" - * functions below, Do _not_ rearrange the order of tests unless - * you're very, very sure of what you are doing. For the sake of - * efficiency, the masks for some tests sometimes assume other test - * have been done prior to them so the number of patterns to test - * for an instruction set can be as broad as possible to reduce the - * number of tests needed. - */ - -static const union decode_item arm_1111_table[] = { - /* Unconditional instructions */ - - /* memory hint 1111 0100 x001 xxxx xxxx xxxx xxxx xxxx */ - /* PLDI (immediate) 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx */ - /* PLDW (immediate) 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx */ - /* PLD (immediate) 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx */ - DECODE_SIMULATE (0xfe300000, 0xf4100000, kprobe_simulate_nop), - - /* memory hint 1111 0110 x001 xxxx xxxx xxxx xxx0 xxxx */ - /* PLDI (register) 1111 0110 x101 xxxx xxxx xxxx xxx0 xxxx */ - /* PLDW (register) 1111 0111 x001 xxxx xxxx xxxx xxx0 xxxx */ - /* PLD (register) 1111 0111 x101 xxxx xxxx xxxx xxx0 xxxx */ - DECODE_SIMULATE (0xfe300010, 0xf6100000, kprobe_simulate_nop), - - /* BLX (immediate) 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx */ - DECODE_SIMULATE (0xfe000000, 0xfa000000, simulate_blx1), - - /* CPS 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */ - /* SETEND 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */ - /* SRS 1111 100x x1x0 xxxx xxxx xxxx xxxx xxxx */ - /* RFE 1111 100x x0x1 xxxx xxxx xxxx xxxx xxxx */ - - /* Coprocessor instructions... */ - /* MCRR2 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx */ - /* MRRC2 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx */ - /* LDC2 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */ - /* STC2 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */ - /* CDP2 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */ - /* MCR2 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */ - /* MRC2 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */ - - /* Other unallocated instructions... */ - DECODE_END -}; - -static const union decode_item arm_cccc_0001_0xx0____0xxx_table[] = { - /* Miscellaneous instructions */ - - /* MRS cpsr cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */ - DECODE_SIMULATEX(0x0ff000f0, 0x01000000, simulate_mrs, - REGS(0, NOPC, 0, 0, 0)), - - /* BX cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */ - DECODE_SIMULATE (0x0ff000f0, 0x01200010, simulate_blx2bx), - - /* BLX (register) cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */ - DECODE_SIMULATEX(0x0ff000f0, 0x01200030, simulate_blx2bx, - REGS(0, 0, 0, 0, NOPC)), - - /* CLZ cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */ - DECODE_EMULATEX (0x0ff000f0, 0x01600010, emulate_rd12rm0_noflags_nopc, - REGS(0, NOPC, 0, 0, NOPC)), - - /* QADD cccc 0001 0000 xxxx xxxx xxxx 0101 xxxx */ - /* QSUB cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx */ - /* QDADD cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx */ - /* QDSUB cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx */ - DECODE_EMULATEX (0x0f9000f0, 0x01000050, emulate_rd12rn16rm0_rwflags_nopc, - REGS(NOPC, NOPC, 0, 0, NOPC)), - - /* BXJ cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */ - /* MSR cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */ - /* MRS spsr cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */ - /* BKPT 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */ - /* SMC cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */ - /* And unallocated instructions... */ - DECODE_END -}; - -static const union decode_item arm_cccc_0001_0xx0____1xx0_table[] = { - /* Halfword multiply and multiply-accumulate */ - - /* SMLALxy cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */ - DECODE_EMULATEX (0x0ff00090, 0x01400080, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc, - REGS(NOPC, NOPC, NOPC, 0, NOPC)), - - /* SMULWy cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */ - DECODE_OR (0x0ff000b0, 0x012000a0), - /* SMULxy cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */ - DECODE_EMULATEX (0x0ff00090, 0x01600080, emulate_rd16rn12rm0rs8_rwflags_nopc, - REGS(NOPC, 0, NOPC, 0, NOPC)), - - /* SMLAxy cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx */ - DECODE_OR (0x0ff00090, 0x01000080), - /* SMLAWy cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx */ - DECODE_EMULATEX (0x0ff000b0, 0x01200080, emulate_rd16rn12rm0rs8_rwflags_nopc, - REGS(NOPC, NOPC, NOPC, 0, NOPC)), - - DECODE_END -}; - -static const union decode_item arm_cccc_0000_____1001_table[] = { - /* Multiply and multiply-accumulate */ - - /* MUL cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx */ - /* MULS cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx */ - DECODE_EMULATEX (0x0fe000f0, 0x00000090, emulate_rd16rn12rm0rs8_rwflags_nopc, - REGS(NOPC, 0, NOPC, 0, NOPC)), - - /* MLA cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx */ - /* MLAS cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx */ - DECODE_OR (0x0fe000f0, 0x00200090), - /* MLS cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx */ - DECODE_EMULATEX (0x0ff000f0, 0x00600090, emulate_rd16rn12rm0rs8_rwflags_nopc, - REGS(NOPC, NOPC, NOPC, 0, NOPC)), - - /* UMAAL cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx */ - DECODE_OR (0x0ff000f0, 0x00400090), - /* UMULL cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx */ - /* UMULLS cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx */ - /* UMLAL cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx */ - /* UMLALS cccc 0000 1011 xxxx xxxx xxxx 1001 xxxx */ - /* SMULL cccc 0000 1100 xxxx xxxx xxxx 1001 xxxx */ - /* SMULLS cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx */ - /* SMLAL cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx */ - /* SMLALS cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx */ - DECODE_EMULATEX (0x0f8000f0, 0x00800090, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc, - REGS(NOPC, NOPC, NOPC, 0, NOPC)), - - DECODE_END -}; - -static const union decode_item arm_cccc_0001_____1001_table[] = { - /* Synchronization primitives */ - -#if __LINUX_ARM_ARCH__ < 6 - /* Deprecated on ARMv6 and may be UNDEFINED on v7 */ - /* SMP/SWPB cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */ - DECODE_EMULATEX (0x0fb000f0, 0x01000090, emulate_rd12rn16rm0_rwflags_nopc, - REGS(NOPC, NOPC, 0, 0, NOPC)), -#endif - /* LDREX/STREX{,D,B,H} cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */ - /* And unallocated instructions... */ - DECODE_END -}; - -static const union decode_item arm_cccc_000x_____1xx1_table[] = { - /* Extra load/store instructions */ - - /* STRHT cccc 0000 xx10 xxxx xxxx xxxx 1011 xxxx */ - /* ??? cccc 0000 xx10 xxxx xxxx xxxx 11x1 xxxx */ - /* LDRHT cccc 0000 xx11 xxxx xxxx xxxx 1011 xxxx */ - /* LDRSBT cccc 0000 xx11 xxxx xxxx xxxx 1101 xxxx */ - /* LDRSHT cccc 0000 xx11 xxxx xxxx xxxx 1111 xxxx */ - DECODE_REJECT (0x0f200090, 0x00200090), - - /* LDRD/STRD lr,pc,{... cccc 000x x0x0 xxxx 111x xxxx 1101 xxxx */ - DECODE_REJECT (0x0e10e0d0, 0x0000e0d0), - - /* LDRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1101 xxxx */ - /* STRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx */ - DECODE_EMULATEX (0x0e5000d0, 0x000000d0, emulate_ldrdstrd, - REGS(NOPCWB, NOPCX, 0, 0, NOPC)), - - /* LDRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1101 xxxx */ - /* STRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1111 xxxx */ - DECODE_EMULATEX (0x0e5000d0, 0x004000d0, emulate_ldrdstrd, - REGS(NOPCWB, NOPCX, 0, 0, 0)), - - /* STRH (register) cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx */ - DECODE_EMULATEX (0x0e5000f0, 0x000000b0, emulate_str, - REGS(NOPCWB, NOPC, 0, 0, NOPC)), - - /* LDRH (register) cccc 000x x0x1 xxxx xxxx xxxx 1011 xxxx */ - /* LDRSB (register) cccc 000x x0x1 xxxx xxxx xxxx 1101 xxxx */ - /* LDRSH (register) cccc 000x x0x1 xxxx xxxx xxxx 1111 xxxx */ - DECODE_EMULATEX (0x0e500090, 0x00100090, emulate_ldr, - REGS(NOPCWB, NOPC, 0, 0, NOPC)), - - /* STRH (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1011 xxxx */ - DECODE_EMULATEX (0x0e5000f0, 0x004000b0, emulate_str, - REGS(NOPCWB, NOPC, 0, 0, 0)), - - /* LDRH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1011 xxxx */ - /* LDRSB (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1101 xxxx */ - /* LDRSH (immediate) cccc 000x x1x1 xxxx xxxx xxxx 1111 xxxx */ - DECODE_EMULATEX (0x0e500090, 0x00500090, emulate_ldr, - REGS(NOPCWB, NOPC, 0, 0, 0)), - - DECODE_END -}; - -static const union decode_item arm_cccc_000x_table[] = { - /* Data-processing (register) */ - - /* <op>S PC, ... cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx */ - DECODE_REJECT (0x0e10f000, 0x0010f000), - - /* MOV IP, SP 1110 0001 1010 0000 1100 0000 0000 1101 */ - DECODE_SIMULATE (0xffffffff, 0xe1a0c00d, simulate_mov_ipsp), - - /* TST (register) cccc 0001 0001 xxxx xxxx xxxx xxx0 xxxx */ - /* TEQ (register) cccc 0001 0011 xxxx xxxx xxxx xxx0 xxxx */ - /* CMP (register) cccc 0001 0101 xxxx xxxx xxxx xxx0 xxxx */ - /* CMN (register) cccc 0001 0111 xxxx xxxx xxxx xxx0 xxxx */ - DECODE_EMULATEX (0x0f900010, 0x01100000, emulate_rd12rn16rm0rs8_rwflags, - REGS(ANY, 0, 0, 0, ANY)), - - /* MOV (register) cccc 0001 101x xxxx xxxx xxxx xxx0 xxxx */ - /* MVN (register) cccc 0001 111x xxxx xxxx xxxx xxx0 xxxx */ - DECODE_EMULATEX (0x0fa00010, 0x01a00000, emulate_rd12rn16rm0rs8_rwflags, - REGS(0, ANY, 0, 0, ANY)), - - /* AND (register) cccc 0000 000x xxxx xxxx xxxx xxx0 xxxx */ - /* EOR (register) cccc 0000 001x xxxx xxxx xxxx xxx0 xxxx */ - /* SUB (register) cccc 0000 010x xxxx xxxx xxxx xxx0 xxxx */ - /* RSB (register) cccc 0000 011x xxxx xxxx xxxx xxx0 xxxx */ - /* ADD (register) cccc 0000 100x xxxx xxxx xxxx xxx0 xxxx */ - /* ADC (register) cccc 0000 101x xxxx xxxx xxxx xxx0 xxxx */ - /* SBC (register) cccc 0000 110x xxxx xxxx xxxx xxx0 xxxx */ - /* RSC (register) cccc 0000 111x xxxx xxxx xxxx xxx0 xxxx */ - /* ORR (register) cccc 0001 100x xxxx xxxx xxxx xxx0 xxxx */ - /* BIC (register) cccc 0001 110x xxxx xxxx xxxx xxx0 xxxx */ - DECODE_EMULATEX (0x0e000010, 0x00000000, emulate_rd12rn16rm0rs8_rwflags, - REGS(ANY, ANY, 0, 0, ANY)), - - /* TST (reg-shift reg) cccc 0001 0001 xxxx xxxx xxxx 0xx1 xxxx */ - /* TEQ (reg-shift reg) cccc 0001 0011 xxxx xxxx xxxx 0xx1 xxxx */ - /* CMP (reg-shift reg) cccc 0001 0101 xxxx xxxx xxxx 0xx1 xxxx */ - /* CMN (reg-shift reg) cccc 0001 0111 xxxx xxxx xxxx 0xx1 xxxx */ - DECODE_EMULATEX (0x0f900090, 0x01100010, emulate_rd12rn16rm0rs8_rwflags, - REGS(ANY, 0, NOPC, 0, ANY)), - - /* MOV (reg-shift reg) cccc 0001 101x xxxx xxxx xxxx 0xx1 xxxx */ - /* MVN (reg-shift reg) cccc 0001 111x xxxx xxxx xxxx 0xx1 xxxx */ - DECODE_EMULATEX (0x0fa00090, 0x01a00010, emulate_rd12rn16rm0rs8_rwflags, - REGS(0, ANY, NOPC, 0, ANY)), - - /* AND (reg-shift reg) cccc 0000 000x xxxx xxxx xxxx 0xx1 xxxx */ - /* EOR (reg-shift reg) cccc 0000 001x xxxx xxxx xxxx 0xx1 xxxx */ - /* SUB (reg-shift reg) cccc 0000 010x xxxx xxxx xxxx 0xx1 xxxx */ - /* RSB (reg-shift reg) cccc 0000 011x xxxx xxxx xxxx 0xx1 xxxx */ - /* ADD (reg-shift reg) cccc 0000 100x xxxx xxxx xxxx 0xx1 xxxx */ - /* ADC (reg-shift reg) cccc 0000 101x xxxx xxxx xxxx 0xx1 xxxx */ - /* SBC (reg-shift reg) cccc 0000 110x xxxx xxxx xxxx 0xx1 xxxx */ - /* RSC (reg-shift reg) cccc 0000 111x xxxx xxxx xxxx 0xx1 xxxx */ - /* ORR (reg-shift reg) cccc 0001 100x xxxx xxxx xxxx 0xx1 xxxx */ - /* BIC (reg-shift reg) cccc 0001 110x xxxx xxxx xxxx 0xx1 xxxx */ - DECODE_EMULATEX (0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags, - REGS(ANY, ANY, NOPC, 0, ANY)), - - DECODE_END -}; - -static const union decode_item arm_cccc_001x_table[] = { - /* Data-processing (immediate) */ - - /* MOVW cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */ - /* MOVT cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0x0fb00000, 0x03000000, emulate_rd12rm0_noflags_nopc, - REGS(0, NOPC, 0, 0, 0)), - - /* YIELD cccc 0011 0010 0000 xxxx xxxx 0000 0001 */ - DECODE_OR (0x0fff00ff, 0x03200001), - /* SEV cccc 0011 0010 0000 xxxx xxxx 0000 0100 */ - DECODE_EMULATE (0x0fff00ff, 0x03200004, kprobe_emulate_none), - /* NOP cccc 0011 0010 0000 xxxx xxxx 0000 0000 */ - /* WFE cccc 0011 0010 0000 xxxx xxxx 0000 0010 */ - /* WFI cccc 0011 0010 0000 xxxx xxxx 0000 0011 */ - DECODE_SIMULATE (0x0fff00fc, 0x03200000, kprobe_simulate_nop), - /* DBG cccc 0011 0010 0000 xxxx xxxx ffff xxxx */ - /* unallocated hints cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */ - /* MSR (immediate) cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx */ - DECODE_REJECT (0x0fb00000, 0x03200000), - - /* <op>S PC, ... cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx */ - DECODE_REJECT (0x0e10f000, 0x0210f000), - - /* TST (immediate) cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx */ - /* TEQ (immediate) cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx */ - /* CMP (immediate) cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx */ - /* CMN (immediate) cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0x0f900000, 0x03100000, emulate_rd12rn16rm0rs8_rwflags, - REGS(ANY, 0, 0, 0, 0)), - - /* MOV (immediate) cccc 0011 101x xxxx xxxx xxxx xxxx xxxx */ - /* MVN (immediate) cccc 0011 111x xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0x0fa00000, 0x03a00000, emulate_rd12rn16rm0rs8_rwflags, - REGS(0, ANY, 0, 0, 0)), - - /* AND (immediate) cccc 0010 000x xxxx xxxx xxxx xxxx xxxx */ - /* EOR (immediate) cccc 0010 001x xxxx xxxx xxxx xxxx xxxx */ - /* SUB (immediate) cccc 0010 010x xxxx xxxx xxxx xxxx xxxx */ - /* RSB (immediate) cccc 0010 011x xxxx xxxx xxxx xxxx xxxx */ - /* ADD (immediate) cccc 0010 100x xxxx xxxx xxxx xxxx xxxx */ - /* ADC (immediate) cccc 0010 101x xxxx xxxx xxxx xxxx xxxx */ - /* SBC (immediate) cccc 0010 110x xxxx xxxx xxxx xxxx xxxx */ - /* RSC (immediate) cccc 0010 111x xxxx xxxx xxxx xxxx xxxx */ - /* ORR (immediate) cccc 0011 100x xxxx xxxx xxxx xxxx xxxx */ - /* BIC (immediate) cccc 0011 110x xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0x0e000000, 0x02000000, emulate_rd12rn16rm0rs8_rwflags, - REGS(ANY, ANY, 0, 0, 0)), - - DECODE_END -}; - -static const union decode_item arm_cccc_0110_____xxx1_table[] = { - /* Media instructions */ - - /* SEL cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx */ - DECODE_EMULATEX (0x0ff000f0, 0x068000b0, emulate_rd12rn16rm0_rwflags_nopc, - REGS(NOPC, NOPC, 0, 0, NOPC)), - - /* SSAT cccc 0110 101x xxxx xxxx xxxx xx01 xxxx */ - /* USAT cccc 0110 111x xxxx xxxx xxxx xx01 xxxx */ - DECODE_OR(0x0fa00030, 0x06a00010), - /* SSAT16 cccc 0110 1010 xxxx xxxx xxxx 0011 xxxx */ - /* USAT16 cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx */ - DECODE_EMULATEX (0x0fb000f0, 0x06a00030, emulate_rd12rn16rm0_rwflags_nopc, - REGS(0, NOPC, 0, 0, NOPC)), - - /* REV cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */ - /* REV16 cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */ - /* RBIT cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */ - /* REVSH cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */ - DECODE_EMULATEX (0x0fb00070, 0x06b00030, emulate_rd12rm0_noflags_nopc, - REGS(0, NOPC, 0, 0, NOPC)), - - /* ??? cccc 0110 0x00 xxxx xxxx xxxx xxx1 xxxx */ - DECODE_REJECT (0x0fb00010, 0x06000010), - /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1011 xxxx */ - DECODE_REJECT (0x0f8000f0, 0x060000b0), - /* ??? cccc 0110 0xxx xxxx xxxx xxxx 1101 xxxx */ - DECODE_REJECT (0x0f8000f0, 0x060000d0), - /* SADD16 cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx */ - /* SADDSUBX cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx */ - /* SSUBADDX cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx */ - /* SSUB16 cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx */ - /* SADD8 cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx */ - /* SSUB8 cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx */ - /* QADD16 cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx */ - /* QADDSUBX cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx */ - /* QSUBADDX cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx */ - /* QSUB16 cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx */ - /* QADD8 cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx */ - /* QSUB8 cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx */ - /* SHADD16 cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx */ - /* SHADDSUBX cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx */ - /* SHSUBADDX cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx */ - /* SHSUB16 cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx */ - /* SHADD8 cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx */ - /* SHSUB8 cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx */ - /* UADD16 cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx */ - /* UADDSUBX cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx */ - /* USUBADDX cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx */ - /* USUB16 cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx */ - /* UADD8 cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx */ - /* USUB8 cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx */ - /* UQADD16 cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx */ - /* UQADDSUBX cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx */ - /* UQSUBADDX cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx */ - /* UQSUB16 cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx */ - /* UQADD8 cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx */ - /* UQSUB8 cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx */ - /* UHADD16 cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx */ - /* UHADDSUBX cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx */ - /* UHSUBADDX cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx */ - /* UHSUB16 cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx */ - /* UHADD8 cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx */ - /* UHSUB8 cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx */ - DECODE_EMULATEX (0x0f800010, 0x06000010, emulate_rd12rn16rm0_rwflags_nopc, - REGS(NOPC, NOPC, 0, 0, NOPC)), - - /* PKHBT cccc 0110 1000 xxxx xxxx xxxx x001 xxxx */ - /* PKHTB cccc 0110 1000 xxxx xxxx xxxx x101 xxxx */ - DECODE_EMULATEX (0x0ff00030, 0x06800010, emulate_rd12rn16rm0_rwflags_nopc, - REGS(NOPC, NOPC, 0, 0, NOPC)), - - /* ??? cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx */ - /* ??? cccc 0110 1101 xxxx xxxx xxxx 0111 xxxx */ - DECODE_REJECT (0x0fb000f0, 0x06900070), - - /* SXTB16 cccc 0110 1000 1111 xxxx xxxx 0111 xxxx */ - /* SXTB cccc 0110 1010 1111 xxxx xxxx 0111 xxxx */ - /* SXTH cccc 0110 1011 1111 xxxx xxxx 0111 xxxx */ - /* UXTB16 cccc 0110 1100 1111 xxxx xxxx 0111 xxxx */ - /* UXTB cccc 0110 1110 1111 xxxx xxxx 0111 xxxx */ - /* UXTH cccc 0110 1111 1111 xxxx xxxx 0111 xxxx */ - DECODE_EMULATEX (0x0f8f00f0, 0x068f0070, emulate_rd12rm0_noflags_nopc, - REGS(0, NOPC, 0, 0, NOPC)), - - /* SXTAB16 cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx */ - /* SXTAB cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx */ - /* SXTAH cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx */ - /* UXTAB16 cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx */ - /* UXTAB cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx */ - /* UXTAH cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx */ - DECODE_EMULATEX (0x0f8000f0, 0x06800070, emulate_rd12rn16rm0_rwflags_nopc, - REGS(NOPCX, NOPC, 0, 0, NOPC)), - - DECODE_END -}; - -static const union decode_item arm_cccc_0111_____xxx1_table[] = { - /* Media instructions */ - - /* UNDEFINED cccc 0111 1111 xxxx xxxx xxxx 1111 xxxx */ - DECODE_REJECT (0x0ff000f0, 0x07f000f0), - - /* SMLALD cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */ - /* SMLSLD cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */ - DECODE_EMULATEX (0x0ff00090, 0x07400010, emulate_rdlo12rdhi16rn0rm8_rwflags_nopc, - REGS(NOPC, NOPC, NOPC, 0, NOPC)), - - /* SMUAD cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx */ - /* SMUSD cccc 0111 0000 xxxx 1111 xxxx 01x1 xxxx */ - DECODE_OR (0x0ff0f090, 0x0700f010), - /* SMMUL cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx */ - DECODE_OR (0x0ff0f0d0, 0x0750f010), - /* USAD8 cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx */ - DECODE_EMULATEX (0x0ff0f0f0, 0x0780f010, emulate_rd16rn12rm0rs8_rwflags_nopc, - REGS(NOPC, 0, NOPC, 0, NOPC)), - - /* SMLAD cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx */ - /* SMLSD cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx */ - DECODE_OR (0x0ff00090, 0x07000010), - /* SMMLA cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx */ - DECODE_OR (0x0ff000d0, 0x07500010), - /* USADA8 cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx */ - DECODE_EMULATEX (0x0ff000f0, 0x07800010, emulate_rd16rn12rm0rs8_rwflags_nopc, - REGS(NOPC, NOPCX, NOPC, 0, NOPC)), - - /* SMMLS cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx */ - DECODE_EMULATEX (0x0ff000d0, 0x075000d0, emulate_rd16rn12rm0rs8_rwflags_nopc, - REGS(NOPC, NOPC, NOPC, 0, NOPC)), - - /* SBFX cccc 0111 101x xxxx xxxx xxxx x101 xxxx */ - /* UBFX cccc 0111 111x xxxx xxxx xxxx x101 xxxx */ - DECODE_EMULATEX (0x0fa00070, 0x07a00050, emulate_rd12rm0_noflags_nopc, - REGS(0, NOPC, 0, 0, NOPC)), - - /* BFC cccc 0111 110x xxxx xxxx xxxx x001 1111 */ - DECODE_EMULATEX (0x0fe0007f, 0x07c0001f, emulate_rd12rm0_noflags_nopc, - REGS(0, NOPC, 0, 0, 0)), - - /* BFI cccc 0111 110x xxxx xxxx xxxx x001 xxxx */ - DECODE_EMULATEX (0x0fe00070, 0x07c00010, emulate_rd12rm0_noflags_nopc, - REGS(0, NOPC, 0, 0, NOPCX)), - - DECODE_END -}; - -static const union decode_item arm_cccc_01xx_table[] = { - /* Load/store word and unsigned byte */ - - /* LDRB/STRB pc,[...] cccc 01xx x0xx xxxx xxxx xxxx xxxx xxxx */ - DECODE_REJECT (0x0c40f000, 0x0440f000), - - /* STRT cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */ - /* LDRT cccc 01x0 x011 xxxx xxxx xxxx xxxx xxxx */ - /* STRBT cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */ - /* LDRBT cccc 01x0 x111 xxxx xxxx xxxx xxxx xxxx */ - DECODE_REJECT (0x0d200000, 0x04200000), - - /* STR (immediate) cccc 010x x0x0 xxxx xxxx xxxx xxxx xxxx */ - /* STRB (immediate) cccc 010x x1x0 xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0x0e100000, 0x04000000, emulate_str, - REGS(NOPCWB, ANY, 0, 0, 0)), - - /* LDR (immediate) cccc 010x x0x1 xxxx xxxx xxxx xxxx xxxx */ - /* LDRB (immediate) cccc 010x x1x1 xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0x0e100000, 0x04100000, emulate_ldr, - REGS(NOPCWB, ANY, 0, 0, 0)), - - /* STR (register) cccc 011x x0x0 xxxx xxxx xxxx xxxx xxxx */ - /* STRB (register) cccc 011x x1x0 xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0x0e100000, 0x06000000, emulate_str, - REGS(NOPCWB, ANY, 0, 0, NOPC)), - - /* LDR (register) cccc 011x x0x1 xxxx xxxx xxxx xxxx xxxx */ - /* LDRB (register) cccc 011x x1x1 xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0x0e100000, 0x06100000, emulate_ldr, - REGS(NOPCWB, ANY, 0, 0, NOPC)), - - DECODE_END -}; - -static const union decode_item arm_cccc_100x_table[] = { - /* Block data transfer instructions */ - - /* LDM cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */ - /* STM cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */ - DECODE_CUSTOM (0x0e400000, 0x08000000, kprobe_decode_ldmstm), - - /* STM (user registers) cccc 100x x1x0 xxxx xxxx xxxx xxxx xxxx */ - /* LDM (user registers) cccc 100x x1x1 xxxx 0xxx xxxx xxxx xxxx */ - /* LDM (exception ret) cccc 100x x1x1 xxxx 1xxx xxxx xxxx xxxx */ - DECODE_END -}; - -const union decode_item kprobe_decode_arm_table[] = { - /* - * Unconditional instructions - * 1111 xxxx xxxx xxxx xxxx xxxx xxxx xxxx - */ - DECODE_TABLE (0xf0000000, 0xf0000000, arm_1111_table), - - /* - * Miscellaneous instructions - * cccc 0001 0xx0 xxxx xxxx xxxx 0xxx xxxx - */ - DECODE_TABLE (0x0f900080, 0x01000000, arm_cccc_0001_0xx0____0xxx_table), - - /* - * Halfword multiply and multiply-accumulate - * cccc 0001 0xx0 xxxx xxxx xxxx 1xx0 xxxx - */ - DECODE_TABLE (0x0f900090, 0x01000080, arm_cccc_0001_0xx0____1xx0_table), - - /* - * Multiply and multiply-accumulate - * cccc 0000 xxxx xxxx xxxx xxxx 1001 xxxx - */ - DECODE_TABLE (0x0f0000f0, 0x00000090, arm_cccc_0000_____1001_table), - - /* - * Synchronization primitives - * cccc 0001 xxxx xxxx xxxx xxxx 1001 xxxx - */ - DECODE_TABLE (0x0f0000f0, 0x01000090, arm_cccc_0001_____1001_table), - - /* - * Extra load/store instructions - * cccc 000x xxxx xxxx xxxx xxxx 1xx1 xxxx - */ - DECODE_TABLE (0x0e000090, 0x00000090, arm_cccc_000x_____1xx1_table), - - /* - * Data-processing (register) - * cccc 000x xxxx xxxx xxxx xxxx xxx0 xxxx - * Data-processing (register-shifted register) - * cccc 000x xxxx xxxx xxxx xxxx 0xx1 xxxx - */ - DECODE_TABLE (0x0e000000, 0x00000000, arm_cccc_000x_table), - - /* - * Data-processing (immediate) - * cccc 001x xxxx xxxx xxxx xxxx xxxx xxxx - */ - DECODE_TABLE (0x0e000000, 0x02000000, arm_cccc_001x_table), - - /* - * Media instructions - * cccc 011x xxxx xxxx xxxx xxxx xxx1 xxxx - */ - DECODE_TABLE (0x0f000010, 0x06000010, arm_cccc_0110_____xxx1_table), - DECODE_TABLE (0x0f000010, 0x07000010, arm_cccc_0111_____xxx1_table), - - /* - * Load/store word and unsigned byte - * cccc 01xx xxxx xxxx xxxx xxxx xxxx xxxx - */ - DECODE_TABLE (0x0c000000, 0x04000000, arm_cccc_01xx_table), - - /* - * Block data transfer instructions - * cccc 100x xxxx xxxx xxxx xxxx xxxx xxxx - */ - DECODE_TABLE (0x0e000000, 0x08000000, arm_cccc_100x_table), - - /* B cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */ - /* BL cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */ - DECODE_SIMULATE (0x0e000000, 0x0a000000, simulate_bbl), - - /* - * Supervisor Call, and coprocessor instructions - */ - - /* MCRR cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx */ - /* MRRC cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx */ - /* LDC cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */ - /* STC cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */ - /* CDP cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */ - /* MCR cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */ - /* MRC cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */ - /* SVC cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */ - DECODE_REJECT (0x0c000000, 0x0c000000), - - DECODE_END -}; -#ifdef CONFIG_ARM_KPROBES_TEST_MODULE -EXPORT_SYMBOL_GPL(kprobe_decode_arm_table); -#endif - -static void __kprobes arm_singlestep(struct kprobe *p, struct pt_regs *regs) -{ - regs->ARM_pc += 4; - p->ainsn.insn_handler(p, regs); -} - -/* Return: - * INSN_REJECTED If instruction is one not allowed to kprobe, - * INSN_GOOD If instruction is supported and uses instruction slot, - * INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot. - * - * For instructions we don't want to kprobe (INSN_REJECTED return result): - * These are generally ones that modify the processor state making - * them "hard" to simulate such as switches processor modes or - * make accesses in alternate modes. Any of these could be simulated - * if the work was put into it, but low return considering they - * should also be very rare. - */ -enum kprobe_insn __kprobes -arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) -{ - asi->insn_singlestep = arm_singlestep; - asi->insn_check_cc = kprobe_condition_checks[insn>>28]; - return kprobe_decode_insn(insn, asi, kprobe_decode_arm_table, false); -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/kprobes-common.c b/ANDROID_3.4.5/arch/arm/kernel/kprobes-common.c deleted file mode 100644 index 18a76282..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/kprobes-common.c +++ /dev/null @@ -1,578 +0,0 @@ -/* - * arch/arm/kernel/kprobes-common.c - * - * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. - * - * Some contents moved here from arch/arm/include/asm/kprobes-arm.c which is - * Copyright (C) 2006, 2007 Motorola Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/kernel.h> -#include <linux/kprobes.h> -#include <asm/system_info.h> - -#include "kprobes.h" - - -#ifndef find_str_pc_offset - -/* - * For STR and STM instructions, an ARM core may choose to use either - * a +8 or a +12 displacement from the current instruction's address. - * Whichever value is chosen for a given core, it must be the same for - * both instructions and may not change. This function measures it. - */ - -int str_pc_offset; - -void __init find_str_pc_offset(void) -{ - int addr, scratch, ret; - - __asm__ ( - "sub %[ret], pc, #4 \n\t" - "str pc, %[addr] \n\t" - "ldr %[scr], %[addr] \n\t" - "sub %[ret], %[scr], %[ret] \n\t" - : [ret] "=r" (ret), [scr] "=r" (scratch), [addr] "+m" (addr)); - - str_pc_offset = ret; -} - -#endif /* !find_str_pc_offset */ - - -#ifndef test_load_write_pc_interworking - -bool load_write_pc_interworks; - -void __init test_load_write_pc_interworking(void) -{ - int arch = cpu_architecture(); - BUG_ON(arch == CPU_ARCH_UNKNOWN); - load_write_pc_interworks = arch >= CPU_ARCH_ARMv5T; -} - -#endif /* !test_load_write_pc_interworking */ - - -#ifndef test_alu_write_pc_interworking - -bool alu_write_pc_interworks; - -void __init test_alu_write_pc_interworking(void) -{ - int arch = cpu_architecture(); - BUG_ON(arch == CPU_ARCH_UNKNOWN); - alu_write_pc_interworks = arch >= CPU_ARCH_ARMv7; -} - -#endif /* !test_alu_write_pc_interworking */ - - -void __init arm_kprobe_decode_init(void) -{ - find_str_pc_offset(); - test_load_write_pc_interworking(); - test_alu_write_pc_interworking(); -} - - -static unsigned long __kprobes __check_eq(unsigned long cpsr) -{ - return cpsr & PSR_Z_BIT; -} - -static unsigned long __kprobes __check_ne(unsigned long cpsr) -{ - return (~cpsr) & PSR_Z_BIT; -} - -static unsigned long __kprobes __check_cs(unsigned long cpsr) -{ - return cpsr & PSR_C_BIT; -} - -static unsigned long __kprobes __check_cc(unsigned long cpsr) -{ - return (~cpsr) & PSR_C_BIT; -} - -static unsigned long __kprobes __check_mi(unsigned long cpsr) -{ - return cpsr & PSR_N_BIT; -} - -static unsigned long __kprobes __check_pl(unsigned long cpsr) -{ - return (~cpsr) & PSR_N_BIT; -} - -static unsigned long __kprobes __check_vs(unsigned long cpsr) -{ - return cpsr & PSR_V_BIT; -} - -static unsigned long __kprobes __check_vc(unsigned long cpsr) -{ - return (~cpsr) & PSR_V_BIT; -} - -static unsigned long __kprobes __check_hi(unsigned long cpsr) -{ - cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ - return cpsr & PSR_C_BIT; -} - -static unsigned long __kprobes __check_ls(unsigned long cpsr) -{ - cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */ - return (~cpsr) & PSR_C_BIT; -} - -static unsigned long __kprobes __check_ge(unsigned long cpsr) -{ - cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ - return (~cpsr) & PSR_N_BIT; -} - -static unsigned long __kprobes __check_lt(unsigned long cpsr) -{ - cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ - return cpsr & PSR_N_BIT; -} - -static unsigned long __kprobes __check_gt(unsigned long cpsr) -{ - unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ - temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ - return (~temp) & PSR_N_BIT; -} - -static unsigned long __kprobes __check_le(unsigned long cpsr) -{ - unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */ - temp |= (cpsr << 1); /* PSR_N_BIT |= PSR_Z_BIT */ - return temp & PSR_N_BIT; -} - -static unsigned long __kprobes __check_al(unsigned long cpsr) -{ - return true; -} - -kprobe_check_cc * const kprobe_condition_checks[16] = { - &__check_eq, &__check_ne, &__check_cs, &__check_cc, - &__check_mi, &__check_pl, &__check_vs, &__check_vc, - &__check_hi, &__check_ls, &__check_ge, &__check_lt, - &__check_gt, &__check_le, &__check_al, &__check_al -}; - - -void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs) -{ -} - -void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs) -{ - p->ainsn.insn_fn(); -} - -static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - int rn = (insn >> 16) & 0xf; - int lbit = insn & (1 << 20); - int wbit = insn & (1 << 21); - int ubit = insn & (1 << 23); - int pbit = insn & (1 << 24); - long *addr = (long *)regs->uregs[rn]; - int reg_bit_vector; - int reg_count; - - reg_count = 0; - reg_bit_vector = insn & 0xffff; - while (reg_bit_vector) { - reg_bit_vector &= (reg_bit_vector - 1); - ++reg_count; - } - - if (!ubit) - addr -= reg_count; - addr += (!pbit == !ubit); - - reg_bit_vector = insn & 0xffff; - while (reg_bit_vector) { - int reg = __ffs(reg_bit_vector); - reg_bit_vector &= (reg_bit_vector - 1); - if (lbit) - regs->uregs[reg] = *addr++; - else - *addr++ = regs->uregs[reg]; - } - - if (wbit) { - if (!ubit) - addr -= reg_count; - addr -= (!pbit == !ubit); - regs->uregs[rn] = (long)addr; - } -} - -static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs) -{ - regs->ARM_pc = (long)p->addr + str_pc_offset; - simulate_ldm1stm1(p, regs); - regs->ARM_pc = (long)p->addr + 4; -} - -static void __kprobes simulate_ldm1_pc(struct kprobe *p, struct pt_regs *regs) -{ - simulate_ldm1stm1(p, regs); - load_write_pc(regs->ARM_pc, regs); -} - -static void __kprobes -emulate_generic_r0_12_noflags(struct kprobe *p, struct pt_regs *regs) -{ - register void *rregs asm("r1") = regs; - register void *rfn asm("lr") = p->ainsn.insn_fn; - - __asm__ __volatile__ ( - "stmdb sp!, {%[regs], r11} \n\t" - "ldmia %[regs], {r0-r12} \n\t" -#if __LINUX_ARM_ARCH__ >= 6 - "blx %[fn] \n\t" -#else - "str %[fn], [sp, #-4]! \n\t" - "adr lr, 1f \n\t" - "ldr pc, [sp], #4 \n\t" - "1: \n\t" -#endif - "ldr lr, [sp], #4 \n\t" /* lr = regs */ - "stmia lr, {r0-r12} \n\t" - "ldr r11, [sp], #4 \n\t" - : [regs] "=r" (rregs), [fn] "=r" (rfn) - : "0" (rregs), "1" (rfn) - : "r0", "r2", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r12", "memory", "cc" - ); -} - -static void __kprobes -emulate_generic_r2_14_noflags(struct kprobe *p, struct pt_regs *regs) -{ - emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+2)); -} - -static void __kprobes -emulate_ldm_r3_15(struct kprobe *p, struct pt_regs *regs) -{ - emulate_generic_r0_12_noflags(p, (struct pt_regs *)(regs->uregs+3)); - load_write_pc(regs->ARM_pc, regs); -} - -enum kprobe_insn __kprobes -kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi) -{ - kprobe_insn_handler_t *handler = 0; - unsigned reglist = insn & 0xffff; - int is_ldm = insn & 0x100000; - int rn = (insn >> 16) & 0xf; - - if (rn <= 12 && (reglist & 0xe000) == 0) { - /* Instruction only uses registers in the range R0..R12 */ - handler = emulate_generic_r0_12_noflags; - - } else if (rn >= 2 && (reglist & 0x8003) == 0) { - /* Instruction only uses registers in the range R2..R14 */ - rn -= 2; - reglist >>= 2; - handler = emulate_generic_r2_14_noflags; - - } else if (rn >= 3 && (reglist & 0x0007) == 0) { - /* Instruction only uses registers in the range R3..R15 */ - if (is_ldm && (reglist & 0x8000)) { - rn -= 3; - reglist >>= 3; - handler = emulate_ldm_r3_15; - } - } - - if (handler) { - /* We can emulate the instruction in (possibly) modified form */ - asi->insn[0] = (insn & 0xfff00000) | (rn << 16) | reglist; - asi->insn_handler = handler; - return INSN_GOOD; - } - - /* Fallback to slower simulation... */ - if (reglist & 0x8000) - handler = is_ldm ? simulate_ldm1_pc : simulate_stm1_pc; - else - handler = simulate_ldm1stm1; - asi->insn_handler = handler; - return INSN_GOOD_NO_SLOT; -} - - -/* - * Prepare an instruction slot to receive an instruction for emulating. - * This is done by placing a subroutine return after the location where the - * instruction will be placed. We also modify ARM instructions to be - * unconditional as the condition code will already be checked before any - * emulation handler is called. - */ -static kprobe_opcode_t __kprobes -prepare_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, - bool thumb) -{ -#ifdef CONFIG_THUMB2_KERNEL - if (thumb) { - u16 *thumb_insn = (u16 *)asi->insn; - thumb_insn[1] = 0x4770; /* Thumb bx lr */ - thumb_insn[2] = 0x4770; /* Thumb bx lr */ - return insn; - } - asi->insn[1] = 0xe12fff1e; /* ARM bx lr */ -#else - asi->insn[1] = 0xe1a0f00e; /* mov pc, lr */ -#endif - /* Make an ARM instruction unconditional */ - if (insn < 0xe0000000) - insn = (insn | 0xe0000000) & ~0x10000000; - return insn; -} - -/* - * Write a (probably modified) instruction into the slot previously prepared by - * prepare_emulated_insn - */ -static void __kprobes -set_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, - bool thumb) -{ -#ifdef CONFIG_THUMB2_KERNEL - if (thumb) { - u16 *ip = (u16 *)asi->insn; - if (is_wide_instruction(insn)) - *ip++ = insn >> 16; - *ip++ = insn; - return; - } -#endif - asi->insn[0] = insn; -} - -/* - * When we modify the register numbers encoded in an instruction to be emulated, - * the new values come from this define. For ARM and 32-bit Thumb instructions - * this gives... - * - * bit position 16 12 8 4 0 - * ---------------+---+---+---+---+---+ - * register r2 r0 r1 -- r3 - */ -#define INSN_NEW_BITS 0x00020103 - -/* Each nibble has same value as that at INSN_NEW_BITS bit 16 */ -#define INSN_SAMEAS16_BITS 0x22222222 - -/* - * Validate and modify each of the registers encoded in an instruction. - * - * Each nibble in regs contains a value from enum decode_reg_type. For each - * non-zero value, the corresponding nibble in pinsn is validated and modified - * according to the type. - */ -static bool __kprobes decode_regs(kprobe_opcode_t* pinsn, u32 regs) -{ - kprobe_opcode_t insn = *pinsn; - kprobe_opcode_t mask = 0xf; /* Start at least significant nibble */ - - for (; regs != 0; regs >>= 4, mask <<= 4) { - - kprobe_opcode_t new_bits = INSN_NEW_BITS; - - switch (regs & 0xf) { - - case REG_TYPE_NONE: - /* Nibble not a register, skip to next */ - continue; - - case REG_TYPE_ANY: - /* Any register is allowed */ - break; - - case REG_TYPE_SAMEAS16: - /* Replace register with same as at bit position 16 */ - new_bits = INSN_SAMEAS16_BITS; - break; - - case REG_TYPE_SP: - /* Only allow SP (R13) */ - if ((insn ^ 0xdddddddd) & mask) - goto reject; - break; - - case REG_TYPE_PC: - /* Only allow PC (R15) */ - if ((insn ^ 0xffffffff) & mask) - goto reject; - break; - - case REG_TYPE_NOSP: - /* Reject SP (R13) */ - if (((insn ^ 0xdddddddd) & mask) == 0) - goto reject; - break; - - case REG_TYPE_NOSPPC: - case REG_TYPE_NOSPPCX: - /* Reject SP and PC (R13 and R15) */ - if (((insn ^ 0xdddddddd) & 0xdddddddd & mask) == 0) - goto reject; - break; - - case REG_TYPE_NOPCWB: - if (!is_writeback(insn)) - break; /* No writeback, so any register is OK */ - /* fall through... */ - case REG_TYPE_NOPC: - case REG_TYPE_NOPCX: - /* Reject PC (R15) */ - if (((insn ^ 0xffffffff) & mask) == 0) - goto reject; - break; - } - - /* Replace value of nibble with new register number... */ - insn &= ~mask; - insn |= new_bits & mask; - } - - *pinsn = insn; - return true; - -reject: - return false; -} - -static const int decode_struct_sizes[NUM_DECODE_TYPES] = { - [DECODE_TYPE_TABLE] = sizeof(struct decode_table), - [DECODE_TYPE_CUSTOM] = sizeof(struct decode_custom), - [DECODE_TYPE_SIMULATE] = sizeof(struct decode_simulate), - [DECODE_TYPE_EMULATE] = sizeof(struct decode_emulate), - [DECODE_TYPE_OR] = sizeof(struct decode_or), - [DECODE_TYPE_REJECT] = sizeof(struct decode_reject) -}; - -/* - * kprobe_decode_insn operates on data tables in order to decode an ARM - * architecture instruction onto which a kprobe has been placed. - * - * These instruction decoding tables are a concatenation of entries each - * of which consist of one of the following structs: - * - * decode_table - * decode_custom - * decode_simulate - * decode_emulate - * decode_or - * decode_reject - * - * Each of these starts with a struct decode_header which has the following - * fields: - * - * type_regs - * mask - * value - * - * The least significant DECODE_TYPE_BITS of type_regs contains a value - * from enum decode_type, this indicates which of the decode_* structs - * the entry contains. The value DECODE_TYPE_END indicates the end of the - * table. - * - * When the table is parsed, each entry is checked in turn to see if it - * matches the instruction to be decoded using the test: - * - * (insn & mask) == value - * - * If no match is found before the end of the table is reached then decoding - * fails with INSN_REJECTED. - * - * When a match is found, decode_regs() is called to validate and modify each - * of the registers encoded in the instruction; the data it uses to do this - * is (type_regs >> DECODE_TYPE_BITS). A validation failure will cause decoding - * to fail with INSN_REJECTED. - * - * Once the instruction has passed the above tests, further processing - * depends on the type of the table entry's decode struct. - * - */ -int __kprobes -kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, - const union decode_item *table, bool thumb) -{ - const struct decode_header *h = (struct decode_header *)table; - const struct decode_header *next; - bool matched = false; - - insn = prepare_emulated_insn(insn, asi, thumb); - - for (;; h = next) { - enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; - u32 regs = h->type_regs.bits >> DECODE_TYPE_BITS; - - if (type == DECODE_TYPE_END) - return INSN_REJECTED; - - next = (struct decode_header *) - ((uintptr_t)h + decode_struct_sizes[type]); - - if (!matched && (insn & h->mask.bits) != h->value.bits) - continue; - - if (!decode_regs(&insn, regs)) - return INSN_REJECTED; - - switch (type) { - - case DECODE_TYPE_TABLE: { - struct decode_table *d = (struct decode_table *)h; - next = (struct decode_header *)d->table.table; - break; - } - - case DECODE_TYPE_CUSTOM: { - struct decode_custom *d = (struct decode_custom *)h; - return (*d->decoder.decoder)(insn, asi); - } - - case DECODE_TYPE_SIMULATE: { - struct decode_simulate *d = (struct decode_simulate *)h; - asi->insn_handler = d->handler.handler; - return INSN_GOOD_NO_SLOT; - } - - case DECODE_TYPE_EMULATE: { - struct decode_emulate *d = (struct decode_emulate *)h; - asi->insn_handler = d->handler.handler; - set_emulated_insn(insn, asi, thumb); - return INSN_GOOD; - } - - case DECODE_TYPE_OR: - matched = true; - break; - - case DECODE_TYPE_REJECT: - default: - return INSN_REJECTED; - } - } - } diff --git a/ANDROID_3.4.5/arch/arm/kernel/kprobes-test-arm.c b/ANDROID_3.4.5/arch/arm/kernel/kprobes-test-arm.c deleted file mode 100644 index ba32b393..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/kprobes-test-arm.c +++ /dev/null @@ -1,1330 +0,0 @@ -/* - * arch/arm/kernel/kprobes-test-arm.c - * - * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/kernel.h> -#include <linux/module.h> - -#include "kprobes-test.h" - - -#define TEST_ISA "32" - -#define TEST_ARM_TO_THUMB_INTERWORK_R(code1, reg, val, code2) \ - TESTCASE_START(code1 #reg code2) \ - TEST_ARG_REG(reg, val) \ - TEST_ARG_REG(14, 99f) \ - TEST_ARG_END("") \ - "50: nop \n\t" \ - "1: "code1 #reg code2" \n\t" \ - " bx lr \n\t" \ - ".thumb \n\t" \ - "3: adr lr, 2f \n\t" \ - " bx lr \n\t" \ - ".arm \n\t" \ - "2: nop \n\t" \ - TESTCASE_END - -#define TEST_ARM_TO_THUMB_INTERWORK_P(code1, reg, val, code2) \ - TESTCASE_START(code1 #reg code2) \ - TEST_ARG_PTR(reg, val) \ - TEST_ARG_REG(14, 99f) \ - TEST_ARG_MEM(15, 3f+1) \ - TEST_ARG_END("") \ - "50: nop \n\t" \ - "1: "code1 #reg code2" \n\t" \ - " bx lr \n\t" \ - ".thumb \n\t" \ - "3: adr lr, 2f \n\t" \ - " bx lr \n\t" \ - ".arm \n\t" \ - "2: nop \n\t" \ - TESTCASE_END - - -void kprobe_arm_test_cases(void) -{ - kprobe_test_flags = 0; - - TEST_GROUP("Data-processing (register), (register-shifted register), (immediate)") - -#define _DATA_PROCESSING_DNM(op,s,val) \ - TEST_RR( op "eq" s " r0, r",1, VAL1,", r",2, val, "") \ - TEST_RR( op "ne" s " r1, r",1, VAL1,", r",2, val, ", lsl #3") \ - TEST_RR( op "cs" s " r2, r",3, VAL1,", r",2, val, ", lsr #4") \ - TEST_RR( op "cc" s " r3, r",3, VAL1,", r",2, val, ", asr #5") \ - TEST_RR( op "mi" s " r4, r",5, VAL1,", r",2, N(val),", asr #6") \ - TEST_RR( op "pl" s " r5, r",5, VAL1,", r",2, val, ", ror #7") \ - TEST_RR( op "vs" s " r6, r",7, VAL1,", r",2, val, ", rrx") \ - TEST_R( op "vc" s " r6, r",7, VAL1,", pc, lsl #3") \ - TEST_R( op "vc" s " r6, r",7, VAL1,", sp, lsr #4") \ - TEST_R( op "vc" s " r6, pc, r",7, VAL1,", asr #5") \ - TEST_R( op "vc" s " r6, sp, r",7, VAL1,", ror #6") \ - TEST_RRR( op "hi" s " r8, r",9, VAL1,", r",14,val, ", lsl r",0, 3,"")\ - TEST_RRR( op "ls" s " r9, r",9, VAL1,", r",14,val, ", lsr r",7, 4,"")\ - TEST_RRR( op "ge" s " r10, r",11,VAL1,", r",14,val, ", asr r",7, 5,"")\ - TEST_RRR( op "lt" s " r11, r",11,VAL1,", r",14,N(val),", asr r",7, 6,"")\ - TEST_RR( op "gt" s " r12, r13" ", r",14,val, ", ror r",14,7,"")\ - TEST_RR( op "le" s " r14, r",0, val, ", r13" ", lsl r",14,8,"")\ - TEST_RR( op s " r12, pc" ", r",14,val, ", ror r",14,7,"")\ - TEST_RR( op s " r14, r",0, val, ", pc" ", lsl r",14,8,"")\ - TEST_R( op "eq" s " r0, r",11,VAL1,", #0xf5") \ - TEST_R( op "ne" s " r11, r",0, VAL1,", #0xf5000000") \ - TEST_R( op s " r7, r",8, VAL2,", #0x000af000") \ - TEST( op s " r4, pc" ", #0x00005a00") - -#define DATA_PROCESSING_DNM(op,val) \ - _DATA_PROCESSING_DNM(op,"",val) \ - _DATA_PROCESSING_DNM(op,"s",val) - -#define DATA_PROCESSING_NM(op,val) \ - TEST_RR( op "ne r",1, VAL1,", r",2, val, "") \ - TEST_RR( op "eq r",1, VAL1,", r",2, val, ", lsl #3") \ - TEST_RR( op "cc r",3, VAL1,", r",2, val, ", lsr #4") \ - TEST_RR( op "cs r",3, VAL1,", r",2, val, ", asr #5") \ - TEST_RR( op "pl r",5, VAL1,", r",2, N(val),", asr #6") \ - TEST_RR( op "mi r",5, VAL1,", r",2, val, ", ror #7") \ - TEST_RR( op "vc r",7, VAL1,", r",2, val, ", rrx") \ - TEST_R ( op "vs r",7, VAL1,", pc, lsl #3") \ - TEST_R ( op "vs r",7, VAL1,", sp, lsr #4") \ - TEST_R( op "vs pc, r",7, VAL1,", asr #5") \ - TEST_R( op "vs sp, r",7, VAL1,", ror #6") \ - TEST_RRR( op "ls r",9, VAL1,", r",14,val, ", lsl r",0, 3,"") \ - TEST_RRR( op "hi r",9, VAL1,", r",14,val, ", lsr r",7, 4,"") \ - TEST_RRR( op "lt r",11,VAL1,", r",14,val, ", asr r",7, 5,"") \ - TEST_RRR( op "ge r",11,VAL1,", r",14,N(val),", asr r",7, 6,"") \ - TEST_RR( op "le r13" ", r",14,val, ", ror r",14,7,"") \ - TEST_RR( op "gt r",0, val, ", r13" ", lsl r",14,8,"") \ - TEST_RR( op " pc" ", r",14,val, ", ror r",14,7,"") \ - TEST_RR( op " r",0, val, ", pc" ", lsl r",14,8,"") \ - TEST_R( op "eq r",11,VAL1,", #0xf5") \ - TEST_R( op "ne r",0, VAL1,", #0xf5000000") \ - TEST_R( op " r",8, VAL2,", #0x000af000") - -#define _DATA_PROCESSING_DM(op,s,val) \ - TEST_R( op "eq" s " r0, r",1, val, "") \ - TEST_R( op "ne" s " r1, r",1, val, ", lsl #3") \ - TEST_R( op "cs" s " r2, r",3, val, ", lsr #4") \ - TEST_R( op "cc" s " r3, r",3, val, ", asr #5") \ - TEST_R( op "mi" s " r4, r",5, N(val),", asr #6") \ - TEST_R( op "pl" s " r5, r",5, val, ", ror #7") \ - TEST_R( op "vs" s " r6, r",10,val, ", rrx") \ - TEST( op "vs" s " r7, pc, lsl #3") \ - TEST( op "vs" s " r7, sp, lsr #4") \ - TEST_RR( op "vc" s " r8, r",7, val, ", lsl r",0, 3,"") \ - TEST_RR( op "hi" s " r9, r",9, val, ", lsr r",7, 4,"") \ - TEST_RR( op "ls" s " r10, r",9, val, ", asr r",7, 5,"") \ - TEST_RR( op "ge" s " r11, r",11,N(val),", asr r",7, 6,"") \ - TEST_RR( op "lt" s " r12, r",11,val, ", ror r",14,7,"") \ - TEST_R( op "gt" s " r14, r13" ", lsl r",14,8,"") \ - TEST_R( op "le" s " r14, pc" ", lsl r",14,8,"") \ - TEST( op "eq" s " r0, #0xf5") \ - TEST( op "ne" s " r11, #0xf5000000") \ - TEST( op s " r7, #0x000af000") \ - TEST( op s " r4, #0x00005a00") - -#define DATA_PROCESSING_DM(op,val) \ - _DATA_PROCESSING_DM(op,"",val) \ - _DATA_PROCESSING_DM(op,"s",val) - - DATA_PROCESSING_DNM("and",0xf00f00ff) - DATA_PROCESSING_DNM("eor",0xf00f00ff) - DATA_PROCESSING_DNM("sub",VAL2) - DATA_PROCESSING_DNM("rsb",VAL2) - DATA_PROCESSING_DNM("add",VAL2) - DATA_PROCESSING_DNM("adc",VAL2) - DATA_PROCESSING_DNM("sbc",VAL2) - DATA_PROCESSING_DNM("rsc",VAL2) - DATA_PROCESSING_NM("tst",0xf00f00ff) - DATA_PROCESSING_NM("teq",0xf00f00ff) - DATA_PROCESSING_NM("cmp",VAL2) - DATA_PROCESSING_NM("cmn",VAL2) - DATA_PROCESSING_DNM("orr",0xf00f00ff) - DATA_PROCESSING_DM("mov",VAL2) - DATA_PROCESSING_DNM("bic",0xf00f00ff) - DATA_PROCESSING_DM("mvn",VAL2) - - TEST("mov ip, sp") /* This has special case emulation code */ - - TEST_SUPPORTED("mov pc, #0x1000"); - TEST_SUPPORTED("mov sp, #0x1000"); - TEST_SUPPORTED("cmp pc, #0x1000"); - TEST_SUPPORTED("cmp sp, #0x1000"); - - /* Data-processing with PC as shift*/ - TEST_UNSUPPORTED(".word 0xe15c0f1e @ cmp r12, r14, asl pc") - TEST_UNSUPPORTED(".word 0xe1a0cf1e @ mov r12, r14, asl pc") - TEST_UNSUPPORTED(".word 0xe08caf1e @ add r10, r12, r14, asl pc") - - /* Data-processing with PC as shift*/ - TEST_UNSUPPORTED("movs pc, r1") - TEST_UNSUPPORTED("movs pc, r1, lsl r2") - TEST_UNSUPPORTED("movs pc, #0x10000") - TEST_UNSUPPORTED("adds pc, lr, r1") - TEST_UNSUPPORTED("adds pc, lr, r1, lsl r2") - TEST_UNSUPPORTED("adds pc, lr, #4") - - /* Data-processing with SP as target */ - TEST("add sp, sp, #16") - TEST("sub sp, sp, #8") - TEST("bic sp, sp, #0x20") - TEST("orr sp, sp, #0x20") - TEST_PR( "add sp, r",10,0,", r",11,4,"") - TEST_PRR("add sp, r",10,0,", r",11,4,", asl r",12,1,"") - TEST_P( "mov sp, r",10,0,"") - TEST_PR( "mov sp, r",10,0,", asl r",12,0,"") - - /* Data-processing with PC as target */ - TEST_BF( "add pc, pc, #2f-1b-8") - TEST_BF_R ("add pc, pc, r",14,2f-1f-8,"") - TEST_BF_R ("add pc, r",14,2f-1f-8,", pc") - TEST_BF_R ("mov pc, r",0,2f,"") - TEST_BF_RR("mov pc, r",0,2f,", asl r",1,0,"") - TEST_BB( "sub pc, pc, #1b-2b+8") -#if __LINUX_ARM_ARCH__ >= 6 - TEST_BB( "sub pc, pc, #1b-2b+8-2") /* UNPREDICTABLE before ARMv6 */ -#endif - TEST_BB_R( "sub pc, pc, r",14, 1f-2f+8,"") - TEST_BB_R( "rsb pc, r",14,1f-2f+8,", pc") - TEST_RR( "add pc, pc, r",10,-2,", asl r",11,1,"") -#ifdef CONFIG_THUMB2_KERNEL - TEST_ARM_TO_THUMB_INTERWORK_R("add pc, pc, r",0,3f-1f-8+1,"") - TEST_ARM_TO_THUMB_INTERWORK_R("sub pc, r",0,3f+8+1,", #8") -#endif - TEST_GROUP("Miscellaneous instructions") - - TEST("mrs r0, cpsr") - TEST("mrspl r7, cpsr") - TEST("mrs r14, cpsr") - TEST_UNSUPPORTED(".word 0xe10ff000 @ mrs r15, cpsr") - TEST_UNSUPPORTED("mrs r0, spsr") - TEST_UNSUPPORTED("mrs lr, spsr") - - TEST_UNSUPPORTED("msr cpsr, r0") - TEST_UNSUPPORTED("msr cpsr_f, lr") - TEST_UNSUPPORTED("msr spsr, r0") - - TEST_BF_R("bx r",0,2f,"") - TEST_BB_R("bx r",7,2f,"") - TEST_BF_R("bxeq r",14,2f,"") - - TEST_R("clz r0, r",0, 0x0,"") - TEST_R("clzeq r7, r",14,0x1,"") - TEST_R("clz lr, r",7, 0xffffffff,"") - TEST( "clz r4, sp") - TEST_UNSUPPORTED(".word 0x016fff10 @ clz pc, r0") - TEST_UNSUPPORTED(".word 0x016f0f1f @ clz r0, pc") - -#if __LINUX_ARM_ARCH__ >= 6 - TEST_UNSUPPORTED("bxj r0") -#endif - - TEST_BF_R("blx r",0,2f,"") - TEST_BB_R("blx r",7,2f,"") - TEST_BF_R("blxeq r",14,2f,"") - TEST_UNSUPPORTED(".word 0x0120003f @ blx pc") - - TEST_RR( "qadd r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR( "qaddvs lr, r",9, VAL2,", r",8, VAL1,"") - TEST_R( "qadd lr, r",9, VAL2,", r13") - TEST_RR( "qsub r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR( "qsubvs lr, r",9, VAL2,", r",8, VAL1,"") - TEST_R( "qsub lr, r",9, VAL2,", r13") - TEST_RR( "qdadd r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR( "qdaddvs lr, r",9, VAL2,", r",8, VAL1,"") - TEST_R( "qdadd lr, r",9, VAL2,", r13") - TEST_RR( "qdsub r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR( "qdsubvs lr, r",9, VAL2,", r",8, VAL1,"") - TEST_R( "qdsub lr, r",9, VAL2,", r13") - TEST_UNSUPPORTED(".word 0xe101f050 @ qadd pc, r0, r1") - TEST_UNSUPPORTED(".word 0xe121f050 @ qsub pc, r0, r1") - TEST_UNSUPPORTED(".word 0xe141f050 @ qdadd pc, r0, r1") - TEST_UNSUPPORTED(".word 0xe161f050 @ qdsub pc, r0, r1") - TEST_UNSUPPORTED(".word 0xe16f2050 @ qdsub r2, r0, pc") - TEST_UNSUPPORTED(".word 0xe161205f @ qdsub r2, pc, r1") - - TEST_UNSUPPORTED("bkpt 0xffff") - TEST_UNSUPPORTED("bkpt 0x0000") - - TEST_UNSUPPORTED(".word 0xe1600070 @ smc #0") - - TEST_GROUP("Halfword multiply and multiply-accumulate") - - TEST_RRR( "smlabb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") - TEST_RRR( "smlabbge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") - TEST_RR( "smlabb lr, r",1, VAL2,", r",2, VAL3,", r13") - TEST_UNSUPPORTED(".word 0xe10f3281 @ smlabb pc, r1, r2, r3") - TEST_RRR( "smlatb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") - TEST_RRR( "smlatbge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") - TEST_RR( "smlatb lr, r",1, VAL2,", r",2, VAL3,", r13") - TEST_UNSUPPORTED(".word 0xe10f32a1 @ smlatb pc, r1, r2, r3") - TEST_RRR( "smlabt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") - TEST_RRR( "smlabtge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") - TEST_RR( "smlabt lr, r",1, VAL2,", r",2, VAL3,", r13") - TEST_UNSUPPORTED(".word 0xe10f32c1 @ smlabt pc, r1, r2, r3") - TEST_RRR( "smlatt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") - TEST_RRR( "smlattge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") - TEST_RR( "smlatt lr, r",1, VAL2,", r",2, VAL3,", r13") - TEST_UNSUPPORTED(".word 0xe10f32e1 @ smlatt pc, r1, r2, r3") - - TEST_RRR( "smlawb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") - TEST_RRR( "smlawbge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") - TEST_RR( "smlawb lr, r",1, VAL2,", r",2, VAL3,", r13") - TEST_UNSUPPORTED(".word 0xe12f3281 @ smlawb pc, r1, r2, r3") - TEST_RRR( "smlawt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") - TEST_RRR( "smlawtge r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") - TEST_RR( "smlawt lr, r",1, VAL2,", r",2, VAL3,", r13") - TEST_UNSUPPORTED(".word 0xe12f32c1 @ smlawt pc, r1, r2, r3") - TEST_UNSUPPORTED(".word 0xe12032cf @ smlawt r0, pc, r2, r3") - TEST_UNSUPPORTED(".word 0xe1203fc1 @ smlawt r0, r1, pc, r3") - TEST_UNSUPPORTED(".word 0xe120f2c1 @ smlawt r0, r1, r2, pc") - - TEST_RR( "smulwb r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR( "smulwbge r7, r",8, VAL3,", r",9, VAL1,"") - TEST_R( "smulwb lr, r",1, VAL2,", r13") - TEST_UNSUPPORTED(".word 0xe12f02a1 @ smulwb pc, r1, r2") - TEST_RR( "smulwt r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR( "smulwtge r7, r",8, VAL3,", r",9, VAL1,"") - TEST_R( "smulwt lr, r",1, VAL2,", r13") - TEST_UNSUPPORTED(".word 0xe12f02e1 @ smulwt pc, r1, r2") - - TEST_RRRR( "smlalbb r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) - TEST_RRRR( "smlalbble r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) - TEST_RRR( "smlalbb r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13") - TEST_UNSUPPORTED(".word 0xe14f1382 @ smlalbb pc, r1, r2, r3") - TEST_UNSUPPORTED(".word 0xe141f382 @ smlalbb r1, pc, r2, r3") - TEST_RRRR( "smlaltb r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) - TEST_RRRR( "smlaltble r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) - TEST_RRR( "smlaltb r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13") - TEST_UNSUPPORTED(".word 0xe14f13a2 @ smlaltb pc, r1, r2, r3") - TEST_UNSUPPORTED(".word 0xe141f3a2 @ smlaltb r1, pc, r2, r3") - TEST_RRRR( "smlalbt r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) - TEST_RRRR( "smlalbtle r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) - TEST_RRR( "smlalbt r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13") - TEST_UNSUPPORTED(".word 0xe14f13c2 @ smlalbt pc, r1, r2, r3") - TEST_UNSUPPORTED(".word 0xe141f3c2 @ smlalbt r1, pc, r2, r3") - TEST_RRRR( "smlaltt r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) - TEST_RRRR( "smlalttle r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) - TEST_RRR( "smlaltt r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13") - TEST_UNSUPPORTED(".word 0xe14f13e2 @ smlalbb pc, r1, r2, r3") - TEST_UNSUPPORTED(".word 0xe140f3e2 @ smlalbb r0, pc, r2, r3") - TEST_UNSUPPORTED(".word 0xe14013ef @ smlalbb r0, r1, pc, r3") - TEST_UNSUPPORTED(".word 0xe1401fe2 @ smlalbb r0, r1, r2, pc") - - TEST_RR( "smulbb r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR( "smulbbge r7, r",8, VAL3,", r",9, VAL1,"") - TEST_R( "smulbb lr, r",1, VAL2,", r13") - TEST_UNSUPPORTED(".word 0xe16f0281 @ smulbb pc, r1, r2") - TEST_RR( "smultb r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR( "smultbge r7, r",8, VAL3,", r",9, VAL1,"") - TEST_R( "smultb lr, r",1, VAL2,", r13") - TEST_UNSUPPORTED(".word 0xe16f02a1 @ smultb pc, r1, r2") - TEST_RR( "smulbt r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR( "smulbtge r7, r",8, VAL3,", r",9, VAL1,"") - TEST_R( "smulbt lr, r",1, VAL2,", r13") - TEST_UNSUPPORTED(".word 0xe16f02c1 @ smultb pc, r1, r2") - TEST_RR( "smultt r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR( "smulttge r7, r",8, VAL3,", r",9, VAL1,"") - TEST_R( "smultt lr, r",1, VAL2,", r13") - TEST_UNSUPPORTED(".word 0xe16f02e1 @ smultt pc, r1, r2") - TEST_UNSUPPORTED(".word 0xe16002ef @ smultt r0, pc, r2") - TEST_UNSUPPORTED(".word 0xe1600fe1 @ smultt r0, r1, pc") - - TEST_GROUP("Multiply and multiply-accumulate") - - TEST_RR( "mul r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR( "mulls r7, r",8, VAL2,", r",9, VAL2,"") - TEST_R( "mul lr, r",4, VAL3,", r13") - TEST_UNSUPPORTED(".word 0xe00f0291 @ mul pc, r1, r2") - TEST_UNSUPPORTED(".word 0xe000029f @ mul r0, pc, r2") - TEST_UNSUPPORTED(".word 0xe0000f91 @ mul r0, r1, pc") - TEST_RR( "muls r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR( "mullss r7, r",8, VAL2,", r",9, VAL2,"") - TEST_R( "muls lr, r",4, VAL3,", r13") - TEST_UNSUPPORTED(".word 0xe01f0291 @ muls pc, r1, r2") - - TEST_RRR( "mla r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") - TEST_RRR( "mlahi r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") - TEST_RR( "mla lr, r",1, VAL2,", r",2, VAL3,", r13") - TEST_UNSUPPORTED(".word 0xe02f3291 @ mla pc, r1, r2, r3") - TEST_RRR( "mlas r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") - TEST_RRR( "mlahis r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") - TEST_RR( "mlas lr, r",1, VAL2,", r",2, VAL3,", r13") - TEST_UNSUPPORTED(".word 0xe03f3291 @ mlas pc, r1, r2, r3") - -#if __LINUX_ARM_ARCH__ >= 6 - TEST_RR( "umaal r0, r1, r",2, VAL1,", r",3, VAL2,"") - TEST_RR( "umaalls r7, r8, r",9, VAL2,", r",10, VAL1,"") - TEST_R( "umaal lr, r12, r",11,VAL3,", r13") - TEST_UNSUPPORTED(".word 0xe041f392 @ umaal pc, r1, r2, r3") - TEST_UNSUPPORTED(".word 0xe04f0392 @ umaal r0, pc, r2, r3") - TEST_UNSUPPORTED(".word 0xe0500090 @ undef") - TEST_UNSUPPORTED(".word 0xe05fff9f @ undef") - - TEST_RRR( "mls r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") - TEST_RRR( "mlshi r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") - TEST_RR( "mls lr, r",1, VAL2,", r",2, VAL3,", r13") - TEST_UNSUPPORTED(".word 0xe06f3291 @ mls pc, r1, r2, r3") - TEST_UNSUPPORTED(".word 0xe060329f @ mls r0, pc, r2, r3") - TEST_UNSUPPORTED(".word 0xe0603f91 @ mls r0, r1, pc, r3") - TEST_UNSUPPORTED(".word 0xe060f291 @ mls r0, r1, r2, pc") -#endif - - TEST_UNSUPPORTED(".word 0xe0700090 @ undef") - TEST_UNSUPPORTED(".word 0xe07fff9f @ undef") - - TEST_RR( "umull r0, r1, r",2, VAL1,", r",3, VAL2,"") - TEST_RR( "umullls r7, r8, r",9, VAL2,", r",10, VAL1,"") - TEST_R( "umull lr, r12, r",11,VAL3,", r13") - TEST_UNSUPPORTED(".word 0xe081f392 @ umull pc, r1, r2, r3") - TEST_UNSUPPORTED(".word 0xe08f1392 @ umull r1, pc, r2, r3") - TEST_RR( "umulls r0, r1, r",2, VAL1,", r",3, VAL2,"") - TEST_RR( "umulllss r7, r8, r",9, VAL2,", r",10, VAL1,"") - TEST_R( "umulls lr, r12, r",11,VAL3,", r13") - TEST_UNSUPPORTED(".word 0xe091f392 @ umulls pc, r1, r2, r3") - TEST_UNSUPPORTED(".word 0xe09f1392 @ umulls r1, pc, r2, r3") - - TEST_RRRR( "umlal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) - TEST_RRRR( "umlalle r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) - TEST_RRR( "umlal r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13") - TEST_UNSUPPORTED(".word 0xe0af1392 @ umlal pc, r1, r2, r3") - TEST_UNSUPPORTED(".word 0xe0a1f392 @ umlal r1, pc, r2, r3") - TEST_RRRR( "umlals r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) - TEST_RRRR( "umlalles r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) - TEST_RRR( "umlals r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13") - TEST_UNSUPPORTED(".word 0xe0bf1392 @ umlals pc, r1, r2, r3") - TEST_UNSUPPORTED(".word 0xe0b1f392 @ umlals r1, pc, r2, r3") - - TEST_RR( "smull r0, r1, r",2, VAL1,", r",3, VAL2,"") - TEST_RR( "smullls r7, r8, r",9, VAL2,", r",10, VAL1,"") - TEST_R( "smull lr, r12, r",11,VAL3,", r13") - TEST_UNSUPPORTED(".word 0xe0c1f392 @ smull pc, r1, r2, r3") - TEST_UNSUPPORTED(".word 0xe0cf1392 @ smull r1, pc, r2, r3") - TEST_RR( "smulls r0, r1, r",2, VAL1,", r",3, VAL2,"") - TEST_RR( "smulllss r7, r8, r",9, VAL2,", r",10, VAL1,"") - TEST_R( "smulls lr, r12, r",11,VAL3,", r13") - TEST_UNSUPPORTED(".word 0xe0d1f392 @ smulls pc, r1, r2, r3") - TEST_UNSUPPORTED(".word 0xe0df1392 @ smulls r1, pc, r2, r3") - - TEST_RRRR( "smlal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) - TEST_RRRR( "smlalle r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) - TEST_RRR( "smlal r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13") - TEST_UNSUPPORTED(".word 0xe0ef1392 @ smlal pc, r1, r2, r3") - TEST_UNSUPPORTED(".word 0xe0e1f392 @ smlal r1, pc, r2, r3") - TEST_RRRR( "smlals r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) - TEST_RRRR( "smlalles r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) - TEST_RRR( "smlals r",14,VAL3,", r",7, VAL4,", r",5, VAL1,", r13") - TEST_UNSUPPORTED(".word 0xe0ff1392 @ smlals pc, r1, r2, r3") - TEST_UNSUPPORTED(".word 0xe0f0f392 @ smlals r0, pc, r2, r3") - TEST_UNSUPPORTED(".word 0xe0f0139f @ smlals r0, r1, pc, r3") - TEST_UNSUPPORTED(".word 0xe0f01f92 @ smlals r0, r1, r2, pc") - - TEST_GROUP("Synchronization primitives") - -#if __LINUX_ARM_ARCH__ < 6 - TEST_RP("swp lr, r",7,VAL2,", [r",8,0,"]") - TEST_R( "swpvs r0, r",1,VAL1,", [sp]") - TEST_RP("swp sp, r",14,VAL2,", [r",12,13*4,"]") -#else - TEST_UNSUPPORTED(".word 0xe108e097 @ swp lr, r7, [r8]") - TEST_UNSUPPORTED(".word 0x610d0091 @ swpvs r0, r1, [sp]") - TEST_UNSUPPORTED(".word 0xe10cd09e @ swp sp, r14 [r12]") -#endif - TEST_UNSUPPORTED(".word 0xe102f091 @ swp pc, r1, [r2]") - TEST_UNSUPPORTED(".word 0xe102009f @ swp r0, pc, [r2]") - TEST_UNSUPPORTED(".word 0xe10f0091 @ swp r0, r1, [pc]") -#if __LINUX_ARM_ARCH__ < 6 - TEST_RP("swpb lr, r",7,VAL2,", [r",8,0,"]") - TEST_R( "swpvsb r0, r",1,VAL1,", [sp]") -#else - TEST_UNSUPPORTED(".word 0xe148e097 @ swpb lr, r7, [r8]") - TEST_UNSUPPORTED(".word 0x614d0091 @ swpvsb r0, r1, [sp]") -#endif - TEST_UNSUPPORTED(".word 0xe142f091 @ swpb pc, r1, [r2]") - - TEST_UNSUPPORTED(".word 0xe1100090") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe1200090") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe1300090") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe1500090") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe1600090") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe1700090") /* Unallocated space */ -#if __LINUX_ARM_ARCH__ >= 6 - TEST_UNSUPPORTED("ldrex r2, [sp]") - TEST_UNSUPPORTED("strexd r0, r2, r3, [sp]") - TEST_UNSUPPORTED("ldrexd r2, r3, [sp]") - TEST_UNSUPPORTED("strexb r0, r2, [sp]") - TEST_UNSUPPORTED("ldrexb r2, [sp]") - TEST_UNSUPPORTED("strexh r0, r2, [sp]") - TEST_UNSUPPORTED("ldrexh r2, [sp]") -#endif - TEST_GROUP("Extra load/store instructions") - - TEST_RPR( "strh r",0, VAL1,", [r",1, 48,", -r",2, 24,"]") - TEST_RPR( "streqh r",14,VAL2,", [r",13,0, ", r",12, 48,"]") - TEST_RPR( "strh r",1, VAL1,", [r",2, 24,", r",3, 48,"]!") - TEST_RPR( "strneh r",12,VAL2,", [r",11,48,", -r",10,24,"]!") - TEST_RPR( "strh r",2, VAL1,", [r",3, 24,"], r",4, 48,"") - TEST_RPR( "strh r",10,VAL2,", [r",9, 48,"], -r",11,24,"") - TEST_UNSUPPORTED(".word 0xe1afc0ba @ strh r12, [pc, r10]!") - TEST_UNSUPPORTED(".word 0xe089f0bb @ strh pc, [r9], r11") - TEST_UNSUPPORTED(".word 0xe089a0bf @ strh r10, [r9], pc") - - TEST_PR( "ldrh r0, [r",0, 48,", -r",2, 24,"]") - TEST_PR( "ldrcsh r14, [r",13,0, ", r",12, 48,"]") - TEST_PR( "ldrh r1, [r",2, 24,", r",3, 48,"]!") - TEST_PR( "ldrcch r12, [r",11,48,", -r",10,24,"]!") - TEST_PR( "ldrh r2, [r",3, 24,"], r",4, 48,"") - TEST_PR( "ldrh r10, [r",9, 48,"], -r",11,24,"") - TEST_UNSUPPORTED(".word 0xe1bfc0ba @ ldrh r12, [pc, r10]!") - TEST_UNSUPPORTED(".word 0xe099f0bb @ ldrh pc, [r9], r11") - TEST_UNSUPPORTED(".word 0xe099a0bf @ ldrh r10, [r9], pc") - - TEST_RP( "strh r",0, VAL1,", [r",1, 24,", #-2]") - TEST_RP( "strmih r",14,VAL2,", [r",13,0, ", #2]") - TEST_RP( "strh r",1, VAL1,", [r",2, 24,", #4]!") - TEST_RP( "strplh r",12,VAL2,", [r",11,24,", #-4]!") - TEST_RP( "strh r",2, VAL1,", [r",3, 24,"], #48") - TEST_RP( "strh r",10,VAL2,", [r",9, 64,"], #-48") - TEST_UNSUPPORTED(".word 0xe1efc3b0 @ strh r12, [pc, #48]!") - TEST_UNSUPPORTED(".word 0xe0c9f3b0 @ strh pc, [r9], #48") - - TEST_P( "ldrh r0, [r",0, 24,", #-2]") - TEST_P( "ldrvsh r14, [r",13,0, ", #2]") - TEST_P( "ldrh r1, [r",2, 24,", #4]!") - TEST_P( "ldrvch r12, [r",11,24,", #-4]!") - TEST_P( "ldrh r2, [r",3, 24,"], #48") - TEST_P( "ldrh r10, [r",9, 64,"], #-48") - TEST( "ldrh r0, [pc, #0]") - TEST_UNSUPPORTED(".word 0xe1ffc3b0 @ ldrh r12, [pc, #48]!") - TEST_UNSUPPORTED(".word 0xe0d9f3b0 @ ldrh pc, [r9], #48") - - TEST_PR( "ldrsb r0, [r",0, 48,", -r",2, 24,"]") - TEST_PR( "ldrhisb r14, [r",13,0,", r",12, 48,"]") - TEST_PR( "ldrsb r1, [r",2, 24,", r",3, 48,"]!") - TEST_PR( "ldrlssb r12, [r",11,48,", -r",10,24,"]!") - TEST_PR( "ldrsb r2, [r",3, 24,"], r",4, 48,"") - TEST_PR( "ldrsb r10, [r",9, 48,"], -r",11,24,"") - TEST_UNSUPPORTED(".word 0xe1bfc0da @ ldrsb r12, [pc, r10]!") - TEST_UNSUPPORTED(".word 0xe099f0db @ ldrsb pc, [r9], r11") - - TEST_P( "ldrsb r0, [r",0, 24,", #-1]") - TEST_P( "ldrgesb r14, [r",13,0, ", #1]") - TEST_P( "ldrsb r1, [r",2, 24,", #4]!") - TEST_P( "ldrltsb r12, [r",11,24,", #-4]!") - TEST_P( "ldrsb r2, [r",3, 24,"], #48") - TEST_P( "ldrsb r10, [r",9, 64,"], #-48") - TEST( "ldrsb r0, [pc, #0]") - TEST_UNSUPPORTED(".word 0xe1ffc3d0 @ ldrsb r12, [pc, #48]!") - TEST_UNSUPPORTED(".word 0xe0d9f3d0 @ ldrsb pc, [r9], #48") - - TEST_PR( "ldrsh r0, [r",0, 48,", -r",2, 24,"]") - TEST_PR( "ldrgtsh r14, [r",13,0, ", r",12, 48,"]") - TEST_PR( "ldrsh r1, [r",2, 24,", r",3, 48,"]!") - TEST_PR( "ldrlesh r12, [r",11,48,", -r",10,24,"]!") - TEST_PR( "ldrsh r2, [r",3, 24,"], r",4, 48,"") - TEST_PR( "ldrsh r10, [r",9, 48,"], -r",11,24,"") - TEST_UNSUPPORTED(".word 0xe1bfc0fa @ ldrsh r12, [pc, r10]!") - TEST_UNSUPPORTED(".word 0xe099f0fb @ ldrsh pc, [r9], r11") - - TEST_P( "ldrsh r0, [r",0, 24,", #-1]") - TEST_P( "ldreqsh r14, [r",13,0 ,", #1]") - TEST_P( "ldrsh r1, [r",2, 24,", #4]!") - TEST_P( "ldrnesh r12, [r",11,24,", #-4]!") - TEST_P( "ldrsh r2, [r",3, 24,"], #48") - TEST_P( "ldrsh r10, [r",9, 64,"], #-48") - TEST( "ldrsh r0, [pc, #0]") - TEST_UNSUPPORTED(".word 0xe1ffc3f0 @ ldrsh r12, [pc, #48]!") - TEST_UNSUPPORTED(".word 0xe0d9f3f0 @ ldrsh pc, [r9], #48") - -#if __LINUX_ARM_ARCH__ >= 7 - TEST_UNSUPPORTED("strht r1, [r2], r3") - TEST_UNSUPPORTED("ldrht r1, [r2], r3") - TEST_UNSUPPORTED("strht r1, [r2], #48") - TEST_UNSUPPORTED("ldrht r1, [r2], #48") - TEST_UNSUPPORTED("ldrsbt r1, [r2], r3") - TEST_UNSUPPORTED("ldrsbt r1, [r2], #48") - TEST_UNSUPPORTED("ldrsht r1, [r2], r3") - TEST_UNSUPPORTED("ldrsht r1, [r2], #48") -#endif - - TEST_RPR( "strd r",0, VAL1,", [r",1, 48,", -r",2,24,"]") - TEST_RPR( "strccd r",8, VAL2,", [r",13,0, ", r",12,48,"]") - TEST_RPR( "strd r",4, VAL1,", [r",2, 24,", r",3, 48,"]!") - TEST_RPR( "strcsd r",12,VAL2,", [r",11,48,", -r",10,24,"]!") - TEST_RPR( "strd r",2, VAL1,", [r",5, 24,"], r",4,48,"") - TEST_RPR( "strd r",10,VAL2,", [r",9, 48,"], -r",7,24,"") - TEST_UNSUPPORTED(".word 0xe1afc0fa @ strd r12, [pc, r10]!") - - TEST_PR( "ldrd r0, [r",0, 48,", -r",2,24,"]") - TEST_PR( "ldrmid r8, [r",13,0, ", r",12,48,"]") - TEST_PR( "ldrd r4, [r",2, 24,", r",3, 48,"]!") - TEST_PR( "ldrpld r6, [r",11,48,", -r",10,24,"]!") - TEST_PR( "ldrd r2, [r",5, 24,"], r",4,48,"") - TEST_PR( "ldrd r10, [r",9,48,"], -r",7,24,"") - TEST_UNSUPPORTED(".word 0xe1afc0da @ ldrd r12, [pc, r10]!") - TEST_UNSUPPORTED(".word 0xe089f0db @ ldrd pc, [r9], r11") - TEST_UNSUPPORTED(".word 0xe089e0db @ ldrd lr, [r9], r11") - TEST_UNSUPPORTED(".word 0xe089c0df @ ldrd r12, [r9], pc") - - TEST_RP( "strd r",0, VAL1,", [r",1, 24,", #-8]") - TEST_RP( "strvsd r",8, VAL2,", [r",13,0, ", #8]") - TEST_RP( "strd r",4, VAL1,", [r",2, 24,", #16]!") - TEST_RP( "strvcd r",12,VAL2,", [r",11,24,", #-16]!") - TEST_RP( "strd r",2, VAL1,", [r",4, 24,"], #48") - TEST_RP( "strd r",10,VAL2,", [r",9, 64,"], #-48") - TEST_UNSUPPORTED(".word 0xe1efc3f0 @ strd r12, [pc, #48]!") - - TEST_P( "ldrd r0, [r",0, 24,", #-8]") - TEST_P( "ldrhid r8, [r",13,0, ", #8]") - TEST_P( "ldrd r4, [r",2, 24,", #16]!") - TEST_P( "ldrlsd r6, [r",11,24,", #-16]!") - TEST_P( "ldrd r2, [r",5, 24,"], #48") - TEST_P( "ldrd r10, [r",9,6,"], #-48") - TEST_UNSUPPORTED(".word 0xe1efc3d0 @ ldrd r12, [pc, #48]!") - TEST_UNSUPPORTED(".word 0xe0c9f3d0 @ ldrd pc, [r9], #48") - TEST_UNSUPPORTED(".word 0xe0c9e3d0 @ ldrd lr, [r9], #48") - - TEST_GROUP("Miscellaneous") - -#if __LINUX_ARM_ARCH__ >= 7 - TEST("movw r0, #0") - TEST("movw r0, #0xffff") - TEST("movw lr, #0xffff") - TEST_UNSUPPORTED(".word 0xe300f000 @ movw pc, #0") - TEST_R("movt r",0, VAL1,", #0") - TEST_R("movt r",0, VAL2,", #0xffff") - TEST_R("movt r",14,VAL1,", #0xffff") - TEST_UNSUPPORTED(".word 0xe340f000 @ movt pc, #0") -#endif - - TEST_UNSUPPORTED("msr cpsr, 0x13") - TEST_UNSUPPORTED("msr cpsr_f, 0xf0000000") - TEST_UNSUPPORTED("msr spsr, 0x13") - -#if __LINUX_ARM_ARCH__ >= 7 - TEST_SUPPORTED("yield") - TEST("sev") - TEST("nop") - TEST("wfi") - TEST_SUPPORTED("wfe") - TEST_UNSUPPORTED("dbg #0") -#endif - - TEST_GROUP("Load/store word and unsigned byte") - -#define LOAD_STORE(byte) \ - TEST_RP( "str"byte" r",0, VAL1,", [r",1, 24,", #-2]") \ - TEST_RP( "str"byte" r",14,VAL2,", [r",13,0, ", #2]") \ - TEST_RP( "str"byte" r",1, VAL1,", [r",2, 24,", #4]!") \ - TEST_RP( "str"byte" r",12,VAL2,", [r",11,24,", #-4]!") \ - TEST_RP( "str"byte" r",2, VAL1,", [r",3, 24,"], #48") \ - TEST_RP( "str"byte" r",10,VAL2,", [r",9, 64,"], #-48") \ - TEST_RPR("str"byte" r",0, VAL1,", [r",1, 48,", -r",2, 24,"]") \ - TEST_RPR("str"byte" r",14,VAL2,", [r",13,0, ", r",12, 48,"]") \ - TEST_RPR("str"byte" r",1, VAL1,", [r",2, 24,", r",3, 48,"]!") \ - TEST_RPR("str"byte" r",12,VAL2,", [r",11,48,", -r",10,24,"]!") \ - TEST_RPR("str"byte" r",2, VAL1,", [r",3, 24,"], r",4, 48,"") \ - TEST_RPR("str"byte" r",10,VAL2,", [r",9, 48,"], -r",11,24,"") \ - TEST_RPR("str"byte" r",0, VAL1,", [r",1, 24,", r",2, 32,", asl #1]")\ - TEST_RPR("str"byte" r",14,VAL2,", [r",13,0, ", r",12, 32,", lsr #2]")\ - TEST_RPR("str"byte" r",1, VAL1,", [r",2, 24,", r",3, 32,", asr #3]!")\ - TEST_RPR("str"byte" r",12,VAL2,", [r",11,24,", r",10, 4,", ror #31]!")\ - TEST_P( "ldr"byte" r0, [r",0, 24,", #-2]") \ - TEST_P( "ldr"byte" r14, [r",13,0, ", #2]") \ - TEST_P( "ldr"byte" r1, [r",2, 24,", #4]!") \ - TEST_P( "ldr"byte" r12, [r",11,24,", #-4]!") \ - TEST_P( "ldr"byte" r2, [r",3, 24,"], #48") \ - TEST_P( "ldr"byte" r10, [r",9, 64,"], #-48") \ - TEST_PR( "ldr"byte" r0, [r",0, 48,", -r",2, 24,"]") \ - TEST_PR( "ldr"byte" r14, [r",13,0, ", r",12, 48,"]") \ - TEST_PR( "ldr"byte" r1, [r",2, 24,", r",3, 48,"]!") \ - TEST_PR( "ldr"byte" r12, [r",11,48,", -r",10,24,"]!") \ - TEST_PR( "ldr"byte" r2, [r",3, 24,"], r",4, 48,"") \ - TEST_PR( "ldr"byte" r10, [r",9, 48,"], -r",11,24,"") \ - TEST_PR( "ldr"byte" r0, [r",0, 24,", r",2, 32,", asl #1]") \ - TEST_PR( "ldr"byte" r14, [r",13,0, ", r",12, 32,", lsr #2]") \ - TEST_PR( "ldr"byte" r1, [r",2, 24,", r",3, 32,", asr #3]!") \ - TEST_PR( "ldr"byte" r12, [r",11,24,", r",10, 4,", ror #31]!") \ - TEST( "ldr"byte" r0, [pc, #0]") \ - TEST_R( "ldr"byte" r12, [pc, r",14,0,"]") - - LOAD_STORE("") - TEST_P( "str pc, [r",0,0,", #15*4]") - TEST_R( "str pc, [sp, r",2,15*4,"]") - TEST_BF( "ldr pc, [sp, #15*4]") - TEST_BF_R("ldr pc, [sp, r",2,15*4,"]") - - TEST_P( "str sp, [r",0,0,", #13*4]") - TEST_R( "str sp, [sp, r",2,13*4,"]") - TEST_BF( "ldr sp, [sp, #13*4]") - TEST_BF_R("ldr sp, [sp, r",2,13*4,"]") - -#ifdef CONFIG_THUMB2_KERNEL - TEST_ARM_TO_THUMB_INTERWORK_P("ldr pc, [r",0,0,", #15*4]") -#endif - TEST_UNSUPPORTED(".word 0xe5af6008 @ str r6, [pc, #8]!") - TEST_UNSUPPORTED(".word 0xe7af6008 @ str r6, [pc, r8]!") - TEST_UNSUPPORTED(".word 0xe5bf6008 @ ldr r6, [pc, #8]!") - TEST_UNSUPPORTED(".word 0xe7bf6008 @ ldr r6, [pc, r8]!") - TEST_UNSUPPORTED(".word 0xe788600f @ str r6, [r8, pc]") - TEST_UNSUPPORTED(".word 0xe798600f @ ldr r6, [r8, pc]") - - LOAD_STORE("b") - TEST_UNSUPPORTED(".word 0xe5f7f008 @ ldrb pc, [r7, #8]!") - TEST_UNSUPPORTED(".word 0xe7f7f008 @ ldrb pc, [r7, r8]!") - TEST_UNSUPPORTED(".word 0xe5ef6008 @ strb r6, [pc, #8]!") - TEST_UNSUPPORTED(".word 0xe7ef6008 @ strb r6, [pc, r3]!") - TEST_UNSUPPORTED(".word 0xe5ff6008 @ ldrb r6, [pc, #8]!") - TEST_UNSUPPORTED(".word 0xe7ff6008 @ ldrb r6, [pc, r3]!") - - TEST_UNSUPPORTED("ldrt r0, [r1], #4") - TEST_UNSUPPORTED("ldrt r1, [r2], r3") - TEST_UNSUPPORTED("strt r2, [r3], #4") - TEST_UNSUPPORTED("strt r3, [r4], r5") - TEST_UNSUPPORTED("ldrbt r4, [r5], #4") - TEST_UNSUPPORTED("ldrbt r5, [r6], r7") - TEST_UNSUPPORTED("strbt r6, [r7], #4") - TEST_UNSUPPORTED("strbt r7, [r8], r9") - -#if __LINUX_ARM_ARCH__ >= 7 - TEST_GROUP("Parallel addition and subtraction, signed") - - TEST_UNSUPPORTED(".word 0xe6000010") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe60fffff") /* Unallocated space */ - - TEST_RR( "sadd16 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "sadd16 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe61cff1a @ sadd16 pc, r12, r10") - TEST_RR( "sasx r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "sasx r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe61cff3a @ sasx pc, r12, r10") - TEST_RR( "ssax r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "ssax r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe61cff5a @ ssax pc, r12, r10") - TEST_RR( "ssub16 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "ssub16 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe61cff7a @ ssub16 pc, r12, r10") - TEST_RR( "sadd8 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "sadd8 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe61cff9a @ sadd8 pc, r12, r10") - TEST_UNSUPPORTED(".word 0xe61000b0") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe61fffbf") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe61000d0") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe61fffdf") /* Unallocated space */ - TEST_RR( "ssub8 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "ssub8 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe61cfffa @ ssub8 pc, r12, r10") - - TEST_RR( "qadd16 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "qadd16 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe62cff1a @ qadd16 pc, r12, r10") - TEST_RR( "qasx r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "qasx r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe62cff3a @ qasx pc, r12, r10") - TEST_RR( "qsax r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "qsax r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe62cff5a @ qsax pc, r12, r10") - TEST_RR( "qsub16 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "qsub16 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe62cff7a @ qsub16 pc, r12, r10") - TEST_RR( "qadd8 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "qadd8 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe62cff9a @ qadd8 pc, r12, r10") - TEST_UNSUPPORTED(".word 0xe62000b0") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe62fffbf") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe62000d0") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe62fffdf") /* Unallocated space */ - TEST_RR( "qsub8 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "qsub8 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe62cfffa @ qsub8 pc, r12, r10") - - TEST_RR( "shadd16 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "shadd16 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe63cff1a @ shadd16 pc, r12, r10") - TEST_RR( "shasx r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "shasx r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe63cff3a @ shasx pc, r12, r10") - TEST_RR( "shsax r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "shsax r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe63cff5a @ shsax pc, r12, r10") - TEST_RR( "shsub16 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "shsub16 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe63cff7a @ shsub16 pc, r12, r10") - TEST_RR( "shadd8 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "shadd8 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe63cff9a @ shadd8 pc, r12, r10") - TEST_UNSUPPORTED(".word 0xe63000b0") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe63fffbf") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe63000d0") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe63fffdf") /* Unallocated space */ - TEST_RR( "shsub8 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "shsub8 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe63cfffa @ shsub8 pc, r12, r10") - - TEST_GROUP("Parallel addition and subtraction, unsigned") - - TEST_UNSUPPORTED(".word 0xe6400010") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe64fffff") /* Unallocated space */ - - TEST_RR( "uadd16 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "uadd16 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe65cff1a @ uadd16 pc, r12, r10") - TEST_RR( "uasx r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "uasx r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe65cff3a @ uasx pc, r12, r10") - TEST_RR( "usax r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "usax r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe65cff5a @ usax pc, r12, r10") - TEST_RR( "usub16 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "usub16 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe65cff7a @ usub16 pc, r12, r10") - TEST_RR( "uadd8 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "uadd8 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe65cff9a @ uadd8 pc, r12, r10") - TEST_UNSUPPORTED(".word 0xe65000b0") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe65fffbf") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe65000d0") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe65fffdf") /* Unallocated space */ - TEST_RR( "usub8 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "usub8 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe65cfffa @ usub8 pc, r12, r10") - - TEST_RR( "uqadd16 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "uqadd16 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe66cff1a @ uqadd16 pc, r12, r10") - TEST_RR( "uqasx r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "uqasx r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe66cff3a @ uqasx pc, r12, r10") - TEST_RR( "uqsax r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "uqsax r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe66cff5a @ uqsax pc, r12, r10") - TEST_RR( "uqsub16 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "uqsub16 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe66cff7a @ uqsub16 pc, r12, r10") - TEST_RR( "uqadd8 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "uqadd8 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe66cff9a @ uqadd8 pc, r12, r10") - TEST_UNSUPPORTED(".word 0xe66000b0") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe66fffbf") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe66000d0") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe66fffdf") /* Unallocated space */ - TEST_RR( "uqsub8 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "uqsub8 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe66cfffa @ uqsub8 pc, r12, r10") - - TEST_RR( "uhadd16 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "uhadd16 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe67cff1a @ uhadd16 pc, r12, r10") - TEST_RR( "uhasx r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "uhasx r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe67cff3a @ uhasx pc, r12, r10") - TEST_RR( "uhsax r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "uhsax r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe67cff5a @ uhsax pc, r12, r10") - TEST_RR( "uhsub16 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "uhsub16 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe67cff7a @ uhsub16 pc, r12, r10") - TEST_RR( "uhadd8 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "uhadd8 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe67cff9a @ uhadd8 pc, r12, r10") - TEST_UNSUPPORTED(".word 0xe67000b0") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe67fffbf") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe67000d0") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe67fffdf") /* Unallocated space */ - TEST_RR( "uhsub8 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "uhsub8 r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe67cfffa @ uhsub8 pc, r12, r10") - TEST_UNSUPPORTED(".word 0xe67feffa @ uhsub8 r14, pc, r10") - TEST_UNSUPPORTED(".word 0xe67cefff @ uhsub8 r14, r12, pc") -#endif /* __LINUX_ARM_ARCH__ >= 7 */ - -#if __LINUX_ARM_ARCH__ >= 6 - TEST_GROUP("Packing, unpacking, saturation, and reversal") - - TEST_RR( "pkhbt r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "pkhbt r14,r",12, HH1,", r",10,HH2,", lsl #2") - TEST_UNSUPPORTED(".word 0xe68cf11a @ pkhbt pc, r12, r10, lsl #2") - TEST_RR( "pkhtb r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "pkhtb r14,r",12, HH1,", r",10,HH2,", asr #2") - TEST_UNSUPPORTED(".word 0xe68cf15a @ pkhtb pc, r12, r10, asr #2") - TEST_UNSUPPORTED(".word 0xe68fe15a @ pkhtb r14, pc, r10, asr #2") - TEST_UNSUPPORTED(".word 0xe68ce15f @ pkhtb r14, r12, pc, asr #2") - TEST_UNSUPPORTED(".word 0xe6900010") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe69fffdf") /* Unallocated space */ - - TEST_R( "ssat r0, #24, r",0, VAL1,"") - TEST_R( "ssat r14, #24, r",12, VAL2,"") - TEST_R( "ssat r0, #24, r",0, VAL1,", lsl #8") - TEST_R( "ssat r14, #24, r",12, VAL2,", asr #8") - TEST_UNSUPPORTED(".word 0xe6b7f01c @ ssat pc, #24, r12") - - TEST_R( "usat r0, #24, r",0, VAL1,"") - TEST_R( "usat r14, #24, r",12, VAL2,"") - TEST_R( "usat r0, #24, r",0, VAL1,", lsl #8") - TEST_R( "usat r14, #24, r",12, VAL2,", asr #8") - TEST_UNSUPPORTED(".word 0xe6f7f01c @ usat pc, #24, r12") - - TEST_RR( "sxtab16 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "sxtab16 r14,r",12, HH2,", r",10,HH1,", ror #8") - TEST_R( "sxtb16 r8, r",7, HH1,"") - TEST_UNSUPPORTED(".word 0xe68cf47a @ sxtab16 pc,r12, r10, ror #8") - - TEST_RR( "sel r0, r",0, VAL1,", r",1, VAL2,"") - TEST_RR( "sel r14, r",12,VAL1,", r",10, VAL2,"") - TEST_UNSUPPORTED(".word 0xe68cffba @ sel pc, r12, r10") - TEST_UNSUPPORTED(".word 0xe68fefba @ sel r14, pc, r10") - TEST_UNSUPPORTED(".word 0xe68cefbf @ sel r14, r12, pc") - - TEST_R( "ssat16 r0, #12, r",0, HH1,"") - TEST_R( "ssat16 r14, #12, r",12, HH2,"") - TEST_UNSUPPORTED(".word 0xe6abff3c @ ssat16 pc, #12, r12") - - TEST_RR( "sxtab r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "sxtab r14,r",12, HH2,", r",10,HH1,", ror #8") - TEST_R( "sxtb r8, r",7, HH1,"") - TEST_UNSUPPORTED(".word 0xe6acf47a @ sxtab pc,r12, r10, ror #8") - - TEST_R( "rev r0, r",0, VAL1,"") - TEST_R( "rev r14, r",12, VAL2,"") - TEST_UNSUPPORTED(".word 0xe6bfff3c @ rev pc, r12") - - TEST_RR( "sxtah r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "sxtah r14,r",12, HH2,", r",10,HH1,", ror #8") - TEST_R( "sxth r8, r",7, HH1,"") - TEST_UNSUPPORTED(".word 0xe6bcf47a @ sxtah pc,r12, r10, ror #8") - - TEST_R( "rev16 r0, r",0, VAL1,"") - TEST_R( "rev16 r14, r",12, VAL2,"") - TEST_UNSUPPORTED(".word 0xe6bfffbc @ rev16 pc, r12") - - TEST_RR( "uxtab16 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "uxtab16 r14,r",12, HH2,", r",10,HH1,", ror #8") - TEST_R( "uxtb16 r8, r",7, HH1,"") - TEST_UNSUPPORTED(".word 0xe6ccf47a @ uxtab16 pc,r12, r10, ror #8") - - TEST_R( "usat16 r0, #12, r",0, HH1,"") - TEST_R( "usat16 r14, #12, r",12, HH2,"") - TEST_UNSUPPORTED(".word 0xe6ecff3c @ usat16 pc, #12, r12") - TEST_UNSUPPORTED(".word 0xe6ecef3f @ usat16 r14, #12, pc") - - TEST_RR( "uxtab r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "uxtab r14,r",12, HH2,", r",10,HH1,", ror #8") - TEST_R( "uxtb r8, r",7, HH1,"") - TEST_UNSUPPORTED(".word 0xe6ecf47a @ uxtab pc,r12, r10, ror #8") - -#if __LINUX_ARM_ARCH__ >= 7 - TEST_R( "rbit r0, r",0, VAL1,"") - TEST_R( "rbit r14, r",12, VAL2,"") - TEST_UNSUPPORTED(".word 0xe6ffff3c @ rbit pc, r12") -#endif - - TEST_RR( "uxtah r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "uxtah r14,r",12, HH2,", r",10,HH1,", ror #8") - TEST_R( "uxth r8, r",7, HH1,"") - TEST_UNSUPPORTED(".word 0xe6fff077 @ uxth pc, r7") - TEST_UNSUPPORTED(".word 0xe6ff807f @ uxth r8, pc") - TEST_UNSUPPORTED(".word 0xe6fcf47a @ uxtah pc, r12, r10, ror #8") - TEST_UNSUPPORTED(".word 0xe6fce47f @ uxtah r14, r12, pc, ror #8") - - TEST_R( "revsh r0, r",0, VAL1,"") - TEST_R( "revsh r14, r",12, VAL2,"") - TEST_UNSUPPORTED(".word 0xe6ffff3c @ revsh pc, r12") - TEST_UNSUPPORTED(".word 0xe6ffef3f @ revsh r14, pc") - - TEST_UNSUPPORTED(".word 0xe6900070") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe69fff7f") /* Unallocated space */ - - TEST_UNSUPPORTED(".word 0xe6d00070") /* Unallocated space */ - TEST_UNSUPPORTED(".word 0xe6dfff7f") /* Unallocated space */ -#endif /* __LINUX_ARM_ARCH__ >= 6 */ - -#if __LINUX_ARM_ARCH__ >= 6 - TEST_GROUP("Signed multiplies") - - TEST_RRR( "smlad r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"") - TEST_RRR( "smlad r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"") - TEST_UNSUPPORTED(".word 0xe70f8a1c @ smlad pc, r12, r10, r8") - TEST_RRR( "smladx r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"") - TEST_RRR( "smladx r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"") - TEST_UNSUPPORTED(".word 0xe70f8a3c @ smladx pc, r12, r10, r8") - - TEST_RR( "smuad r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "smuad r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe70ffa1c @ smuad pc, r12, r10") - TEST_RR( "smuadx r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "smuadx r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe70ffa3c @ smuadx pc, r12, r10") - - TEST_RRR( "smlsd r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"") - TEST_RRR( "smlsd r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"") - TEST_UNSUPPORTED(".word 0xe70f8a5c @ smlsd pc, r12, r10, r8") - TEST_RRR( "smlsdx r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"") - TEST_RRR( "smlsdx r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"") - TEST_UNSUPPORTED(".word 0xe70f8a7c @ smlsdx pc, r12, r10, r8") - - TEST_RR( "smusd r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "smusd r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe70ffa5c @ smusd pc, r12, r10") - TEST_RR( "smusdx r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "smusdx r14, r",12,HH2,", r",10,HH1,"") - TEST_UNSUPPORTED(".word 0xe70ffa7c @ smusdx pc, r12, r10") - - TEST_RRRR( "smlald r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2) - TEST_RRRR( "smlald r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1) - TEST_UNSUPPORTED(".word 0xe74af819 @ smlald pc, r10, r9, r8") - TEST_UNSUPPORTED(".word 0xe74fb819 @ smlald r11, pc, r9, r8") - TEST_UNSUPPORTED(".word 0xe74ab81f @ smlald r11, r10, pc, r8") - TEST_UNSUPPORTED(".word 0xe74abf19 @ smlald r11, r10, r9, pc") - - TEST_RRRR( "smlaldx r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2) - TEST_RRRR( "smlaldx r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1) - TEST_UNSUPPORTED(".word 0xe74af839 @ smlaldx pc, r10, r9, r8") - TEST_UNSUPPORTED(".word 0xe74fb839 @ smlaldx r11, pc, r9, r8") - - TEST_RRR( "smmla r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"") - TEST_RRR( "smmla r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"") - TEST_UNSUPPORTED(".word 0xe75f8a1c @ smmla pc, r12, r10, r8") - TEST_RRR( "smmlar r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"") - TEST_RRR( "smmlar r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"") - TEST_UNSUPPORTED(".word 0xe75f8a3c @ smmlar pc, r12, r10, r8") - - TEST_RR( "smmul r0, r",0, VAL1,", r",1, VAL2,"") - TEST_RR( "smmul r14, r",12,VAL2,", r",10,VAL1,"") - TEST_UNSUPPORTED(".word 0xe75ffa1c @ smmul pc, r12, r10") - TEST_RR( "smmulr r0, r",0, VAL1,", r",1, VAL2,"") - TEST_RR( "smmulr r14, r",12,VAL2,", r",10,VAL1,"") - TEST_UNSUPPORTED(".word 0xe75ffa3c @ smmulr pc, r12, r10") - - TEST_RRR( "smmls r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"") - TEST_RRR( "smmls r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"") - TEST_UNSUPPORTED(".word 0xe75f8adc @ smmls pc, r12, r10, r8") - TEST_RRR( "smmlsr r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"") - TEST_RRR( "smmlsr r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"") - TEST_UNSUPPORTED(".word 0xe75f8afc @ smmlsr pc, r12, r10, r8") - TEST_UNSUPPORTED(".word 0xe75e8aff @ smmlsr r14, pc, r10, r8") - TEST_UNSUPPORTED(".word 0xe75e8ffc @ smmlsr r14, r12, pc, r8") - TEST_UNSUPPORTED(".word 0xe75efafc @ smmlsr r14, r12, r10, pc") - - TEST_RR( "usad8 r0, r",0, VAL1,", r",1, VAL2,"") - TEST_RR( "usad8 r14, r",12,VAL2,", r",10,VAL1,"") - TEST_UNSUPPORTED(".word 0xe75ffa1c @ usad8 pc, r12, r10") - TEST_UNSUPPORTED(".word 0xe75efa1f @ usad8 r14, pc, r10") - TEST_UNSUPPORTED(".word 0xe75eff1c @ usad8 r14, r12, pc") - - TEST_RRR( "usada8 r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL3,"") - TEST_RRR( "usada8 r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL3,"") - TEST_UNSUPPORTED(".word 0xe78f8a1c @ usada8 pc, r12, r10, r8") - TEST_UNSUPPORTED(".word 0xe78e8a1f @ usada8 r14, pc, r10, r8") - TEST_UNSUPPORTED(".word 0xe78e8f1c @ usada8 r14, r12, pc, r8") -#endif /* __LINUX_ARM_ARCH__ >= 6 */ - -#if __LINUX_ARM_ARCH__ >= 7 - TEST_GROUP("Bit Field") - - TEST_R( "sbfx r0, r",0 , VAL1,", #0, #31") - TEST_R( "sbfxeq r14, r",12, VAL2,", #8, #16") - TEST_R( "sbfx r4, r",10, VAL1,", #16, #15") - TEST_UNSUPPORTED(".word 0xe7aff45c @ sbfx pc, r12, #8, #16") - - TEST_R( "ubfx r0, r",0 , VAL1,", #0, #31") - TEST_R( "ubfxcs r14, r",12, VAL2,", #8, #16") - TEST_R( "ubfx r4, r",10, VAL1,", #16, #15") - TEST_UNSUPPORTED(".word 0xe7eff45c @ ubfx pc, r12, #8, #16") - TEST_UNSUPPORTED(".word 0xe7efc45f @ ubfx r12, pc, #8, #16") - - TEST_R( "bfc r",0, VAL1,", #4, #20") - TEST_R( "bfcvs r",14,VAL2,", #4, #20") - TEST_R( "bfc r",7, VAL1,", #0, #31") - TEST_R( "bfc r",8, VAL2,", #0, #31") - TEST_UNSUPPORTED(".word 0xe7def01f @ bfc pc, #0, #31"); - - TEST_RR( "bfi r",0, VAL1,", r",0 , VAL2,", #0, #31") - TEST_RR( "bfipl r",12,VAL1,", r",14 , VAL2,", #4, #20") - TEST_UNSUPPORTED(".word 0xe7d7f21e @ bfi pc, r14, #4, #20") - - TEST_UNSUPPORTED(".word 0x07f000f0") /* Permanently UNDEFINED */ - TEST_UNSUPPORTED(".word 0x07ffffff") /* Permanently UNDEFINED */ -#endif /* __LINUX_ARM_ARCH__ >= 6 */ - - TEST_GROUP("Branch, branch with link, and block data transfer") - - TEST_P( "stmda r",0, 16*4,", {r0}") - TEST_P( "stmeqda r",4, 16*4,", {r0-r15}") - TEST_P( "stmneda r",8, 16*4,"!, {r8-r15}") - TEST_P( "stmda r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") - TEST_P( "stmda r",13,0, "!, {pc}") - - TEST_P( "ldmda r",0, 16*4,", {r0}") - TEST_BF_P("ldmcsda r",4, 15*4,", {r0-r15}") - TEST_BF_P("ldmccda r",7, 15*4,"!, {r8-r15}") - TEST_P( "ldmda r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") - TEST_BF_P("ldmda r",14,15*4,"!, {pc}") - - TEST_P( "stmia r",0, 16*4,", {r0}") - TEST_P( "stmmiia r",4, 16*4,", {r0-r15}") - TEST_P( "stmplia r",8, 16*4,"!, {r8-r15}") - TEST_P( "stmia r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") - TEST_P( "stmia r",14,0, "!, {pc}") - - TEST_P( "ldmia r",0, 16*4,", {r0}") - TEST_BF_P("ldmvsia r",4, 0, ", {r0-r15}") - TEST_BF_P("ldmvcia r",7, 8*4, "!, {r8-r15}") - TEST_P( "ldmia r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") - TEST_BF_P("ldmia r",14,15*4,"!, {pc}") - - TEST_P( "stmdb r",0, 16*4,", {r0}") - TEST_P( "stmhidb r",4, 16*4,", {r0-r15}") - TEST_P( "stmlsdb r",8, 16*4,"!, {r8-r15}") - TEST_P( "stmdb r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") - TEST_P( "stmdb r",13,4, "!, {pc}") - - TEST_P( "ldmdb r",0, 16*4,", {r0}") - TEST_BF_P("ldmgedb r",4, 16*4,", {r0-r15}") - TEST_BF_P("ldmltdb r",7, 16*4,"!, {r8-r15}") - TEST_P( "ldmdb r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") - TEST_BF_P("ldmdb r",14,16*4,"!, {pc}") - - TEST_P( "stmib r",0, 16*4,", {r0}") - TEST_P( "stmgtib r",4, 16*4,", {r0-r15}") - TEST_P( "stmleib r",8, 16*4,"!, {r8-r15}") - TEST_P( "stmib r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") - TEST_P( "stmib r",13,-4, "!, {pc}") - - TEST_P( "ldmib r",0, 16*4,", {r0}") - TEST_BF_P("ldmeqib r",4, -4,", {r0-r15}") - TEST_BF_P("ldmneib r",7, 7*4,"!, {r8-r15}") - TEST_P( "ldmib r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") - TEST_BF_P("ldmib r",14,14*4,"!, {pc}") - - TEST_P( "stmdb r",13,16*4,"!, {r3-r12,lr}") - TEST_P( "stmeqdb r",13,16*4,"!, {r3-r12}") - TEST_P( "stmnedb r",2, 16*4,", {r3-r12,lr}") - TEST_P( "stmdb r",13,16*4,"!, {r2-r12,lr}") - TEST_P( "stmdb r",0, 16*4,", {r0-r12}") - TEST_P( "stmdb r",0, 16*4,", {r0-r12,lr}") - - TEST_BF_P("ldmia r",13,5*4, "!, {r3-r12,pc}") - TEST_P( "ldmccia r",13,5*4, "!, {r3-r12}") - TEST_BF_P("ldmcsia r",2, 5*4, "!, {r3-r12,pc}") - TEST_BF_P("ldmia r",13,4*4, "!, {r2-r12,pc}") - TEST_P( "ldmia r",0, 16*4,", {r0-r12}") - TEST_P( "ldmia r",0, 16*4,", {r0-r12,lr}") - -#ifdef CONFIG_THUMB2_KERNEL - TEST_ARM_TO_THUMB_INTERWORK_P("ldmplia r",0,15*4,", {pc}") - TEST_ARM_TO_THUMB_INTERWORK_P("ldmmiia r",13,0,", {r0-r15}") -#endif - TEST_BF("b 2f") - TEST_BF("bl 2f") - TEST_BB("b 2b") - TEST_BB("bl 2b") - - TEST_BF("beq 2f") - TEST_BF("bleq 2f") - TEST_BB("bne 2b") - TEST_BB("blne 2b") - - TEST_BF("bgt 2f") - TEST_BF("blgt 2f") - TEST_BB("blt 2b") - TEST_BB("bllt 2b") - - TEST_GROUP("Supervisor Call, and coprocessor instructions") - - /* - * We can't really test these by executing them, so all - * we can do is check that probes are, or are not allowed. - * At the moment none are allowed... - */ -#define TEST_COPROCESSOR(code) TEST_UNSUPPORTED(code) - -#define COPROCESSOR_INSTRUCTIONS_ST_LD(two,cc) \ - TEST_COPROCESSOR("stc"two" 0, cr0, [r13, #4]") \ - TEST_COPROCESSOR("stc"two" 0, cr0, [r13, #-4]") \ - TEST_COPROCESSOR("stc"two" 0, cr0, [r13, #4]!") \ - TEST_COPROCESSOR("stc"two" 0, cr0, [r13, #-4]!") \ - TEST_COPROCESSOR("stc"two" 0, cr0, [r13], #4") \ - TEST_COPROCESSOR("stc"two" 0, cr0, [r13], #-4") \ - TEST_COPROCESSOR("stc"two" 0, cr0, [r13], {1}") \ - TEST_COPROCESSOR("stc"two"l 0, cr0, [r13, #4]") \ - TEST_COPROCESSOR("stc"two"l 0, cr0, [r13, #-4]") \ - TEST_COPROCESSOR("stc"two"l 0, cr0, [r13, #4]!") \ - TEST_COPROCESSOR("stc"two"l 0, cr0, [r13, #-4]!") \ - TEST_COPROCESSOR("stc"two"l 0, cr0, [r13], #4") \ - TEST_COPROCESSOR("stc"two"l 0, cr0, [r13], #-4") \ - TEST_COPROCESSOR("stc"two"l 0, cr0, [r13], {1}") \ - TEST_COPROCESSOR("ldc"two" 0, cr0, [r13, #4]") \ - TEST_COPROCESSOR("ldc"two" 0, cr0, [r13, #-4]") \ - TEST_COPROCESSOR("ldc"two" 0, cr0, [r13, #4]!") \ - TEST_COPROCESSOR("ldc"two" 0, cr0, [r13, #-4]!") \ - TEST_COPROCESSOR("ldc"two" 0, cr0, [r13], #4") \ - TEST_COPROCESSOR("ldc"two" 0, cr0, [r13], #-4") \ - TEST_COPROCESSOR("ldc"two" 0, cr0, [r13], {1}") \ - TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13, #4]") \ - TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13, #-4]") \ - TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13, #4]!") \ - TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13, #-4]!") \ - TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13], #4") \ - TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13], #-4") \ - TEST_COPROCESSOR("ldc"two"l 0, cr0, [r13], {1}") \ - \ - TEST_COPROCESSOR( "stc"two" 0, cr0, [r15, #4]") \ - TEST_COPROCESSOR( "stc"two" 0, cr0, [r15, #-4]") \ - TEST_UNSUPPORTED(".word 0x"cc"daf0001 @ stc"two" 0, cr0, [r15, #4]!") \ - TEST_UNSUPPORTED(".word 0x"cc"d2f0001 @ stc"two" 0, cr0, [r15, #-4]!") \ - TEST_UNSUPPORTED(".word 0x"cc"caf0001 @ stc"two" 0, cr0, [r15], #4") \ - TEST_UNSUPPORTED(".word 0x"cc"c2f0001 @ stc"two" 0, cr0, [r15], #-4") \ - TEST_COPROCESSOR( "stc"two" 0, cr0, [r15], {1}") \ - TEST_COPROCESSOR( "stc"two"l 0, cr0, [r15, #4]") \ - TEST_COPROCESSOR( "stc"two"l 0, cr0, [r15, #-4]") \ - TEST_UNSUPPORTED(".word 0x"cc"def0001 @ stc"two"l 0, cr0, [r15, #4]!") \ - TEST_UNSUPPORTED(".word 0x"cc"d6f0001 @ stc"two"l 0, cr0, [r15, #-4]!") \ - TEST_UNSUPPORTED(".word 0x"cc"cef0001 @ stc"two"l 0, cr0, [r15], #4") \ - TEST_UNSUPPORTED(".word 0x"cc"c6f0001 @ stc"two"l 0, cr0, [r15], #-4") \ - TEST_COPROCESSOR( "stc"two"l 0, cr0, [r15], {1}") \ - TEST_COPROCESSOR( "ldc"two" 0, cr0, [r15, #4]") \ - TEST_COPROCESSOR( "ldc"two" 0, cr0, [r15, #-4]") \ - TEST_UNSUPPORTED(".word 0x"cc"dbf0001 @ ldc"two" 0, cr0, [r15, #4]!") \ - TEST_UNSUPPORTED(".word 0x"cc"d3f0001 @ ldc"two" 0, cr0, [r15, #-4]!") \ - TEST_UNSUPPORTED(".word 0x"cc"cbf0001 @ ldc"two" 0, cr0, [r15], #4") \ - TEST_UNSUPPORTED(".word 0x"cc"c3f0001 @ ldc"two" 0, cr0, [r15], #-4") \ - TEST_COPROCESSOR( "ldc"two" 0, cr0, [r15], {1}") \ - TEST_COPROCESSOR( "ldc"two"l 0, cr0, [r15, #4]") \ - TEST_COPROCESSOR( "ldc"two"l 0, cr0, [r15, #-4]") \ - TEST_UNSUPPORTED(".word 0x"cc"dff0001 @ ldc"two"l 0, cr0, [r15, #4]!") \ - TEST_UNSUPPORTED(".word 0x"cc"d7f0001 @ ldc"two"l 0, cr0, [r15, #-4]!") \ - TEST_UNSUPPORTED(".word 0x"cc"cff0001 @ ldc"two"l 0, cr0, [r15], #4") \ - TEST_UNSUPPORTED(".word 0x"cc"c7f0001 @ ldc"two"l 0, cr0, [r15], #-4") \ - TEST_COPROCESSOR( "ldc"two"l 0, cr0, [r15], {1}") - -#define COPROCESSOR_INSTRUCTIONS_MC_MR(two,cc) \ - \ - TEST_COPROCESSOR( "mcrr"two" 0, 15, r0, r14, cr0") \ - TEST_COPROCESSOR( "mcrr"two" 15, 0, r14, r0, cr15") \ - TEST_UNSUPPORTED(".word 0x"cc"c4f00f0 @ mcrr"two" 0, 15, r0, r15, cr0") \ - TEST_UNSUPPORTED(".word 0x"cc"c40ff0f @ mcrr"two" 15, 0, r15, r0, cr15") \ - TEST_COPROCESSOR( "mrrc"two" 0, 15, r0, r14, cr0") \ - TEST_COPROCESSOR( "mrrc"two" 15, 0, r14, r0, cr15") \ - TEST_UNSUPPORTED(".word 0x"cc"c5f00f0 @ mrrc"two" 0, 15, r0, r15, cr0") \ - TEST_UNSUPPORTED(".word 0x"cc"c50ff0f @ mrrc"two" 15, 0, r15, r0, cr15") \ - TEST_COPROCESSOR( "cdp"two" 15, 15, cr15, cr15, cr15, 7") \ - TEST_COPROCESSOR( "cdp"two" 0, 0, cr0, cr0, cr0, 0") \ - TEST_COPROCESSOR( "mcr"two" 15, 7, r15, cr15, cr15, 7") \ - TEST_COPROCESSOR( "mcr"two" 0, 0, r0, cr0, cr0, 0") \ - TEST_COPROCESSOR( "mrc"two" 15, 7, r15, cr15, cr15, 7") \ - TEST_COPROCESSOR( "mrc"two" 0, 0, r0, cr0, cr0, 0") - - COPROCESSOR_INSTRUCTIONS_ST_LD("","e") - COPROCESSOR_INSTRUCTIONS_MC_MR("","e") - TEST_UNSUPPORTED("svc 0") - TEST_UNSUPPORTED("svc 0xffffff") - - TEST_UNSUPPORTED("svc 0") - - TEST_GROUP("Unconditional instruction") - -#if __LINUX_ARM_ARCH__ >= 6 - TEST_UNSUPPORTED("srsda sp, 0x13") - TEST_UNSUPPORTED("srsdb sp, 0x13") - TEST_UNSUPPORTED("srsia sp, 0x13") - TEST_UNSUPPORTED("srsib sp, 0x13") - TEST_UNSUPPORTED("srsda sp!, 0x13") - TEST_UNSUPPORTED("srsdb sp!, 0x13") - TEST_UNSUPPORTED("srsia sp!, 0x13") - TEST_UNSUPPORTED("srsib sp!, 0x13") - - TEST_UNSUPPORTED("rfeda sp") - TEST_UNSUPPORTED("rfedb sp") - TEST_UNSUPPORTED("rfeia sp") - TEST_UNSUPPORTED("rfeib sp") - TEST_UNSUPPORTED("rfeda sp!") - TEST_UNSUPPORTED("rfedb sp!") - TEST_UNSUPPORTED("rfeia sp!") - TEST_UNSUPPORTED("rfeib sp!") - TEST_UNSUPPORTED(".word 0xf81d0a00 @ rfeda pc") - TEST_UNSUPPORTED(".word 0xf91d0a00 @ rfedb pc") - TEST_UNSUPPORTED(".word 0xf89d0a00 @ rfeia pc") - TEST_UNSUPPORTED(".word 0xf99d0a00 @ rfeib pc") - TEST_UNSUPPORTED(".word 0xf83d0a00 @ rfeda pc!") - TEST_UNSUPPORTED(".word 0xf93d0a00 @ rfedb pc!") - TEST_UNSUPPORTED(".word 0xf8bd0a00 @ rfeia pc!") - TEST_UNSUPPORTED(".word 0xf9bd0a00 @ rfeib pc!") -#endif /* __LINUX_ARM_ARCH__ >= 6 */ - -#if __LINUX_ARM_ARCH__ >= 6 - TEST_X( "blx __dummy_thumb_subroutine_even", - ".thumb \n\t" - ".space 4 \n\t" - ".type __dummy_thumb_subroutine_even, %%function \n\t" - "__dummy_thumb_subroutine_even: \n\t" - "mov r0, pc \n\t" - "bx lr \n\t" - ".arm \n\t" - ) - TEST( "blx __dummy_thumb_subroutine_even") - - TEST_X( "blx __dummy_thumb_subroutine_odd", - ".thumb \n\t" - ".space 2 \n\t" - ".type __dummy_thumb_subroutine_odd, %%function \n\t" - "__dummy_thumb_subroutine_odd: \n\t" - "mov r0, pc \n\t" - "bx lr \n\t" - ".arm \n\t" - ) - TEST( "blx __dummy_thumb_subroutine_odd") -#endif /* __LINUX_ARM_ARCH__ >= 6 */ - - COPROCESSOR_INSTRUCTIONS_ST_LD("2","f") -#if __LINUX_ARM_ARCH__ >= 6 - COPROCESSOR_INSTRUCTIONS_MC_MR("2","f") -#endif - - TEST_GROUP("Miscellaneous instructions, memory hints, and Advanced SIMD instructions") - -#if __LINUX_ARM_ARCH__ >= 6 - TEST_UNSUPPORTED("cps 0x13") - TEST_UNSUPPORTED("cpsie i") - TEST_UNSUPPORTED("cpsid i") - TEST_UNSUPPORTED("cpsie i,0x13") - TEST_UNSUPPORTED("cpsid i,0x13") - TEST_UNSUPPORTED("setend le") - TEST_UNSUPPORTED("setend be") -#endif - -#if __LINUX_ARM_ARCH__ >= 7 - TEST_P("pli [r",0,0b,", #16]") - TEST( "pli [pc, #0]") - TEST_RR("pli [r",12,0b,", r",0, 16,"]") - TEST_RR("pli [r",0, 0b,", -r",12,16,", lsl #4]") -#endif - -#if __LINUX_ARM_ARCH__ >= 5 - TEST_P("pld [r",0,32,", #-16]") - TEST( "pld [pc, #0]") - TEST_PR("pld [r",7, 24, ", r",0, 16,"]") - TEST_PR("pld [r",8, 24, ", -r",12,16,", lsl #4]") -#endif - -#if __LINUX_ARM_ARCH__ >= 7 - TEST_SUPPORTED( ".word 0xf590f000 @ pldw [r0, #0]") - TEST_SUPPORTED( ".word 0xf797f000 @ pldw [r7, r0]") - TEST_SUPPORTED( ".word 0xf798f18c @ pldw [r8, r12, lsl #3]"); -#endif - -#if __LINUX_ARM_ARCH__ >= 7 - TEST_UNSUPPORTED("clrex") - TEST_UNSUPPORTED("dsb") - TEST_UNSUPPORTED("dmb") - TEST_UNSUPPORTED("isb") -#endif - - verbose("\n"); -} - diff --git a/ANDROID_3.4.5/arch/arm/kernel/kprobes-test-thumb.c b/ANDROID_3.4.5/arch/arm/kernel/kprobes-test-thumb.c deleted file mode 100644 index 5d8b8579..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/kprobes-test-thumb.c +++ /dev/null @@ -1,1187 +0,0 @@ -/* - * arch/arm/kernel/kprobes-test-thumb.c - * - * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/kernel.h> -#include <linux/module.h> - -#include "kprobes-test.h" - - -#define TEST_ISA "16" - -#define DONT_TEST_IN_ITBLOCK(tests) \ - kprobe_test_flags |= TEST_FLAG_NO_ITBLOCK; \ - tests \ - kprobe_test_flags &= ~TEST_FLAG_NO_ITBLOCK; - -#define CONDITION_INSTRUCTIONS(cc_pos, tests) \ - kprobe_test_cc_position = cc_pos; \ - DONT_TEST_IN_ITBLOCK(tests) \ - kprobe_test_cc_position = 0; - -#define TEST_ITBLOCK(code) \ - kprobe_test_flags |= TEST_FLAG_FULL_ITBLOCK; \ - TESTCASE_START(code) \ - TEST_ARG_END("") \ - "50: nop \n\t" \ - "1: "code" \n\t" \ - " mov r1, #0x11 \n\t" \ - " mov r2, #0x22 \n\t" \ - " mov r3, #0x33 \n\t" \ - "2: nop \n\t" \ - TESTCASE_END \ - kprobe_test_flags &= ~TEST_FLAG_FULL_ITBLOCK; - -#define TEST_THUMB_TO_ARM_INTERWORK_P(code1, reg, val, code2) \ - TESTCASE_START(code1 #reg code2) \ - TEST_ARG_PTR(reg, val) \ - TEST_ARG_REG(14, 99f+1) \ - TEST_ARG_MEM(15, 3f) \ - TEST_ARG_END("") \ - " nop \n\t" /* To align 1f */ \ - "50: nop \n\t" \ - "1: "code1 #reg code2" \n\t" \ - " bx lr \n\t" \ - ".arm \n\t" \ - "3: adr lr, 2f+1 \n\t" \ - " bx lr \n\t" \ - ".thumb \n\t" \ - "2: nop \n\t" \ - TESTCASE_END - - -void kprobe_thumb16_test_cases(void) -{ - kprobe_test_flags = TEST_FLAG_NARROW_INSTR; - - TEST_GROUP("Shift (immediate), add, subtract, move, and compare") - - TEST_R( "lsls r7, r",0,VAL1,", #5") - TEST_R( "lsls r0, r",7,VAL2,", #11") - TEST_R( "lsrs r7, r",0,VAL1,", #5") - TEST_R( "lsrs r0, r",7,VAL2,", #11") - TEST_R( "asrs r7, r",0,VAL1,", #5") - TEST_R( "asrs r0, r",7,VAL2,", #11") - TEST_RR( "adds r2, r",0,VAL1,", r",7,VAL2,"") - TEST_RR( "adds r5, r",7,VAL2,", r",0,VAL2,"") - TEST_RR( "subs r2, r",0,VAL1,", r",7,VAL2,"") - TEST_RR( "subs r5, r",7,VAL2,", r",0,VAL2,"") - TEST_R( "adds r7, r",0,VAL1,", #5") - TEST_R( "adds r0, r",7,VAL2,", #2") - TEST_R( "subs r7, r",0,VAL1,", #5") - TEST_R( "subs r0, r",7,VAL2,", #2") - TEST( "movs.n r0, #0x5f") - TEST( "movs.n r7, #0xa0") - TEST_R( "cmp.n r",0,0x5e, ", #0x5f") - TEST_R( "cmp.n r",5,0x15f,", #0x5f") - TEST_R( "cmp.n r",7,0xa0, ", #0xa0") - TEST_R( "adds.n r",0,VAL1,", #0x5f") - TEST_R( "adds.n r",7,VAL2,", #0xa0") - TEST_R( "subs.n r",0,VAL1,", #0x5f") - TEST_R( "subs.n r",7,VAL2,", #0xa0") - - TEST_GROUP("16-bit Thumb data-processing instructions") - -#define DATA_PROCESSING16(op,val) \ - TEST_RR( op" r",0,VAL1,", r",7,val,"") \ - TEST_RR( op" r",7,VAL2,", r",0,val,"") - - DATA_PROCESSING16("ands",0xf00f00ff) - DATA_PROCESSING16("eors",0xf00f00ff) - DATA_PROCESSING16("lsls",11) - DATA_PROCESSING16("lsrs",11) - DATA_PROCESSING16("asrs",11) - DATA_PROCESSING16("adcs",VAL2) - DATA_PROCESSING16("sbcs",VAL2) - DATA_PROCESSING16("rors",11) - DATA_PROCESSING16("tst",0xf00f00ff) - TEST_R("rsbs r",0,VAL1,", #0") - TEST_R("rsbs r",7,VAL2,", #0") - DATA_PROCESSING16("cmp",0xf00f00ff) - DATA_PROCESSING16("cmn",0xf00f00ff) - DATA_PROCESSING16("orrs",0xf00f00ff) - DATA_PROCESSING16("muls",VAL2) - DATA_PROCESSING16("bics",0xf00f00ff) - DATA_PROCESSING16("mvns",VAL2) - - TEST_GROUP("Special data instructions and branch and exchange") - - TEST_RR( "add r",0, VAL1,", r",7,VAL2,"") - TEST_RR( "add r",3, VAL2,", r",8,VAL3,"") - TEST_RR( "add r",8, VAL3,", r",0,VAL1,"") - TEST_R( "add sp" ", r",8,-8, "") - TEST_R( "add r",14,VAL1,", pc") - TEST_BF_R("add pc" ", r",0,2f-1f-8,"") - TEST_UNSUPPORTED(".short 0x44ff @ add pc, pc") - - TEST_RR( "cmp r",3,VAL1,", r",8,VAL2,"") - TEST_RR( "cmp r",8,VAL2,", r",0,VAL1,"") - TEST_R( "cmp sp" ", r",8,-8, "") - - TEST_R( "mov r0, r",7,VAL2,"") - TEST_R( "mov r3, r",8,VAL3,"") - TEST_R( "mov r8, r",0,VAL1,"") - TEST_P( "mov sp, r",8,-8, "") - TEST( "mov lr, pc") - TEST_BF_R("mov pc, r",0,2f, "") - - TEST_BF_R("bx r",0, 2f+1,"") - TEST_BF_R("bx r",14,2f+1,"") - TESTCASE_START("bx pc") - TEST_ARG_REG(14, 99f+1) - TEST_ARG_END("") - " nop \n\t" /* To align the bx pc*/ - "50: nop \n\t" - "1: bx pc \n\t" - " bx lr \n\t" - ".arm \n\t" - " adr lr, 2f+1 \n\t" - " bx lr \n\t" - ".thumb \n\t" - "2: nop \n\t" - TESTCASE_END - - TEST_BF_R("blx r",0, 2f+1,"") - TEST_BB_R("blx r",14,2f+1,"") - TEST_UNSUPPORTED(".short 0x47f8 @ blx pc") - - TEST_GROUP("Load from Literal Pool") - - TEST_X( "ldr r0, 3f", - ".align \n\t" - "3: .word "__stringify(VAL1)) - TEST_X( "ldr r7, 3f", - ".space 128 \n\t" - ".align \n\t" - "3: .word "__stringify(VAL2)) - - TEST_GROUP("16-bit Thumb Load/store instructions") - - TEST_RPR("str r",0, VAL1,", [r",1, 24,", r",2, 48,"]") - TEST_RPR("str r",7, VAL2,", [r",6, 24,", r",5, 48,"]") - TEST_RPR("strh r",0, VAL1,", [r",1, 24,", r",2, 48,"]") - TEST_RPR("strh r",7, VAL2,", [r",6, 24,", r",5, 48,"]") - TEST_RPR("strb r",0, VAL1,", [r",1, 24,", r",2, 48,"]") - TEST_RPR("strb r",7, VAL2,", [r",6, 24,", r",5, 48,"]") - TEST_PR( "ldrsb r0, [r",1, 24,", r",2, 48,"]") - TEST_PR( "ldrsb r7, [r",6, 24,", r",5, 50,"]") - TEST_PR( "ldr r0, [r",1, 24,", r",2, 48,"]") - TEST_PR( "ldr r7, [r",6, 24,", r",5, 48,"]") - TEST_PR( "ldrh r0, [r",1, 24,", r",2, 48,"]") - TEST_PR( "ldrh r7, [r",6, 24,", r",5, 50,"]") - TEST_PR( "ldrb r0, [r",1, 24,", r",2, 48,"]") - TEST_PR( "ldrb r7, [r",6, 24,", r",5, 50,"]") - TEST_PR( "ldrsh r0, [r",1, 24,", r",2, 48,"]") - TEST_PR( "ldrsh r7, [r",6, 24,", r",5, 50,"]") - - TEST_RP("str r",0, VAL1,", [r",1, 24,", #120]") - TEST_RP("str r",7, VAL2,", [r",6, 24,", #120]") - TEST_P( "ldr r0, [r",1, 24,", #120]") - TEST_P( "ldr r7, [r",6, 24,", #120]") - TEST_RP("strb r",0, VAL1,", [r",1, 24,", #30]") - TEST_RP("strb r",7, VAL2,", [r",6, 24,", #30]") - TEST_P( "ldrb r0, [r",1, 24,", #30]") - TEST_P( "ldrb r7, [r",6, 24,", #30]") - TEST_RP("strh r",0, VAL1,", [r",1, 24,", #60]") - TEST_RP("strh r",7, VAL2,", [r",6, 24,", #60]") - TEST_P( "ldrh r0, [r",1, 24,", #60]") - TEST_P( "ldrh r7, [r",6, 24,", #60]") - - TEST_R( "str r",0, VAL1,", [sp, #0]") - TEST_R( "str r",7, VAL2,", [sp, #160]") - TEST( "ldr r0, [sp, #0]") - TEST( "ldr r7, [sp, #160]") - - TEST_RP("str r",0, VAL1,", [r",0, 24,"]") - TEST_P( "ldr r0, [r",0, 24,"]") - - TEST_GROUP("Generate PC-/SP-relative address") - - TEST("add r0, pc, #4") - TEST("add r7, pc, #1020") - TEST("add r0, sp, #4") - TEST("add r7, sp, #1020") - - TEST_GROUP("Miscellaneous 16-bit instructions") - - TEST_UNSUPPORTED( "cpsie i") - TEST_UNSUPPORTED( "cpsid i") - TEST_UNSUPPORTED( "setend le") - TEST_UNSUPPORTED( "setend be") - - TEST("add sp, #"__stringify(TEST_MEMORY_SIZE)) /* Assumes TEST_MEMORY_SIZE < 0x400 */ - TEST("sub sp, #0x7f*4") - -DONT_TEST_IN_ITBLOCK( - TEST_BF_R( "cbnz r",0,0, ", 2f") - TEST_BF_R( "cbz r",2,-1,", 2f") - TEST_BF_RX( "cbnz r",4,1, ", 2f", SPACE_0x20) - TEST_BF_RX( "cbz r",7,0, ", 2f", SPACE_0x40) -) - TEST_R("sxth r0, r",7, HH1,"") - TEST_R("sxth r7, r",0, HH2,"") - TEST_R("sxtb r0, r",7, HH1,"") - TEST_R("sxtb r7, r",0, HH2,"") - TEST_R("uxth r0, r",7, HH1,"") - TEST_R("uxth r7, r",0, HH2,"") - TEST_R("uxtb r0, r",7, HH1,"") - TEST_R("uxtb r7, r",0, HH2,"") - TEST_R("rev r0, r",7, VAL1,"") - TEST_R("rev r7, r",0, VAL2,"") - TEST_R("rev16 r0, r",7, VAL1,"") - TEST_R("rev16 r7, r",0, VAL2,"") - TEST_UNSUPPORTED(".short 0xba80") - TEST_UNSUPPORTED(".short 0xbabf") - TEST_R("revsh r0, r",7, VAL1,"") - TEST_R("revsh r7, r",0, VAL2,"") - -#define TEST_POPPC(code, offset) \ - TESTCASE_START(code) \ - TEST_ARG_PTR(13, offset) \ - TEST_ARG_END("") \ - TEST_BRANCH_F(code) \ - TESTCASE_END - - TEST("push {r0}") - TEST("push {r7}") - TEST("push {r14}") - TEST("push {r0-r7,r14}") - TEST("push {r0,r2,r4,r6,r14}") - TEST("push {r1,r3,r5,r7}") - TEST("pop {r0}") - TEST("pop {r7}") - TEST("pop {r0,r2,r4,r6}") - TEST_POPPC("pop {pc}",15*4) - TEST_POPPC("pop {r0-r7,pc}",7*4) - TEST_POPPC("pop {r1,r3,r5,r7,pc}",11*4) - TEST_THUMB_TO_ARM_INTERWORK_P("pop {pc} @ ",13,15*4,"") - TEST_THUMB_TO_ARM_INTERWORK_P("pop {r0-r7,pc} @ ",13,7*4,"") - - TEST_UNSUPPORTED("bkpt.n 0") - TEST_UNSUPPORTED("bkpt.n 255") - - TEST_SUPPORTED("yield") - TEST("sev") - TEST("nop") - TEST("wfi") - TEST_SUPPORTED("wfe") - TEST_UNSUPPORTED(".short 0xbf50") /* Unassigned hints */ - TEST_UNSUPPORTED(".short 0xbff0") /* Unassigned hints */ - -#define TEST_IT(code, code2) \ - TESTCASE_START(code) \ - TEST_ARG_END("") \ - "50: nop \n\t" \ - "1: "code" \n\t" \ - " "code2" \n\t" \ - "2: nop \n\t" \ - TESTCASE_END - -DONT_TEST_IN_ITBLOCK( - TEST_IT("it eq","moveq r0,#0") - TEST_IT("it vc","movvc r0,#0") - TEST_IT("it le","movle r0,#0") - TEST_IT("ite eq","moveq r0,#0\n\t movne r1,#1") - TEST_IT("itet vc","movvc r0,#0\n\t movvs r1,#1\n\t movvc r2,#2") - TEST_IT("itete le","movle r0,#0\n\t movgt r1,#1\n\t movle r2,#2\n\t movgt r3,#3") - TEST_IT("itttt le","movle r0,#0\n\t movle r1,#1\n\t movle r2,#2\n\t movle r3,#3") - TEST_IT("iteee le","movle r0,#0\n\t movgt r1,#1\n\t movgt r2,#2\n\t movgt r3,#3") -) - - TEST_GROUP("Load and store multiple") - - TEST_P("ldmia r",4, 16*4,"!, {r0,r7}") - TEST_P("ldmia r",7, 16*4,"!, {r0-r6}") - TEST_P("stmia r",4, 16*4,"!, {r0,r7}") - TEST_P("stmia r",0, 16*4,"!, {r0-r7}") - - TEST_GROUP("Conditional branch and Supervisor Call instructions") - -CONDITION_INSTRUCTIONS(8, - TEST_BF("beq 2f") - TEST_BB("bne 2b") - TEST_BF("bgt 2f") - TEST_BB("blt 2b") -) - TEST_UNSUPPORTED(".short 0xde00") - TEST_UNSUPPORTED(".short 0xdeff") - TEST_UNSUPPORTED("svc #0x00") - TEST_UNSUPPORTED("svc #0xff") - - TEST_GROUP("Unconditional branch") - - TEST_BF( "b 2f") - TEST_BB( "b 2b") - TEST_BF_X("b 2f", SPACE_0x400) - TEST_BB_X("b 2b", SPACE_0x400) - - TEST_GROUP("Testing instructions in IT blocks") - - TEST_ITBLOCK("subs.n r0, r0") - - verbose("\n"); -} - - -void kprobe_thumb32_test_cases(void) -{ - kprobe_test_flags = 0; - - TEST_GROUP("Load/store multiple") - - TEST_UNSUPPORTED("rfedb sp") - TEST_UNSUPPORTED("rfeia sp") - TEST_UNSUPPORTED("rfedb sp!") - TEST_UNSUPPORTED("rfeia sp!") - - TEST_P( "stmia r",0, 16*4,", {r0,r8}") - TEST_P( "stmia r",4, 16*4,", {r0-r12,r14}") - TEST_P( "stmia r",7, 16*4,"!, {r8-r12,r14}") - TEST_P( "stmia r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") - - TEST_P( "ldmia r",0, 16*4,", {r0,r8}") - TEST_P( "ldmia r",4, 0, ", {r0-r12,r14}") - TEST_BF_P("ldmia r",5, 8*4, "!, {r6-r12,r15}") - TEST_P( "ldmia r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") - TEST_BF_P("ldmia r",14,14*4,"!, {r4,pc}") - - TEST_P( "stmdb r",0, 16*4,", {r0,r8}") - TEST_P( "stmdb r",4, 16*4,", {r0-r12,r14}") - TEST_P( "stmdb r",5, 16*4,"!, {r8-r12,r14}") - TEST_P( "stmdb r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") - - TEST_P( "ldmdb r",0, 16*4,", {r0,r8}") - TEST_P( "ldmdb r",4, 16*4,", {r0-r12,r14}") - TEST_BF_P("ldmdb r",5, 16*4,"!, {r6-r12,r15}") - TEST_P( "ldmdb r",12,16*4,"!, {r1,r3,r5,r7,r8-r11,r14}") - TEST_BF_P("ldmdb r",14,16*4,"!, {r4,pc}") - - TEST_P( "stmdb r",13,16*4,"!, {r3-r12,lr}") - TEST_P( "stmdb r",13,16*4,"!, {r3-r12}") - TEST_P( "stmdb r",2, 16*4,", {r3-r12,lr}") - TEST_P( "stmdb r",13,16*4,"!, {r2-r12,lr}") - TEST_P( "stmdb r",0, 16*4,", {r0-r12}") - TEST_P( "stmdb r",0, 16*4,", {r0-r12,lr}") - - TEST_BF_P("ldmia r",13,5*4, "!, {r3-r12,pc}") - TEST_P( "ldmia r",13,5*4, "!, {r3-r12}") - TEST_BF_P("ldmia r",2, 5*4, "!, {r3-r12,pc}") - TEST_BF_P("ldmia r",13,4*4, "!, {r2-r12,pc}") - TEST_P( "ldmia r",0, 16*4,", {r0-r12}") - TEST_P( "ldmia r",0, 16*4,", {r0-r12,lr}") - - TEST_THUMB_TO_ARM_INTERWORK_P("ldmia r",0,14*4,", {r12,pc}") - TEST_THUMB_TO_ARM_INTERWORK_P("ldmia r",13,2*4,", {r0-r12,pc}") - - TEST_UNSUPPORTED(".short 0xe88f,0x0101 @ stmia pc, {r0,r8}") - TEST_UNSUPPORTED(".short 0xe92f,0x5f00 @ stmdb pc!, {r8-r12,r14}") - TEST_UNSUPPORTED(".short 0xe8bd,0xc000 @ ldmia r13!, {r14,pc}") - TEST_UNSUPPORTED(".short 0xe93e,0xc000 @ ldmdb r14!, {r14,pc}") - TEST_UNSUPPORTED(".short 0xe8a7,0x3f00 @ stmia r7!, {r8-r12,sp}") - TEST_UNSUPPORTED(".short 0xe8a7,0x9f00 @ stmia r7!, {r8-r12,pc}") - TEST_UNSUPPORTED(".short 0xe93e,0x2010 @ ldmdb r14!, {r4,sp}") - - TEST_GROUP("Load/store double or exclusive, table branch") - - TEST_P( "ldrd r0, r1, [r",1, 24,", #-16]") - TEST( "ldrd r12, r14, [sp, #16]") - TEST_P( "ldrd r1, r0, [r",7, 24,", #-16]!") - TEST( "ldrd r14, r12, [sp, #16]!") - TEST_P( "ldrd r1, r0, [r",7, 24,"], #16") - TEST( "ldrd r7, r8, [sp], #-16") - - TEST_X( "ldrd r12, r14, 3f", - ".align 3 \n\t" - "3: .word "__stringify(VAL1)" \n\t" - " .word "__stringify(VAL2)) - - TEST_UNSUPPORTED(".short 0xe9ff,0xec04 @ ldrd r14, r12, [pc, #16]!") - TEST_UNSUPPORTED(".short 0xe8ff,0xec04 @ ldrd r14, r12, [pc], #16") - TEST_UNSUPPORTED(".short 0xe9d4,0xd800 @ ldrd sp, r8, [r4]") - TEST_UNSUPPORTED(".short 0xe9d4,0xf800 @ ldrd pc, r8, [r4]") - TEST_UNSUPPORTED(".short 0xe9d4,0x7d00 @ ldrd r7, sp, [r4]") - TEST_UNSUPPORTED(".short 0xe9d4,0x7f00 @ ldrd r7, pc, [r4]") - - TEST_RRP("strd r",0, VAL1,", r",1, VAL2,", [r",1, 24,", #-16]") - TEST_RR( "strd r",12,VAL2,", r",14,VAL1,", [sp, #16]") - TEST_RRP("strd r",1, VAL1,", r",0, VAL2,", [r",7, 24,", #-16]!") - TEST_RR( "strd r",14,VAL2,", r",12,VAL1,", [sp, #16]!") - TEST_RRP("strd r",1, VAL1,", r",0, VAL2,", [r",7, 24,"], #16") - TEST_RR( "strd r",7, VAL2,", r",8, VAL1,", [sp], #-16") - TEST_UNSUPPORTED(".short 0xe9ef,0xec04 @ strd r14, r12, [pc, #16]!") - TEST_UNSUPPORTED(".short 0xe8ef,0xec04 @ strd r14, r12, [pc], #16") - - TEST_RX("tbb [pc, r",0, (9f-(1f+4)),"]", - "9: \n\t" - ".byte (2f-1b-4)>>1 \n\t" - ".byte (3f-1b-4)>>1 \n\t" - "3: mvn r0, r0 \n\t" - "2: nop \n\t") - - TEST_RX("tbb [pc, r",4, (9f-(1f+4)+1),"]", - "9: \n\t" - ".byte (2f-1b-4)>>1 \n\t" - ".byte (3f-1b-4)>>1 \n\t" - "3: mvn r0, r0 \n\t" - "2: nop \n\t") - - TEST_RRX("tbb [r",1,9f,", r",2,0,"]", - "9: \n\t" - ".byte (2f-1b-4)>>1 \n\t" - ".byte (3f-1b-4)>>1 \n\t" - "3: mvn r0, r0 \n\t" - "2: nop \n\t") - - TEST_RX("tbh [pc, r",7, (9f-(1f+4))>>1,"]", - "9: \n\t" - ".short (2f-1b-4)>>1 \n\t" - ".short (3f-1b-4)>>1 \n\t" - "3: mvn r0, r0 \n\t" - "2: nop \n\t") - - TEST_RX("tbh [pc, r",12, ((9f-(1f+4))>>1)+1,"]", - "9: \n\t" - ".short (2f-1b-4)>>1 \n\t" - ".short (3f-1b-4)>>1 \n\t" - "3: mvn r0, r0 \n\t" - "2: nop \n\t") - - TEST_RRX("tbh [r",1,9f, ", r",14,1,"]", - "9: \n\t" - ".short (2f-1b-4)>>1 \n\t" - ".short (3f-1b-4)>>1 \n\t" - "3: mvn r0, r0 \n\t" - "2: nop \n\t") - - TEST_UNSUPPORTED(".short 0xe8d1,0xf01f @ tbh [r1, pc]") - TEST_UNSUPPORTED(".short 0xe8d1,0xf01d @ tbh [r1, sp]") - TEST_UNSUPPORTED(".short 0xe8dd,0xf012 @ tbh [sp, r2]") - - TEST_UNSUPPORTED("strexb r0, r1, [r2]") - TEST_UNSUPPORTED("strexh r0, r1, [r2]") - TEST_UNSUPPORTED("strexd r0, r1, [r2]") - TEST_UNSUPPORTED("ldrexb r0, [r1]") - TEST_UNSUPPORTED("ldrexh r0, [r1]") - TEST_UNSUPPORTED("ldrexd r0, [r1]") - - TEST_GROUP("Data-processing (shifted register) and (modified immediate)") - -#define _DATA_PROCESSING32_DNM(op,s,val) \ - TEST_RR(op s".w r0, r",1, VAL1,", r",2, val, "") \ - TEST_RR(op s" r1, r",1, VAL1,", r",2, val, ", lsl #3") \ - TEST_RR(op s" r2, r",3, VAL1,", r",2, val, ", lsr #4") \ - TEST_RR(op s" r3, r",3, VAL1,", r",2, val, ", asr #5") \ - TEST_RR(op s" r4, r",5, VAL1,", r",2, N(val),", asr #6") \ - TEST_RR(op s" r5, r",5, VAL1,", r",2, val, ", ror #7") \ - TEST_RR(op s" r8, r",9, VAL1,", r",10,val, ", rrx") \ - TEST_R( op s" r0, r",11,VAL1,", #0x00010001") \ - TEST_R( op s" r11, r",0, VAL1,", #0xf5000000") \ - TEST_R( op s" r7, r",8, VAL2,", #0x000af000") - -#define DATA_PROCESSING32_DNM(op,val) \ - _DATA_PROCESSING32_DNM(op,"",val) \ - _DATA_PROCESSING32_DNM(op,"s",val) - -#define DATA_PROCESSING32_NM(op,val) \ - TEST_RR(op".w r",1, VAL1,", r",2, val, "") \ - TEST_RR(op" r",1, VAL1,", r",2, val, ", lsl #3") \ - TEST_RR(op" r",3, VAL1,", r",2, val, ", lsr #4") \ - TEST_RR(op" r",3, VAL1,", r",2, val, ", asr #5") \ - TEST_RR(op" r",5, VAL1,", r",2, N(val),", asr #6") \ - TEST_RR(op" r",5, VAL1,", r",2, val, ", ror #7") \ - TEST_RR(op" r",9, VAL1,", r",10,val, ", rrx") \ - TEST_R( op" r",11,VAL1,", #0x00010001") \ - TEST_R( op" r",0, VAL1,", #0xf5000000") \ - TEST_R( op" r",8, VAL2,", #0x000af000") - -#define _DATA_PROCESSING32_DM(op,s,val) \ - TEST_R( op s".w r0, r",14, val, "") \ - TEST_R( op s" r1, r",12, val, ", lsl #3") \ - TEST_R( op s" r2, r",11, val, ", lsr #4") \ - TEST_R( op s" r3, r",10, val, ", asr #5") \ - TEST_R( op s" r4, r",9, N(val),", asr #6") \ - TEST_R( op s" r5, r",8, val, ", ror #7") \ - TEST_R( op s" r8, r",7,val, ", rrx") \ - TEST( op s" r0, #0x00010001") \ - TEST( op s" r11, #0xf5000000") \ - TEST( op s" r7, #0x000af000") \ - TEST( op s" r4, #0x00005a00") - -#define DATA_PROCESSING32_DM(op,val) \ - _DATA_PROCESSING32_DM(op,"",val) \ - _DATA_PROCESSING32_DM(op,"s",val) - - DATA_PROCESSING32_DNM("and",0xf00f00ff) - DATA_PROCESSING32_NM("tst",0xf00f00ff) - DATA_PROCESSING32_DNM("bic",0xf00f00ff) - DATA_PROCESSING32_DNM("orr",0xf00f00ff) - DATA_PROCESSING32_DM("mov",VAL2) - DATA_PROCESSING32_DNM("orn",0xf00f00ff) - DATA_PROCESSING32_DM("mvn",VAL2) - DATA_PROCESSING32_DNM("eor",0xf00f00ff) - DATA_PROCESSING32_NM("teq",0xf00f00ff) - DATA_PROCESSING32_DNM("add",VAL2) - DATA_PROCESSING32_NM("cmn",VAL2) - DATA_PROCESSING32_DNM("adc",VAL2) - DATA_PROCESSING32_DNM("sbc",VAL2) - DATA_PROCESSING32_DNM("sub",VAL2) - DATA_PROCESSING32_NM("cmp",VAL2) - DATA_PROCESSING32_DNM("rsb",VAL2) - - TEST_RR("pkhbt r0, r",0, HH1,", r",1, HH2,"") - TEST_RR("pkhbt r14,r",12, HH1,", r",10,HH2,", lsl #2") - TEST_RR("pkhtb r0, r",0, HH1,", r",1, HH2,"") - TEST_RR("pkhtb r14,r",12, HH1,", r",10,HH2,", asr #2") - - TEST_UNSUPPORTED(".short 0xea17,0x0f0d @ tst.w r7, sp") - TEST_UNSUPPORTED(".short 0xea17,0x0f0f @ tst.w r7, pc") - TEST_UNSUPPORTED(".short 0xea1d,0x0f07 @ tst.w sp, r7") - TEST_UNSUPPORTED(".short 0xea1f,0x0f07 @ tst.w pc, r7") - TEST_UNSUPPORTED(".short 0xf01d,0x1f08 @ tst sp, #0x00080008") - TEST_UNSUPPORTED(".short 0xf01f,0x1f08 @ tst pc, #0x00080008") - - TEST_UNSUPPORTED(".short 0xea97,0x0f0d @ teq.w r7, sp") - TEST_UNSUPPORTED(".short 0xea97,0x0f0f @ teq.w r7, pc") - TEST_UNSUPPORTED(".short 0xea9d,0x0f07 @ teq.w sp, r7") - TEST_UNSUPPORTED(".short 0xea9f,0x0f07 @ teq.w pc, r7") - TEST_UNSUPPORTED(".short 0xf09d,0x1f08 @ tst sp, #0x00080008") - TEST_UNSUPPORTED(".short 0xf09f,0x1f08 @ tst pc, #0x00080008") - - TEST_UNSUPPORTED(".short 0xeb17,0x0f0d @ cmn.w r7, sp") - TEST_UNSUPPORTED(".short 0xeb17,0x0f0f @ cmn.w r7, pc") - TEST_P("cmn.w sp, r",7,0,"") - TEST_UNSUPPORTED(".short 0xeb1f,0x0f07 @ cmn.w pc, r7") - TEST( "cmn sp, #0x00080008") - TEST_UNSUPPORTED(".short 0xf11f,0x1f08 @ cmn pc, #0x00080008") - - TEST_UNSUPPORTED(".short 0xebb7,0x0f0d @ cmp.w r7, sp") - TEST_UNSUPPORTED(".short 0xebb7,0x0f0f @ cmp.w r7, pc") - TEST_P("cmp.w sp, r",7,0,"") - TEST_UNSUPPORTED(".short 0xebbf,0x0f07 @ cmp.w pc, r7") - TEST( "cmp sp, #0x00080008") - TEST_UNSUPPORTED(".short 0xf1bf,0x1f08 @ cmp pc, #0x00080008") - - TEST_UNSUPPORTED(".short 0xea5f,0x070d @ movs.w r7, sp") - TEST_UNSUPPORTED(".short 0xea5f,0x070f @ movs.w r7, pc") - TEST_UNSUPPORTED(".short 0xea5f,0x0d07 @ movs.w sp, r7") - TEST_UNSUPPORTED(".short 0xea4f,0x0f07 @ mov.w pc, r7") - TEST_UNSUPPORTED(".short 0xf04f,0x1d08 @ mov sp, #0x00080008") - TEST_UNSUPPORTED(".short 0xf04f,0x1f08 @ mov pc, #0x00080008") - - TEST_R("add.w r0, sp, r",1, 4,"") - TEST_R("adds r0, sp, r",1, 4,", asl #3") - TEST_R("add r0, sp, r",1, 4,", asl #4") - TEST_R("add r0, sp, r",1, 16,", ror #1") - TEST_R("add.w sp, sp, r",1, 4,"") - TEST_R("add sp, sp, r",1, 4,", asl #3") - TEST_UNSUPPORTED(".short 0xeb0d,0x1d01 @ add sp, sp, r1, asl #4") - TEST_UNSUPPORTED(".short 0xeb0d,0x0d71 @ add sp, sp, r1, ror #1") - TEST( "add.w r0, sp, #24") - TEST( "add.w sp, sp, #24") - TEST_UNSUPPORTED(".short 0xeb0d,0x0f01 @ add pc, sp, r1") - TEST_UNSUPPORTED(".short 0xeb0d,0x000f @ add r0, sp, pc") - TEST_UNSUPPORTED(".short 0xeb0d,0x000d @ add r0, sp, sp") - TEST_UNSUPPORTED(".short 0xeb0d,0x0d0f @ add sp, sp, pc") - TEST_UNSUPPORTED(".short 0xeb0d,0x0d0d @ add sp, sp, sp") - - TEST_R("sub.w r0, sp, r",1, 4,"") - TEST_R("subs r0, sp, r",1, 4,", asl #3") - TEST_R("sub r0, sp, r",1, 4,", asl #4") - TEST_R("sub r0, sp, r",1, 16,", ror #1") - TEST_R("sub.w sp, sp, r",1, 4,"") - TEST_R("sub sp, sp, r",1, 4,", asl #3") - TEST_UNSUPPORTED(".short 0xebad,0x1d01 @ sub sp, sp, r1, asl #4") - TEST_UNSUPPORTED(".short 0xebad,0x0d71 @ sub sp, sp, r1, ror #1") - TEST_UNSUPPORTED(".short 0xebad,0x0f01 @ sub pc, sp, r1") - TEST( "sub.w r0, sp, #24") - TEST( "sub.w sp, sp, #24") - - TEST_UNSUPPORTED(".short 0xea02,0x010f @ and r1, r2, pc") - TEST_UNSUPPORTED(".short 0xea0f,0x0103 @ and r1, pc, r3") - TEST_UNSUPPORTED(".short 0xea02,0x0f03 @ and pc, r2, r3") - TEST_UNSUPPORTED(".short 0xea02,0x010d @ and r1, r2, sp") - TEST_UNSUPPORTED(".short 0xea0d,0x0103 @ and r1, sp, r3") - TEST_UNSUPPORTED(".short 0xea02,0x0d03 @ and sp, r2, r3") - TEST_UNSUPPORTED(".short 0xf00d,0x1108 @ and r1, sp, #0x00080008") - TEST_UNSUPPORTED(".short 0xf00f,0x1108 @ and r1, pc, #0x00080008") - TEST_UNSUPPORTED(".short 0xf002,0x1d08 @ and sp, r8, #0x00080008") - TEST_UNSUPPORTED(".short 0xf002,0x1f08 @ and pc, r8, #0x00080008") - - TEST_UNSUPPORTED(".short 0xeb02,0x010f @ add r1, r2, pc") - TEST_UNSUPPORTED(".short 0xeb0f,0x0103 @ add r1, pc, r3") - TEST_UNSUPPORTED(".short 0xeb02,0x0f03 @ add pc, r2, r3") - TEST_UNSUPPORTED(".short 0xeb02,0x010d @ add r1, r2, sp") - TEST_SUPPORTED( ".short 0xeb0d,0x0103 @ add r1, sp, r3") - TEST_UNSUPPORTED(".short 0xeb02,0x0d03 @ add sp, r2, r3") - TEST_SUPPORTED( ".short 0xf10d,0x1108 @ add r1, sp, #0x00080008") - TEST_UNSUPPORTED(".short 0xf10d,0x1f08 @ add pc, sp, #0x00080008") - TEST_UNSUPPORTED(".short 0xf10f,0x1108 @ add r1, pc, #0x00080008") - TEST_UNSUPPORTED(".short 0xf102,0x1d08 @ add sp, r8, #0x00080008") - TEST_UNSUPPORTED(".short 0xf102,0x1f08 @ add pc, r8, #0x00080008") - - TEST_UNSUPPORTED(".short 0xeaa0,0x0000") - TEST_UNSUPPORTED(".short 0xeaf0,0x0000") - TEST_UNSUPPORTED(".short 0xeb20,0x0000") - TEST_UNSUPPORTED(".short 0xeb80,0x0000") - TEST_UNSUPPORTED(".short 0xebe0,0x0000") - - TEST_UNSUPPORTED(".short 0xf0a0,0x0000") - TEST_UNSUPPORTED(".short 0xf0c0,0x0000") - TEST_UNSUPPORTED(".short 0xf0f0,0x0000") - TEST_UNSUPPORTED(".short 0xf120,0x0000") - TEST_UNSUPPORTED(".short 0xf180,0x0000") - TEST_UNSUPPORTED(".short 0xf1e0,0x0000") - - TEST_GROUP("Coprocessor instructions") - - TEST_UNSUPPORTED(".short 0xec00,0x0000") - TEST_UNSUPPORTED(".short 0xeff0,0x0000") - TEST_UNSUPPORTED(".short 0xfc00,0x0000") - TEST_UNSUPPORTED(".short 0xfff0,0x0000") - - TEST_GROUP("Data-processing (plain binary immediate)") - - TEST_R("addw r0, r",1, VAL1,", #0x123") - TEST( "addw r14, sp, #0xf5a") - TEST( "addw sp, sp, #0x20") - TEST( "addw r7, pc, #0x888") - TEST_UNSUPPORTED(".short 0xf20f,0x1f20 @ addw pc, pc, #0x120") - TEST_UNSUPPORTED(".short 0xf20d,0x1f20 @ addw pc, sp, #0x120") - TEST_UNSUPPORTED(".short 0xf20f,0x1d20 @ addw sp, pc, #0x120") - TEST_UNSUPPORTED(".short 0xf200,0x1d20 @ addw sp, r0, #0x120") - - TEST_R("subw r0, r",1, VAL1,", #0x123") - TEST( "subw r14, sp, #0xf5a") - TEST( "subw sp, sp, #0x20") - TEST( "subw r7, pc, #0x888") - TEST_UNSUPPORTED(".short 0xf2af,0x1f20 @ subw pc, pc, #0x120") - TEST_UNSUPPORTED(".short 0xf2ad,0x1f20 @ subw pc, sp, #0x120") - TEST_UNSUPPORTED(".short 0xf2af,0x1d20 @ subw sp, pc, #0x120") - TEST_UNSUPPORTED(".short 0xf2a0,0x1d20 @ subw sp, r0, #0x120") - - TEST("movw r0, #0") - TEST("movw r0, #0xffff") - TEST("movw lr, #0xffff") - TEST_UNSUPPORTED(".short 0xf240,0x0d00 @ movw sp, #0") - TEST_UNSUPPORTED(".short 0xf240,0x0f00 @ movw pc, #0") - - TEST_R("movt r",0, VAL1,", #0") - TEST_R("movt r",0, VAL2,", #0xffff") - TEST_R("movt r",14,VAL1,", #0xffff") - TEST_UNSUPPORTED(".short 0xf2c0,0x0d00 @ movt sp, #0") - TEST_UNSUPPORTED(".short 0xf2c0,0x0f00 @ movt pc, #0") - - TEST_R( "ssat r0, #24, r",0, VAL1,"") - TEST_R( "ssat r14, #24, r",12, VAL2,"") - TEST_R( "ssat r0, #24, r",0, VAL1,", lsl #8") - TEST_R( "ssat r14, #24, r",12, VAL2,", asr #8") - TEST_UNSUPPORTED(".short 0xf30c,0x0d17 @ ssat sp, #24, r12") - TEST_UNSUPPORTED(".short 0xf30c,0x0f17 @ ssat pc, #24, r12") - TEST_UNSUPPORTED(".short 0xf30d,0x0c17 @ ssat r12, #24, sp") - TEST_UNSUPPORTED(".short 0xf30f,0x0c17 @ ssat r12, #24, pc") - - TEST_R( "usat r0, #24, r",0, VAL1,"") - TEST_R( "usat r14, #24, r",12, VAL2,"") - TEST_R( "usat r0, #24, r",0, VAL1,", lsl #8") - TEST_R( "usat r14, #24, r",12, VAL2,", asr #8") - TEST_UNSUPPORTED(".short 0xf38c,0x0d17 @ usat sp, #24, r12") - TEST_UNSUPPORTED(".short 0xf38c,0x0f17 @ usat pc, #24, r12") - TEST_UNSUPPORTED(".short 0xf38d,0x0c17 @ usat r12, #24, sp") - TEST_UNSUPPORTED(".short 0xf38f,0x0c17 @ usat r12, #24, pc") - - TEST_R( "ssat16 r0, #12, r",0, HH1,"") - TEST_R( "ssat16 r14, #12, r",12, HH2,"") - TEST_UNSUPPORTED(".short 0xf32c,0x0d0b @ ssat16 sp, #12, r12") - TEST_UNSUPPORTED(".short 0xf32c,0x0f0b @ ssat16 pc, #12, r12") - TEST_UNSUPPORTED(".short 0xf32d,0x0c0b @ ssat16 r12, #12, sp") - TEST_UNSUPPORTED(".short 0xf32f,0x0c0b @ ssat16 r12, #12, pc") - - TEST_R( "usat16 r0, #12, r",0, HH1,"") - TEST_R( "usat16 r14, #12, r",12, HH2,"") - TEST_UNSUPPORTED(".short 0xf3ac,0x0d0b @ usat16 sp, #12, r12") - TEST_UNSUPPORTED(".short 0xf3ac,0x0f0b @ usat16 pc, #12, r12") - TEST_UNSUPPORTED(".short 0xf3ad,0x0c0b @ usat16 r12, #12, sp") - TEST_UNSUPPORTED(".short 0xf3af,0x0c0b @ usat16 r12, #12, pc") - - TEST_R( "sbfx r0, r",0 , VAL1,", #0, #31") - TEST_R( "sbfx r14, r",12, VAL2,", #8, #16") - TEST_R( "sbfx r4, r",10, VAL1,", #16, #15") - TEST_UNSUPPORTED(".short 0xf34c,0x2d0f @ sbfx sp, r12, #8, #16") - TEST_UNSUPPORTED(".short 0xf34c,0x2f0f @ sbfx pc, r12, #8, #16") - TEST_UNSUPPORTED(".short 0xf34d,0x2c0f @ sbfx r12, sp, #8, #16") - TEST_UNSUPPORTED(".short 0xf34f,0x2c0f @ sbfx r12, pc, #8, #16") - - TEST_R( "ubfx r0, r",0 , VAL1,", #0, #31") - TEST_R( "ubfx r14, r",12, VAL2,", #8, #16") - TEST_R( "ubfx r4, r",10, VAL1,", #16, #15") - TEST_UNSUPPORTED(".short 0xf3cc,0x2d0f @ ubfx sp, r12, #8, #16") - TEST_UNSUPPORTED(".short 0xf3cc,0x2f0f @ ubfx pc, r12, #8, #16") - TEST_UNSUPPORTED(".short 0xf3cd,0x2c0f @ ubfx r12, sp, #8, #16") - TEST_UNSUPPORTED(".short 0xf3cf,0x2c0f @ ubfx r12, pc, #8, #16") - - TEST_R( "bfc r",0, VAL1,", #4, #20") - TEST_R( "bfc r",14,VAL2,", #4, #20") - TEST_R( "bfc r",7, VAL1,", #0, #31") - TEST_R( "bfc r",8, VAL2,", #0, #31") - TEST_UNSUPPORTED(".short 0xf36f,0x0d1e @ bfc sp, #0, #31") - TEST_UNSUPPORTED(".short 0xf36f,0x0f1e @ bfc pc, #0, #31") - - TEST_RR( "bfi r",0, VAL1,", r",0 , VAL2,", #0, #31") - TEST_RR( "bfi r",12,VAL1,", r",14 , VAL2,", #4, #20") - TEST_UNSUPPORTED(".short 0xf36e,0x1d17 @ bfi sp, r14, #4, #20") - TEST_UNSUPPORTED(".short 0xf36e,0x1f17 @ bfi pc, r14, #4, #20") - TEST_UNSUPPORTED(".short 0xf36d,0x1e17 @ bfi r14, sp, #4, #20") - - TEST_GROUP("Branches and miscellaneous control") - -CONDITION_INSTRUCTIONS(22, - TEST_BF("beq.w 2f") - TEST_BB("bne.w 2b") - TEST_BF("bgt.w 2f") - TEST_BB("blt.w 2b") - TEST_BF_X("bpl.w 2f", SPACE_0x1000) -) - - TEST_UNSUPPORTED("msr cpsr, r0") - TEST_UNSUPPORTED("msr cpsr_f, r1") - TEST_UNSUPPORTED("msr spsr, r2") - - TEST_UNSUPPORTED("cpsie.w i") - TEST_UNSUPPORTED("cpsid.w i") - TEST_UNSUPPORTED("cps 0x13") - - TEST_SUPPORTED("yield.w") - TEST("sev.w") - TEST("nop.w") - TEST("wfi.w") - TEST_SUPPORTED("wfe.w") - TEST_UNSUPPORTED("dbg.w #0") - - TEST_UNSUPPORTED("clrex") - TEST_UNSUPPORTED("dsb") - TEST_UNSUPPORTED("dmb") - TEST_UNSUPPORTED("isb") - - TEST_UNSUPPORTED("bxj r0") - - TEST_UNSUPPORTED("subs pc, lr, #4") - - TEST("mrs r0, cpsr") - TEST("mrs r14, cpsr") - TEST_UNSUPPORTED(".short 0xf3ef,0x8d00 @ mrs sp, spsr") - TEST_UNSUPPORTED(".short 0xf3ef,0x8f00 @ mrs pc, spsr") - TEST_UNSUPPORTED("mrs r0, spsr") - TEST_UNSUPPORTED("mrs lr, spsr") - - TEST_UNSUPPORTED(".short 0xf7f0,0x8000 @ smc #0") - - TEST_UNSUPPORTED(".short 0xf7f0,0xa000 @ undefeined") - - TEST_BF( "b.w 2f") - TEST_BB( "b.w 2b") - TEST_BF_X("b.w 2f", SPACE_0x1000) - - TEST_BF( "bl.w 2f") - TEST_BB( "bl.w 2b") - TEST_BB_X("bl.w 2b", SPACE_0x1000) - - TEST_X( "blx __dummy_arm_subroutine", - ".arm \n\t" - ".align \n\t" - ".type __dummy_arm_subroutine, %%function \n\t" - "__dummy_arm_subroutine: \n\t" - "mov r0, pc \n\t" - "bx lr \n\t" - ".thumb \n\t" - ) - TEST( "blx __dummy_arm_subroutine") - - TEST_GROUP("Store single data item") - -#define SINGLE_STORE(size) \ - TEST_RP( "str"size" r",0, VAL1,", [r",11,-1024,", #1024]") \ - TEST_RP( "str"size" r",14,VAL2,", [r",1, -1024,", #1080]") \ - TEST_RP( "str"size" r",0, VAL1,", [r",11,256, ", #-120]") \ - TEST_RP( "str"size" r",14,VAL2,", [r",1, 256, ", #-128]") \ - TEST_RP( "str"size" r",0, VAL1,", [r",11,24, "], #120") \ - TEST_RP( "str"size" r",14,VAL2,", [r",1, 24, "], #128") \ - TEST_RP( "str"size" r",0, VAL1,", [r",11,24, "], #-120") \ - TEST_RP( "str"size" r",14,VAL2,", [r",1, 24, "], #-128") \ - TEST_RP( "str"size" r",0, VAL1,", [r",11,24, ", #120]!") \ - TEST_RP( "str"size" r",14,VAL2,", [r",1, 24, ", #128]!") \ - TEST_RP( "str"size" r",0, VAL1,", [r",11,256, ", #-120]!") \ - TEST_RP( "str"size" r",14,VAL2,", [r",1, 256, ", #-128]!") \ - TEST_RPR("str"size".w r",0, VAL1,", [r",1, 0,", r",2, 4,"]") \ - TEST_RPR("str"size" r",14,VAL2,", [r",10,0,", r",11,4,", lsl #1]") \ - TEST_R( "str"size".w r",7, VAL1,", [sp, #24]") \ - TEST_RP( "str"size".w r",0, VAL2,", [r",0,0, "]") \ - TEST_UNSUPPORTED("str"size"t r0, [r1, #4]") - - SINGLE_STORE("b") - SINGLE_STORE("h") - SINGLE_STORE("") - - TEST("str sp, [sp]") - TEST_UNSUPPORTED(".short 0xf8cf,0xe000 @ str r14, [pc]") - TEST_UNSUPPORTED(".short 0xf8ce,0xf000 @ str pc, [r14]") - - TEST_GROUP("Advanced SIMD element or structure load/store instructions") - - TEST_UNSUPPORTED(".short 0xf900,0x0000") - TEST_UNSUPPORTED(".short 0xf92f,0xffff") - TEST_UNSUPPORTED(".short 0xf980,0x0000") - TEST_UNSUPPORTED(".short 0xf9ef,0xffff") - - TEST_GROUP("Load single data item and memory hints") - -#define SINGLE_LOAD(size) \ - TEST_P( "ldr"size" r0, [r",11,-1024, ", #1024]") \ - TEST_P( "ldr"size" r14, [r",1, -1024,", #1080]") \ - TEST_P( "ldr"size" r0, [r",11,256, ", #-120]") \ - TEST_P( "ldr"size" r14, [r",1, 256, ", #-128]") \ - TEST_P( "ldr"size" r0, [r",11,24, "], #120") \ - TEST_P( "ldr"size" r14, [r",1, 24, "], #128") \ - TEST_P( "ldr"size" r0, [r",11,24, "], #-120") \ - TEST_P( "ldr"size" r14, [r",1,24, "], #-128") \ - TEST_P( "ldr"size" r0, [r",11,24, ", #120]!") \ - TEST_P( "ldr"size" r14, [r",1, 24, ", #128]!") \ - TEST_P( "ldr"size" r0, [r",11,256, ", #-120]!") \ - TEST_P( "ldr"size" r14, [r",1, 256, ", #-128]!") \ - TEST_PR("ldr"size".w r0, [r",1, 0,", r",2, 4,"]") \ - TEST_PR("ldr"size" r14, [r",10,0,", r",11,4,", lsl #1]") \ - TEST_X( "ldr"size".w r0, 3f", \ - ".align 3 \n\t" \ - "3: .word "__stringify(VAL1)) \ - TEST_X( "ldr"size".w r14, 3f", \ - ".align 3 \n\t" \ - "3: .word "__stringify(VAL2)) \ - TEST( "ldr"size".w r7, 3b") \ - TEST( "ldr"size".w r7, [sp, #24]") \ - TEST_P( "ldr"size".w r0, [r",0,0, "]") \ - TEST_UNSUPPORTED("ldr"size"t r0, [r1, #4]") - - SINGLE_LOAD("b") - SINGLE_LOAD("sb") - SINGLE_LOAD("h") - SINGLE_LOAD("sh") - SINGLE_LOAD("") - - TEST_BF_P("ldr pc, [r",14, 15*4,"]") - TEST_P( "ldr sp, [r",14, 13*4,"]") - TEST_BF_R("ldr pc, [sp, r",14, 15*4,"]") - TEST_R( "ldr sp, [sp, r",14, 13*4,"]") - TEST_THUMB_TO_ARM_INTERWORK_P("ldr pc, [r",0,0,", #15*4]") - TEST_SUPPORTED("ldr sp, 99f") - TEST_SUPPORTED("ldr pc, 99f") - - TEST_UNSUPPORTED(".short 0xf854,0x700d @ ldr r7, [r4, sp]") - TEST_UNSUPPORTED(".short 0xf854,0x700f @ ldr r7, [r4, pc]") - TEST_UNSUPPORTED(".short 0xf814,0x700d @ ldrb r7, [r4, sp]") - TEST_UNSUPPORTED(".short 0xf814,0x700f @ ldrb r7, [r4, pc]") - TEST_UNSUPPORTED(".short 0xf89f,0xd004 @ ldrb sp, 99f") - TEST_UNSUPPORTED(".short 0xf814,0xd008 @ ldrb sp, [r4, r8]") - TEST_UNSUPPORTED(".short 0xf894,0xd000 @ ldrb sp, [r4]") - - TEST_UNSUPPORTED(".short 0xf860,0x0000") /* Unallocated space */ - TEST_UNSUPPORTED(".short 0xf9ff,0xffff") /* Unallocated space */ - TEST_UNSUPPORTED(".short 0xf950,0x0000") /* Unallocated space */ - TEST_UNSUPPORTED(".short 0xf95f,0xffff") /* Unallocated space */ - TEST_UNSUPPORTED(".short 0xf800,0x0800") /* Unallocated space */ - TEST_UNSUPPORTED(".short 0xf97f,0xfaff") /* Unallocated space */ - - TEST( "pli [pc, #4]") - TEST( "pli [pc, #-4]") - TEST( "pld [pc, #4]") - TEST( "pld [pc, #-4]") - - TEST_P( "pld [r",0,-1024,", #1024]") - TEST( ".short 0xf8b0,0xf400 @ pldw [r0, #1024]") - TEST_P( "pli [r",4, 0b,", #1024]") - TEST_P( "pld [r",7, 120,", #-120]") - TEST( ".short 0xf837,0xfc78 @ pldw [r7, #-120]") - TEST_P( "pli [r",11,120,", #-120]") - TEST( "pld [sp, #0]") - - TEST_PR("pld [r",7, 24, ", r",0, 16,"]") - TEST_PR("pld [r",8, 24, ", r",12,16,", lsl #3]") - TEST_SUPPORTED(".short 0xf837,0xf000 @ pldw [r7, r0]") - TEST_SUPPORTED(".short 0xf838,0xf03c @ pldw [r8, r12, lsl #3]"); - TEST_RR("pli [r",12,0b,", r",0, 16,"]") - TEST_RR("pli [r",0, 0b,", r",12,16,", lsl #3]") - TEST_R( "pld [sp, r",1, 16,"]") - TEST_UNSUPPORTED(".short 0xf817,0xf00d @pld [r7, sp]") - TEST_UNSUPPORTED(".short 0xf817,0xf00f @pld [r7, pc]") - - TEST_GROUP("Data-processing (register)") - -#define SHIFTS32(op) \ - TEST_RR(op" r0, r",1, VAL1,", r",2, 3, "") \ - TEST_RR(op" r14, r",12,VAL2,", r",11,10,"") - - SHIFTS32("lsl") - SHIFTS32("lsls") - SHIFTS32("lsr") - SHIFTS32("lsrs") - SHIFTS32("asr") - SHIFTS32("asrs") - SHIFTS32("ror") - SHIFTS32("rors") - - TEST_UNSUPPORTED(".short 0xfa01,0xff02 @ lsl pc, r1, r2") - TEST_UNSUPPORTED(".short 0xfa01,0xfd02 @ lsl sp, r1, r2") - TEST_UNSUPPORTED(".short 0xfa0f,0xf002 @ lsl r0, pc, r2") - TEST_UNSUPPORTED(".short 0xfa0d,0xf002 @ lsl r0, sp, r2") - TEST_UNSUPPORTED(".short 0xfa01,0xf00f @ lsl r0, r1, pc") - TEST_UNSUPPORTED(".short 0xfa01,0xf00d @ lsl r0, r1, sp") - - TEST_RR( "sxtah r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "sxtah r14,r",12, HH2,", r",10,HH1,", ror #8") - TEST_R( "sxth r8, r",7, HH1,"") - - TEST_UNSUPPORTED(".short 0xfa0f,0xff87 @ sxth pc, r7"); - TEST_UNSUPPORTED(".short 0xfa0f,0xfd87 @ sxth sp, r7"); - TEST_UNSUPPORTED(".short 0xfa0f,0xf88f @ sxth r8, pc"); - TEST_UNSUPPORTED(".short 0xfa0f,0xf88d @ sxth r8, sp"); - - TEST_RR( "uxtah r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "uxtah r14,r",12, HH2,", r",10,HH1,", ror #8") - TEST_R( "uxth r8, r",7, HH1,"") - - TEST_RR( "sxtab16 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "sxtab16 r14,r",12, HH2,", r",10,HH1,", ror #8") - TEST_R( "sxtb16 r8, r",7, HH1,"") - - TEST_RR( "uxtab16 r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "uxtab16 r14,r",12, HH2,", r",10,HH1,", ror #8") - TEST_R( "uxtb16 r8, r",7, HH1,"") - - TEST_RR( "sxtab r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "sxtab r14,r",12, HH2,", r",10,HH1,", ror #8") - TEST_R( "sxtb r8, r",7, HH1,"") - - TEST_RR( "uxtab r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "uxtab r14,r",12, HH2,", r",10,HH1,", ror #8") - TEST_R( "uxtb r8, r",7, HH1,"") - - TEST_UNSUPPORTED(".short 0xfa60,0x00f0") - TEST_UNSUPPORTED(".short 0xfa7f,0xffff") - -#define PARALLEL_ADD_SUB(op) \ - TEST_RR( op"add16 r0, r",0, HH1,", r",1, HH2,"") \ - TEST_RR( op"add16 r14, r",12,HH2,", r",10,HH1,"") \ - TEST_RR( op"asx r0, r",0, HH1,", r",1, HH2,"") \ - TEST_RR( op"asx r14, r",12,HH2,", r",10,HH1,"") \ - TEST_RR( op"sax r0, r",0, HH1,", r",1, HH2,"") \ - TEST_RR( op"sax r14, r",12,HH2,", r",10,HH1,"") \ - TEST_RR( op"sub16 r0, r",0, HH1,", r",1, HH2,"") \ - TEST_RR( op"sub16 r14, r",12,HH2,", r",10,HH1,"") \ - TEST_RR( op"add8 r0, r",0, HH1,", r",1, HH2,"") \ - TEST_RR( op"add8 r14, r",12,HH2,", r",10,HH1,"") \ - TEST_RR( op"sub8 r0, r",0, HH1,", r",1, HH2,"") \ - TEST_RR( op"sub8 r14, r",12,HH2,", r",10,HH1,"") - - TEST_GROUP("Parallel addition and subtraction, signed") - - PARALLEL_ADD_SUB("s") - PARALLEL_ADD_SUB("q") - PARALLEL_ADD_SUB("sh") - - TEST_GROUP("Parallel addition and subtraction, unsigned") - - PARALLEL_ADD_SUB("u") - PARALLEL_ADD_SUB("uq") - PARALLEL_ADD_SUB("uh") - - TEST_GROUP("Miscellaneous operations") - - TEST_RR("qadd r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR("qadd lr, r",9, VAL2,", r",8, VAL1,"") - TEST_RR("qsub r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR("qsub lr, r",9, VAL2,", r",8, VAL1,"") - TEST_RR("qdadd r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR("qdadd lr, r",9, VAL2,", r",8, VAL1,"") - TEST_RR("qdsub r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR("qdsub lr, r",9, VAL2,", r",8, VAL1,"") - - TEST_R("rev.w r0, r",0, VAL1,"") - TEST_R("rev r14, r",12, VAL2,"") - TEST_R("rev16.w r0, r",0, VAL1,"") - TEST_R("rev16 r14, r",12, VAL2,"") - TEST_R("rbit r0, r",0, VAL1,"") - TEST_R("rbit r14, r",12, VAL2,"") - TEST_R("revsh.w r0, r",0, VAL1,"") - TEST_R("revsh r14, r",12, VAL2,"") - - TEST_UNSUPPORTED(".short 0xfa9c,0xff8c @ rev pc, r12"); - TEST_UNSUPPORTED(".short 0xfa9c,0xfd8c @ rev sp, r12"); - TEST_UNSUPPORTED(".short 0xfa9f,0xfe8f @ rev r14, pc"); - TEST_UNSUPPORTED(".short 0xfa9d,0xfe8d @ rev r14, sp"); - - TEST_RR("sel r0, r",0, VAL1,", r",1, VAL2,"") - TEST_RR("sel r14, r",12,VAL1,", r",10, VAL2,"") - - TEST_R("clz r0, r",0, 0x0,"") - TEST_R("clz r7, r",14,0x1,"") - TEST_R("clz lr, r",7, 0xffffffff,"") - - TEST_UNSUPPORTED(".short 0xfa80,0xf030") /* Unallocated space */ - TEST_UNSUPPORTED(".short 0xfaff,0xff7f") /* Unallocated space */ - TEST_UNSUPPORTED(".short 0xfab0,0xf000") /* Unallocated space */ - TEST_UNSUPPORTED(".short 0xfaff,0xff7f") /* Unallocated space */ - - TEST_GROUP("Multiply, multiply accumulate, and absolute difference operations") - - TEST_RR( "mul r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR( "mul r7, r",8, VAL2,", r",9, VAL2,"") - TEST_UNSUPPORTED(".short 0xfb08,0xff09 @ mul pc, r8, r9") - TEST_UNSUPPORTED(".short 0xfb08,0xfd09 @ mul sp, r8, r9") - TEST_UNSUPPORTED(".short 0xfb0f,0xf709 @ mul r7, pc, r9") - TEST_UNSUPPORTED(".short 0xfb0d,0xf709 @ mul r7, sp, r9") - TEST_UNSUPPORTED(".short 0xfb08,0xf70f @ mul r7, r8, pc") - TEST_UNSUPPORTED(".short 0xfb08,0xf70d @ mul r7, r8, sp") - - TEST_RRR( "mla r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") - TEST_RRR( "mla r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") - TEST_UNSUPPORTED(".short 0xfb08,0xaf09 @ mla pc, r8, r9, r10"); - TEST_UNSUPPORTED(".short 0xfb08,0xad09 @ mla sp, r8, r9, r10"); - TEST_UNSUPPORTED(".short 0xfb0f,0xa709 @ mla r7, pc, r9, r10"); - TEST_UNSUPPORTED(".short 0xfb0d,0xa709 @ mla r7, sp, r9, r10"); - TEST_UNSUPPORTED(".short 0xfb08,0xa70f @ mla r7, r8, pc, r10"); - TEST_UNSUPPORTED(".short 0xfb08,0xa70d @ mla r7, r8, sp, r10"); - TEST_UNSUPPORTED(".short 0xfb08,0xd709 @ mla r7, r8, r9, sp"); - - TEST_RRR( "mls r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") - TEST_RRR( "mls r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") - - TEST_RRR( "smlabb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") - TEST_RRR( "smlabb r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") - TEST_RRR( "smlatb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") - TEST_RRR( "smlatb r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") - TEST_RRR( "smlabt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") - TEST_RRR( "smlabt r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") - TEST_RRR( "smlatt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") - TEST_RRR( "smlatt r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") - TEST_RR( "smulbb r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR( "smulbb r7, r",8, VAL3,", r",9, VAL1,"") - TEST_RR( "smultb r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR( "smultb r7, r",8, VAL3,", r",9, VAL1,"") - TEST_RR( "smulbt r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR( "smulbt r7, r",8, VAL3,", r",9, VAL1,"") - TEST_RR( "smultt r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR( "smultt r7, r",8, VAL3,", r",9, VAL1,"") - - TEST_RRR( "smlad r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"") - TEST_RRR( "smlad r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"") - TEST_RRR( "smladx r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"") - TEST_RRR( "smladx r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"") - TEST_RR( "smuad r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "smuad r14, r",12,HH2,", r",10,HH1,"") - TEST_RR( "smuadx r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "smuadx r14, r",12,HH2,", r",10,HH1,"") - - TEST_RRR( "smlawb r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") - TEST_RRR( "smlawb r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") - TEST_RRR( "smlawt r0, r",1, VAL1,", r",2, VAL2,", r",3, VAL3,"") - TEST_RRR( "smlawt r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"") - TEST_RR( "smulwb r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR( "smulwb r7, r",8, VAL3,", r",9, VAL1,"") - TEST_RR( "smulwt r0, r",1, VAL1,", r",2, VAL2,"") - TEST_RR( "smulwt r7, r",8, VAL3,", r",9, VAL1,"") - - TEST_RRR( "smlsd r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"") - TEST_RRR( "smlsd r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"") - TEST_RRR( "smlsdx r0, r",0, HH1,", r",1, HH2,", r",2, VAL1,"") - TEST_RRR( "smlsdx r14, r",12,HH2,", r",10,HH1,", r",8, VAL2,"") - TEST_RR( "smusd r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "smusd r14, r",12,HH2,", r",10,HH1,"") - TEST_RR( "smusdx r0, r",0, HH1,", r",1, HH2,"") - TEST_RR( "smusdx r14, r",12,HH2,", r",10,HH1,"") - - TEST_RRR( "smmla r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"") - TEST_RRR( "smmla r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"") - TEST_RRR( "smmlar r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"") - TEST_RRR( "smmlar r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"") - TEST_RR( "smmul r0, r",0, VAL1,", r",1, VAL2,"") - TEST_RR( "smmul r14, r",12,VAL2,", r",10,VAL1,"") - TEST_RR( "smmulr r0, r",0, VAL1,", r",1, VAL2,"") - TEST_RR( "smmulr r14, r",12,VAL2,", r",10,VAL1,"") - - TEST_RRR( "smmls r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"") - TEST_RRR( "smmls r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"") - TEST_RRR( "smmlsr r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL1,"") - TEST_RRR( "smmlsr r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL2,"") - - TEST_RRR( "usada8 r0, r",0, VAL1,", r",1, VAL2,", r",2, VAL3,"") - TEST_RRR( "usada8 r14, r",12,VAL2,", r",10,VAL1,", r",8, VAL3,"") - TEST_RR( "usad8 r0, r",0, VAL1,", r",1, VAL2,"") - TEST_RR( "usad8 r14, r",12,VAL2,", r",10,VAL1,"") - - TEST_UNSUPPORTED(".short 0xfb00,0xf010") /* Unallocated space */ - TEST_UNSUPPORTED(".short 0xfb0f,0xff1f") /* Unallocated space */ - TEST_UNSUPPORTED(".short 0xfb70,0xf010") /* Unallocated space */ - TEST_UNSUPPORTED(".short 0xfb7f,0xff1f") /* Unallocated space */ - TEST_UNSUPPORTED(".short 0xfb70,0x0010") /* Unallocated space */ - TEST_UNSUPPORTED(".short 0xfb7f,0xff1f") /* Unallocated space */ - - TEST_GROUP("Long multiply, long multiply accumulate, and divide") - - TEST_RR( "smull r0, r1, r",2, VAL1,", r",3, VAL2,"") - TEST_RR( "smull r7, r8, r",9, VAL2,", r",10, VAL1,"") - TEST_UNSUPPORTED(".short 0xfb89,0xf80a @ smull pc, r8, r9, r10"); - TEST_UNSUPPORTED(".short 0xfb89,0xd80a @ smull sp, r8, r9, r10"); - TEST_UNSUPPORTED(".short 0xfb89,0x7f0a @ smull r7, pc, r9, r10"); - TEST_UNSUPPORTED(".short 0xfb89,0x7d0a @ smull r7, sp, r9, r10"); - TEST_UNSUPPORTED(".short 0xfb8f,0x780a @ smull r7, r8, pc, r10"); - TEST_UNSUPPORTED(".short 0xfb8d,0x780a @ smull r7, r8, sp, r10"); - TEST_UNSUPPORTED(".short 0xfb89,0x780f @ smull r7, r8, r9, pc"); - TEST_UNSUPPORTED(".short 0xfb89,0x780d @ smull r7, r8, r9, sp"); - - TEST_RR( "umull r0, r1, r",2, VAL1,", r",3, VAL2,"") - TEST_RR( "umull r7, r8, r",9, VAL2,", r",10, VAL1,"") - - TEST_RRRR( "smlal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) - TEST_RRRR( "smlal r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) - - TEST_RRRR( "smlalbb r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) - TEST_RRRR( "smlalbb r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) - TEST_RRRR( "smlalbt r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) - TEST_RRRR( "smlalbt r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) - TEST_RRRR( "smlaltb r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) - TEST_RRRR( "smlaltb r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) - TEST_RRRR( "smlaltt r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) - TEST_RRRR( "smlaltt r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) - - TEST_RRRR( "smlald r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2) - TEST_RRRR( "smlald r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1) - TEST_RRRR( "smlaldx r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2) - TEST_RRRR( "smlaldx r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1) - - TEST_RRRR( "smlsld r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2) - TEST_RRRR( "smlsld r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1) - TEST_RRRR( "smlsldx r",0, VAL1,", r",1, VAL2, ", r",0, HH1,", r",1, HH2) - TEST_RRRR( "smlsldx r",11,VAL2,", r",10,VAL1, ", r",9, HH2,", r",8, HH1) - - TEST_RRRR( "umlal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) - TEST_RRRR( "umlal r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) - TEST_RRRR( "umaal r",0, VAL1,", r",1, VAL2,", r",2, VAL3,", r",3, VAL4) - TEST_RRRR( "umaal r",8, VAL4,", r",9, VAL1,", r",10,VAL2,", r",11,VAL3) - - TEST_GROUP("Coprocessor instructions") - - TEST_UNSUPPORTED(".short 0xfc00,0x0000") - TEST_UNSUPPORTED(".short 0xffff,0xffff") - - TEST_GROUP("Testing instructions in IT blocks") - - TEST_ITBLOCK("sub.w r0, r0") - - verbose("\n"); -} - diff --git a/ANDROID_3.4.5/arch/arm/kernel/kprobes-test.c b/ANDROID_3.4.5/arch/arm/kernel/kprobes-test.c deleted file mode 100644 index 1862d8f2..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/kprobes-test.c +++ /dev/null @@ -1,1696 +0,0 @@ -/* - * arch/arm/kernel/kprobes-test.c - * - * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* - * This file contains test code for ARM kprobes. - * - * The top level function run_all_tests() executes tests for all of the - * supported instruction sets: ARM, 16-bit Thumb, and 32-bit Thumb. These tests - * fall into two categories; run_api_tests() checks basic functionality of the - * kprobes API, and run_test_cases() is a comprehensive test for kprobes - * instruction decoding and simulation. - * - * run_test_cases() first checks the kprobes decoding table for self consistency - * (using table_test()) then executes a series of test cases for each of the CPU - * instruction forms. coverage_start() and coverage_end() are used to verify - * that these test cases cover all of the possible combinations of instructions - * described by the kprobes decoding tables. - * - * The individual test cases are in kprobes-test-arm.c and kprobes-test-thumb.c - * which use the macros defined in kprobes-test.h. The rest of this - * documentation will describe the operation of the framework used by these - * test cases. - */ - -/* - * TESTING METHODOLOGY - * ------------------- - * - * The methodology used to test an ARM instruction 'test_insn' is to use - * inline assembler like: - * - * test_before: nop - * test_case: test_insn - * test_after: nop - * - * When the test case is run a kprobe is placed of each nop. The - * post-handler of the test_before probe is used to modify the saved CPU - * register context to that which we require for the test case. The - * pre-handler of the of the test_after probe saves a copy of the CPU - * register context. In this way we can execute test_insn with a specific - * register context and see the results afterwards. - * - * To actually test the kprobes instruction emulation we perform the above - * step a second time but with an additional kprobe on the test_case - * instruction itself. If the emulation is accurate then the results seen - * by the test_after probe will be identical to the first run which didn't - * have a probe on test_case. - * - * Each test case is run several times with a variety of variations in the - * flags value of stored in CPSR, and for Thumb code, different ITState. - * - * For instructions which can modify PC, a second test_after probe is used - * like this: - * - * test_before: nop - * test_case: test_insn - * test_after: nop - * b test_done - * test_after2: nop - * test_done: - * - * The test case is constructed such that test_insn branches to - * test_after2, or, if testing a conditional instruction, it may just - * continue to test_after. The probes inserted at both locations let us - * determine which happened. A similar approach is used for testing - * backwards branches... - * - * b test_before - * b test_done @ helps to cope with off by 1 branches - * test_after2: nop - * b test_done - * test_before: nop - * test_case: test_insn - * test_after: nop - * test_done: - * - * The macros used to generate the assembler instructions describe above - * are TEST_INSTRUCTION, TEST_BRANCH_F (branch forwards) and TEST_BRANCH_B - * (branch backwards). In these, the local variables numbered 1, 50, 2 and - * 99 represent: test_before, test_case, test_after2 and test_done. - * - * FRAMEWORK - * --------- - * - * Each test case is wrapped between the pair of macros TESTCASE_START and - * TESTCASE_END. As well as performing the inline assembler boilerplate, - * these call out to the kprobes_test_case_start() and - * kprobes_test_case_end() functions which drive the execution of the test - * case. The specific arguments to use for each test case are stored as - * inline data constructed using the various TEST_ARG_* macros. Putting - * this all together, a simple test case may look like: - * - * TESTCASE_START("Testing mov r0, r7") - * TEST_ARG_REG(7, 0x12345678) // Set r7=0x12345678 - * TEST_ARG_END("") - * TEST_INSTRUCTION("mov r0, r7") - * TESTCASE_END - * - * Note, in practice the single convenience macro TEST_R would be used for this - * instead. - * - * The above would expand to assembler looking something like: - * - * @ TESTCASE_START - * bl __kprobes_test_case_start - * @ start of inline data... - * .ascii "mov r0, r7" @ text title for test case - * .byte 0 - * .align 2 - * - * @ TEST_ARG_REG - * .byte ARG_TYPE_REG - * .byte 7 - * .short 0 - * .word 0x1234567 - * - * @ TEST_ARG_END - * .byte ARG_TYPE_END - * .byte TEST_ISA @ flags, including ISA being tested - * .short 50f-0f @ offset of 'test_before' - * .short 2f-0f @ offset of 'test_after2' (if relevent) - * .short 99f-0f @ offset of 'test_done' - * @ start of test case code... - * 0: - * .code TEST_ISA @ switch to ISA being tested - * - * @ TEST_INSTRUCTION - * 50: nop @ location for 'test_before' probe - * 1: mov r0, r7 @ the test case instruction 'test_insn' - * nop @ location for 'test_after' probe - * - * // TESTCASE_END - * 2: - * 99: bl __kprobes_test_case_end_##TEST_ISA - * .code NONMAL_ISA - * - * When the above is execute the following happens... - * - * __kprobes_test_case_start() is an assembler wrapper which sets up space - * for a stack buffer and calls the C function kprobes_test_case_start(). - * This C function will do some initial processing of the inline data and - * setup some global state. It then inserts the test_before and test_after - * kprobes and returns a value which causes the assembler wrapper to jump - * to the start of the test case code, (local label '0'). - * - * When the test case code executes, the test_before probe will be hit and - * test_before_post_handler will call setup_test_context(). This fills the - * stack buffer and CPU registers with a test pattern and then processes - * the test case arguments. In our example there is one TEST_ARG_REG which - * indicates that R7 should be loaded with the value 0x12345678. - * - * When the test_before probe ends, the test case continues and executes - * the "mov r0, r7" instruction. It then hits the test_after probe and the - * pre-handler for this (test_after_pre_handler) will save a copy of the - * CPU register context. This should now have R0 holding the same value as - * R7. - * - * Finally we get to the call to __kprobes_test_case_end_{32,16}. This is - * an assembler wrapper which switches back to the ISA used by the test - * code and calls the C function kprobes_test_case_end(). - * - * For each run through the test case, test_case_run_count is incremented - * by one. For even runs, kprobes_test_case_end() saves a copy of the - * register and stack buffer contents from the test case just run. It then - * inserts a kprobe on the test case instruction 'test_insn' and returns a - * value to cause the test case code to be re-run. - * - * For odd numbered runs, kprobes_test_case_end() compares the register and - * stack buffer contents to those that were saved on the previous even - * numbered run (the one without the kprobe on test_insn). These should be - * the same if the kprobe instruction simulation routine is correct. - * - * The pair of test case runs is repeated with different combinations of - * flag values in CPSR and, for Thumb, different ITState. This is - * controlled by test_context_cpsr(). - * - * BUILDING TEST CASES - * ------------------- - * - * - * As an aid to building test cases, the stack buffer is initialised with - * some special values: - * - * [SP+13*4] Contains SP+120. This can be used to test instructions - * which load a value into SP. - * - * [SP+15*4] When testing branching instructions using TEST_BRANCH_{F,B}, - * this holds the target address of the branch, 'test_after2'. - * This can be used to test instructions which load a PC value - * from memory. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/kprobes.h> - -#include <asm/opcodes.h> - -#include "kprobes.h" -#include "kprobes-test.h" - - -#define BENCHMARKING 1 - - -/* - * Test basic API - */ - -static bool test_regs_ok; -static int test_func_instance; -static int pre_handler_called; -static int post_handler_called; -static int jprobe_func_called; -static int kretprobe_handler_called; - -#define FUNC_ARG1 0x12345678 -#define FUNC_ARG2 0xabcdef - - -#ifndef CONFIG_THUMB2_KERNEL - -long arm_func(long r0, long r1); - -static void __used __naked __arm_kprobes_test_func(void) -{ - __asm__ __volatile__ ( - ".arm \n\t" - ".type arm_func, %%function \n\t" - "arm_func: \n\t" - "adds r0, r0, r1 \n\t" - "bx lr \n\t" - ".code "NORMAL_ISA /* Back to Thumb if necessary */ - : : : "r0", "r1", "cc" - ); -} - -#else /* CONFIG_THUMB2_KERNEL */ - -long thumb16_func(long r0, long r1); -long thumb32even_func(long r0, long r1); -long thumb32odd_func(long r0, long r1); - -static void __used __naked __thumb_kprobes_test_funcs(void) -{ - __asm__ __volatile__ ( - ".type thumb16_func, %%function \n\t" - "thumb16_func: \n\t" - "adds.n r0, r0, r1 \n\t" - "bx lr \n\t" - - ".align \n\t" - ".type thumb32even_func, %%function \n\t" - "thumb32even_func: \n\t" - "adds.w r0, r0, r1 \n\t" - "bx lr \n\t" - - ".align \n\t" - "nop.n \n\t" - ".type thumb32odd_func, %%function \n\t" - "thumb32odd_func: \n\t" - "adds.w r0, r0, r1 \n\t" - "bx lr \n\t" - - : : : "r0", "r1", "cc" - ); -} - -#endif /* CONFIG_THUMB2_KERNEL */ - - -static int call_test_func(long (*func)(long, long), bool check_test_regs) -{ - long ret; - - ++test_func_instance; - test_regs_ok = false; - - ret = (*func)(FUNC_ARG1, FUNC_ARG2); - if (ret != FUNC_ARG1 + FUNC_ARG2) { - pr_err("FAIL: call_test_func: func returned %lx\n", ret); - return false; - } - - if (check_test_regs && !test_regs_ok) { - pr_err("FAIL: test regs not OK\n"); - return false; - } - - return true; -} - -static int __kprobes pre_handler(struct kprobe *p, struct pt_regs *regs) -{ - pre_handler_called = test_func_instance; - if (regs->ARM_r0 == FUNC_ARG1 && regs->ARM_r1 == FUNC_ARG2) - test_regs_ok = true; - return 0; -} - -static void __kprobes post_handler(struct kprobe *p, struct pt_regs *regs, - unsigned long flags) -{ - post_handler_called = test_func_instance; - if (regs->ARM_r0 != FUNC_ARG1 + FUNC_ARG2 || regs->ARM_r1 != FUNC_ARG2) - test_regs_ok = false; -} - -static struct kprobe the_kprobe = { - .addr = 0, - .pre_handler = pre_handler, - .post_handler = post_handler -}; - -static int test_kprobe(long (*func)(long, long)) -{ - int ret; - - the_kprobe.addr = (kprobe_opcode_t *)func; - ret = register_kprobe(&the_kprobe); - if (ret < 0) { - pr_err("FAIL: register_kprobe failed with %d\n", ret); - return ret; - } - - ret = call_test_func(func, true); - - unregister_kprobe(&the_kprobe); - the_kprobe.flags = 0; /* Clear disable flag to allow reuse */ - - if (!ret) - return -EINVAL; - if (pre_handler_called != test_func_instance) { - pr_err("FAIL: kprobe pre_handler not called\n"); - return -EINVAL; - } - if (post_handler_called != test_func_instance) { - pr_err("FAIL: kprobe post_handler not called\n"); - return -EINVAL; - } - if (!call_test_func(func, false)) - return -EINVAL; - if (pre_handler_called == test_func_instance || - post_handler_called == test_func_instance) { - pr_err("FAIL: probe called after unregistering\n"); - return -EINVAL; - } - - return 0; -} - -static void __kprobes jprobe_func(long r0, long r1) -{ - jprobe_func_called = test_func_instance; - if (r0 == FUNC_ARG1 && r1 == FUNC_ARG2) - test_regs_ok = true; - jprobe_return(); -} - -static struct jprobe the_jprobe = { - .entry = jprobe_func, -}; - -static int test_jprobe(long (*func)(long, long)) -{ - int ret; - - the_jprobe.kp.addr = (kprobe_opcode_t *)func; - ret = register_jprobe(&the_jprobe); - if (ret < 0) { - pr_err("FAIL: register_jprobe failed with %d\n", ret); - return ret; - } - - ret = call_test_func(func, true); - - unregister_jprobe(&the_jprobe); - the_jprobe.kp.flags = 0; /* Clear disable flag to allow reuse */ - - if (!ret) - return -EINVAL; - if (jprobe_func_called != test_func_instance) { - pr_err("FAIL: jprobe handler function not called\n"); - return -EINVAL; - } - if (!call_test_func(func, false)) - return -EINVAL; - if (jprobe_func_called == test_func_instance) { - pr_err("FAIL: probe called after unregistering\n"); - return -EINVAL; - } - - return 0; -} - -static int __kprobes -kretprobe_handler(struct kretprobe_instance *ri, struct pt_regs *regs) -{ - kretprobe_handler_called = test_func_instance; - if (regs_return_value(regs) == FUNC_ARG1 + FUNC_ARG2) - test_regs_ok = true; - return 0; -} - -static struct kretprobe the_kretprobe = { - .handler = kretprobe_handler, -}; - -static int test_kretprobe(long (*func)(long, long)) -{ - int ret; - - the_kretprobe.kp.addr = (kprobe_opcode_t *)func; - ret = register_kretprobe(&the_kretprobe); - if (ret < 0) { - pr_err("FAIL: register_kretprobe failed with %d\n", ret); - return ret; - } - - ret = call_test_func(func, true); - - unregister_kretprobe(&the_kretprobe); - the_kretprobe.kp.flags = 0; /* Clear disable flag to allow reuse */ - - if (!ret) - return -EINVAL; - if (kretprobe_handler_called != test_func_instance) { - pr_err("FAIL: kretprobe handler not called\n"); - return -EINVAL; - } - if (!call_test_func(func, false)) - return -EINVAL; - if (jprobe_func_called == test_func_instance) { - pr_err("FAIL: kretprobe called after unregistering\n"); - return -EINVAL; - } - - return 0; -} - -static int run_api_tests(long (*func)(long, long)) -{ - int ret; - - pr_info(" kprobe\n"); - ret = test_kprobe(func); - if (ret < 0) - return ret; - - pr_info(" jprobe\n"); - ret = test_jprobe(func); - if (ret < 0) - return ret; - - pr_info(" kretprobe\n"); - ret = test_kretprobe(func); - if (ret < 0) - return ret; - - return 0; -} - - -/* - * Benchmarking - */ - -#if BENCHMARKING - -static void __naked benchmark_nop(void) -{ - __asm__ __volatile__ ( - "nop \n\t" - "bx lr" - ); -} - -#ifdef CONFIG_THUMB2_KERNEL -#define wide ".w" -#else -#define wide -#endif - -static void __naked benchmark_pushpop1(void) -{ - __asm__ __volatile__ ( - "stmdb"wide" sp!, {r3-r11,lr} \n\t" - "ldmia"wide" sp!, {r3-r11,pc}" - ); -} - -static void __naked benchmark_pushpop2(void) -{ - __asm__ __volatile__ ( - "stmdb"wide" sp!, {r0-r8,lr} \n\t" - "ldmia"wide" sp!, {r0-r8,pc}" - ); -} - -static void __naked benchmark_pushpop3(void) -{ - __asm__ __volatile__ ( - "stmdb"wide" sp!, {r4,lr} \n\t" - "ldmia"wide" sp!, {r4,pc}" - ); -} - -static void __naked benchmark_pushpop4(void) -{ - __asm__ __volatile__ ( - "stmdb"wide" sp!, {r0,lr} \n\t" - "ldmia"wide" sp!, {r0,pc}" - ); -} - - -#ifdef CONFIG_THUMB2_KERNEL - -static void __naked benchmark_pushpop_thumb(void) -{ - __asm__ __volatile__ ( - "push.n {r0-r7,lr} \n\t" - "pop.n {r0-r7,pc}" - ); -} - -#endif - -static int __kprobes -benchmark_pre_handler(struct kprobe *p, struct pt_regs *regs) -{ - return 0; -} - -static int benchmark(void(*fn)(void)) -{ - unsigned n, i, t, t0; - - for (n = 1000; ; n *= 2) { - t0 = sched_clock(); - for (i = n; i > 0; --i) - fn(); - t = sched_clock() - t0; - if (t >= 250000000) - break; /* Stop once we took more than 0.25 seconds */ - } - return t / n; /* Time for one iteration in nanoseconds */ -}; - -static int kprobe_benchmark(void(*fn)(void), unsigned offset) -{ - struct kprobe k = { - .addr = (kprobe_opcode_t *)((uintptr_t)fn + offset), - .pre_handler = benchmark_pre_handler, - }; - - int ret = register_kprobe(&k); - if (ret < 0) { - pr_err("FAIL: register_kprobe failed with %d\n", ret); - return ret; - } - - ret = benchmark(fn); - - unregister_kprobe(&k); - return ret; -}; - -struct benchmarks { - void (*fn)(void); - unsigned offset; - const char *title; -}; - -static int run_benchmarks(void) -{ - int ret; - struct benchmarks list[] = { - {&benchmark_nop, 0, "nop"}, - /* - * benchmark_pushpop{1,3} will have the optimised - * instruction emulation, whilst benchmark_pushpop{2,4} will - * be the equivalent unoptimised instructions. - */ - {&benchmark_pushpop1, 0, "stmdb sp!, {r3-r11,lr}"}, - {&benchmark_pushpop1, 4, "ldmia sp!, {r3-r11,pc}"}, - {&benchmark_pushpop2, 0, "stmdb sp!, {r0-r8,lr}"}, - {&benchmark_pushpop2, 4, "ldmia sp!, {r0-r8,pc}"}, - {&benchmark_pushpop3, 0, "stmdb sp!, {r4,lr}"}, - {&benchmark_pushpop3, 4, "ldmia sp!, {r4,pc}"}, - {&benchmark_pushpop4, 0, "stmdb sp!, {r0,lr}"}, - {&benchmark_pushpop4, 4, "ldmia sp!, {r0,pc}"}, -#ifdef CONFIG_THUMB2_KERNEL - {&benchmark_pushpop_thumb, 0, "push.n {r0-r7,lr}"}, - {&benchmark_pushpop_thumb, 2, "pop.n {r0-r7,pc}"}, -#endif - {0} - }; - - struct benchmarks *b; - for (b = list; b->fn; ++b) { - ret = kprobe_benchmark(b->fn, b->offset); - if (ret < 0) - return ret; - pr_info(" %dns for kprobe %s\n", ret, b->title); - } - - pr_info("\n"); - return 0; -} - -#endif /* BENCHMARKING */ - - -/* - * Decoding table self-consistency tests - */ - -static const int decode_struct_sizes[NUM_DECODE_TYPES] = { - [DECODE_TYPE_TABLE] = sizeof(struct decode_table), - [DECODE_TYPE_CUSTOM] = sizeof(struct decode_custom), - [DECODE_TYPE_SIMULATE] = sizeof(struct decode_simulate), - [DECODE_TYPE_EMULATE] = sizeof(struct decode_emulate), - [DECODE_TYPE_OR] = sizeof(struct decode_or), - [DECODE_TYPE_REJECT] = sizeof(struct decode_reject) -}; - -static int table_iter(const union decode_item *table, - int (*fn)(const struct decode_header *, void *), - void *args) -{ - const struct decode_header *h = (struct decode_header *)table; - int result; - - for (;;) { - enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; - - if (type == DECODE_TYPE_END) - return 0; - - result = fn(h, args); - if (result) - return result; - - h = (struct decode_header *) - ((uintptr_t)h + decode_struct_sizes[type]); - - } -} - -static int table_test_fail(const struct decode_header *h, const char* message) -{ - - pr_err("FAIL: kprobes test failure \"%s\" (mask %08x, value %08x)\n", - message, h->mask.bits, h->value.bits); - return -EINVAL; -} - -struct table_test_args { - const union decode_item *root_table; - u32 parent_mask; - u32 parent_value; -}; - -static int table_test_fn(const struct decode_header *h, void *args) -{ - struct table_test_args *a = (struct table_test_args *)args; - enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; - - if (h->value.bits & ~h->mask.bits) - return table_test_fail(h, "Match value has bits not in mask"); - - if ((h->mask.bits & a->parent_mask) != a->parent_mask) - return table_test_fail(h, "Mask has bits not in parent mask"); - - if ((h->value.bits ^ a->parent_value) & a->parent_mask) - return table_test_fail(h, "Value is inconsistent with parent"); - - if (type == DECODE_TYPE_TABLE) { - struct decode_table *d = (struct decode_table *)h; - struct table_test_args args2 = *a; - args2.parent_mask = h->mask.bits; - args2.parent_value = h->value.bits; - return table_iter(d->table.table, table_test_fn, &args2); - } - - return 0; -} - -static int table_test(const union decode_item *table) -{ - struct table_test_args args = { - .root_table = table, - .parent_mask = 0, - .parent_value = 0 - }; - return table_iter(args.root_table, table_test_fn, &args); -} - - -/* - * Decoding table test coverage analysis - * - * coverage_start() builds a coverage_table which contains a list of - * coverage_entry's to match each entry in the specified kprobes instruction - * decoding table. - * - * When test cases are run, coverage_add() is called to process each case. - * This looks up the corresponding entry in the coverage_table and sets it as - * being matched, as well as clearing the regs flag appropriate for the test. - * - * After all test cases have been run, coverage_end() is called to check that - * all entries in coverage_table have been matched and that all regs flags are - * cleared. I.e. that all possible combinations of instructions described by - * the kprobes decoding tables have had a test case executed for them. - */ - -bool coverage_fail; - -#define MAX_COVERAGE_ENTRIES 256 - -struct coverage_entry { - const struct decode_header *header; - unsigned regs; - unsigned nesting; - char matched; -}; - -struct coverage_table { - struct coverage_entry *base; - unsigned num_entries; - unsigned nesting; -}; - -struct coverage_table coverage; - -#define COVERAGE_ANY_REG (1<<0) -#define COVERAGE_SP (1<<1) -#define COVERAGE_PC (1<<2) -#define COVERAGE_PCWB (1<<3) - -static const char coverage_register_lookup[16] = { - [REG_TYPE_ANY] = COVERAGE_ANY_REG | COVERAGE_SP | COVERAGE_PC, - [REG_TYPE_SAMEAS16] = COVERAGE_ANY_REG, - [REG_TYPE_SP] = COVERAGE_SP, - [REG_TYPE_PC] = COVERAGE_PC, - [REG_TYPE_NOSP] = COVERAGE_ANY_REG | COVERAGE_SP, - [REG_TYPE_NOSPPC] = COVERAGE_ANY_REG | COVERAGE_SP | COVERAGE_PC, - [REG_TYPE_NOPC] = COVERAGE_ANY_REG | COVERAGE_PC, - [REG_TYPE_NOPCWB] = COVERAGE_ANY_REG | COVERAGE_PC | COVERAGE_PCWB, - [REG_TYPE_NOPCX] = COVERAGE_ANY_REG, - [REG_TYPE_NOSPPCX] = COVERAGE_ANY_REG | COVERAGE_SP, -}; - -unsigned coverage_start_registers(const struct decode_header *h) -{ - unsigned regs = 0; - int i; - for (i = 0; i < 20; i += 4) { - int r = (h->type_regs.bits >> (DECODE_TYPE_BITS + i)) & 0xf; - regs |= coverage_register_lookup[r] << i; - } - return regs; -} - -static int coverage_start_fn(const struct decode_header *h, void *args) -{ - struct coverage_table *coverage = (struct coverage_table *)args; - enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; - struct coverage_entry *entry = coverage->base + coverage->num_entries; - - if (coverage->num_entries == MAX_COVERAGE_ENTRIES - 1) { - pr_err("FAIL: Out of space for test coverage data"); - return -ENOMEM; - } - - ++coverage->num_entries; - - entry->header = h; - entry->regs = coverage_start_registers(h); - entry->nesting = coverage->nesting; - entry->matched = false; - - if (type == DECODE_TYPE_TABLE) { - struct decode_table *d = (struct decode_table *)h; - int ret; - ++coverage->nesting; - ret = table_iter(d->table.table, coverage_start_fn, coverage); - --coverage->nesting; - return ret; - } - - return 0; -} - -static int coverage_start(const union decode_item *table) -{ - coverage.base = kmalloc(MAX_COVERAGE_ENTRIES * - sizeof(struct coverage_entry), GFP_KERNEL); - coverage.num_entries = 0; - coverage.nesting = 0; - return table_iter(table, coverage_start_fn, &coverage); -} - -static void -coverage_add_registers(struct coverage_entry *entry, kprobe_opcode_t insn) -{ - int regs = entry->header->type_regs.bits >> DECODE_TYPE_BITS; - int i; - for (i = 0; i < 20; i += 4) { - enum decode_reg_type reg_type = (regs >> i) & 0xf; - int reg = (insn >> i) & 0xf; - int flag; - - if (!reg_type) - continue; - - if (reg == 13) - flag = COVERAGE_SP; - else if (reg == 15) - flag = COVERAGE_PC; - else - flag = COVERAGE_ANY_REG; - entry->regs &= ~(flag << i); - - switch (reg_type) { - - case REG_TYPE_NONE: - case REG_TYPE_ANY: - case REG_TYPE_SAMEAS16: - break; - - case REG_TYPE_SP: - if (reg != 13) - return; - break; - - case REG_TYPE_PC: - if (reg != 15) - return; - break; - - case REG_TYPE_NOSP: - if (reg == 13) - return; - break; - - case REG_TYPE_NOSPPC: - case REG_TYPE_NOSPPCX: - if (reg == 13 || reg == 15) - return; - break; - - case REG_TYPE_NOPCWB: - if (!is_writeback(insn)) - break; - if (reg == 15) { - entry->regs &= ~(COVERAGE_PCWB << i); - return; - } - break; - - case REG_TYPE_NOPC: - case REG_TYPE_NOPCX: - if (reg == 15) - return; - break; - } - - } -} - -static void coverage_add(kprobe_opcode_t insn) -{ - struct coverage_entry *entry = coverage.base; - struct coverage_entry *end = coverage.base + coverage.num_entries; - bool matched = false; - unsigned nesting = 0; - - for (; entry < end; ++entry) { - const struct decode_header *h = entry->header; - enum decode_type type = h->type_regs.bits & DECODE_TYPE_MASK; - - if (entry->nesting > nesting) - continue; /* Skip sub-table we didn't match */ - - if (entry->nesting < nesting) - break; /* End of sub-table we were scanning */ - - if (!matched) { - if ((insn & h->mask.bits) != h->value.bits) - continue; - entry->matched = true; - } - - switch (type) { - - case DECODE_TYPE_TABLE: - ++nesting; - break; - - case DECODE_TYPE_CUSTOM: - case DECODE_TYPE_SIMULATE: - case DECODE_TYPE_EMULATE: - coverage_add_registers(entry, insn); - return; - - case DECODE_TYPE_OR: - matched = true; - break; - - case DECODE_TYPE_REJECT: - default: - return; - } - - } -} - -static void coverage_end(void) -{ - struct coverage_entry *entry = coverage.base; - struct coverage_entry *end = coverage.base + coverage.num_entries; - - for (; entry < end; ++entry) { - u32 mask = entry->header->mask.bits; - u32 value = entry->header->value.bits; - - if (entry->regs) { - pr_err("FAIL: Register test coverage missing for %08x %08x (%05x)\n", - mask, value, entry->regs); - coverage_fail = true; - } - if (!entry->matched) { - pr_err("FAIL: Test coverage entry missing for %08x %08x\n", - mask, value); - coverage_fail = true; - } - } - - kfree(coverage.base); -} - - -/* - * Framework for instruction set test cases - */ - -void __naked __kprobes_test_case_start(void) -{ - __asm__ __volatile__ ( - "stmdb sp!, {r4-r11} \n\t" - "sub sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t" - "bic r0, lr, #1 @ r0 = inline title string \n\t" - "mov r1, sp \n\t" - "bl kprobes_test_case_start \n\t" - "bx r0 \n\t" - ); -} - -#ifndef CONFIG_THUMB2_KERNEL - -void __naked __kprobes_test_case_end_32(void) -{ - __asm__ __volatile__ ( - "mov r4, lr \n\t" - "bl kprobes_test_case_end \n\t" - "cmp r0, #0 \n\t" - "movne pc, r0 \n\t" - "mov r0, r4 \n\t" - "add sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t" - "ldmia sp!, {r4-r11} \n\t" - "mov pc, r0 \n\t" - ); -} - -#else /* CONFIG_THUMB2_KERNEL */ - -void __naked __kprobes_test_case_end_16(void) -{ - __asm__ __volatile__ ( - "mov r4, lr \n\t" - "bl kprobes_test_case_end \n\t" - "cmp r0, #0 \n\t" - "bxne r0 \n\t" - "mov r0, r4 \n\t" - "add sp, sp, #"__stringify(TEST_MEMORY_SIZE)"\n\t" - "ldmia sp!, {r4-r11} \n\t" - "bx r0 \n\t" - ); -} - -void __naked __kprobes_test_case_end_32(void) -{ - __asm__ __volatile__ ( - ".arm \n\t" - "orr lr, lr, #1 @ will return to Thumb code \n\t" - "ldr pc, 1f \n\t" - "1: \n\t" - ".word __kprobes_test_case_end_16 \n\t" - ); -} - -#endif - - -int kprobe_test_flags; -int kprobe_test_cc_position; - -static int test_try_count; -static int test_pass_count; -static int test_fail_count; - -static struct pt_regs initial_regs; -static struct pt_regs expected_regs; -static struct pt_regs result_regs; - -static u32 expected_memory[TEST_MEMORY_SIZE/sizeof(u32)]; - -static const char *current_title; -static struct test_arg *current_args; -static u32 *current_stack; -static uintptr_t current_branch_target; - -static uintptr_t current_code_start; -static kprobe_opcode_t current_instruction; - - -#define TEST_CASE_PASSED -1 -#define TEST_CASE_FAILED -2 - -static int test_case_run_count; -static bool test_case_is_thumb; -static int test_instance; - -/* - * We ignore the state of the imprecise abort disable flag (CPSR.A) because this - * can change randomly as the kernel doesn't take care to preserve or initialise - * this across context switches. Also, with Security Extentions, the flag may - * not be under control of the kernel; for this reason we ignore the state of - * the FIQ disable flag CPSR.F as well. - */ -#define PSR_IGNORE_BITS (PSR_A_BIT | PSR_F_BIT) - -static unsigned long test_check_cc(int cc, unsigned long cpsr) -{ - int ret = arm_check_condition(cc << 28, cpsr); - - return (ret != ARM_OPCODE_CONDTEST_FAIL); -} - -static int is_last_scenario; -static int probe_should_run; /* 0 = no, 1 = yes, -1 = unknown */ -static int memory_needs_checking; - -static unsigned long test_context_cpsr(int scenario) -{ - unsigned long cpsr; - - probe_should_run = 1; - - /* Default case is that we cycle through 16 combinations of flags */ - cpsr = (scenario & 0xf) << 28; /* N,Z,C,V flags */ - cpsr |= (scenario & 0xf) << 16; /* GE flags */ - cpsr |= (scenario & 0x1) << 27; /* Toggle Q flag */ - - if (!test_case_is_thumb) { - /* Testing ARM code */ - int cc = current_instruction >> 28; - - probe_should_run = test_check_cc(cc, cpsr) != 0; - if (scenario == 15) - is_last_scenario = true; - - } else if (kprobe_test_flags & TEST_FLAG_NO_ITBLOCK) { - /* Testing Thumb code without setting ITSTATE */ - if (kprobe_test_cc_position) { - int cc = (current_instruction >> kprobe_test_cc_position) & 0xf; - probe_should_run = test_check_cc(cc, cpsr) != 0; - } - - if (scenario == 15) - is_last_scenario = true; - - } else if (kprobe_test_flags & TEST_FLAG_FULL_ITBLOCK) { - /* Testing Thumb code with all combinations of ITSTATE */ - unsigned x = (scenario >> 4); - unsigned cond_base = x % 7; /* ITSTATE<7:5> */ - unsigned mask = x / 7 + 2; /* ITSTATE<4:0>, bits reversed */ - - if (mask > 0x1f) { - /* Finish by testing state from instruction 'itt al' */ - cond_base = 7; - mask = 0x4; - if ((scenario & 0xf) == 0xf) - is_last_scenario = true; - } - - cpsr |= cond_base << 13; /* ITSTATE<7:5> */ - cpsr |= (mask & 0x1) << 12; /* ITSTATE<4> */ - cpsr |= (mask & 0x2) << 10; /* ITSTATE<3> */ - cpsr |= (mask & 0x4) << 8; /* ITSTATE<2> */ - cpsr |= (mask & 0x8) << 23; /* ITSTATE<1> */ - cpsr |= (mask & 0x10) << 21; /* ITSTATE<0> */ - - probe_should_run = test_check_cc((cpsr >> 12) & 0xf, cpsr) != 0; - - } else { - /* Testing Thumb code with several combinations of ITSTATE */ - switch (scenario) { - case 16: /* Clear NZCV flags and 'it eq' state (false as Z=0) */ - cpsr = 0x00000800; - probe_should_run = 0; - break; - case 17: /* Set NZCV flags and 'it vc' state (false as V=1) */ - cpsr = 0xf0007800; - probe_should_run = 0; - break; - case 18: /* Clear NZCV flags and 'it ls' state (true as C=0) */ - cpsr = 0x00009800; - break; - case 19: /* Set NZCV flags and 'it cs' state (true as C=1) */ - cpsr = 0xf0002800; - is_last_scenario = true; - break; - } - } - - return cpsr; -} - -static void setup_test_context(struct pt_regs *regs) -{ - int scenario = test_case_run_count>>1; - unsigned long val; - struct test_arg *args; - int i; - - is_last_scenario = false; - memory_needs_checking = false; - - /* Initialise test memory on stack */ - val = (scenario & 1) ? VALM : ~VALM; - for (i = 0; i < TEST_MEMORY_SIZE / sizeof(current_stack[0]); ++i) - current_stack[i] = val + (i << 8); - /* Put target of branch on stack for tests which load PC from memory */ - if (current_branch_target) - current_stack[15] = current_branch_target; - /* Put a value for SP on stack for tests which load SP from memory */ - current_stack[13] = (u32)current_stack + 120; - - /* Initialise register values to their default state */ - val = (scenario & 2) ? VALR : ~VALR; - for (i = 0; i < 13; ++i) - regs->uregs[i] = val ^ (i << 8); - regs->ARM_lr = val ^ (14 << 8); - regs->ARM_cpsr &= ~(APSR_MASK | PSR_IT_MASK); - regs->ARM_cpsr |= test_context_cpsr(scenario); - - /* Perform testcase specific register setup */ - args = current_args; - for (; args[0].type != ARG_TYPE_END; ++args) - switch (args[0].type) { - case ARG_TYPE_REG: { - struct test_arg_regptr *arg = - (struct test_arg_regptr *)args; - regs->uregs[arg->reg] = arg->val; - break; - } - case ARG_TYPE_PTR: { - struct test_arg_regptr *arg = - (struct test_arg_regptr *)args; - regs->uregs[arg->reg] = - (unsigned long)current_stack + arg->val; - memory_needs_checking = true; - break; - } - case ARG_TYPE_MEM: { - struct test_arg_mem *arg = (struct test_arg_mem *)args; - current_stack[arg->index] = arg->val; - break; - } - default: - break; - } -} - -struct test_probe { - struct kprobe kprobe; - bool registered; - int hit; -}; - -static void unregister_test_probe(struct test_probe *probe) -{ - if (probe->registered) { - unregister_kprobe(&probe->kprobe); - probe->kprobe.flags = 0; /* Clear disable flag to allow reuse */ - } - probe->registered = false; -} - -static int register_test_probe(struct test_probe *probe) -{ - int ret; - - if (probe->registered) - BUG(); - - ret = register_kprobe(&probe->kprobe); - if (ret >= 0) { - probe->registered = true; - probe->hit = -1; - } - return ret; -} - -static int __kprobes -test_before_pre_handler(struct kprobe *p, struct pt_regs *regs) -{ - container_of(p, struct test_probe, kprobe)->hit = test_instance; - return 0; -} - -static void __kprobes -test_before_post_handler(struct kprobe *p, struct pt_regs *regs, - unsigned long flags) -{ - setup_test_context(regs); - initial_regs = *regs; - initial_regs.ARM_cpsr &= ~PSR_IGNORE_BITS; -} - -static int __kprobes -test_case_pre_handler(struct kprobe *p, struct pt_regs *regs) -{ - container_of(p, struct test_probe, kprobe)->hit = test_instance; - return 0; -} - -static int __kprobes -test_after_pre_handler(struct kprobe *p, struct pt_regs *regs) -{ - if (container_of(p, struct test_probe, kprobe)->hit == test_instance) - return 0; /* Already run for this test instance */ - - result_regs = *regs; - result_regs.ARM_cpsr &= ~PSR_IGNORE_BITS; - - /* Undo any changes done to SP by the test case */ - regs->ARM_sp = (unsigned long)current_stack; - - container_of(p, struct test_probe, kprobe)->hit = test_instance; - return 0; -} - -static struct test_probe test_before_probe = { - .kprobe.pre_handler = test_before_pre_handler, - .kprobe.post_handler = test_before_post_handler, -}; - -static struct test_probe test_case_probe = { - .kprobe.pre_handler = test_case_pre_handler, -}; - -static struct test_probe test_after_probe = { - .kprobe.pre_handler = test_after_pre_handler, -}; - -static struct test_probe test_after2_probe = { - .kprobe.pre_handler = test_after_pre_handler, -}; - -static void test_case_cleanup(void) -{ - unregister_test_probe(&test_before_probe); - unregister_test_probe(&test_case_probe); - unregister_test_probe(&test_after_probe); - unregister_test_probe(&test_after2_probe); -} - -static void print_registers(struct pt_regs *regs) -{ - pr_err("r0 %08lx | r1 %08lx | r2 %08lx | r3 %08lx\n", - regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, regs->ARM_r3); - pr_err("r4 %08lx | r5 %08lx | r6 %08lx | r7 %08lx\n", - regs->ARM_r4, regs->ARM_r5, regs->ARM_r6, regs->ARM_r7); - pr_err("r8 %08lx | r9 %08lx | r10 %08lx | r11 %08lx\n", - regs->ARM_r8, regs->ARM_r9, regs->ARM_r10, regs->ARM_fp); - pr_err("r12 %08lx | sp %08lx | lr %08lx | pc %08lx\n", - regs->ARM_ip, regs->ARM_sp, regs->ARM_lr, regs->ARM_pc); - pr_err("cpsr %08lx\n", regs->ARM_cpsr); -} - -static void print_memory(u32 *mem, size_t size) -{ - int i; - for (i = 0; i < size / sizeof(u32); i += 4) - pr_err("%08x %08x %08x %08x\n", mem[i], mem[i+1], - mem[i+2], mem[i+3]); -} - -static size_t expected_memory_size(u32 *sp) -{ - size_t size = sizeof(expected_memory); - int offset = (uintptr_t)sp - (uintptr_t)current_stack; - if (offset > 0) - size -= offset; - return size; -} - -static void test_case_failed(const char *message) -{ - test_case_cleanup(); - - pr_err("FAIL: %s\n", message); - pr_err("FAIL: Test %s\n", current_title); - pr_err("FAIL: Scenario %d\n", test_case_run_count >> 1); -} - -static unsigned long next_instruction(unsigned long pc) -{ -#ifdef CONFIG_THUMB2_KERNEL - if ((pc & 1) && !is_wide_instruction(*(u16 *)(pc - 1))) - return pc + 2; - else -#endif - return pc + 4; -} - -static uintptr_t __used kprobes_test_case_start(const char *title, void *stack) -{ - struct test_arg *args; - struct test_arg_end *end_arg; - unsigned long test_code; - - args = (struct test_arg *)PTR_ALIGN(title + strlen(title) + 1, 4); - - current_title = title; - current_args = args; - current_stack = stack; - - ++test_try_count; - - while (args->type != ARG_TYPE_END) - ++args; - end_arg = (struct test_arg_end *)args; - - test_code = (unsigned long)(args + 1); /* Code starts after args */ - - test_case_is_thumb = end_arg->flags & ARG_FLAG_THUMB; - if (test_case_is_thumb) - test_code |= 1; - - current_code_start = test_code; - - current_branch_target = 0; - if (end_arg->branch_offset != end_arg->end_offset) - current_branch_target = test_code + end_arg->branch_offset; - - test_code += end_arg->code_offset; - test_before_probe.kprobe.addr = (kprobe_opcode_t *)test_code; - - test_code = next_instruction(test_code); - test_case_probe.kprobe.addr = (kprobe_opcode_t *)test_code; - - if (test_case_is_thumb) { - u16 *p = (u16 *)(test_code & ~1); - current_instruction = p[0]; - if (is_wide_instruction(current_instruction)) { - current_instruction <<= 16; - current_instruction |= p[1]; - } - } else { - current_instruction = *(u32 *)test_code; - } - - if (current_title[0] == '.') - verbose("%s\n", current_title); - else - verbose("%s\t@ %0*x\n", current_title, - test_case_is_thumb ? 4 : 8, - current_instruction); - - test_code = next_instruction(test_code); - test_after_probe.kprobe.addr = (kprobe_opcode_t *)test_code; - - if (kprobe_test_flags & TEST_FLAG_NARROW_INSTR) { - if (!test_case_is_thumb || - is_wide_instruction(current_instruction)) { - test_case_failed("expected 16-bit instruction"); - goto fail; - } - } else { - if (test_case_is_thumb && - !is_wide_instruction(current_instruction)) { - test_case_failed("expected 32-bit instruction"); - goto fail; - } - } - - coverage_add(current_instruction); - - if (end_arg->flags & ARG_FLAG_UNSUPPORTED) { - if (register_test_probe(&test_case_probe) < 0) - goto pass; - test_case_failed("registered probe for unsupported instruction"); - goto fail; - } - - if (end_arg->flags & ARG_FLAG_SUPPORTED) { - if (register_test_probe(&test_case_probe) >= 0) - goto pass; - test_case_failed("couldn't register probe for supported instruction"); - goto fail; - } - - if (register_test_probe(&test_before_probe) < 0) { - test_case_failed("register test_before_probe failed"); - goto fail; - } - if (register_test_probe(&test_after_probe) < 0) { - test_case_failed("register test_after_probe failed"); - goto fail; - } - if (current_branch_target) { - test_after2_probe.kprobe.addr = - (kprobe_opcode_t *)current_branch_target; - if (register_test_probe(&test_after2_probe) < 0) { - test_case_failed("register test_after2_probe failed"); - goto fail; - } - } - - /* Start first run of test case */ - test_case_run_count = 0; - ++test_instance; - return current_code_start; -pass: - test_case_run_count = TEST_CASE_PASSED; - return (uintptr_t)test_after_probe.kprobe.addr; -fail: - test_case_run_count = TEST_CASE_FAILED; - return (uintptr_t)test_after_probe.kprobe.addr; -} - -static bool check_test_results(void) -{ - size_t mem_size = 0; - u32 *mem = 0; - - if (memcmp(&expected_regs, &result_regs, sizeof(expected_regs))) { - test_case_failed("registers differ"); - goto fail; - } - - if (memory_needs_checking) { - mem = (u32 *)result_regs.ARM_sp; - mem_size = expected_memory_size(mem); - if (memcmp(expected_memory, mem, mem_size)) { - test_case_failed("test memory differs"); - goto fail; - } - } - - return true; - -fail: - pr_err("initial_regs:\n"); - print_registers(&initial_regs); - pr_err("expected_regs:\n"); - print_registers(&expected_regs); - pr_err("result_regs:\n"); - print_registers(&result_regs); - - if (mem) { - pr_err("current_stack=%p\n", current_stack); - pr_err("expected_memory:\n"); - print_memory(expected_memory, mem_size); - pr_err("result_memory:\n"); - print_memory(mem, mem_size); - } - - return false; -} - -static uintptr_t __used kprobes_test_case_end(void) -{ - if (test_case_run_count < 0) { - if (test_case_run_count == TEST_CASE_PASSED) - /* kprobes_test_case_start did all the needed testing */ - goto pass; - else - /* kprobes_test_case_start failed */ - goto fail; - } - - if (test_before_probe.hit != test_instance) { - test_case_failed("test_before_handler not run"); - goto fail; - } - - if (test_after_probe.hit != test_instance && - test_after2_probe.hit != test_instance) { - test_case_failed("test_after_handler not run"); - goto fail; - } - - /* - * Even numbered test runs ran without a probe on the test case so - * we can gather reference results. The subsequent odd numbered run - * will have the probe inserted. - */ - if ((test_case_run_count & 1) == 0) { - /* Save results from run without probe */ - u32 *mem = (u32 *)result_regs.ARM_sp; - expected_regs = result_regs; - memcpy(expected_memory, mem, expected_memory_size(mem)); - - /* Insert probe onto test case instruction */ - if (register_test_probe(&test_case_probe) < 0) { - test_case_failed("register test_case_probe failed"); - goto fail; - } - } else { - /* Check probe ran as expected */ - if (probe_should_run == 1) { - if (test_case_probe.hit != test_instance) { - test_case_failed("test_case_handler not run"); - goto fail; - } - } else if (probe_should_run == 0) { - if (test_case_probe.hit == test_instance) { - test_case_failed("test_case_handler ran"); - goto fail; - } - } - - /* Remove probe for any subsequent reference run */ - unregister_test_probe(&test_case_probe); - - if (!check_test_results()) - goto fail; - - if (is_last_scenario) - goto pass; - } - - /* Do next test run */ - ++test_case_run_count; - ++test_instance; - return current_code_start; -fail: - ++test_fail_count; - goto end; -pass: - ++test_pass_count; -end: - test_case_cleanup(); - return 0; -} - - -/* - * Top level test functions - */ - -static int run_test_cases(void (*tests)(void), const union decode_item *table) -{ - int ret; - - pr_info(" Check decoding tables\n"); - ret = table_test(table); - if (ret) - return ret; - - pr_info(" Run test cases\n"); - ret = coverage_start(table); - if (ret) - return ret; - - tests(); - - coverage_end(); - return 0; -} - - -static int __init run_all_tests(void) -{ - int ret = 0; - - pr_info("Begining kprobe tests...\n"); - -#ifndef CONFIG_THUMB2_KERNEL - - pr_info("Probe ARM code\n"); - ret = run_api_tests(arm_func); - if (ret) - goto out; - - pr_info("ARM instruction simulation\n"); - ret = run_test_cases(kprobe_arm_test_cases, kprobe_decode_arm_table); - if (ret) - goto out; - -#else /* CONFIG_THUMB2_KERNEL */ - - pr_info("Probe 16-bit Thumb code\n"); - ret = run_api_tests(thumb16_func); - if (ret) - goto out; - - pr_info("Probe 32-bit Thumb code, even halfword\n"); - ret = run_api_tests(thumb32even_func); - if (ret) - goto out; - - pr_info("Probe 32-bit Thumb code, odd halfword\n"); - ret = run_api_tests(thumb32odd_func); - if (ret) - goto out; - - pr_info("16-bit Thumb instruction simulation\n"); - ret = run_test_cases(kprobe_thumb16_test_cases, - kprobe_decode_thumb16_table); - if (ret) - goto out; - - pr_info("32-bit Thumb instruction simulation\n"); - ret = run_test_cases(kprobe_thumb32_test_cases, - kprobe_decode_thumb32_table); - if (ret) - goto out; -#endif - - pr_info("Total instruction simulation tests=%d, pass=%d fail=%d\n", - test_try_count, test_pass_count, test_fail_count); - if (test_fail_count) { - ret = -EINVAL; - goto out; - } - -#if BENCHMARKING - pr_info("Benchmarks\n"); - ret = run_benchmarks(); - if (ret) - goto out; -#endif - -#if __LINUX_ARM_ARCH__ >= 7 - /* We are able to run all test cases so coverage should be complete */ - if (coverage_fail) { - pr_err("FAIL: Test coverage checks failed\n"); - ret = -EINVAL; - goto out; - } -#endif - -out: - if (ret == 0) - pr_info("Finished kprobe tests OK\n"); - else - pr_err("kprobe tests failed\n"); - - return ret; -} - - -/* - * Module setup - */ - -#ifdef MODULE - -static void __exit kprobe_test_exit(void) -{ -} - -module_init(run_all_tests) -module_exit(kprobe_test_exit) -MODULE_LICENSE("GPL"); - -#else /* !MODULE */ - -late_initcall(run_all_tests); - -#endif diff --git a/ANDROID_3.4.5/arch/arm/kernel/kprobes-test.h b/ANDROID_3.4.5/arch/arm/kernel/kprobes-test.h deleted file mode 100644 index e28a869b..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/kprobes-test.h +++ /dev/null @@ -1,432 +0,0 @@ -/* - * arch/arm/kernel/kprobes-test.h - * - * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#define VERBOSE 0 /* Set to '1' for more logging of test cases */ - -#ifdef CONFIG_THUMB2_KERNEL -#define NORMAL_ISA "16" -#else -#define NORMAL_ISA "32" -#endif - - -/* Flags used in kprobe_test_flags */ -#define TEST_FLAG_NO_ITBLOCK (1<<0) -#define TEST_FLAG_FULL_ITBLOCK (1<<1) -#define TEST_FLAG_NARROW_INSTR (1<<2) - -extern int kprobe_test_flags; -extern int kprobe_test_cc_position; - - -#define TEST_MEMORY_SIZE 256 - - -/* - * Test case structures. - * - * The arguments given to test cases can be one of three types. - * - * ARG_TYPE_REG - * Load a register with the given value. - * - * ARG_TYPE_PTR - * Load a register with a pointer into the stack buffer (SP + given value). - * - * ARG_TYPE_MEM - * Store the given value into the stack buffer at [SP+index]. - * - */ - -#define ARG_TYPE_END 0 -#define ARG_TYPE_REG 1 -#define ARG_TYPE_PTR 2 -#define ARG_TYPE_MEM 3 - -#define ARG_FLAG_UNSUPPORTED 0x01 -#define ARG_FLAG_SUPPORTED 0x02 -#define ARG_FLAG_THUMB 0x10 /* Must be 16 so TEST_ISA can be used */ -#define ARG_FLAG_ARM 0x20 /* Must be 32 so TEST_ISA can be used */ - -struct test_arg { - u8 type; /* ARG_TYPE_x */ - u8 _padding[7]; -}; - -struct test_arg_regptr { - u8 type; /* ARG_TYPE_REG or ARG_TYPE_PTR */ - u8 reg; - u8 _padding[2]; - u32 val; -}; - -struct test_arg_mem { - u8 type; /* ARG_TYPE_MEM */ - u8 index; - u8 _padding[2]; - u32 val; -}; - -struct test_arg_end { - u8 type; /* ARG_TYPE_END */ - u8 flags; /* ARG_FLAG_x */ - u16 code_offset; - u16 branch_offset; - u16 end_offset; -}; - - -/* - * Building blocks for test cases. - * - * Each test case is wrapped between TESTCASE_START and TESTCASE_END. - * - * To specify arguments for a test case the TEST_ARG_{REG,PTR,MEM} macros are - * used followed by a terminating TEST_ARG_END. - * - * After this, the instruction to be tested is defined with TEST_INSTRUCTION. - * Or for branches, TEST_BRANCH_B and TEST_BRANCH_F (branch forwards/backwards). - * - * Some specific test cases may make use of other custom constructs. - */ - -#if VERBOSE -#define verbose(fmt, ...) pr_info(fmt, ##__VA_ARGS__) -#else -#define verbose(fmt, ...) -#endif - -#define TEST_GROUP(title) \ - verbose("\n"); \ - verbose(title"\n"); \ - verbose("---------------------------------------------------------\n"); - -#define TESTCASE_START(title) \ - __asm__ __volatile__ ( \ - "bl __kprobes_test_case_start \n\t" \ - /* don't use .asciz here as 'title' may be */ \ - /* multiple strings to be concatenated. */ \ - ".ascii "#title" \n\t" \ - ".byte 0 \n\t" \ - ".align 2 \n\t" - -#define TEST_ARG_REG(reg, val) \ - ".byte "__stringify(ARG_TYPE_REG)" \n\t" \ - ".byte "#reg" \n\t" \ - ".short 0 \n\t" \ - ".word "#val" \n\t" - -#define TEST_ARG_PTR(reg, val) \ - ".byte "__stringify(ARG_TYPE_PTR)" \n\t" \ - ".byte "#reg" \n\t" \ - ".short 0 \n\t" \ - ".word "#val" \n\t" - -#define TEST_ARG_MEM(index, val) \ - ".byte "__stringify(ARG_TYPE_MEM)" \n\t" \ - ".byte "#index" \n\t" \ - ".short 0 \n\t" \ - ".word "#val" \n\t" - -#define TEST_ARG_END(flags) \ - ".byte "__stringify(ARG_TYPE_END)" \n\t" \ - ".byte "TEST_ISA flags" \n\t" \ - ".short 50f-0f \n\t" \ - ".short 2f-0f \n\t" \ - ".short 99f-0f \n\t" \ - ".code "TEST_ISA" \n\t" \ - "0: \n\t" - -#define TEST_INSTRUCTION(instruction) \ - "50: nop \n\t" \ - "1: "instruction" \n\t" \ - " nop \n\t" - -#define TEST_BRANCH_F(instruction) \ - TEST_INSTRUCTION(instruction) \ - " b 99f \n\t" \ - "2: nop \n\t" - -#define TEST_BRANCH_B(instruction) \ - " b 50f \n\t" \ - " b 99f \n\t" \ - "2: nop \n\t" \ - " b 99f \n\t" \ - TEST_INSTRUCTION(instruction) - -#define TEST_BRANCH_FX(instruction, codex) \ - TEST_INSTRUCTION(instruction) \ - " b 99f \n\t" \ - codex" \n\t" \ - " b 99f \n\t" \ - "2: nop \n\t" - -#define TEST_BRANCH_BX(instruction, codex) \ - " b 50f \n\t" \ - " b 99f \n\t" \ - "2: nop \n\t" \ - " b 99f \n\t" \ - codex" \n\t" \ - TEST_INSTRUCTION(instruction) - -#define TESTCASE_END \ - "2: \n\t" \ - "99: \n\t" \ - " bl __kprobes_test_case_end_"TEST_ISA" \n\t" \ - ".code "NORMAL_ISA" \n\t" \ - : : \ - : "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc" \ - ); - - -/* - * Macros to define test cases. - * - * Those of the form TEST_{R,P,M}* can be used to define test cases - * which take combinations of the three basic types of arguments. E.g. - * - * TEST_R One register argument - * TEST_RR Two register arguments - * TEST_RPR A register, a pointer, then a register argument - * - * For testing instructions which may branch, there are macros TEST_BF_* - * and TEST_BB_* for branching forwards and backwards. - * - * TEST_SUPPORTED and TEST_UNSUPPORTED don't cause the code to be executed, - * the just verify that a kprobe is or is not allowed on the given instruction. - */ - -#define TEST(code) \ - TESTCASE_START(code) \ - TEST_ARG_END("") \ - TEST_INSTRUCTION(code) \ - TESTCASE_END - -#define TEST_UNSUPPORTED(code) \ - TESTCASE_START(code) \ - TEST_ARG_END("|"__stringify(ARG_FLAG_UNSUPPORTED)) \ - TEST_INSTRUCTION(code) \ - TESTCASE_END - -#define TEST_SUPPORTED(code) \ - TESTCASE_START(code) \ - TEST_ARG_END("|"__stringify(ARG_FLAG_SUPPORTED)) \ - TEST_INSTRUCTION(code) \ - TESTCASE_END - -#define TEST_R(code1, reg, val, code2) \ - TESTCASE_START(code1 #reg code2) \ - TEST_ARG_REG(reg, val) \ - TEST_ARG_END("") \ - TEST_INSTRUCTION(code1 #reg code2) \ - TESTCASE_END - -#define TEST_RR(code1, reg1, val1, code2, reg2, val2, code3) \ - TESTCASE_START(code1 #reg1 code2 #reg2 code3) \ - TEST_ARG_REG(reg1, val1) \ - TEST_ARG_REG(reg2, val2) \ - TEST_ARG_END("") \ - TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3) \ - TESTCASE_END - -#define TEST_RRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\ - TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \ - TEST_ARG_REG(reg1, val1) \ - TEST_ARG_REG(reg2, val2) \ - TEST_ARG_REG(reg3, val3) \ - TEST_ARG_END("") \ - TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \ - TESTCASE_END - -#define TEST_RRRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4, reg4, val4) \ - TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4 #reg4) \ - TEST_ARG_REG(reg1, val1) \ - TEST_ARG_REG(reg2, val2) \ - TEST_ARG_REG(reg3, val3) \ - TEST_ARG_REG(reg4, val4) \ - TEST_ARG_END("") \ - TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4 #reg4) \ - TESTCASE_END - -#define TEST_P(code1, reg1, val1, code2) \ - TESTCASE_START(code1 #reg1 code2) \ - TEST_ARG_PTR(reg1, val1) \ - TEST_ARG_END("") \ - TEST_INSTRUCTION(code1 #reg1 code2) \ - TESTCASE_END - -#define TEST_PR(code1, reg1, val1, code2, reg2, val2, code3) \ - TESTCASE_START(code1 #reg1 code2 #reg2 code3) \ - TEST_ARG_PTR(reg1, val1) \ - TEST_ARG_REG(reg2, val2) \ - TEST_ARG_END("") \ - TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3) \ - TESTCASE_END - -#define TEST_RP(code1, reg1, val1, code2, reg2, val2, code3) \ - TESTCASE_START(code1 #reg1 code2 #reg2 code3) \ - TEST_ARG_REG(reg1, val1) \ - TEST_ARG_PTR(reg2, val2) \ - TEST_ARG_END("") \ - TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3) \ - TESTCASE_END - -#define TEST_PRR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\ - TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \ - TEST_ARG_PTR(reg1, val1) \ - TEST_ARG_REG(reg2, val2) \ - TEST_ARG_REG(reg3, val3) \ - TEST_ARG_END("") \ - TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \ - TESTCASE_END - -#define TEST_RPR(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\ - TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \ - TEST_ARG_REG(reg1, val1) \ - TEST_ARG_PTR(reg2, val2) \ - TEST_ARG_REG(reg3, val3) \ - TEST_ARG_END("") \ - TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \ - TESTCASE_END - -#define TEST_RRP(code1, reg1, val1, code2, reg2, val2, code3, reg3, val3, code4)\ - TESTCASE_START(code1 #reg1 code2 #reg2 code3 #reg3 code4) \ - TEST_ARG_REG(reg1, val1) \ - TEST_ARG_REG(reg2, val2) \ - TEST_ARG_PTR(reg3, val3) \ - TEST_ARG_END("") \ - TEST_INSTRUCTION(code1 #reg1 code2 #reg2 code3 #reg3 code4) \ - TESTCASE_END - -#define TEST_BF_P(code1, reg1, val1, code2) \ - TESTCASE_START(code1 #reg1 code2) \ - TEST_ARG_PTR(reg1, val1) \ - TEST_ARG_END("") \ - TEST_BRANCH_F(code1 #reg1 code2) \ - TESTCASE_END - -#define TEST_BF(code) \ - TESTCASE_START(code) \ - TEST_ARG_END("") \ - TEST_BRANCH_F(code) \ - TESTCASE_END - -#define TEST_BB(code) \ - TESTCASE_START(code) \ - TEST_ARG_END("") \ - TEST_BRANCH_B(code) \ - TESTCASE_END - -#define TEST_BF_R(code1, reg, val, code2) \ - TESTCASE_START(code1 #reg code2) \ - TEST_ARG_REG(reg, val) \ - TEST_ARG_END("") \ - TEST_BRANCH_F(code1 #reg code2) \ - TESTCASE_END - -#define TEST_BB_R(code1, reg, val, code2) \ - TESTCASE_START(code1 #reg code2) \ - TEST_ARG_REG(reg, val) \ - TEST_ARG_END("") \ - TEST_BRANCH_B(code1 #reg code2) \ - TESTCASE_END - -#define TEST_BF_RR(code1, reg1, val1, code2, reg2, val2, code3) \ - TESTCASE_START(code1 #reg1 code2 #reg2 code3) \ - TEST_ARG_REG(reg1, val1) \ - TEST_ARG_REG(reg2, val2) \ - TEST_ARG_END("") \ - TEST_BRANCH_F(code1 #reg1 code2 #reg2 code3) \ - TESTCASE_END - -#define TEST_BF_X(code, codex) \ - TESTCASE_START(code) \ - TEST_ARG_END("") \ - TEST_BRANCH_FX(code, codex) \ - TESTCASE_END - -#define TEST_BB_X(code, codex) \ - TESTCASE_START(code) \ - TEST_ARG_END("") \ - TEST_BRANCH_BX(code, codex) \ - TESTCASE_END - -#define TEST_BF_RX(code1, reg, val, code2, codex) \ - TESTCASE_START(code1 #reg code2) \ - TEST_ARG_REG(reg, val) \ - TEST_ARG_END("") \ - TEST_BRANCH_FX(code1 #reg code2, codex) \ - TESTCASE_END - -#define TEST_X(code, codex) \ - TESTCASE_START(code) \ - TEST_ARG_END("") \ - TEST_INSTRUCTION(code) \ - " b 99f \n\t" \ - " "codex" \n\t" \ - TESTCASE_END - -#define TEST_RX(code1, reg, val, code2, codex) \ - TESTCASE_START(code1 #reg code2) \ - TEST_ARG_REG(reg, val) \ - TEST_ARG_END("") \ - TEST_INSTRUCTION(code1 __stringify(reg) code2) \ - " b 99f \n\t" \ - " "codex" \n\t" \ - TESTCASE_END - -#define TEST_RRX(code1, reg1, val1, code2, reg2, val2, code3, codex) \ - TESTCASE_START(code1 #reg1 code2 #reg2 code3) \ - TEST_ARG_REG(reg1, val1) \ - TEST_ARG_REG(reg2, val2) \ - TEST_ARG_END("") \ - TEST_INSTRUCTION(code1 __stringify(reg1) code2 __stringify(reg2) code3) \ - " b 99f \n\t" \ - " "codex" \n\t" \ - TESTCASE_END - - -/* - * Macros for defining space directives spread over multiple lines. - * These are required so the compiler guesses better the length of inline asm - * code and will spill the literal pool early enough to avoid generating PC - * relative loads with out of range offsets. - */ -#define TWICE(x) x x -#define SPACE_0x8 TWICE(".space 4\n\t") -#define SPACE_0x10 TWICE(SPACE_0x8) -#define SPACE_0x20 TWICE(SPACE_0x10) -#define SPACE_0x40 TWICE(SPACE_0x20) -#define SPACE_0x80 TWICE(SPACE_0x40) -#define SPACE_0x100 TWICE(SPACE_0x80) -#define SPACE_0x200 TWICE(SPACE_0x100) -#define SPACE_0x400 TWICE(SPACE_0x200) -#define SPACE_0x800 TWICE(SPACE_0x400) -#define SPACE_0x1000 TWICE(SPACE_0x800) - - -/* Various values used in test cases... */ -#define N(val) (val ^ 0xffffffff) -#define VAL1 0x12345678 -#define VAL2 N(VAL1) -#define VAL3 0xa5f801 -#define VAL4 N(VAL3) -#define VALM 0x456789ab -#define VALR 0xdeaddead -#define HH1 0x0123fecb -#define HH2 0xa9874567 - - -#ifdef CONFIG_THUMB2_KERNEL -void kprobe_thumb16_test_cases(void); -void kprobe_thumb32_test_cases(void); -#else -void kprobe_arm_test_cases(void); -#endif diff --git a/ANDROID_3.4.5/arch/arm/kernel/kprobes-thumb.c b/ANDROID_3.4.5/arch/arm/kernel/kprobes-thumb.c deleted file mode 100644 index 8f96ec77..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/kprobes-thumb.c +++ /dev/null @@ -1,1469 +0,0 @@ -/* - * arch/arm/kernel/kprobes-thumb.c - * - * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/kernel.h> -#include <linux/kprobes.h> -#include <linux/module.h> - -#include "kprobes.h" - - -/* - * True if current instruction is in an IT block. - */ -#define in_it_block(cpsr) ((cpsr & 0x06000c00) != 0x00000000) - -/* - * Return the condition code to check for the currently executing instruction. - * This is in ITSTATE<7:4> which is in CPSR<15:12> but is only valid if - * in_it_block returns true. - */ -#define current_cond(cpsr) ((cpsr >> 12) & 0xf) - -/* - * Return the PC value for a probe in thumb code. - * This is the address of the probed instruction plus 4. - * We subtract one because the address will have bit zero set to indicate - * a pointer to thumb code. - */ -static inline unsigned long __kprobes thumb_probe_pc(struct kprobe *p) -{ - return (unsigned long)p->addr - 1 + 4; -} - -static void __kprobes -t32_simulate_table_branch(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - unsigned long pc = thumb_probe_pc(p); - int rn = (insn >> 16) & 0xf; - int rm = insn & 0xf; - - unsigned long rnv = (rn == 15) ? pc : regs->uregs[rn]; - unsigned long rmv = regs->uregs[rm]; - unsigned int halfwords; - - if (insn & 0x10) /* TBH */ - halfwords = ((u16 *)rnv)[rmv]; - else /* TBB */ - halfwords = ((u8 *)rnv)[rmv]; - - regs->ARM_pc = pc + 2 * halfwords; -} - -static void __kprobes -t32_simulate_mrs(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - int rd = (insn >> 8) & 0xf; - unsigned long mask = 0xf8ff03df; /* Mask out execution state */ - regs->uregs[rd] = regs->ARM_cpsr & mask; -} - -static void __kprobes -t32_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - unsigned long pc = thumb_probe_pc(p); - - long offset = insn & 0x7ff; /* imm11 */ - offset += (insn & 0x003f0000) >> 5; /* imm6 */ - offset += (insn & 0x00002000) << 4; /* J1 */ - offset += (insn & 0x00000800) << 7; /* J2 */ - offset -= (insn & 0x04000000) >> 7; /* Apply sign bit */ - - regs->ARM_pc = pc + (offset * 2); -} - -static enum kprobe_insn __kprobes -t32_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi) -{ - int cc = (insn >> 22) & 0xf; - asi->insn_check_cc = kprobe_condition_checks[cc]; - asi->insn_handler = t32_simulate_cond_branch; - return INSN_GOOD_NO_SLOT; -} - -static void __kprobes -t32_simulate_branch(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - unsigned long pc = thumb_probe_pc(p); - - long offset = insn & 0x7ff; /* imm11 */ - offset += (insn & 0x03ff0000) >> 5; /* imm10 */ - offset += (insn & 0x00002000) << 9; /* J1 */ - offset += (insn & 0x00000800) << 10; /* J2 */ - if (insn & 0x04000000) - offset -= 0x00800000; /* Apply sign bit */ - else - offset ^= 0x00600000; /* Invert J1 and J2 */ - - if (insn & (1 << 14)) { - /* BL or BLX */ - regs->ARM_lr = (unsigned long)p->addr + 4; - if (!(insn & (1 << 12))) { - /* BLX so switch to ARM mode */ - regs->ARM_cpsr &= ~PSR_T_BIT; - pc &= ~3; - } - } - - regs->ARM_pc = pc + (offset * 2); -} - -static void __kprobes -t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - unsigned long addr = thumb_probe_pc(p) & ~3; - int rt = (insn >> 12) & 0xf; - unsigned long rtv; - - long offset = insn & 0xfff; - if (insn & 0x00800000) - addr += offset; - else - addr -= offset; - - if (insn & 0x00400000) { - /* LDR */ - rtv = *(unsigned long *)addr; - if (rt == 15) { - bx_write_pc(rtv, regs); - return; - } - } else if (insn & 0x00200000) { - /* LDRH */ - if (insn & 0x01000000) - rtv = *(s16 *)addr; - else - rtv = *(u16 *)addr; - } else { - /* LDRB */ - if (insn & 0x01000000) - rtv = *(s8 *)addr; - else - rtv = *(u8 *)addr; - } - - regs->uregs[rt] = rtv; -} - -static enum kprobe_insn __kprobes -t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi) -{ - enum kprobe_insn ret = kprobe_decode_ldmstm(insn, asi); - - /* Fixup modified instruction to have halfwords in correct order...*/ - insn = asi->insn[0]; - ((u16 *)asi->insn)[0] = insn >> 16; - ((u16 *)asi->insn)[1] = insn & 0xffff; - - return ret; -} - -static void __kprobes -t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - unsigned long pc = thumb_probe_pc(p) & ~3; - int rt1 = (insn >> 12) & 0xf; - int rt2 = (insn >> 8) & 0xf; - int rn = (insn >> 16) & 0xf; - - register unsigned long rt1v asm("r0") = regs->uregs[rt1]; - register unsigned long rt2v asm("r1") = regs->uregs[rt2]; - register unsigned long rnv asm("r2") = (rn == 15) ? pc - : regs->uregs[rn]; - - __asm__ __volatile__ ( - "blx %[fn]" - : "=r" (rt1v), "=r" (rt2v), "=r" (rnv) - : "0" (rt1v), "1" (rt2v), "2" (rnv), [fn] "r" (p->ainsn.insn_fn) - : "lr", "memory", "cc" - ); - - if (rn != 15) - regs->uregs[rn] = rnv; /* Writeback base register */ - regs->uregs[rt1] = rt1v; - regs->uregs[rt2] = rt2v; -} - -static void __kprobes -t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - int rt = (insn >> 12) & 0xf; - int rn = (insn >> 16) & 0xf; - int rm = insn & 0xf; - - register unsigned long rtv asm("r0") = regs->uregs[rt]; - register unsigned long rnv asm("r2") = regs->uregs[rn]; - register unsigned long rmv asm("r3") = regs->uregs[rm]; - - __asm__ __volatile__ ( - "blx %[fn]" - : "=r" (rtv), "=r" (rnv) - : "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn) - : "lr", "memory", "cc" - ); - - regs->uregs[rn] = rnv; /* Writeback base register */ - if (rt == 15) /* Can't be true for a STR as they aren't allowed */ - bx_write_pc(rtv, regs); - else - regs->uregs[rt] = rtv; -} - -static void __kprobes -t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - int rd = (insn >> 8) & 0xf; - int rn = (insn >> 16) & 0xf; - int rm = insn & 0xf; - - register unsigned long rdv asm("r1") = regs->uregs[rd]; - register unsigned long rnv asm("r2") = regs->uregs[rn]; - register unsigned long rmv asm("r3") = regs->uregs[rm]; - unsigned long cpsr = regs->ARM_cpsr; - - __asm__ __volatile__ ( - "msr cpsr_fs, %[cpsr] \n\t" - "blx %[fn] \n\t" - "mrs %[cpsr], cpsr \n\t" - : "=r" (rdv), [cpsr] "=r" (cpsr) - : "0" (rdv), "r" (rnv), "r" (rmv), - "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) - : "lr", "memory", "cc" - ); - - regs->uregs[rd] = rdv; - regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); -} - -static void __kprobes -t32_emulate_rd8pc16_noflags(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - unsigned long pc = thumb_probe_pc(p); - int rd = (insn >> 8) & 0xf; - - register unsigned long rdv asm("r1") = regs->uregs[rd]; - register unsigned long rnv asm("r2") = pc & ~3; - - __asm__ __volatile__ ( - "blx %[fn]" - : "=r" (rdv) - : "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn) - : "lr", "memory", "cc" - ); - - regs->uregs[rd] = rdv; -} - -static void __kprobes -t32_emulate_rd8rn16_noflags(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - int rd = (insn >> 8) & 0xf; - int rn = (insn >> 16) & 0xf; - - register unsigned long rdv asm("r1") = regs->uregs[rd]; - register unsigned long rnv asm("r2") = regs->uregs[rn]; - - __asm__ __volatile__ ( - "blx %[fn]" - : "=r" (rdv) - : "0" (rdv), "r" (rnv), [fn] "r" (p->ainsn.insn_fn) - : "lr", "memory", "cc" - ); - - regs->uregs[rd] = rdv; -} - -static void __kprobes -t32_emulate_rdlo12rdhi8rn16rm0_noflags(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - int rdlo = (insn >> 12) & 0xf; - int rdhi = (insn >> 8) & 0xf; - int rn = (insn >> 16) & 0xf; - int rm = insn & 0xf; - - register unsigned long rdlov asm("r0") = regs->uregs[rdlo]; - register unsigned long rdhiv asm("r1") = regs->uregs[rdhi]; - register unsigned long rnv asm("r2") = regs->uregs[rn]; - register unsigned long rmv asm("r3") = regs->uregs[rm]; - - __asm__ __volatile__ ( - "blx %[fn]" - : "=r" (rdlov), "=r" (rdhiv) - : "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv), - [fn] "r" (p->ainsn.insn_fn) - : "lr", "memory", "cc" - ); - - regs->uregs[rdlo] = rdlov; - regs->uregs[rdhi] = rdhiv; -} - -/* These emulation encodings are functionally equivalent... */ -#define t32_emulate_rd8rn16rm0ra12_noflags \ - t32_emulate_rdlo12rdhi8rn16rm0_noflags - -static const union decode_item t32_table_1110_100x_x0xx[] = { - /* Load/store multiple instructions */ - - /* Rn is PC 1110 100x x0xx 1111 xxxx xxxx xxxx xxxx */ - DECODE_REJECT (0xfe4f0000, 0xe80f0000), - - /* SRS 1110 1000 00x0 xxxx xxxx xxxx xxxx xxxx */ - /* RFE 1110 1000 00x1 xxxx xxxx xxxx xxxx xxxx */ - DECODE_REJECT (0xffc00000, 0xe8000000), - /* SRS 1110 1001 10x0 xxxx xxxx xxxx xxxx xxxx */ - /* RFE 1110 1001 10x1 xxxx xxxx xxxx xxxx xxxx */ - DECODE_REJECT (0xffc00000, 0xe9800000), - - /* STM Rn, {...pc} 1110 100x x0x0 xxxx 1xxx xxxx xxxx xxxx */ - DECODE_REJECT (0xfe508000, 0xe8008000), - /* LDM Rn, {...lr,pc} 1110 100x x0x1 xxxx 11xx xxxx xxxx xxxx */ - DECODE_REJECT (0xfe50c000, 0xe810c000), - /* LDM/STM Rn, {...sp} 1110 100x x0xx xxxx xx1x xxxx xxxx xxxx */ - DECODE_REJECT (0xfe402000, 0xe8002000), - - /* STMIA 1110 1000 10x0 xxxx xxxx xxxx xxxx xxxx */ - /* LDMIA 1110 1000 10x1 xxxx xxxx xxxx xxxx xxxx */ - /* STMDB 1110 1001 00x0 xxxx xxxx xxxx xxxx xxxx */ - /* LDMDB 1110 1001 00x1 xxxx xxxx xxxx xxxx xxxx */ - DECODE_CUSTOM (0xfe400000, 0xe8000000, t32_decode_ldmstm), - - DECODE_END -}; - -static const union decode_item t32_table_1110_100x_x1xx[] = { - /* Load/store dual, load/store exclusive, table branch */ - - /* STRD (immediate) 1110 1000 x110 xxxx xxxx xxxx xxxx xxxx */ - /* LDRD (immediate) 1110 1000 x111 xxxx xxxx xxxx xxxx xxxx */ - DECODE_OR (0xff600000, 0xe8600000), - /* STRD (immediate) 1110 1001 x1x0 xxxx xxxx xxxx xxxx xxxx */ - /* LDRD (immediate) 1110 1001 x1x1 xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xff400000, 0xe9400000, t32_emulate_ldrdstrd, - REGS(NOPCWB, NOSPPC, NOSPPC, 0, 0)), - - /* TBB 1110 1000 1101 xxxx xxxx xxxx 0000 xxxx */ - /* TBH 1110 1000 1101 xxxx xxxx xxxx 0001 xxxx */ - DECODE_SIMULATEX(0xfff000e0, 0xe8d00000, t32_simulate_table_branch, - REGS(NOSP, 0, 0, 0, NOSPPC)), - - /* STREX 1110 1000 0100 xxxx xxxx xxxx xxxx xxxx */ - /* LDREX 1110 1000 0101 xxxx xxxx xxxx xxxx xxxx */ - /* STREXB 1110 1000 1100 xxxx xxxx xxxx 0100 xxxx */ - /* STREXH 1110 1000 1100 xxxx xxxx xxxx 0101 xxxx */ - /* STREXD 1110 1000 1100 xxxx xxxx xxxx 0111 xxxx */ - /* LDREXB 1110 1000 1101 xxxx xxxx xxxx 0100 xxxx */ - /* LDREXH 1110 1000 1101 xxxx xxxx xxxx 0101 xxxx */ - /* LDREXD 1110 1000 1101 xxxx xxxx xxxx 0111 xxxx */ - /* And unallocated instructions... */ - DECODE_END -}; - -static const union decode_item t32_table_1110_101x[] = { - /* Data-processing (shifted register) */ - - /* TST 1110 1010 0001 xxxx xxxx 1111 xxxx xxxx */ - /* TEQ 1110 1010 1001 xxxx xxxx 1111 xxxx xxxx */ - DECODE_EMULATEX (0xff700f00, 0xea100f00, t32_emulate_rd8rn16rm0_rwflags, - REGS(NOSPPC, 0, 0, 0, NOSPPC)), - - /* CMN 1110 1011 0001 xxxx xxxx 1111 xxxx xxxx */ - DECODE_OR (0xfff00f00, 0xeb100f00), - /* CMP 1110 1011 1011 xxxx xxxx 1111 xxxx xxxx */ - DECODE_EMULATEX (0xfff00f00, 0xebb00f00, t32_emulate_rd8rn16rm0_rwflags, - REGS(NOPC, 0, 0, 0, NOSPPC)), - - /* MOV 1110 1010 010x 1111 xxxx xxxx xxxx xxxx */ - /* MVN 1110 1010 011x 1111 xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xffcf0000, 0xea4f0000, t32_emulate_rd8rn16rm0_rwflags, - REGS(0, 0, NOSPPC, 0, NOSPPC)), - - /* ??? 1110 1010 101x xxxx xxxx xxxx xxxx xxxx */ - /* ??? 1110 1010 111x xxxx xxxx xxxx xxxx xxxx */ - DECODE_REJECT (0xffa00000, 0xeaa00000), - /* ??? 1110 1011 001x xxxx xxxx xxxx xxxx xxxx */ - DECODE_REJECT (0xffe00000, 0xeb200000), - /* ??? 1110 1011 100x xxxx xxxx xxxx xxxx xxxx */ - DECODE_REJECT (0xffe00000, 0xeb800000), - /* ??? 1110 1011 111x xxxx xxxx xxxx xxxx xxxx */ - DECODE_REJECT (0xffe00000, 0xebe00000), - - /* ADD/SUB SP, SP, Rm, LSL #0..3 */ - /* 1110 1011 x0xx 1101 x000 1101 xx00 xxxx */ - DECODE_EMULATEX (0xff4f7f30, 0xeb0d0d00, t32_emulate_rd8rn16rm0_rwflags, - REGS(SP, 0, SP, 0, NOSPPC)), - - /* ADD/SUB SP, SP, Rm, shift */ - /* 1110 1011 x0xx 1101 xxxx 1101 xxxx xxxx */ - DECODE_REJECT (0xff4f0f00, 0xeb0d0d00), - - /* ADD/SUB Rd, SP, Rm, shift */ - /* 1110 1011 x0xx 1101 xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xff4f0000, 0xeb0d0000, t32_emulate_rd8rn16rm0_rwflags, - REGS(SP, 0, NOPC, 0, NOSPPC)), - - /* AND 1110 1010 000x xxxx xxxx xxxx xxxx xxxx */ - /* BIC 1110 1010 001x xxxx xxxx xxxx xxxx xxxx */ - /* ORR 1110 1010 010x xxxx xxxx xxxx xxxx xxxx */ - /* ORN 1110 1010 011x xxxx xxxx xxxx xxxx xxxx */ - /* EOR 1110 1010 100x xxxx xxxx xxxx xxxx xxxx */ - /* PKH 1110 1010 110x xxxx xxxx xxxx xxxx xxxx */ - /* ADD 1110 1011 000x xxxx xxxx xxxx xxxx xxxx */ - /* ADC 1110 1011 010x xxxx xxxx xxxx xxxx xxxx */ - /* SBC 1110 1011 011x xxxx xxxx xxxx xxxx xxxx */ - /* SUB 1110 1011 101x xxxx xxxx xxxx xxxx xxxx */ - /* RSB 1110 1011 110x xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfe000000, 0xea000000, t32_emulate_rd8rn16rm0_rwflags, - REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)), - - DECODE_END -}; - -static const union decode_item t32_table_1111_0x0x___0[] = { - /* Data-processing (modified immediate) */ - - /* TST 1111 0x00 0001 xxxx 0xxx 1111 xxxx xxxx */ - /* TEQ 1111 0x00 1001 xxxx 0xxx 1111 xxxx xxxx */ - DECODE_EMULATEX (0xfb708f00, 0xf0100f00, t32_emulate_rd8rn16rm0_rwflags, - REGS(NOSPPC, 0, 0, 0, 0)), - - /* CMN 1111 0x01 0001 xxxx 0xxx 1111 xxxx xxxx */ - DECODE_OR (0xfbf08f00, 0xf1100f00), - /* CMP 1111 0x01 1011 xxxx 0xxx 1111 xxxx xxxx */ - DECODE_EMULATEX (0xfbf08f00, 0xf1b00f00, t32_emulate_rd8rn16rm0_rwflags, - REGS(NOPC, 0, 0, 0, 0)), - - /* MOV 1111 0x00 010x 1111 0xxx xxxx xxxx xxxx */ - /* MVN 1111 0x00 011x 1111 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfbcf8000, 0xf04f0000, t32_emulate_rd8rn16rm0_rwflags, - REGS(0, 0, NOSPPC, 0, 0)), - - /* ??? 1111 0x00 101x xxxx 0xxx xxxx xxxx xxxx */ - DECODE_REJECT (0xfbe08000, 0xf0a00000), - /* ??? 1111 0x00 110x xxxx 0xxx xxxx xxxx xxxx */ - /* ??? 1111 0x00 111x xxxx 0xxx xxxx xxxx xxxx */ - DECODE_REJECT (0xfbc08000, 0xf0c00000), - /* ??? 1111 0x01 001x xxxx 0xxx xxxx xxxx xxxx */ - DECODE_REJECT (0xfbe08000, 0xf1200000), - /* ??? 1111 0x01 100x xxxx 0xxx xxxx xxxx xxxx */ - DECODE_REJECT (0xfbe08000, 0xf1800000), - /* ??? 1111 0x01 111x xxxx 0xxx xxxx xxxx xxxx */ - DECODE_REJECT (0xfbe08000, 0xf1e00000), - - /* ADD Rd, SP, #imm 1111 0x01 000x 1101 0xxx xxxx xxxx xxxx */ - /* SUB Rd, SP, #imm 1111 0x01 101x 1101 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfb4f8000, 0xf10d0000, t32_emulate_rd8rn16rm0_rwflags, - REGS(SP, 0, NOPC, 0, 0)), - - /* AND 1111 0x00 000x xxxx 0xxx xxxx xxxx xxxx */ - /* BIC 1111 0x00 001x xxxx 0xxx xxxx xxxx xxxx */ - /* ORR 1111 0x00 010x xxxx 0xxx xxxx xxxx xxxx */ - /* ORN 1111 0x00 011x xxxx 0xxx xxxx xxxx xxxx */ - /* EOR 1111 0x00 100x xxxx 0xxx xxxx xxxx xxxx */ - /* ADD 1111 0x01 000x xxxx 0xxx xxxx xxxx xxxx */ - /* ADC 1111 0x01 010x xxxx 0xxx xxxx xxxx xxxx */ - /* SBC 1111 0x01 011x xxxx 0xxx xxxx xxxx xxxx */ - /* SUB 1111 0x01 101x xxxx 0xxx xxxx xxxx xxxx */ - /* RSB 1111 0x01 110x xxxx 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfa008000, 0xf0000000, t32_emulate_rd8rn16rm0_rwflags, - REGS(NOSPPC, 0, NOSPPC, 0, 0)), - - DECODE_END -}; - -static const union decode_item t32_table_1111_0x1x___0[] = { - /* Data-processing (plain binary immediate) */ - - /* ADDW Rd, PC, #imm 1111 0x10 0000 1111 0xxx xxxx xxxx xxxx */ - DECODE_OR (0xfbff8000, 0xf20f0000), - /* SUBW Rd, PC, #imm 1111 0x10 1010 1111 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfbff8000, 0xf2af0000, t32_emulate_rd8pc16_noflags, - REGS(PC, 0, NOSPPC, 0, 0)), - - /* ADDW SP, SP, #imm 1111 0x10 0000 1101 0xxx 1101 xxxx xxxx */ - DECODE_OR (0xfbff8f00, 0xf20d0d00), - /* SUBW SP, SP, #imm 1111 0x10 1010 1101 0xxx 1101 xxxx xxxx */ - DECODE_EMULATEX (0xfbff8f00, 0xf2ad0d00, t32_emulate_rd8rn16_noflags, - REGS(SP, 0, SP, 0, 0)), - - /* ADDW 1111 0x10 0000 xxxx 0xxx xxxx xxxx xxxx */ - DECODE_OR (0xfbf08000, 0xf2000000), - /* SUBW 1111 0x10 1010 xxxx 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfbf08000, 0xf2a00000, t32_emulate_rd8rn16_noflags, - REGS(NOPCX, 0, NOSPPC, 0, 0)), - - /* MOVW 1111 0x10 0100 xxxx 0xxx xxxx xxxx xxxx */ - /* MOVT 1111 0x10 1100 xxxx 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfb708000, 0xf2400000, t32_emulate_rd8rn16_noflags, - REGS(0, 0, NOSPPC, 0, 0)), - - /* SSAT16 1111 0x11 0010 xxxx 0000 xxxx 00xx xxxx */ - /* SSAT 1111 0x11 00x0 xxxx 0xxx xxxx xxxx xxxx */ - /* USAT16 1111 0x11 1010 xxxx 0000 xxxx 00xx xxxx */ - /* USAT 1111 0x11 10x0 xxxx 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfb508000, 0xf3000000, t32_emulate_rd8rn16rm0_rwflags, - REGS(NOSPPC, 0, NOSPPC, 0, 0)), - - /* SFBX 1111 0x11 0100 xxxx 0xxx xxxx xxxx xxxx */ - /* UFBX 1111 0x11 1100 xxxx 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfb708000, 0xf3400000, t32_emulate_rd8rn16_noflags, - REGS(NOSPPC, 0, NOSPPC, 0, 0)), - - /* BFC 1111 0x11 0110 1111 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfbff8000, 0xf36f0000, t32_emulate_rd8rn16_noflags, - REGS(0, 0, NOSPPC, 0, 0)), - - /* BFI 1111 0x11 0110 xxxx 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfbf08000, 0xf3600000, t32_emulate_rd8rn16_noflags, - REGS(NOSPPCX, 0, NOSPPC, 0, 0)), - - DECODE_END -}; - -static const union decode_item t32_table_1111_0xxx___1[] = { - /* Branches and miscellaneous control */ - - /* YIELD 1111 0011 1010 xxxx 10x0 x000 0000 0001 */ - DECODE_OR (0xfff0d7ff, 0xf3a08001), - /* SEV 1111 0011 1010 xxxx 10x0 x000 0000 0100 */ - DECODE_EMULATE (0xfff0d7ff, 0xf3a08004, kprobe_emulate_none), - /* NOP 1111 0011 1010 xxxx 10x0 x000 0000 0000 */ - /* WFE 1111 0011 1010 xxxx 10x0 x000 0000 0010 */ - /* WFI 1111 0011 1010 xxxx 10x0 x000 0000 0011 */ - DECODE_SIMULATE (0xfff0d7fc, 0xf3a08000, kprobe_simulate_nop), - - /* MRS Rd, CPSR 1111 0011 1110 xxxx 10x0 xxxx xxxx xxxx */ - DECODE_SIMULATEX(0xfff0d000, 0xf3e08000, t32_simulate_mrs, - REGS(0, 0, NOSPPC, 0, 0)), - - /* - * Unsupported instructions - * 1111 0x11 1xxx xxxx 10x0 xxxx xxxx xxxx - * - * MSR 1111 0011 100x xxxx 10x0 xxxx xxxx xxxx - * DBG hint 1111 0011 1010 xxxx 10x0 x000 1111 xxxx - * Unallocated hints 1111 0011 1010 xxxx 10x0 x000 xxxx xxxx - * CPS 1111 0011 1010 xxxx 10x0 xxxx xxxx xxxx - * CLREX/DSB/DMB/ISB 1111 0011 1011 xxxx 10x0 xxxx xxxx xxxx - * BXJ 1111 0011 1100 xxxx 10x0 xxxx xxxx xxxx - * SUBS PC,LR,#<imm8> 1111 0011 1101 xxxx 10x0 xxxx xxxx xxxx - * MRS Rd, SPSR 1111 0011 1111 xxxx 10x0 xxxx xxxx xxxx - * SMC 1111 0111 1111 xxxx 1000 xxxx xxxx xxxx - * UNDEFINED 1111 0111 1111 xxxx 1010 xxxx xxxx xxxx - * ??? 1111 0111 1xxx xxxx 1010 xxxx xxxx xxxx - */ - DECODE_REJECT (0xfb80d000, 0xf3808000), - - /* Bcc 1111 0xxx xxxx xxxx 10x0 xxxx xxxx xxxx */ - DECODE_CUSTOM (0xf800d000, 0xf0008000, t32_decode_cond_branch), - - /* BLX 1111 0xxx xxxx xxxx 11x0 xxxx xxxx xxx0 */ - DECODE_OR (0xf800d001, 0xf000c000), - /* B 1111 0xxx xxxx xxxx 10x1 xxxx xxxx xxxx */ - /* BL 1111 0xxx xxxx xxxx 11x1 xxxx xxxx xxxx */ - DECODE_SIMULATE (0xf8009000, 0xf0009000, t32_simulate_branch), - - DECODE_END -}; - -static const union decode_item t32_table_1111_100x_x0x1__1111[] = { - /* Memory hints */ - - /* PLD (literal) 1111 1000 x001 1111 1111 xxxx xxxx xxxx */ - /* PLI (literal) 1111 1001 x001 1111 1111 xxxx xxxx xxxx */ - DECODE_SIMULATE (0xfe7ff000, 0xf81ff000, kprobe_simulate_nop), - - /* PLD{W} (immediate) 1111 1000 10x1 xxxx 1111 xxxx xxxx xxxx */ - DECODE_OR (0xffd0f000, 0xf890f000), - /* PLD{W} (immediate) 1111 1000 00x1 xxxx 1111 1100 xxxx xxxx */ - DECODE_OR (0xffd0ff00, 0xf810fc00), - /* PLI (immediate) 1111 1001 1001 xxxx 1111 xxxx xxxx xxxx */ - DECODE_OR (0xfff0f000, 0xf990f000), - /* PLI (immediate) 1111 1001 0001 xxxx 1111 1100 xxxx xxxx */ - DECODE_SIMULATEX(0xfff0ff00, 0xf910fc00, kprobe_simulate_nop, - REGS(NOPCX, 0, 0, 0, 0)), - - /* PLD{W} (register) 1111 1000 00x1 xxxx 1111 0000 00xx xxxx */ - DECODE_OR (0xffd0ffc0, 0xf810f000), - /* PLI (register) 1111 1001 0001 xxxx 1111 0000 00xx xxxx */ - DECODE_SIMULATEX(0xfff0ffc0, 0xf910f000, kprobe_simulate_nop, - REGS(NOPCX, 0, 0, 0, NOSPPC)), - - /* Other unallocated instructions... */ - DECODE_END -}; - -static const union decode_item t32_table_1111_100x[] = { - /* Store/Load single data item */ - - /* ??? 1111 100x x11x xxxx xxxx xxxx xxxx xxxx */ - DECODE_REJECT (0xfe600000, 0xf8600000), - - /* ??? 1111 1001 0101 xxxx xxxx xxxx xxxx xxxx */ - DECODE_REJECT (0xfff00000, 0xf9500000), - - /* ??? 1111 100x 0xxx xxxx xxxx 10x0 xxxx xxxx */ - DECODE_REJECT (0xfe800d00, 0xf8000800), - - /* STRBT 1111 1000 0000 xxxx xxxx 1110 xxxx xxxx */ - /* STRHT 1111 1000 0010 xxxx xxxx 1110 xxxx xxxx */ - /* STRT 1111 1000 0100 xxxx xxxx 1110 xxxx xxxx */ - /* LDRBT 1111 1000 0001 xxxx xxxx 1110 xxxx xxxx */ - /* LDRSBT 1111 1001 0001 xxxx xxxx 1110 xxxx xxxx */ - /* LDRHT 1111 1000 0011 xxxx xxxx 1110 xxxx xxxx */ - /* LDRSHT 1111 1001 0011 xxxx xxxx 1110 xxxx xxxx */ - /* LDRT 1111 1000 0101 xxxx xxxx 1110 xxxx xxxx */ - DECODE_REJECT (0xfe800f00, 0xf8000e00), - - /* STR{,B,H} Rn,[PC...] 1111 1000 xxx0 1111 xxxx xxxx xxxx xxxx */ - DECODE_REJECT (0xff1f0000, 0xf80f0000), - - /* STR{,B,H} PC,[Rn...] 1111 1000 xxx0 xxxx 1111 xxxx xxxx xxxx */ - DECODE_REJECT (0xff10f000, 0xf800f000), - - /* LDR (literal) 1111 1000 x101 1111 xxxx xxxx xxxx xxxx */ - DECODE_SIMULATEX(0xff7f0000, 0xf85f0000, t32_simulate_ldr_literal, - REGS(PC, ANY, 0, 0, 0)), - - /* STR (immediate) 1111 1000 0100 xxxx xxxx 1xxx xxxx xxxx */ - /* LDR (immediate) 1111 1000 0101 xxxx xxxx 1xxx xxxx xxxx */ - DECODE_OR (0xffe00800, 0xf8400800), - /* STR (immediate) 1111 1000 1100 xxxx xxxx xxxx xxxx xxxx */ - /* LDR (immediate) 1111 1000 1101 xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xffe00000, 0xf8c00000, t32_emulate_ldrstr, - REGS(NOPCX, ANY, 0, 0, 0)), - - /* STR (register) 1111 1000 0100 xxxx xxxx 0000 00xx xxxx */ - /* LDR (register) 1111 1000 0101 xxxx xxxx 0000 00xx xxxx */ - DECODE_EMULATEX (0xffe00fc0, 0xf8400000, t32_emulate_ldrstr, - REGS(NOPCX, ANY, 0, 0, NOSPPC)), - - /* LDRB (literal) 1111 1000 x001 1111 xxxx xxxx xxxx xxxx */ - /* LDRSB (literal) 1111 1001 x001 1111 xxxx xxxx xxxx xxxx */ - /* LDRH (literal) 1111 1000 x011 1111 xxxx xxxx xxxx xxxx */ - /* LDRSH (literal) 1111 1001 x011 1111 xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfe5f0000, 0xf81f0000, t32_simulate_ldr_literal, - REGS(PC, NOSPPCX, 0, 0, 0)), - - /* STRB (immediate) 1111 1000 0000 xxxx xxxx 1xxx xxxx xxxx */ - /* STRH (immediate) 1111 1000 0010 xxxx xxxx 1xxx xxxx xxxx */ - /* LDRB (immediate) 1111 1000 0001 xxxx xxxx 1xxx xxxx xxxx */ - /* LDRSB (immediate) 1111 1001 0001 xxxx xxxx 1xxx xxxx xxxx */ - /* LDRH (immediate) 1111 1000 0011 xxxx xxxx 1xxx xxxx xxxx */ - /* LDRSH (immediate) 1111 1001 0011 xxxx xxxx 1xxx xxxx xxxx */ - DECODE_OR (0xfec00800, 0xf8000800), - /* STRB (immediate) 1111 1000 1000 xxxx xxxx xxxx xxxx xxxx */ - /* STRH (immediate) 1111 1000 1010 xxxx xxxx xxxx xxxx xxxx */ - /* LDRB (immediate) 1111 1000 1001 xxxx xxxx xxxx xxxx xxxx */ - /* LDRSB (immediate) 1111 1001 1001 xxxx xxxx xxxx xxxx xxxx */ - /* LDRH (immediate) 1111 1000 1011 xxxx xxxx xxxx xxxx xxxx */ - /* LDRSH (immediate) 1111 1001 1011 xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfec00000, 0xf8800000, t32_emulate_ldrstr, - REGS(NOPCX, NOSPPCX, 0, 0, 0)), - - /* STRB (register) 1111 1000 0000 xxxx xxxx 0000 00xx xxxx */ - /* STRH (register) 1111 1000 0010 xxxx xxxx 0000 00xx xxxx */ - /* LDRB (register) 1111 1000 0001 xxxx xxxx 0000 00xx xxxx */ - /* LDRSB (register) 1111 1001 0001 xxxx xxxx 0000 00xx xxxx */ - /* LDRH (register) 1111 1000 0011 xxxx xxxx 0000 00xx xxxx */ - /* LDRSH (register) 1111 1001 0011 xxxx xxxx 0000 00xx xxxx */ - DECODE_EMULATEX (0xfe800fc0, 0xf8000000, t32_emulate_ldrstr, - REGS(NOPCX, NOSPPCX, 0, 0, NOSPPC)), - - /* Other unallocated instructions... */ - DECODE_END -}; - -static const union decode_item t32_table_1111_1010___1111[] = { - /* Data-processing (register) */ - - /* ??? 1111 1010 011x xxxx 1111 xxxx 1xxx xxxx */ - DECODE_REJECT (0xffe0f080, 0xfa60f080), - - /* SXTH 1111 1010 0000 1111 1111 xxxx 1xxx xxxx */ - /* UXTH 1111 1010 0001 1111 1111 xxxx 1xxx xxxx */ - /* SXTB16 1111 1010 0010 1111 1111 xxxx 1xxx xxxx */ - /* UXTB16 1111 1010 0011 1111 1111 xxxx 1xxx xxxx */ - /* SXTB 1111 1010 0100 1111 1111 xxxx 1xxx xxxx */ - /* UXTB 1111 1010 0101 1111 1111 xxxx 1xxx xxxx */ - DECODE_EMULATEX (0xff8ff080, 0xfa0ff080, t32_emulate_rd8rn16rm0_rwflags, - REGS(0, 0, NOSPPC, 0, NOSPPC)), - - - /* ??? 1111 1010 1xxx xxxx 1111 xxxx 0x11 xxxx */ - DECODE_REJECT (0xff80f0b0, 0xfa80f030), - /* ??? 1111 1010 1x11 xxxx 1111 xxxx 0xxx xxxx */ - DECODE_REJECT (0xffb0f080, 0xfab0f000), - - /* SADD16 1111 1010 1001 xxxx 1111 xxxx 0000 xxxx */ - /* SASX 1111 1010 1010 xxxx 1111 xxxx 0000 xxxx */ - /* SSAX 1111 1010 1110 xxxx 1111 xxxx 0000 xxxx */ - /* SSUB16 1111 1010 1101 xxxx 1111 xxxx 0000 xxxx */ - /* SADD8 1111 1010 1000 xxxx 1111 xxxx 0000 xxxx */ - /* SSUB8 1111 1010 1100 xxxx 1111 xxxx 0000 xxxx */ - - /* QADD16 1111 1010 1001 xxxx 1111 xxxx 0001 xxxx */ - /* QASX 1111 1010 1010 xxxx 1111 xxxx 0001 xxxx */ - /* QSAX 1111 1010 1110 xxxx 1111 xxxx 0001 xxxx */ - /* QSUB16 1111 1010 1101 xxxx 1111 xxxx 0001 xxxx */ - /* QADD8 1111 1010 1000 xxxx 1111 xxxx 0001 xxxx */ - /* QSUB8 1111 1010 1100 xxxx 1111 xxxx 0001 xxxx */ - - /* SHADD16 1111 1010 1001 xxxx 1111 xxxx 0010 xxxx */ - /* SHASX 1111 1010 1010 xxxx 1111 xxxx 0010 xxxx */ - /* SHSAX 1111 1010 1110 xxxx 1111 xxxx 0010 xxxx */ - /* SHSUB16 1111 1010 1101 xxxx 1111 xxxx 0010 xxxx */ - /* SHADD8 1111 1010 1000 xxxx 1111 xxxx 0010 xxxx */ - /* SHSUB8 1111 1010 1100 xxxx 1111 xxxx 0010 xxxx */ - - /* UADD16 1111 1010 1001 xxxx 1111 xxxx 0100 xxxx */ - /* UASX 1111 1010 1010 xxxx 1111 xxxx 0100 xxxx */ - /* USAX 1111 1010 1110 xxxx 1111 xxxx 0100 xxxx */ - /* USUB16 1111 1010 1101 xxxx 1111 xxxx 0100 xxxx */ - /* UADD8 1111 1010 1000 xxxx 1111 xxxx 0100 xxxx */ - /* USUB8 1111 1010 1100 xxxx 1111 xxxx 0100 xxxx */ - - /* UQADD16 1111 1010 1001 xxxx 1111 xxxx 0101 xxxx */ - /* UQASX 1111 1010 1010 xxxx 1111 xxxx 0101 xxxx */ - /* UQSAX 1111 1010 1110 xxxx 1111 xxxx 0101 xxxx */ - /* UQSUB16 1111 1010 1101 xxxx 1111 xxxx 0101 xxxx */ - /* UQADD8 1111 1010 1000 xxxx 1111 xxxx 0101 xxxx */ - /* UQSUB8 1111 1010 1100 xxxx 1111 xxxx 0101 xxxx */ - - /* UHADD16 1111 1010 1001 xxxx 1111 xxxx 0110 xxxx */ - /* UHASX 1111 1010 1010 xxxx 1111 xxxx 0110 xxxx */ - /* UHSAX 1111 1010 1110 xxxx 1111 xxxx 0110 xxxx */ - /* UHSUB16 1111 1010 1101 xxxx 1111 xxxx 0110 xxxx */ - /* UHADD8 1111 1010 1000 xxxx 1111 xxxx 0110 xxxx */ - /* UHSUB8 1111 1010 1100 xxxx 1111 xxxx 0110 xxxx */ - DECODE_OR (0xff80f080, 0xfa80f000), - - /* SXTAH 1111 1010 0000 xxxx 1111 xxxx 1xxx xxxx */ - /* UXTAH 1111 1010 0001 xxxx 1111 xxxx 1xxx xxxx */ - /* SXTAB16 1111 1010 0010 xxxx 1111 xxxx 1xxx xxxx */ - /* UXTAB16 1111 1010 0011 xxxx 1111 xxxx 1xxx xxxx */ - /* SXTAB 1111 1010 0100 xxxx 1111 xxxx 1xxx xxxx */ - /* UXTAB 1111 1010 0101 xxxx 1111 xxxx 1xxx xxxx */ - DECODE_OR (0xff80f080, 0xfa00f080), - - /* QADD 1111 1010 1000 xxxx 1111 xxxx 1000 xxxx */ - /* QDADD 1111 1010 1000 xxxx 1111 xxxx 1001 xxxx */ - /* QSUB 1111 1010 1000 xxxx 1111 xxxx 1010 xxxx */ - /* QDSUB 1111 1010 1000 xxxx 1111 xxxx 1011 xxxx */ - DECODE_OR (0xfff0f0c0, 0xfa80f080), - - /* SEL 1111 1010 1010 xxxx 1111 xxxx 1000 xxxx */ - DECODE_OR (0xfff0f0f0, 0xfaa0f080), - - /* LSL 1111 1010 000x xxxx 1111 xxxx 0000 xxxx */ - /* LSR 1111 1010 001x xxxx 1111 xxxx 0000 xxxx */ - /* ASR 1111 1010 010x xxxx 1111 xxxx 0000 xxxx */ - /* ROR 1111 1010 011x xxxx 1111 xxxx 0000 xxxx */ - DECODE_EMULATEX (0xff80f0f0, 0xfa00f000, t32_emulate_rd8rn16rm0_rwflags, - REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)), - - /* CLZ 1111 1010 1010 xxxx 1111 xxxx 1000 xxxx */ - DECODE_OR (0xfff0f0f0, 0xfab0f080), - - /* REV 1111 1010 1001 xxxx 1111 xxxx 1000 xxxx */ - /* REV16 1111 1010 1001 xxxx 1111 xxxx 1001 xxxx */ - /* RBIT 1111 1010 1001 xxxx 1111 xxxx 1010 xxxx */ - /* REVSH 1111 1010 1001 xxxx 1111 xxxx 1011 xxxx */ - DECODE_EMULATEX (0xfff0f0c0, 0xfa90f080, t32_emulate_rd8rn16_noflags, - REGS(NOSPPC, 0, NOSPPC, 0, SAMEAS16)), - - /* Other unallocated instructions... */ - DECODE_END -}; - -static const union decode_item t32_table_1111_1011_0[] = { - /* Multiply, multiply accumulate, and absolute difference */ - - /* ??? 1111 1011 0000 xxxx 1111 xxxx 0001 xxxx */ - DECODE_REJECT (0xfff0f0f0, 0xfb00f010), - /* ??? 1111 1011 0111 xxxx 1111 xxxx 0001 xxxx */ - DECODE_REJECT (0xfff0f0f0, 0xfb70f010), - - /* SMULxy 1111 1011 0001 xxxx 1111 xxxx 00xx xxxx */ - DECODE_OR (0xfff0f0c0, 0xfb10f000), - /* MUL 1111 1011 0000 xxxx 1111 xxxx 0000 xxxx */ - /* SMUAD{X} 1111 1011 0010 xxxx 1111 xxxx 000x xxxx */ - /* SMULWy 1111 1011 0011 xxxx 1111 xxxx 000x xxxx */ - /* SMUSD{X} 1111 1011 0100 xxxx 1111 xxxx 000x xxxx */ - /* SMMUL{R} 1111 1011 0101 xxxx 1111 xxxx 000x xxxx */ - /* USAD8 1111 1011 0111 xxxx 1111 xxxx 0000 xxxx */ - DECODE_EMULATEX (0xff80f0e0, 0xfb00f000, t32_emulate_rd8rn16rm0_rwflags, - REGS(NOSPPC, 0, NOSPPC, 0, NOSPPC)), - - /* ??? 1111 1011 0111 xxxx xxxx xxxx 0001 xxxx */ - DECODE_REJECT (0xfff000f0, 0xfb700010), - - /* SMLAxy 1111 1011 0001 xxxx xxxx xxxx 00xx xxxx */ - DECODE_OR (0xfff000c0, 0xfb100000), - /* MLA 1111 1011 0000 xxxx xxxx xxxx 0000 xxxx */ - /* MLS 1111 1011 0000 xxxx xxxx xxxx 0001 xxxx */ - /* SMLAD{X} 1111 1011 0010 xxxx xxxx xxxx 000x xxxx */ - /* SMLAWy 1111 1011 0011 xxxx xxxx xxxx 000x xxxx */ - /* SMLSD{X} 1111 1011 0100 xxxx xxxx xxxx 000x xxxx */ - /* SMMLA{R} 1111 1011 0101 xxxx xxxx xxxx 000x xxxx */ - /* SMMLS{R} 1111 1011 0110 xxxx xxxx xxxx 000x xxxx */ - /* USADA8 1111 1011 0111 xxxx xxxx xxxx 0000 xxxx */ - DECODE_EMULATEX (0xff8000c0, 0xfb000000, t32_emulate_rd8rn16rm0ra12_noflags, - REGS(NOSPPC, NOSPPCX, NOSPPC, 0, NOSPPC)), - - /* Other unallocated instructions... */ - DECODE_END -}; - -static const union decode_item t32_table_1111_1011_1[] = { - /* Long multiply, long multiply accumulate, and divide */ - - /* UMAAL 1111 1011 1110 xxxx xxxx xxxx 0110 xxxx */ - DECODE_OR (0xfff000f0, 0xfbe00060), - /* SMLALxy 1111 1011 1100 xxxx xxxx xxxx 10xx xxxx */ - DECODE_OR (0xfff000c0, 0xfbc00080), - /* SMLALD{X} 1111 1011 1100 xxxx xxxx xxxx 110x xxxx */ - /* SMLSLD{X} 1111 1011 1101 xxxx xxxx xxxx 110x xxxx */ - DECODE_OR (0xffe000e0, 0xfbc000c0), - /* SMULL 1111 1011 1000 xxxx xxxx xxxx 0000 xxxx */ - /* UMULL 1111 1011 1010 xxxx xxxx xxxx 0000 xxxx */ - /* SMLAL 1111 1011 1100 xxxx xxxx xxxx 0000 xxxx */ - /* UMLAL 1111 1011 1110 xxxx xxxx xxxx 0000 xxxx */ - DECODE_EMULATEX (0xff9000f0, 0xfb800000, t32_emulate_rdlo12rdhi8rn16rm0_noflags, - REGS(NOSPPC, NOSPPC, NOSPPC, 0, NOSPPC)), - - /* SDIV 1111 1011 1001 xxxx xxxx xxxx 1111 xxxx */ - /* UDIV 1111 1011 1011 xxxx xxxx xxxx 1111 xxxx */ - /* Other unallocated instructions... */ - DECODE_END -}; - -const union decode_item kprobe_decode_thumb32_table[] = { - - /* - * Load/store multiple instructions - * 1110 100x x0xx xxxx xxxx xxxx xxxx xxxx - */ - DECODE_TABLE (0xfe400000, 0xe8000000, t32_table_1110_100x_x0xx), - - /* - * Load/store dual, load/store exclusive, table branch - * 1110 100x x1xx xxxx xxxx xxxx xxxx xxxx - */ - DECODE_TABLE (0xfe400000, 0xe8400000, t32_table_1110_100x_x1xx), - - /* - * Data-processing (shifted register) - * 1110 101x xxxx xxxx xxxx xxxx xxxx xxxx - */ - DECODE_TABLE (0xfe000000, 0xea000000, t32_table_1110_101x), - - /* - * Coprocessor instructions - * 1110 11xx xxxx xxxx xxxx xxxx xxxx xxxx - */ - DECODE_REJECT (0xfc000000, 0xec000000), - - /* - * Data-processing (modified immediate) - * 1111 0x0x xxxx xxxx 0xxx xxxx xxxx xxxx - */ - DECODE_TABLE (0xfa008000, 0xf0000000, t32_table_1111_0x0x___0), - - /* - * Data-processing (plain binary immediate) - * 1111 0x1x xxxx xxxx 0xxx xxxx xxxx xxxx - */ - DECODE_TABLE (0xfa008000, 0xf2000000, t32_table_1111_0x1x___0), - - /* - * Branches and miscellaneous control - * 1111 0xxx xxxx xxxx 1xxx xxxx xxxx xxxx - */ - DECODE_TABLE (0xf8008000, 0xf0008000, t32_table_1111_0xxx___1), - - /* - * Advanced SIMD element or structure load/store instructions - * 1111 1001 xxx0 xxxx xxxx xxxx xxxx xxxx - */ - DECODE_REJECT (0xff100000, 0xf9000000), - - /* - * Memory hints - * 1111 100x x0x1 xxxx 1111 xxxx xxxx xxxx - */ - DECODE_TABLE (0xfe50f000, 0xf810f000, t32_table_1111_100x_x0x1__1111), - - /* - * Store single data item - * 1111 1000 xxx0 xxxx xxxx xxxx xxxx xxxx - * Load single data items - * 1111 100x xxx1 xxxx xxxx xxxx xxxx xxxx - */ - DECODE_TABLE (0xfe000000, 0xf8000000, t32_table_1111_100x), - - /* - * Data-processing (register) - * 1111 1010 xxxx xxxx 1111 xxxx xxxx xxxx - */ - DECODE_TABLE (0xff00f000, 0xfa00f000, t32_table_1111_1010___1111), - - /* - * Multiply, multiply accumulate, and absolute difference - * 1111 1011 0xxx xxxx xxxx xxxx xxxx xxxx - */ - DECODE_TABLE (0xff800000, 0xfb000000, t32_table_1111_1011_0), - - /* - * Long multiply, long multiply accumulate, and divide - * 1111 1011 1xxx xxxx xxxx xxxx xxxx xxxx - */ - DECODE_TABLE (0xff800000, 0xfb800000, t32_table_1111_1011_1), - - /* - * Coprocessor instructions - * 1111 11xx xxxx xxxx xxxx xxxx xxxx xxxx - */ - DECODE_END -}; -#ifdef CONFIG_ARM_KPROBES_TEST_MODULE -EXPORT_SYMBOL_GPL(kprobe_decode_thumb32_table); -#endif - -static void __kprobes -t16_simulate_bxblx(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - unsigned long pc = thumb_probe_pc(p); - int rm = (insn >> 3) & 0xf; - unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm]; - - if (insn & (1 << 7)) /* BLX ? */ - regs->ARM_lr = (unsigned long)p->addr + 2; - - bx_write_pc(rmv, regs); -} - -static void __kprobes -t16_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - unsigned long* base = (unsigned long *)(thumb_probe_pc(p) & ~3); - long index = insn & 0xff; - int rt = (insn >> 8) & 0x7; - regs->uregs[rt] = base[index]; -} - -static void __kprobes -t16_simulate_ldrstr_sp_relative(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - unsigned long* base = (unsigned long *)regs->ARM_sp; - long index = insn & 0xff; - int rt = (insn >> 8) & 0x7; - if (insn & 0x800) /* LDR */ - regs->uregs[rt] = base[index]; - else /* STR */ - base[index] = regs->uregs[rt]; -} - -static void __kprobes -t16_simulate_reladr(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - unsigned long base = (insn & 0x800) ? regs->ARM_sp - : (thumb_probe_pc(p) & ~3); - long offset = insn & 0xff; - int rt = (insn >> 8) & 0x7; - regs->uregs[rt] = base + offset * 4; -} - -static void __kprobes -t16_simulate_add_sp_imm(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - long imm = insn & 0x7f; - if (insn & 0x80) /* SUB */ - regs->ARM_sp -= imm * 4; - else /* ADD */ - regs->ARM_sp += imm * 4; -} - -static void __kprobes -t16_simulate_cbz(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - int rn = insn & 0x7; - kprobe_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn; - if (nonzero & 0x800) { - long i = insn & 0x200; - long imm5 = insn & 0xf8; - unsigned long pc = thumb_probe_pc(p); - regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2); - } -} - -static void __kprobes -t16_simulate_it(struct kprobe *p, struct pt_regs *regs) -{ - /* - * The 8 IT state bits are split into two parts in CPSR: - * ITSTATE<1:0> are in CPSR<26:25> - * ITSTATE<7:2> are in CPSR<15:10> - * The new IT state is in the lower byte of insn. - */ - kprobe_opcode_t insn = p->opcode; - unsigned long cpsr = regs->ARM_cpsr; - cpsr &= ~PSR_IT_MASK; - cpsr |= (insn & 0xfc) << 8; - cpsr |= (insn & 0x03) << 25; - regs->ARM_cpsr = cpsr; -} - -static void __kprobes -t16_singlestep_it(struct kprobe *p, struct pt_regs *regs) -{ - regs->ARM_pc += 2; - t16_simulate_it(p, regs); -} - -static enum kprobe_insn __kprobes -t16_decode_it(kprobe_opcode_t insn, struct arch_specific_insn *asi) -{ - asi->insn_singlestep = t16_singlestep_it; - return INSN_GOOD_NO_SLOT; -} - -static void __kprobes -t16_simulate_cond_branch(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - unsigned long pc = thumb_probe_pc(p); - long offset = insn & 0x7f; - offset -= insn & 0x80; /* Apply sign bit */ - regs->ARM_pc = pc + (offset * 2); -} - -static enum kprobe_insn __kprobes -t16_decode_cond_branch(kprobe_opcode_t insn, struct arch_specific_insn *asi) -{ - int cc = (insn >> 8) & 0xf; - asi->insn_check_cc = kprobe_condition_checks[cc]; - asi->insn_handler = t16_simulate_cond_branch; - return INSN_GOOD_NO_SLOT; -} - -static void __kprobes -t16_simulate_branch(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - unsigned long pc = thumb_probe_pc(p); - long offset = insn & 0x3ff; - offset -= insn & 0x400; /* Apply sign bit */ - regs->ARM_pc = pc + (offset * 2); -} - -static unsigned long __kprobes -t16_emulate_loregs(struct kprobe *p, struct pt_regs *regs) -{ - unsigned long oldcpsr = regs->ARM_cpsr; - unsigned long newcpsr; - - __asm__ __volatile__ ( - "msr cpsr_fs, %[oldcpsr] \n\t" - "ldmia %[regs], {r0-r7} \n\t" - "blx %[fn] \n\t" - "stmia %[regs], {r0-r7} \n\t" - "mrs %[newcpsr], cpsr \n\t" - : [newcpsr] "=r" (newcpsr) - : [oldcpsr] "r" (oldcpsr), [regs] "r" (regs), - [fn] "r" (p->ainsn.insn_fn) - : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "lr", "memory", "cc" - ); - - return (oldcpsr & ~APSR_MASK) | (newcpsr & APSR_MASK); -} - -static void __kprobes -t16_emulate_loregs_rwflags(struct kprobe *p, struct pt_regs *regs) -{ - regs->ARM_cpsr = t16_emulate_loregs(p, regs); -} - -static void __kprobes -t16_emulate_loregs_noitrwflags(struct kprobe *p, struct pt_regs *regs) -{ - unsigned long cpsr = t16_emulate_loregs(p, regs); - if (!in_it_block(cpsr)) - regs->ARM_cpsr = cpsr; -} - -static void __kprobes -t16_emulate_hiregs(struct kprobe *p, struct pt_regs *regs) -{ - kprobe_opcode_t insn = p->opcode; - unsigned long pc = thumb_probe_pc(p); - int rdn = (insn & 0x7) | ((insn & 0x80) >> 4); - int rm = (insn >> 3) & 0xf; - - register unsigned long rdnv asm("r1"); - register unsigned long rmv asm("r0"); - unsigned long cpsr = regs->ARM_cpsr; - - rdnv = (rdn == 15) ? pc : regs->uregs[rdn]; - rmv = (rm == 15) ? pc : regs->uregs[rm]; - - __asm__ __volatile__ ( - "msr cpsr_fs, %[cpsr] \n\t" - "blx %[fn] \n\t" - "mrs %[cpsr], cpsr \n\t" - : "=r" (rdnv), [cpsr] "=r" (cpsr) - : "0" (rdnv), "r" (rmv), "1" (cpsr), [fn] "r" (p->ainsn.insn_fn) - : "lr", "memory", "cc" - ); - - if (rdn == 15) - rdnv &= ~1; - - regs->uregs[rdn] = rdnv; - regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); -} - -static enum kprobe_insn __kprobes -t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi) -{ - insn &= ~0x00ff; - insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */ - ((u16 *)asi->insn)[0] = insn; - asi->insn_handler = t16_emulate_hiregs; - return INSN_GOOD; -} - -static void __kprobes -t16_emulate_push(struct kprobe *p, struct pt_regs *regs) -{ - __asm__ __volatile__ ( - "ldr r9, [%[regs], #13*4] \n\t" - "ldr r8, [%[regs], #14*4] \n\t" - "ldmia %[regs], {r0-r7} \n\t" - "blx %[fn] \n\t" - "str r9, [%[regs], #13*4] \n\t" - : - : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn) - : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", - "lr", "memory", "cc" - ); -} - -static enum kprobe_insn __kprobes -t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi) -{ - /* - * To simulate a PUSH we use a Thumb-2 "STMDB R9!, {registers}" - * and call it with R9=SP and LR in the register list represented - * by R8. - */ - ((u16 *)asi->insn)[0] = 0xe929; /* 1st half STMDB R9!,{} */ - ((u16 *)asi->insn)[1] = insn & 0x1ff; /* 2nd half (register list) */ - asi->insn_handler = t16_emulate_push; - return INSN_GOOD; -} - -static void __kprobes -t16_emulate_pop_nopc(struct kprobe *p, struct pt_regs *regs) -{ - __asm__ __volatile__ ( - "ldr r9, [%[regs], #13*4] \n\t" - "ldmia %[regs], {r0-r7} \n\t" - "blx %[fn] \n\t" - "stmia %[regs], {r0-r7} \n\t" - "str r9, [%[regs], #13*4] \n\t" - : - : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn) - : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", - "lr", "memory", "cc" - ); -} - -static void __kprobes -t16_emulate_pop_pc(struct kprobe *p, struct pt_regs *regs) -{ - register unsigned long pc asm("r8"); - - __asm__ __volatile__ ( - "ldr r9, [%[regs], #13*4] \n\t" - "ldmia %[regs], {r0-r7} \n\t" - "blx %[fn] \n\t" - "stmia %[regs], {r0-r7} \n\t" - "str r9, [%[regs], #13*4] \n\t" - : "=r" (pc) - : [regs] "r" (regs), [fn] "r" (p->ainsn.insn_fn) - : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", - "lr", "memory", "cc" - ); - - bx_write_pc(pc, regs); -} - -static enum kprobe_insn __kprobes -t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi) -{ - /* - * To simulate a POP we use a Thumb-2 "LDMDB R9!, {registers}" - * and call it with R9=SP and PC in the register list represented - * by R8. - */ - ((u16 *)asi->insn)[0] = 0xe8b9; /* 1st half LDMIA R9!,{} */ - ((u16 *)asi->insn)[1] = insn & 0x1ff; /* 2nd half (register list) */ - asi->insn_handler = insn & 0x100 ? t16_emulate_pop_pc - : t16_emulate_pop_nopc; - return INSN_GOOD; -} - -static const union decode_item t16_table_1011[] = { - /* Miscellaneous 16-bit instructions */ - - /* ADD (SP plus immediate) 1011 0000 0xxx xxxx */ - /* SUB (SP minus immediate) 1011 0000 1xxx xxxx */ - DECODE_SIMULATE (0xff00, 0xb000, t16_simulate_add_sp_imm), - - /* CBZ 1011 00x1 xxxx xxxx */ - /* CBNZ 1011 10x1 xxxx xxxx */ - DECODE_SIMULATE (0xf500, 0xb100, t16_simulate_cbz), - - /* SXTH 1011 0010 00xx xxxx */ - /* SXTB 1011 0010 01xx xxxx */ - /* UXTH 1011 0010 10xx xxxx */ - /* UXTB 1011 0010 11xx xxxx */ - /* REV 1011 1010 00xx xxxx */ - /* REV16 1011 1010 01xx xxxx */ - /* ??? 1011 1010 10xx xxxx */ - /* REVSH 1011 1010 11xx xxxx */ - DECODE_REJECT (0xffc0, 0xba80), - DECODE_EMULATE (0xf500, 0xb000, t16_emulate_loregs_rwflags), - - /* PUSH 1011 010x xxxx xxxx */ - DECODE_CUSTOM (0xfe00, 0xb400, t16_decode_push), - /* POP 1011 110x xxxx xxxx */ - DECODE_CUSTOM (0xfe00, 0xbc00, t16_decode_pop), - - /* - * If-Then, and hints - * 1011 1111 xxxx xxxx - */ - - /* YIELD 1011 1111 0001 0000 */ - DECODE_OR (0xffff, 0xbf10), - /* SEV 1011 1111 0100 0000 */ - DECODE_EMULATE (0xffff, 0xbf40, kprobe_emulate_none), - /* NOP 1011 1111 0000 0000 */ - /* WFE 1011 1111 0010 0000 */ - /* WFI 1011 1111 0011 0000 */ - DECODE_SIMULATE (0xffcf, 0xbf00, kprobe_simulate_nop), - /* Unassigned hints 1011 1111 xxxx 0000 */ - DECODE_REJECT (0xff0f, 0xbf00), - /* IT 1011 1111 xxxx xxxx */ - DECODE_CUSTOM (0xff00, 0xbf00, t16_decode_it), - - /* SETEND 1011 0110 010x xxxx */ - /* CPS 1011 0110 011x xxxx */ - /* BKPT 1011 1110 xxxx xxxx */ - /* And unallocated instructions... */ - DECODE_END -}; - -const union decode_item kprobe_decode_thumb16_table[] = { - - /* - * Shift (immediate), add, subtract, move, and compare - * 00xx xxxx xxxx xxxx - */ - - /* CMP (immediate) 0010 1xxx xxxx xxxx */ - DECODE_EMULATE (0xf800, 0x2800, t16_emulate_loregs_rwflags), - - /* ADD (register) 0001 100x xxxx xxxx */ - /* SUB (register) 0001 101x xxxx xxxx */ - /* LSL (immediate) 0000 0xxx xxxx xxxx */ - /* LSR (immediate) 0000 1xxx xxxx xxxx */ - /* ASR (immediate) 0001 0xxx xxxx xxxx */ - /* ADD (immediate, Thumb) 0001 110x xxxx xxxx */ - /* SUB (immediate, Thumb) 0001 111x xxxx xxxx */ - /* MOV (immediate) 0010 0xxx xxxx xxxx */ - /* ADD (immediate, Thumb) 0011 0xxx xxxx xxxx */ - /* SUB (immediate, Thumb) 0011 1xxx xxxx xxxx */ - DECODE_EMULATE (0xc000, 0x0000, t16_emulate_loregs_noitrwflags), - - /* - * 16-bit Thumb data-processing instructions - * 0100 00xx xxxx xxxx - */ - - /* TST (register) 0100 0010 00xx xxxx */ - DECODE_EMULATE (0xffc0, 0x4200, t16_emulate_loregs_rwflags), - /* CMP (register) 0100 0010 10xx xxxx */ - /* CMN (register) 0100 0010 11xx xxxx */ - DECODE_EMULATE (0xff80, 0x4280, t16_emulate_loregs_rwflags), - /* AND (register) 0100 0000 00xx xxxx */ - /* EOR (register) 0100 0000 01xx xxxx */ - /* LSL (register) 0100 0000 10xx xxxx */ - /* LSR (register) 0100 0000 11xx xxxx */ - /* ASR (register) 0100 0001 00xx xxxx */ - /* ADC (register) 0100 0001 01xx xxxx */ - /* SBC (register) 0100 0001 10xx xxxx */ - /* ROR (register) 0100 0001 11xx xxxx */ - /* RSB (immediate) 0100 0010 01xx xxxx */ - /* ORR (register) 0100 0011 00xx xxxx */ - /* MUL 0100 0011 00xx xxxx */ - /* BIC (register) 0100 0011 10xx xxxx */ - /* MVN (register) 0100 0011 10xx xxxx */ - DECODE_EMULATE (0xfc00, 0x4000, t16_emulate_loregs_noitrwflags), - - /* - * Special data instructions and branch and exchange - * 0100 01xx xxxx xxxx - */ - - /* BLX pc 0100 0111 1111 1xxx */ - DECODE_REJECT (0xfff8, 0x47f8), - - /* BX (register) 0100 0111 0xxx xxxx */ - /* BLX (register) 0100 0111 1xxx xxxx */ - DECODE_SIMULATE (0xff00, 0x4700, t16_simulate_bxblx), - - /* ADD pc, pc 0100 0100 1111 1111 */ - DECODE_REJECT (0xffff, 0x44ff), - - /* ADD (register) 0100 0100 xxxx xxxx */ - /* CMP (register) 0100 0101 xxxx xxxx */ - /* MOV (register) 0100 0110 xxxx xxxx */ - DECODE_CUSTOM (0xfc00, 0x4400, t16_decode_hiregs), - - /* - * Load from Literal Pool - * LDR (literal) 0100 1xxx xxxx xxxx - */ - DECODE_SIMULATE (0xf800, 0x4800, t16_simulate_ldr_literal), - - /* - * 16-bit Thumb Load/store instructions - * 0101 xxxx xxxx xxxx - * 011x xxxx xxxx xxxx - * 100x xxxx xxxx xxxx - */ - - /* STR (register) 0101 000x xxxx xxxx */ - /* STRH (register) 0101 001x xxxx xxxx */ - /* STRB (register) 0101 010x xxxx xxxx */ - /* LDRSB (register) 0101 011x xxxx xxxx */ - /* LDR (register) 0101 100x xxxx xxxx */ - /* LDRH (register) 0101 101x xxxx xxxx */ - /* LDRB (register) 0101 110x xxxx xxxx */ - /* LDRSH (register) 0101 111x xxxx xxxx */ - /* STR (immediate, Thumb) 0110 0xxx xxxx xxxx */ - /* LDR (immediate, Thumb) 0110 1xxx xxxx xxxx */ - /* STRB (immediate, Thumb) 0111 0xxx xxxx xxxx */ - /* LDRB (immediate, Thumb) 0111 1xxx xxxx xxxx */ - DECODE_EMULATE (0xc000, 0x4000, t16_emulate_loregs_rwflags), - /* STRH (immediate, Thumb) 1000 0xxx xxxx xxxx */ - /* LDRH (immediate, Thumb) 1000 1xxx xxxx xxxx */ - DECODE_EMULATE (0xf000, 0x8000, t16_emulate_loregs_rwflags), - /* STR (immediate, Thumb) 1001 0xxx xxxx xxxx */ - /* LDR (immediate, Thumb) 1001 1xxx xxxx xxxx */ - DECODE_SIMULATE (0xf000, 0x9000, t16_simulate_ldrstr_sp_relative), - - /* - * Generate PC-/SP-relative address - * ADR (literal) 1010 0xxx xxxx xxxx - * ADD (SP plus immediate) 1010 1xxx xxxx xxxx - */ - DECODE_SIMULATE (0xf000, 0xa000, t16_simulate_reladr), - - /* - * Miscellaneous 16-bit instructions - * 1011 xxxx xxxx xxxx - */ - DECODE_TABLE (0xf000, 0xb000, t16_table_1011), - - /* STM 1100 0xxx xxxx xxxx */ - /* LDM 1100 1xxx xxxx xxxx */ - DECODE_EMULATE (0xf000, 0xc000, t16_emulate_loregs_rwflags), - - /* - * Conditional branch, and Supervisor Call - */ - - /* Permanently UNDEFINED 1101 1110 xxxx xxxx */ - /* SVC 1101 1111 xxxx xxxx */ - DECODE_REJECT (0xfe00, 0xde00), - - /* Conditional branch 1101 xxxx xxxx xxxx */ - DECODE_CUSTOM (0xf000, 0xd000, t16_decode_cond_branch), - - /* - * Unconditional branch - * B 1110 0xxx xxxx xxxx - */ - DECODE_SIMULATE (0xf800, 0xe000, t16_simulate_branch), - - DECODE_END -}; -#ifdef CONFIG_ARM_KPROBES_TEST_MODULE -EXPORT_SYMBOL_GPL(kprobe_decode_thumb16_table); -#endif - -static unsigned long __kprobes thumb_check_cc(unsigned long cpsr) -{ - if (unlikely(in_it_block(cpsr))) - return kprobe_condition_checks[current_cond(cpsr)](cpsr); - return true; -} - -static void __kprobes thumb16_singlestep(struct kprobe *p, struct pt_regs *regs) -{ - regs->ARM_pc += 2; - p->ainsn.insn_handler(p, regs); - regs->ARM_cpsr = it_advance(regs->ARM_cpsr); -} - -static void __kprobes thumb32_singlestep(struct kprobe *p, struct pt_regs *regs) -{ - regs->ARM_pc += 4; - p->ainsn.insn_handler(p, regs); - regs->ARM_cpsr = it_advance(regs->ARM_cpsr); -} - -enum kprobe_insn __kprobes -thumb16_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) -{ - asi->insn_singlestep = thumb16_singlestep; - asi->insn_check_cc = thumb_check_cc; - return kprobe_decode_insn(insn, asi, kprobe_decode_thumb16_table, true); -} - -enum kprobe_insn __kprobes -thumb32_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi) -{ - asi->insn_singlestep = thumb32_singlestep; - asi->insn_check_cc = thumb_check_cc; - return kprobe_decode_insn(insn, asi, kprobe_decode_thumb32_table, true); -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/kprobes.c b/ANDROID_3.4.5/arch/arm/kernel/kprobes.c deleted file mode 100644 index 4dd41fc9..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/kprobes.c +++ /dev/null @@ -1,618 +0,0 @@ -/* - * arch/arm/kernel/kprobes.c - * - * Kprobes on ARM - * - * Abhishek Sagar <sagar.abhishek@gmail.com> - * Copyright (C) 2006, 2007 Motorola Inc. - * - * Nicolas Pitre <nico@marvell.com> - * Copyright (C) 2007 Marvell Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ - -#include <linux/kernel.h> -#include <linux/kprobes.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/stop_machine.h> -#include <linux/stringify.h> -#include <asm/traps.h> -#include <asm/cacheflush.h> - -#include "kprobes.h" -#include "patch.h" - -#define MIN_STACK_SIZE(addr) \ - min((unsigned long)MAX_STACK_SIZE, \ - (unsigned long)current_thread_info() + THREAD_START_SP - (addr)) - -#define flush_insns(addr, size) \ - flush_icache_range((unsigned long)(addr), \ - (unsigned long)(addr) + \ - (size)) - -/* Used as a marker in ARM_pc to note when we're in a jprobe. */ -#define JPROBE_MAGIC_ADDR 0xffffffff - -DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; -DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); - - -int __kprobes arch_prepare_kprobe(struct kprobe *p) -{ - kprobe_opcode_t insn; - kprobe_opcode_t tmp_insn[MAX_INSN_SIZE]; - unsigned long addr = (unsigned long)p->addr; - bool thumb; - kprobe_decode_insn_t *decode_insn; - int is; - - if (in_exception_text(addr)) - return -EINVAL; - -#ifdef CONFIG_THUMB2_KERNEL - thumb = true; - addr &= ~1; /* Bit 0 would normally be set to indicate Thumb code */ - insn = ((u16 *)addr)[0]; - if (is_wide_instruction(insn)) { - insn <<= 16; - insn |= ((u16 *)addr)[1]; - decode_insn = thumb32_kprobe_decode_insn; - } else - decode_insn = thumb16_kprobe_decode_insn; -#else /* !CONFIG_THUMB2_KERNEL */ - thumb = false; - if (addr & 0x3) - return -EINVAL; - insn = *p->addr; - decode_insn = arm_kprobe_decode_insn; -#endif - - p->opcode = insn; - p->ainsn.insn = tmp_insn; - - switch ((*decode_insn)(insn, &p->ainsn)) { - case INSN_REJECTED: /* not supported */ - return -EINVAL; - - case INSN_GOOD: /* instruction uses slot */ - p->ainsn.insn = get_insn_slot(); - if (!p->ainsn.insn) - return -ENOMEM; - for (is = 0; is < MAX_INSN_SIZE; ++is) - p->ainsn.insn[is] = tmp_insn[is]; - flush_insns(p->ainsn.insn, - sizeof(p->ainsn.insn[0]) * MAX_INSN_SIZE); - p->ainsn.insn_fn = (kprobe_insn_fn_t *) - ((uintptr_t)p->ainsn.insn | thumb); - break; - - case INSN_GOOD_NO_SLOT: /* instruction doesn't need insn slot */ - p->ainsn.insn = NULL; - break; - } - - return 0; -} - -void __kprobes arch_arm_kprobe(struct kprobe *p) -{ - unsigned int brkp; - void *addr; - - if (IS_ENABLED(CONFIG_THUMB2_KERNEL)) { - /* Remove any Thumb flag */ - addr = (void *)((uintptr_t)p->addr & ~1); - - if (is_wide_instruction(p->opcode)) - brkp = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION; - else - brkp = KPROBE_THUMB16_BREAKPOINT_INSTRUCTION; - } else { - kprobe_opcode_t insn = p->opcode; - - addr = p->addr; - brkp = KPROBE_ARM_BREAKPOINT_INSTRUCTION; - - if (insn >= 0xe0000000) - brkp |= 0xe0000000; /* Unconditional instruction */ - else - brkp |= insn & 0xf0000000; /* Copy condition from insn */ - } - - patch_text(addr, brkp); -} - -/* - * The actual disarming is done here on each CPU and synchronized using - * stop_machine. This synchronization is necessary on SMP to avoid removing - * a probe between the moment the 'Undefined Instruction' exception is raised - * and the moment the exception handler reads the faulting instruction from - * memory. It is also needed to atomically set the two half-words of a 32-bit - * Thumb breakpoint. - */ -int __kprobes __arch_disarm_kprobe(void *p) -{ - struct kprobe *kp = p; - void *addr = (void *)((uintptr_t)kp->addr & ~1); - - __patch_text(addr, kp->opcode); - - return 0; -} - -void __kprobes arch_disarm_kprobe(struct kprobe *p) -{ - stop_machine(__arch_disarm_kprobe, p, cpu_online_mask); -} - -void __kprobes arch_remove_kprobe(struct kprobe *p) -{ - if (p->ainsn.insn) { - free_insn_slot(p->ainsn.insn, 0); - p->ainsn.insn = NULL; - } -} - -static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb) -{ - kcb->prev_kprobe.kp = kprobe_running(); - kcb->prev_kprobe.status = kcb->kprobe_status; -} - -static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb) -{ - __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; - kcb->kprobe_status = kcb->prev_kprobe.status; -} - -static void __kprobes set_current_kprobe(struct kprobe *p) -{ - __get_cpu_var(current_kprobe) = p; -} - -static void __kprobes -singlestep_skip(struct kprobe *p, struct pt_regs *regs) -{ -#ifdef CONFIG_THUMB2_KERNEL - regs->ARM_cpsr = it_advance(regs->ARM_cpsr); - if (is_wide_instruction(p->opcode)) - regs->ARM_pc += 4; - else - regs->ARM_pc += 2; -#else - regs->ARM_pc += 4; -#endif -} - -static inline void __kprobes -singlestep(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb) -{ - p->ainsn.insn_singlestep(p, regs); -} - -/* - * Called with IRQs disabled. IRQs must remain disabled from that point - * all the way until processing this kprobe is complete. The current - * kprobes implementation cannot process more than one nested level of - * kprobe, and that level is reserved for user kprobe handlers, so we can't - * risk encountering a new kprobe in an interrupt handler. - */ -void __kprobes kprobe_handler(struct pt_regs *regs) -{ - struct kprobe *p, *cur; - struct kprobe_ctlblk *kcb; - - kcb = get_kprobe_ctlblk(); - cur = kprobe_running(); - -#ifdef CONFIG_THUMB2_KERNEL - /* - * First look for a probe which was registered using an address with - * bit 0 set, this is the usual situation for pointers to Thumb code. - * If not found, fallback to looking for one with bit 0 clear. - */ - p = get_kprobe((kprobe_opcode_t *)(regs->ARM_pc | 1)); - if (!p) - p = get_kprobe((kprobe_opcode_t *)regs->ARM_pc); - -#else /* ! CONFIG_THUMB2_KERNEL */ - p = get_kprobe((kprobe_opcode_t *)regs->ARM_pc); -#endif - - if (p) { - if (cur) { - /* Kprobe is pending, so we're recursing. */ - switch (kcb->kprobe_status) { - case KPROBE_HIT_ACTIVE: - case KPROBE_HIT_SSDONE: - /* A pre- or post-handler probe got us here. */ - kprobes_inc_nmissed_count(p); - save_previous_kprobe(kcb); - set_current_kprobe(p); - kcb->kprobe_status = KPROBE_REENTER; - singlestep(p, regs, kcb); - restore_previous_kprobe(kcb); - break; - default: - /* impossible cases */ - BUG(); - } - } else if (p->ainsn.insn_check_cc(regs->ARM_cpsr)) { - /* Probe hit and conditional execution check ok. */ - set_current_kprobe(p); - kcb->kprobe_status = KPROBE_HIT_ACTIVE; - - /* - * If we have no pre-handler or it returned 0, we - * continue with normal processing. If we have a - * pre-handler and it returned non-zero, it prepped - * for calling the break_handler below on re-entry, - * so get out doing nothing more here. - */ - if (!p->pre_handler || !p->pre_handler(p, regs)) { - kcb->kprobe_status = KPROBE_HIT_SS; - singlestep(p, regs, kcb); - if (p->post_handler) { - kcb->kprobe_status = KPROBE_HIT_SSDONE; - p->post_handler(p, regs, 0); - } - reset_current_kprobe(); - } - } else { - /* - * Probe hit but conditional execution check failed, - * so just skip the instruction and continue as if - * nothing had happened. - */ - singlestep_skip(p, regs); - } - } else if (cur) { - /* We probably hit a jprobe. Call its break handler. */ - if (cur->break_handler && cur->break_handler(cur, regs)) { - kcb->kprobe_status = KPROBE_HIT_SS; - singlestep(cur, regs, kcb); - if (cur->post_handler) { - kcb->kprobe_status = KPROBE_HIT_SSDONE; - cur->post_handler(cur, regs, 0); - } - } - reset_current_kprobe(); - } else { - /* - * The probe was removed and a race is in progress. - * There is nothing we can do about it. Let's restart - * the instruction. By the time we can restart, the - * real instruction will be there. - */ - } -} - -static int __kprobes kprobe_trap_handler(struct pt_regs *regs, unsigned int instr) -{ - unsigned long flags; - local_irq_save(flags); - kprobe_handler(regs); - local_irq_restore(flags); - return 0; -} - -int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr) -{ - struct kprobe *cur = kprobe_running(); - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - - switch (kcb->kprobe_status) { - case KPROBE_HIT_SS: - case KPROBE_REENTER: - /* - * We are here because the instruction being single - * stepped caused a page fault. We reset the current - * kprobe and the PC to point back to the probe address - * and allow the page fault handler to continue as a - * normal page fault. - */ - regs->ARM_pc = (long)cur->addr; - if (kcb->kprobe_status == KPROBE_REENTER) { - restore_previous_kprobe(kcb); - } else { - reset_current_kprobe(); - } - break; - - case KPROBE_HIT_ACTIVE: - case KPROBE_HIT_SSDONE: - /* - * We increment the nmissed count for accounting, - * we can also use npre/npostfault count for accounting - * these specific fault cases. - */ - kprobes_inc_nmissed_count(cur); - - /* - * We come here because instructions in the pre/post - * handler caused the page_fault, this could happen - * if handler tries to access user space by - * copy_from_user(), get_user() etc. Let the - * user-specified handler try to fix it. - */ - if (cur->fault_handler && cur->fault_handler(cur, regs, fsr)) - return 1; - break; - - default: - break; - } - - return 0; -} - -int __kprobes kprobe_exceptions_notify(struct notifier_block *self, - unsigned long val, void *data) -{ - /* - * notify_die() is currently never called on ARM, - * so this callback is currently empty. - */ - return NOTIFY_DONE; -} - -/* - * When a retprobed function returns, trampoline_handler() is called, - * calling the kretprobe's handler. We construct a struct pt_regs to - * give a view of registers r0-r11 to the user return-handler. This is - * not a complete pt_regs structure, but that should be plenty sufficient - * for kretprobe handlers which should normally be interested in r0 only - * anyway. - */ -void __naked __kprobes kretprobe_trampoline(void) -{ - __asm__ __volatile__ ( - "stmdb sp!, {r0 - r11} \n\t" - "mov r0, sp \n\t" - "bl trampoline_handler \n\t" - "mov lr, r0 \n\t" - "ldmia sp!, {r0 - r11} \n\t" -#ifdef CONFIG_THUMB2_KERNEL - "bx lr \n\t" -#else - "mov pc, lr \n\t" -#endif - : : : "memory"); -} - -/* Called from kretprobe_trampoline */ -static __used __kprobes void *trampoline_handler(struct pt_regs *regs) -{ - struct kretprobe_instance *ri = NULL; - struct hlist_head *head, empty_rp; - struct hlist_node *node, *tmp; - unsigned long flags, orig_ret_address = 0; - unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; - - INIT_HLIST_HEAD(&empty_rp); - kretprobe_hash_lock(current, &head, &flags); - - /* - * It is possible to have multiple instances associated with a given - * task either because multiple functions in the call path have - * a return probe installed on them, and/or more than one return - * probe was registered for a target function. - * - * We can handle this because: - * - instances are always inserted at the head of the list - * - when multiple return probes are registered for the same - * function, the first instance's ret_addr will point to the - * real return address, and all the rest will point to - * kretprobe_trampoline - */ - hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { - if (ri->task != current) - /* another task is sharing our hash bucket */ - continue; - - if (ri->rp && ri->rp->handler) { - __get_cpu_var(current_kprobe) = &ri->rp->kp; - get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE; - ri->rp->handler(ri, regs); - __get_cpu_var(current_kprobe) = NULL; - } - - orig_ret_address = (unsigned long)ri->ret_addr; - recycle_rp_inst(ri, &empty_rp); - - if (orig_ret_address != trampoline_address) - /* - * This is the real return address. Any other - * instances associated with this task are for - * other calls deeper on the call stack - */ - break; - } - - kretprobe_assert(ri, orig_ret_address, trampoline_address); - kretprobe_hash_unlock(current, &flags); - - hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { - hlist_del(&ri->hlist); - kfree(ri); - } - - return (void *)orig_ret_address; -} - -void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, - struct pt_regs *regs) -{ - ri->ret_addr = (kprobe_opcode_t *)regs->ARM_lr; - - /* Replace the return addr with trampoline addr. */ - regs->ARM_lr = (unsigned long)&kretprobe_trampoline; -} - -int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) -{ - struct jprobe *jp = container_of(p, struct jprobe, kp); - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - long sp_addr = regs->ARM_sp; - long cpsr; - - kcb->jprobe_saved_regs = *regs; - memcpy(kcb->jprobes_stack, (void *)sp_addr, MIN_STACK_SIZE(sp_addr)); - regs->ARM_pc = (long)jp->entry; - - cpsr = regs->ARM_cpsr | PSR_I_BIT; -#ifdef CONFIG_THUMB2_KERNEL - /* Set correct Thumb state in cpsr */ - if (regs->ARM_pc & 1) - cpsr |= PSR_T_BIT; - else - cpsr &= ~PSR_T_BIT; -#endif - regs->ARM_cpsr = cpsr; - - preempt_disable(); - return 1; -} - -void __kprobes jprobe_return(void) -{ - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - - __asm__ __volatile__ ( - /* - * Setup an empty pt_regs. Fill SP and PC fields as - * they're needed by longjmp_break_handler. - * - * We allocate some slack between the original SP and start of - * our fabricated regs. To be precise we want to have worst case - * covered which is STMFD with all 16 regs so we allocate 2 * - * sizeof(struct_pt_regs)). - * - * This is to prevent any simulated instruction from writing - * over the regs when they are accessing the stack. - */ -#ifdef CONFIG_THUMB2_KERNEL - "sub r0, %0, %1 \n\t" - "mov sp, r0 \n\t" -#else - "sub sp, %0, %1 \n\t" -#endif - "ldr r0, ="__stringify(JPROBE_MAGIC_ADDR)"\n\t" - "str %0, [sp, %2] \n\t" - "str r0, [sp, %3] \n\t" - "mov r0, sp \n\t" - "bl kprobe_handler \n\t" - - /* - * Return to the context saved by setjmp_pre_handler - * and restored by longjmp_break_handler. - */ -#ifdef CONFIG_THUMB2_KERNEL - "ldr lr, [sp, %2] \n\t" /* lr = saved sp */ - "ldrd r0, r1, [sp, %5] \n\t" /* r0,r1 = saved lr,pc */ - "ldr r2, [sp, %4] \n\t" /* r2 = saved psr */ - "stmdb lr!, {r0, r1, r2} \n\t" /* push saved lr and */ - /* rfe context */ - "ldmia sp, {r0 - r12} \n\t" - "mov sp, lr \n\t" - "ldr lr, [sp], #4 \n\t" - "rfeia sp! \n\t" -#else - "ldr r0, [sp, %4] \n\t" - "msr cpsr_cxsf, r0 \n\t" - "ldmia sp, {r0 - pc} \n\t" -#endif - : - : "r" (kcb->jprobe_saved_regs.ARM_sp), - "I" (sizeof(struct pt_regs) * 2), - "J" (offsetof(struct pt_regs, ARM_sp)), - "J" (offsetof(struct pt_regs, ARM_pc)), - "J" (offsetof(struct pt_regs, ARM_cpsr)), - "J" (offsetof(struct pt_regs, ARM_lr)) - : "memory", "cc"); -} - -int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) -{ - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - long stack_addr = kcb->jprobe_saved_regs.ARM_sp; - long orig_sp = regs->ARM_sp; - struct jprobe *jp = container_of(p, struct jprobe, kp); - - if (regs->ARM_pc == JPROBE_MAGIC_ADDR) { - if (orig_sp != stack_addr) { - struct pt_regs *saved_regs = - (struct pt_regs *)kcb->jprobe_saved_regs.ARM_sp; - printk("current sp %lx does not match saved sp %lx\n", - orig_sp, stack_addr); - printk("Saved registers for jprobe %p\n", jp); - show_regs(saved_regs); - printk("Current registers\n"); - show_regs(regs); - BUG(); - } - *regs = kcb->jprobe_saved_regs; - memcpy((void *)stack_addr, kcb->jprobes_stack, - MIN_STACK_SIZE(stack_addr)); - preempt_enable_no_resched(); - return 1; - } - return 0; -} - -int __kprobes arch_trampoline_kprobe(struct kprobe *p) -{ - return 0; -} - -#ifdef CONFIG_THUMB2_KERNEL - -static struct undef_hook kprobes_thumb16_break_hook = { - .instr_mask = 0xffff, - .instr_val = KPROBE_THUMB16_BREAKPOINT_INSTRUCTION, - .cpsr_mask = MODE_MASK, - .cpsr_val = SVC_MODE, - .fn = kprobe_trap_handler, -}; - -static struct undef_hook kprobes_thumb32_break_hook = { - .instr_mask = 0xffffffff, - .instr_val = KPROBE_THUMB32_BREAKPOINT_INSTRUCTION, - .cpsr_mask = MODE_MASK, - .cpsr_val = SVC_MODE, - .fn = kprobe_trap_handler, -}; - -#else /* !CONFIG_THUMB2_KERNEL */ - -static struct undef_hook kprobes_arm_break_hook = { - .instr_mask = 0x0fffffff, - .instr_val = KPROBE_ARM_BREAKPOINT_INSTRUCTION, - .cpsr_mask = MODE_MASK, - .cpsr_val = SVC_MODE, - .fn = kprobe_trap_handler, -}; - -#endif /* !CONFIG_THUMB2_KERNEL */ - -int __init arch_init_kprobes() -{ - arm_kprobe_decode_init(); -#ifdef CONFIG_THUMB2_KERNEL - register_undef_hook(&kprobes_thumb16_break_hook); - register_undef_hook(&kprobes_thumb32_break_hook); -#else - register_undef_hook(&kprobes_arm_break_hook); -#endif - return 0; -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/kprobes.h b/ANDROID_3.4.5/arch/arm/kernel/kprobes.h deleted file mode 100644 index 38945f78..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/kprobes.h +++ /dev/null @@ -1,428 +0,0 @@ -/* - * arch/arm/kernel/kprobes.h - * - * Copyright (C) 2011 Jon Medhurst <tixy@yxit.co.uk>. - * - * Some contents moved here from arch/arm/include/asm/kprobes.h which is - * Copyright (C) 2006, 2007 Motorola Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ - -#ifndef _ARM_KERNEL_KPROBES_H -#define _ARM_KERNEL_KPROBES_H - -/* - * These undefined instructions must be unique and - * reserved solely for kprobes' use. - */ -#define KPROBE_ARM_BREAKPOINT_INSTRUCTION 0x07f001f8 -#define KPROBE_THUMB16_BREAKPOINT_INSTRUCTION 0xde18 -#define KPROBE_THUMB32_BREAKPOINT_INSTRUCTION 0xf7f0a018 - - -enum kprobe_insn { - INSN_REJECTED, - INSN_GOOD, - INSN_GOOD_NO_SLOT -}; - -typedef enum kprobe_insn (kprobe_decode_insn_t)(kprobe_opcode_t, - struct arch_specific_insn *); - -#ifdef CONFIG_THUMB2_KERNEL - -enum kprobe_insn thumb16_kprobe_decode_insn(kprobe_opcode_t, - struct arch_specific_insn *); -enum kprobe_insn thumb32_kprobe_decode_insn(kprobe_opcode_t, - struct arch_specific_insn *); - -#else /* !CONFIG_THUMB2_KERNEL */ - -enum kprobe_insn arm_kprobe_decode_insn(kprobe_opcode_t, - struct arch_specific_insn *); -#endif - -void __init arm_kprobe_decode_init(void); - -extern kprobe_check_cc * const kprobe_condition_checks[16]; - - -#if __LINUX_ARM_ARCH__ >= 7 - -/* str_pc_offset is architecturally defined from ARMv7 onwards */ -#define str_pc_offset 8 -#define find_str_pc_offset() - -#else /* __LINUX_ARM_ARCH__ < 7 */ - -/* We need a run-time check to determine str_pc_offset */ -extern int str_pc_offset; -void __init find_str_pc_offset(void); - -#endif - - -/* - * Update ITSTATE after normal execution of an IT block instruction. - * - * The 8 IT state bits are split into two parts in CPSR: - * ITSTATE<1:0> are in CPSR<26:25> - * ITSTATE<7:2> are in CPSR<15:10> - */ -static inline unsigned long it_advance(unsigned long cpsr) - { - if ((cpsr & 0x06000400) == 0) { - /* ITSTATE<2:0> == 0 means end of IT block, so clear IT state */ - cpsr &= ~PSR_IT_MASK; - } else { - /* We need to shift left ITSTATE<4:0> */ - const unsigned long mask = 0x06001c00; /* Mask ITSTATE<4:0> */ - unsigned long it = cpsr & mask; - it <<= 1; - it |= it >> (27 - 10); /* Carry ITSTATE<2> to correct place */ - it &= mask; - cpsr &= ~mask; - cpsr |= it; - } - return cpsr; -} - -static inline void __kprobes bx_write_pc(long pcv, struct pt_regs *regs) -{ - long cpsr = regs->ARM_cpsr; - if (pcv & 0x1) { - cpsr |= PSR_T_BIT; - pcv &= ~0x1; - } else { - cpsr &= ~PSR_T_BIT; - pcv &= ~0x2; /* Avoid UNPREDICTABLE address allignment */ - } - regs->ARM_cpsr = cpsr; - regs->ARM_pc = pcv; -} - - -#if __LINUX_ARM_ARCH__ >= 6 - -/* Kernels built for >= ARMv6 should never run on <= ARMv5 hardware, so... */ -#define load_write_pc_interworks true -#define test_load_write_pc_interworking() - -#else /* __LINUX_ARM_ARCH__ < 6 */ - -/* We need run-time testing to determine if load_write_pc() should interwork. */ -extern bool load_write_pc_interworks; -void __init test_load_write_pc_interworking(void); - -#endif - -static inline void __kprobes load_write_pc(long pcv, struct pt_regs *regs) -{ - if (load_write_pc_interworks) - bx_write_pc(pcv, regs); - else - regs->ARM_pc = pcv; -} - - -#if __LINUX_ARM_ARCH__ >= 7 - -#define alu_write_pc_interworks true -#define test_alu_write_pc_interworking() - -#elif __LINUX_ARM_ARCH__ <= 5 - -/* Kernels built for <= ARMv5 should never run on >= ARMv6 hardware, so... */ -#define alu_write_pc_interworks false -#define test_alu_write_pc_interworking() - -#else /* __LINUX_ARM_ARCH__ == 6 */ - -/* We could be an ARMv6 binary on ARMv7 hardware so we need a run-time check. */ -extern bool alu_write_pc_interworks; -void __init test_alu_write_pc_interworking(void); - -#endif /* __LINUX_ARM_ARCH__ == 6 */ - -static inline void __kprobes alu_write_pc(long pcv, struct pt_regs *regs) -{ - if (alu_write_pc_interworks) - bx_write_pc(pcv, regs); - else - regs->ARM_pc = pcv; -} - - -void __kprobes kprobe_simulate_nop(struct kprobe *p, struct pt_regs *regs); -void __kprobes kprobe_emulate_none(struct kprobe *p, struct pt_regs *regs); - -enum kprobe_insn __kprobes -kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi); - -/* - * Test if load/store instructions writeback the address register. - * if P (bit 24) == 0 or W (bit 21) == 1 - */ -#define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000) - -/* - * The following definitions and macros are used to build instruction - * decoding tables for use by kprobe_decode_insn. - * - * These tables are a concatenation of entries each of which consist of one of - * the decode_* structs. All of the fields in every type of decode structure - * are of the union type decode_item, therefore the entire decode table can be - * viewed as an array of these and declared like: - * - * static const union decode_item table_name[] = {}; - * - * In order to construct each entry in the table, macros are used to - * initialise a number of sequential decode_item values in a layout which - * matches the relevant struct. E.g. DECODE_SIMULATE initialise a struct - * decode_simulate by initialising four decode_item objects like this... - * - * {.bits = _type}, - * {.bits = _mask}, - * {.bits = _value}, - * {.handler = _handler}, - * - * Initialising a specified member of the union means that the compiler - * will produce a warning if the argument is of an incorrect type. - * - * Below is a list of each of the macros used to initialise entries and a - * description of the action performed when that entry is matched to an - * instruction. A match is found when (instruction & mask) == value. - * - * DECODE_TABLE(mask, value, table) - * Instruction decoding jumps to parsing the new sub-table 'table'. - * - * DECODE_CUSTOM(mask, value, decoder) - * The custom function 'decoder' is called to the complete decoding - * of an instruction. - * - * DECODE_SIMULATE(mask, value, handler) - * Set the probes instruction handler to 'handler', this will be used - * to simulate the instruction when the probe is hit. Decoding returns - * with INSN_GOOD_NO_SLOT. - * - * DECODE_EMULATE(mask, value, handler) - * Set the probes instruction handler to 'handler', this will be used - * to emulate the instruction when the probe is hit. The modified - * instruction (see below) is placed in the probes instruction slot so it - * may be called by the emulation code. Decoding returns with INSN_GOOD. - * - * DECODE_REJECT(mask, value) - * Instruction decoding fails with INSN_REJECTED - * - * DECODE_OR(mask, value) - * This allows the mask/value test of multiple table entries to be - * logically ORed. Once an 'or' entry is matched the decoding action to - * be performed is that of the next entry which isn't an 'or'. E.g. - * - * DECODE_OR (mask1, value1) - * DECODE_OR (mask2, value2) - * DECODE_SIMULATE (mask3, value3, simulation_handler) - * - * This means that if any of the three mask/value pairs match the - * instruction being decoded, then 'simulation_handler' will be used - * for it. - * - * Both the SIMULATE and EMULATE macros have a second form which take an - * additional 'regs' argument. - * - * DECODE_SIMULATEX(mask, value, handler, regs) - * DECODE_EMULATEX (mask, value, handler, regs) - * - * These are used to specify what kind of CPU register is encoded in each of the - * least significant 5 nibbles of the instruction being decoded. The regs value - * is specified using the REGS macro, this takes any of the REG_TYPE_* values - * from enum decode_reg_type as arguments; only the '*' part of the name is - * given. E.g. - * - * REGS(0, ANY, NOPC, 0, ANY) - * - * This indicates an instruction is encoded like: - * - * bits 19..16 ignore - * bits 15..12 any register allowed here - * bits 11.. 8 any register except PC allowed here - * bits 7.. 4 ignore - * bits 3.. 0 any register allowed here - * - * This register specification is checked after a decode table entry is found to - * match an instruction (through the mask/value test). Any invalid register then - * found in the instruction will cause decoding to fail with INSN_REJECTED. In - * the above example this would happen if bits 11..8 of the instruction were - * 1111, indicating R15 or PC. - * - * As well as checking for legal combinations of registers, this data is also - * used to modify the registers encoded in the instructions so that an - * emulation routines can use it. (See decode_regs() and INSN_NEW_BITS.) - * - * Here is a real example which matches ARM instructions of the form - * "AND <Rd>,<Rn>,<Rm>,<shift> <Rs>" - * - * DECODE_EMULATEX (0x0e000090, 0x00000010, emulate_rd12rn16rm0rs8_rwflags, - * REGS(ANY, ANY, NOPC, 0, ANY)), - * ^ ^ ^ ^ - * Rn Rd Rs Rm - * - * Decoding the instruction "AND R4, R5, R6, ASL R15" will be rejected because - * Rs == R15 - * - * Decoding the instruction "AND R4, R5, R6, ASL R7" will be accepted and the - * instruction will be modified to "AND R0, R2, R3, ASL R1" and then placed into - * the kprobes instruction slot. This can then be called later by the handler - * function emulate_rd12rn16rm0rs8_rwflags in order to simulate the instruction. - */ - -enum decode_type { - DECODE_TYPE_END, - DECODE_TYPE_TABLE, - DECODE_TYPE_CUSTOM, - DECODE_TYPE_SIMULATE, - DECODE_TYPE_EMULATE, - DECODE_TYPE_OR, - DECODE_TYPE_REJECT, - NUM_DECODE_TYPES /* Must be last enum */ -}; - -#define DECODE_TYPE_BITS 4 -#define DECODE_TYPE_MASK ((1 << DECODE_TYPE_BITS) - 1) - -enum decode_reg_type { - REG_TYPE_NONE = 0, /* Not a register, ignore */ - REG_TYPE_ANY, /* Any register allowed */ - REG_TYPE_SAMEAS16, /* Register should be same as that at bits 19..16 */ - REG_TYPE_SP, /* Register must be SP */ - REG_TYPE_PC, /* Register must be PC */ - REG_TYPE_NOSP, /* Register must not be SP */ - REG_TYPE_NOSPPC, /* Register must not be SP or PC */ - REG_TYPE_NOPC, /* Register must not be PC */ - REG_TYPE_NOPCWB, /* No PC if load/store write-back flag also set */ - - /* The following types are used when the encoding for PC indicates - * another instruction form. This distiction only matters for test - * case coverage checks. - */ - REG_TYPE_NOPCX, /* Register must not be PC */ - REG_TYPE_NOSPPCX, /* Register must not be SP or PC */ - - /* Alias to allow '0' arg to be used in REGS macro. */ - REG_TYPE_0 = REG_TYPE_NONE -}; - -#define REGS(r16, r12, r8, r4, r0) \ - ((REG_TYPE_##r16) << 16) + \ - ((REG_TYPE_##r12) << 12) + \ - ((REG_TYPE_##r8) << 8) + \ - ((REG_TYPE_##r4) << 4) + \ - (REG_TYPE_##r0) - -union decode_item { - u32 bits; - const union decode_item *table; - kprobe_insn_handler_t *handler; - kprobe_decode_insn_t *decoder; -}; - - -#define DECODE_END \ - {.bits = DECODE_TYPE_END} - - -struct decode_header { - union decode_item type_regs; - union decode_item mask; - union decode_item value; -}; - -#define DECODE_HEADER(_type, _mask, _value, _regs) \ - {.bits = (_type) | ((_regs) << DECODE_TYPE_BITS)}, \ - {.bits = (_mask)}, \ - {.bits = (_value)} - - -struct decode_table { - struct decode_header header; - union decode_item table; -}; - -#define DECODE_TABLE(_mask, _value, _table) \ - DECODE_HEADER(DECODE_TYPE_TABLE, _mask, _value, 0), \ - {.table = (_table)} - - -struct decode_custom { - struct decode_header header; - union decode_item decoder; -}; - -#define DECODE_CUSTOM(_mask, _value, _decoder) \ - DECODE_HEADER(DECODE_TYPE_CUSTOM, _mask, _value, 0), \ - {.decoder = (_decoder)} - - -struct decode_simulate { - struct decode_header header; - union decode_item handler; -}; - -#define DECODE_SIMULATEX(_mask, _value, _handler, _regs) \ - DECODE_HEADER(DECODE_TYPE_SIMULATE, _mask, _value, _regs), \ - {.handler = (_handler)} - -#define DECODE_SIMULATE(_mask, _value, _handler) \ - DECODE_SIMULATEX(_mask, _value, _handler, 0) - - -struct decode_emulate { - struct decode_header header; - union decode_item handler; -}; - -#define DECODE_EMULATEX(_mask, _value, _handler, _regs) \ - DECODE_HEADER(DECODE_TYPE_EMULATE, _mask, _value, _regs), \ - {.handler = (_handler)} - -#define DECODE_EMULATE(_mask, _value, _handler) \ - DECODE_EMULATEX(_mask, _value, _handler, 0) - - -struct decode_or { - struct decode_header header; -}; - -#define DECODE_OR(_mask, _value) \ - DECODE_HEADER(DECODE_TYPE_OR, _mask, _value, 0) - - -struct decode_reject { - struct decode_header header; -}; - -#define DECODE_REJECT(_mask, _value) \ - DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0) - - -#ifdef CONFIG_THUMB2_KERNEL -extern const union decode_item kprobe_decode_thumb16_table[]; -extern const union decode_item kprobe_decode_thumb32_table[]; -#else -extern const union decode_item kprobe_decode_arm_table[]; -#endif - - -int kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi, - const union decode_item *table, bool thumb16); - - -#endif /* _ARM_KERNEL_KPROBES_H */ diff --git a/ANDROID_3.4.5/arch/arm/kernel/leds.c b/ANDROID_3.4.5/arch/arm/kernel/leds.c deleted file mode 100644 index 2050399e..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/leds.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * LED support code, ripped out of arch/arm/kernel/time.c - * - * Copyright (C) 1994-2001 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/export.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/notifier.h> -#include <linux/cpu.h> -#include <linux/syscore_ops.h> -#include <linux/string.h> - -#include <asm/leds.h> - -static void dummy_leds_event(led_event_t evt) -{ -} - -void (*leds_event)(led_event_t) = dummy_leds_event; - -struct leds_evt_name { - const char name[8]; - int on; - int off; -}; - -static const struct leds_evt_name evt_names[] = { - { "amber", led_amber_on, led_amber_off }, - { "blue", led_blue_on, led_blue_off }, - { "green", led_green_on, led_green_off }, - { "red", led_red_on, led_red_off }, -}; - -static ssize_t leds_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - int ret = -EINVAL, len = strcspn(buf, " "); - - if (len > 0 && buf[len] == '\0') - len--; - - if (strncmp(buf, "claim", len) == 0) { - leds_event(led_claim); - ret = size; - } else if (strncmp(buf, "release", len) == 0) { - leds_event(led_release); - ret = size; - } else { - int i; - - for (i = 0; i < ARRAY_SIZE(evt_names); i++) { - if (strlen(evt_names[i].name) != len || - strncmp(buf, evt_names[i].name, len) != 0) - continue; - if (strncmp(buf+len, " on", 3) == 0) { - leds_event(evt_names[i].on); - ret = size; - } else if (strncmp(buf+len, " off", 4) == 0) { - leds_event(evt_names[i].off); - ret = size; - } - break; - } - } - return ret; -} - -static DEVICE_ATTR(event, 0200, NULL, leds_store); - -static struct bus_type leds_subsys = { - .name = "leds", - .dev_name = "leds", -}; - -static struct device leds_device = { - .id = 0, - .bus = &leds_subsys, -}; - -static int leds_suspend(void) -{ - leds_event(led_stop); - return 0; -} - -static void leds_resume(void) -{ - leds_event(led_start); -} - -static void leds_shutdown(void) -{ - leds_event(led_halted); -} - -static struct syscore_ops leds_syscore_ops = { - .shutdown = leds_shutdown, - .suspend = leds_suspend, - .resume = leds_resume, -}; - -static int leds_idle_notifier(struct notifier_block *nb, unsigned long val, - void *data) -{ - switch (val) { - case IDLE_START: - leds_event(led_idle_start); - break; - case IDLE_END: - leds_event(led_idle_end); - break; - } - - return 0; -} - -static struct notifier_block leds_idle_nb = { - .notifier_call = leds_idle_notifier, -}; - -static int __init leds_init(void) -{ - int ret; - ret = subsys_system_register(&leds_subsys, NULL); - if (ret == 0) - ret = device_register(&leds_device); - if (ret == 0) - ret = device_create_file(&leds_device, &dev_attr_event); - if (ret == 0) { - register_syscore_ops(&leds_syscore_ops); - idle_notifier_register(&leds_idle_nb); - } - - return ret; -} - -device_initcall(leds_init); - -EXPORT_SYMBOL(leds_event); diff --git a/ANDROID_3.4.5/arch/arm/kernel/machine_kexec.c b/ANDROID_3.4.5/arch/arm/kernel/machine_kexec.c deleted file mode 100644 index dfcdb9f7..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/machine_kexec.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * machine_kexec.c - handle transition of Linux booting another kernel - */ - -#include <linux/mm.h> -#include <linux/kexec.h> -#include <linux/delay.h> -#include <linux/reboot.h> -#include <linux/io.h> -#include <linux/irq.h> -#include <asm/pgtable.h> -#include <asm/pgalloc.h> -#include <asm/mmu_context.h> -#include <asm/cacheflush.h> -#include <asm/mach-types.h> -#include <asm/system_misc.h> - -extern const unsigned char relocate_new_kernel[]; -extern const unsigned int relocate_new_kernel_size; - -extern unsigned long kexec_start_address; -extern unsigned long kexec_indirection_page; -extern unsigned long kexec_mach_type; -extern unsigned long kexec_boot_atags; - -static atomic_t waiting_for_crash_ipi; - -/* - * Provide a dummy crash_notes definition while crash dump arrives to arm. - * This prevents breakage of crash_notes attribute in kernel/ksysfs.c. - */ - -int machine_kexec_prepare(struct kimage *image) -{ - return 0; -} - -void machine_kexec_cleanup(struct kimage *image) -{ -} - -void machine_crash_nonpanic_core(void *unused) -{ - struct pt_regs regs; - - crash_setup_regs(®s, NULL); - printk(KERN_DEBUG "CPU %u will stop doing anything useful since another CPU has crashed\n", - smp_processor_id()); - crash_save_cpu(®s, smp_processor_id()); - flush_cache_all(); - - atomic_dec(&waiting_for_crash_ipi); - while (1) - cpu_relax(); -} - -static void machine_kexec_mask_interrupts(void) -{ - unsigned int i; - struct irq_desc *desc; - - for_each_irq_desc(i, desc) { - struct irq_chip *chip; - - chip = irq_desc_get_chip(desc); - if (!chip) - continue; - - if (chip->irq_eoi && irqd_irq_inprogress(&desc->irq_data)) - chip->irq_eoi(&desc->irq_data); - - if (chip->irq_mask) - chip->irq_mask(&desc->irq_data); - - if (chip->irq_disable && !irqd_irq_disabled(&desc->irq_data)) - chip->irq_disable(&desc->irq_data); - } -} - -void machine_crash_shutdown(struct pt_regs *regs) -{ - unsigned long msecs; - - local_irq_disable(); - - atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1); - smp_call_function(machine_crash_nonpanic_core, NULL, false); - msecs = 1000; /* Wait at most a second for the other cpus to stop */ - while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) { - mdelay(1); - msecs--; - } - if (atomic_read(&waiting_for_crash_ipi) > 0) - printk(KERN_WARNING "Non-crashing CPUs did not react to IPI\n"); - - crash_save_cpu(regs, smp_processor_id()); - machine_kexec_mask_interrupts(); - - printk(KERN_INFO "Loading crashdump kernel...\n"); -} - -/* - * Function pointer to optional machine-specific reinitialization - */ -void (*kexec_reinit)(void); - -void machine_kexec(struct kimage *image) -{ - unsigned long page_list; - unsigned long reboot_code_buffer_phys; - void *reboot_code_buffer; - - - page_list = image->head & PAGE_MASK; - - /* we need both effective and real address here */ - reboot_code_buffer_phys = - page_to_pfn(image->control_code_page) << PAGE_SHIFT; - reboot_code_buffer = page_address(image->control_code_page); - - /* Prepare parameters for reboot_code_buffer*/ - kexec_start_address = image->start; - kexec_indirection_page = page_list; - kexec_mach_type = machine_arch_type; - kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; - - /* copy our kernel relocation code to the control code page */ - memcpy(reboot_code_buffer, - relocate_new_kernel, relocate_new_kernel_size); - - - flush_icache_range((unsigned long) reboot_code_buffer, - (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE); - printk(KERN_INFO "Bye!\n"); - - if (kexec_reinit) - kexec_reinit(); - - soft_restart(reboot_code_buffer_phys); -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/module.c b/ANDROID_3.4.5/arch/arm/kernel/module.c deleted file mode 100644 index 1e9be5d2..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/module.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * linux/arch/arm/kernel/module.c - * - * Copyright (C) 2002 Russell King. - * Modified for nommu by Hyok S. Choi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Module allocation method suggested by Andi Kleen. - */ -#include <linux/module.h> -#include <linux/moduleloader.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/elf.h> -#include <linux/vmalloc.h> -#include <linux/fs.h> -#include <linux/string.h> -#include <linux/gfp.h> - -#include <asm/pgtable.h> -#include <asm/sections.h> -#include <asm/smp_plat.h> -#include <asm/unwind.h> - -#ifdef CONFIG_XIP_KERNEL -/* - * The XIP kernel text is mapped in the module area for modules and - * some other stuff to work without any indirect relocations. - * MODULES_VADDR is redefined here and not in asm/memory.h to avoid - * recompiling the whole kernel when CONFIG_XIP_KERNEL is turned on/off. - */ -#undef MODULES_VADDR -#define MODULES_VADDR (((unsigned long)_etext + ~PMD_MASK) & PMD_MASK) -#endif - -#ifdef CONFIG_MMU -void *module_alloc(unsigned long size) -{ - return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, - GFP_KERNEL, PAGE_KERNEL_EXEC, -1, - __builtin_return_address(0)); -} -#endif - -int -apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, - unsigned int relindex, struct module *module) -{ - Elf32_Shdr *symsec = sechdrs + symindex; - Elf32_Shdr *relsec = sechdrs + relindex; - Elf32_Shdr *dstsec = sechdrs + relsec->sh_info; - Elf32_Rel *rel = (void *)relsec->sh_addr; - unsigned int i; - - for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++, rel++) { - unsigned long loc; - Elf32_Sym *sym; - const char *symname; - s32 offset; -#ifdef CONFIG_THUMB2_KERNEL - u32 upper, lower, sign, j1, j2; -#endif - - offset = ELF32_R_SYM(rel->r_info); - if (offset < 0 || offset > (symsec->sh_size / sizeof(Elf32_Sym))) { - pr_err("%s: section %u reloc %u: bad relocation sym offset\n", - module->name, relindex, i); - return -ENOEXEC; - } - - sym = ((Elf32_Sym *)symsec->sh_addr) + offset; - symname = strtab + sym->st_name; - - if (rel->r_offset < 0 || rel->r_offset > dstsec->sh_size - sizeof(u32)) { - pr_err("%s: section %u reloc %u sym '%s': out of bounds relocation, offset %d size %u\n", - module->name, relindex, i, symname, - rel->r_offset, dstsec->sh_size); - return -ENOEXEC; - } - - loc = dstsec->sh_addr + rel->r_offset; - - switch (ELF32_R_TYPE(rel->r_info)) { - case R_ARM_NONE: - /* ignore */ - break; - - case R_ARM_ABS32: - *(u32 *)loc += sym->st_value; - break; - - case R_ARM_PC24: - case R_ARM_CALL: - case R_ARM_JUMP24: - offset = (*(u32 *)loc & 0x00ffffff) << 2; - if (offset & 0x02000000) - offset -= 0x04000000; - - offset += sym->st_value - loc; - if (offset & 3 || - offset <= (s32)0xfe000000 || - offset >= (s32)0x02000000) { - pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n", - module->name, relindex, i, symname, - ELF32_R_TYPE(rel->r_info), loc, - sym->st_value); - return -ENOEXEC; - } - - offset >>= 2; - - *(u32 *)loc &= 0xff000000; - *(u32 *)loc |= offset & 0x00ffffff; - break; - - case R_ARM_V4BX: - /* Preserve Rm and the condition code. Alter - * other bits to re-code instruction as - * MOV PC,Rm. - */ - *(u32 *)loc &= 0xf000000f; - *(u32 *)loc |= 0x01a0f000; - break; - - case R_ARM_PREL31: - offset = *(u32 *)loc + sym->st_value - loc; - *(u32 *)loc = offset & 0x7fffffff; - break; - - case R_ARM_MOVW_ABS_NC: - case R_ARM_MOVT_ABS: - offset = *(u32 *)loc; - offset = ((offset & 0xf0000) >> 4) | (offset & 0xfff); - offset = (offset ^ 0x8000) - 0x8000; - - offset += sym->st_value; - if (ELF32_R_TYPE(rel->r_info) == R_ARM_MOVT_ABS) - offset >>= 16; - - *(u32 *)loc &= 0xfff0f000; - *(u32 *)loc |= ((offset & 0xf000) << 4) | - (offset & 0x0fff); - break; - -#ifdef CONFIG_THUMB2_KERNEL - case R_ARM_THM_CALL: - case R_ARM_THM_JUMP24: - upper = *(u16 *)loc; - lower = *(u16 *)(loc + 2); - - /* - * 25 bit signed address range (Thumb-2 BL and B.W - * instructions): - * S:I1:I2:imm10:imm11:0 - * where: - * S = upper[10] = offset[24] - * I1 = ~(J1 ^ S) = offset[23] - * I2 = ~(J2 ^ S) = offset[22] - * imm10 = upper[9:0] = offset[21:12] - * imm11 = lower[10:0] = offset[11:1] - * J1 = lower[13] - * J2 = lower[11] - */ - sign = (upper >> 10) & 1; - j1 = (lower >> 13) & 1; - j2 = (lower >> 11) & 1; - offset = (sign << 24) | ((~(j1 ^ sign) & 1) << 23) | - ((~(j2 ^ sign) & 1) << 22) | - ((upper & 0x03ff) << 12) | - ((lower & 0x07ff) << 1); - if (offset & 0x01000000) - offset -= 0x02000000; - offset += sym->st_value - loc; - - /* - * For function symbols, only Thumb addresses are - * allowed (no interworking). - * - * For non-function symbols, the destination - * has no specific ARM/Thumb disposition, so - * the branch is resolved under the assumption - * that interworking is not required. - */ - if ((ELF32_ST_TYPE(sym->st_info) == STT_FUNC && - !(offset & 1)) || - offset <= (s32)0xff000000 || - offset >= (s32)0x01000000) { - pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n", - module->name, relindex, i, symname, - ELF32_R_TYPE(rel->r_info), loc, - sym->st_value); - return -ENOEXEC; - } - - sign = (offset >> 24) & 1; - j1 = sign ^ (~(offset >> 23) & 1); - j2 = sign ^ (~(offset >> 22) & 1); - *(u16 *)loc = (u16)((upper & 0xf800) | (sign << 10) | - ((offset >> 12) & 0x03ff)); - *(u16 *)(loc + 2) = (u16)((lower & 0xd000) | - (j1 << 13) | (j2 << 11) | - ((offset >> 1) & 0x07ff)); - break; - - case R_ARM_THM_MOVW_ABS_NC: - case R_ARM_THM_MOVT_ABS: - upper = *(u16 *)loc; - lower = *(u16 *)(loc + 2); - - /* - * MOVT/MOVW instructions encoding in Thumb-2: - * - * i = upper[10] - * imm4 = upper[3:0] - * imm3 = lower[14:12] - * imm8 = lower[7:0] - * - * imm16 = imm4:i:imm3:imm8 - */ - offset = ((upper & 0x000f) << 12) | - ((upper & 0x0400) << 1) | - ((lower & 0x7000) >> 4) | (lower & 0x00ff); - offset = (offset ^ 0x8000) - 0x8000; - offset += sym->st_value; - - if (ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_ABS) - offset >>= 16; - - *(u16 *)loc = (u16)((upper & 0xfbf0) | - ((offset & 0xf000) >> 12) | - ((offset & 0x0800) >> 1)); - *(u16 *)(loc + 2) = (u16)((lower & 0x8f00) | - ((offset & 0x0700) << 4) | - (offset & 0x00ff)); - break; -#endif - - default: - printk(KERN_ERR "%s: unknown relocation: %u\n", - module->name, ELF32_R_TYPE(rel->r_info)); - return -ENOEXEC; - } - } - return 0; -} - -struct mod_unwind_map { - const Elf_Shdr *unw_sec; - const Elf_Shdr *txt_sec; -}; - -static const Elf_Shdr *find_mod_section(const Elf32_Ehdr *hdr, - const Elf_Shdr *sechdrs, const char *name) -{ - const Elf_Shdr *s, *se; - const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; - - for (s = sechdrs, se = sechdrs + hdr->e_shnum; s < se; s++) - if (strcmp(name, secstrs + s->sh_name) == 0) - return s; - - return NULL; -} - -extern void fixup_pv_table(const void *, unsigned long); -extern void fixup_smp(const void *, unsigned long); - -int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, - struct module *mod) -{ - const Elf_Shdr *s = NULL; -#ifdef CONFIG_ARM_UNWIND - const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; - const Elf_Shdr *sechdrs_end = sechdrs + hdr->e_shnum; - struct mod_unwind_map maps[ARM_SEC_MAX]; - int i; - - memset(maps, 0, sizeof(maps)); - - for (s = sechdrs; s < sechdrs_end; s++) { - const char *secname = secstrs + s->sh_name; - - if (!(s->sh_flags & SHF_ALLOC)) - continue; - - if (strcmp(".ARM.exidx.init.text", secname) == 0) - maps[ARM_SEC_INIT].unw_sec = s; - else if (strcmp(".ARM.exidx.devinit.text", secname) == 0) - maps[ARM_SEC_DEVINIT].unw_sec = s; - else if (strcmp(".ARM.exidx", secname) == 0) - maps[ARM_SEC_CORE].unw_sec = s; - else if (strcmp(".ARM.exidx.exit.text", secname) == 0) - maps[ARM_SEC_EXIT].unw_sec = s; - else if (strcmp(".ARM.exidx.devexit.text", secname) == 0) - maps[ARM_SEC_DEVEXIT].unw_sec = s; - else if (strcmp(".init.text", secname) == 0) - maps[ARM_SEC_INIT].txt_sec = s; - else if (strcmp(".devinit.text", secname) == 0) - maps[ARM_SEC_DEVINIT].txt_sec = s; - else if (strcmp(".text", secname) == 0) - maps[ARM_SEC_CORE].txt_sec = s; - else if (strcmp(".exit.text", secname) == 0) - maps[ARM_SEC_EXIT].txt_sec = s; - else if (strcmp(".devexit.text", secname) == 0) - maps[ARM_SEC_DEVEXIT].txt_sec = s; - } - - for (i = 0; i < ARM_SEC_MAX; i++) - if (maps[i].unw_sec && maps[i].txt_sec) - mod->arch.unwind[i] = - unwind_table_add(maps[i].unw_sec->sh_addr, - maps[i].unw_sec->sh_size, - maps[i].txt_sec->sh_addr, - maps[i].txt_sec->sh_size); -#endif -#ifdef CONFIG_ARM_PATCH_PHYS_VIRT - s = find_mod_section(hdr, sechdrs, ".pv_table"); - if (s) - fixup_pv_table((void *)s->sh_addr, s->sh_size); -#endif - s = find_mod_section(hdr, sechdrs, ".alt.smp.init"); - if (s && !is_smp()) -#ifdef CONFIG_SMP_ON_UP - fixup_smp((void *)s->sh_addr, s->sh_size); -#else - return -EINVAL; -#endif - return 0; -} - -void -module_arch_cleanup(struct module *mod) -{ -#ifdef CONFIG_ARM_UNWIND - int i; - - for (i = 0; i < ARM_SEC_MAX; i++) - if (mod->arch.unwind[i]) - unwind_table_del(mod->arch.unwind[i]); -#endif -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/opcodes.c b/ANDROID_3.4.5/arch/arm/kernel/opcodes.c deleted file mode 100644 index f8179c6a..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/opcodes.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * linux/arch/arm/kernel/opcodes.c - * - * A32 condition code lookup feature moved from nwfpe/fpopcode.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/module.h> -#include <asm/opcodes.h> - -#define ARM_OPCODE_CONDITION_UNCOND 0xf - -/* - * condition code lookup table - * index into the table is test code: EQ, NE, ... LT, GT, AL, NV - * - * bit position in short is condition code: NZCV - */ -static const unsigned short cc_map[16] = { - 0xF0F0, /* EQ == Z set */ - 0x0F0F, /* NE */ - 0xCCCC, /* CS == C set */ - 0x3333, /* CC */ - 0xFF00, /* MI == N set */ - 0x00FF, /* PL */ - 0xAAAA, /* VS == V set */ - 0x5555, /* VC */ - 0x0C0C, /* HI == C set && Z clear */ - 0xF3F3, /* LS == C clear || Z set */ - 0xAA55, /* GE == (N==V) */ - 0x55AA, /* LT == (N!=V) */ - 0x0A05, /* GT == (!Z && (N==V)) */ - 0xF5FA, /* LE == (Z || (N!=V)) */ - 0xFFFF, /* AL always */ - 0 /* NV */ -}; - -/* - * Returns: - * ARM_OPCODE_CONDTEST_FAIL - if condition fails - * ARM_OPCODE_CONDTEST_PASS - if condition passes (including AL) - * ARM_OPCODE_CONDTEST_UNCOND - if NV condition, or separate unconditional - * opcode space from v5 onwards - * - * Code that tests whether a conditional instruction would pass its condition - * check should check that return value == ARM_OPCODE_CONDTEST_PASS. - * - * Code that tests if a condition means that the instruction would be executed - * (regardless of conditional or unconditional) should instead check that the - * return value != ARM_OPCODE_CONDTEST_FAIL. - */ -asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr) -{ - u32 cc_bits = opcode >> 28; - u32 psr_cond = psr >> 28; - unsigned int ret; - - if (cc_bits != ARM_OPCODE_CONDITION_UNCOND) { - if ((cc_map[cc_bits] >> (psr_cond)) & 1) - ret = ARM_OPCODE_CONDTEST_PASS; - else - ret = ARM_OPCODE_CONDTEST_FAIL; - } else { - ret = ARM_OPCODE_CONDTEST_UNCOND; - } - - return ret; -} -EXPORT_SYMBOL_GPL(arm_check_condition); diff --git a/ANDROID_3.4.5/arch/arm/kernel/patch.c b/ANDROID_3.4.5/arch/arm/kernel/patch.c deleted file mode 100644 index 07314af4..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/patch.c +++ /dev/null @@ -1,75 +0,0 @@ -#include <linux/kernel.h> -#include <linux/kprobes.h> -#include <linux/stop_machine.h> - -#include <asm/cacheflush.h> -#include <asm/smp_plat.h> -#include <asm/opcodes.h> - -#include "patch.h" - -struct patch { - void *addr; - unsigned int insn; -}; - -void __kprobes __patch_text(void *addr, unsigned int insn) -{ - bool thumb2 = IS_ENABLED(CONFIG_THUMB2_KERNEL); - int size; - - if (thumb2 && __opcode_is_thumb16(insn)) { - *(u16 *)addr = __opcode_to_mem_thumb16(insn); - size = sizeof(u16); - } else if (thumb2 && ((uintptr_t)addr & 2)) { - u16 first = __opcode_thumb32_first(insn); - u16 second = __opcode_thumb32_second(insn); - u16 *addrh = addr; - - addrh[0] = __opcode_to_mem_thumb16(first); - addrh[1] = __opcode_to_mem_thumb16(second); - - size = sizeof(u32); - } else { - if (thumb2) - insn = __opcode_to_mem_thumb32(insn); - else - insn = __opcode_to_mem_arm(insn); - - *(u32 *)addr = insn; - size = sizeof(u32); - } - - flush_icache_range((uintptr_t)(addr), - (uintptr_t)(addr) + size); -} - -static int __kprobes patch_text_stop_machine(void *data) -{ - struct patch *patch = data; - - __patch_text(patch->addr, patch->insn); - - return 0; -} - -void __kprobes patch_text(void *addr, unsigned int insn) -{ - struct patch patch = { - .addr = addr, - .insn = insn, - }; - - if (cache_ops_need_broadcast()) { - stop_machine(patch_text_stop_machine, &patch, cpu_online_mask); - } else { - bool straddles_word = IS_ENABLED(CONFIG_THUMB2_KERNEL) - && __opcode_is_thumb32(insn) - && ((uintptr_t)addr & 2); - - if (straddles_word) - stop_machine(patch_text_stop_machine, &patch, NULL); - else - __patch_text(addr, insn); - } -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/patch.h b/ANDROID_3.4.5/arch/arm/kernel/patch.h deleted file mode 100644 index b4731f2d..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/patch.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _ARM_KERNEL_PATCH_H -#define _ARM_KERNEL_PATCH_H - -void patch_text(void *addr, unsigned int insn); -void __patch_text(void *addr, unsigned int insn); - -#endif diff --git a/ANDROID_3.4.5/arch/arm/kernel/perf_event.c b/ANDROID_3.4.5/arch/arm/kernel/perf_event.c deleted file mode 100644 index 186c8cb9..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/perf_event.c +++ /dev/null @@ -1,855 +0,0 @@ -#undef DEBUG - -/* - * ARM performance counter support. - * - * Copyright (C) 2009 picoChip Designs, Ltd., Jamie Iles - * Copyright (C) 2010 ARM Ltd., Will Deacon <will.deacon@arm.com> - * - * This code is based on the sparc64 perf event code, which is in turn based - * on the x86 code. Callchain code is based on the ARM OProfile backtrace - * code. - */ -#define pr_fmt(fmt) "hw perfevents: " fmt - -#include <linux/bitmap.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/export.h> -#include <linux/perf_event.h> -#include <linux/platform_device.h> -#include <linux/spinlock.h> -#include <linux/uaccess.h> - -#include <asm/cputype.h> -#include <asm/irq.h> -#include <asm/irq_regs.h> -#include <asm/pmu.h> -#include <asm/stacktrace.h> - -/* - * ARMv6 supports a maximum of 3 events, starting from index 0. If we add - * another platform that supports more, we need to increase this to be the - * largest of all platforms. - * - * ARMv7 supports up to 32 events: - * cycle counter CCNT + 31 events counters CNT0..30. - * Cortex-A8 has 1+4 counters, Cortex-A9 has 1+6 counters. - */ -#define ARMPMU_MAX_HWEVENTS 32 - -static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events); -static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask); -static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events); - -#define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu)) - -/* Set at runtime when we know what CPU type we are. */ -static struct arm_pmu *cpu_pmu; - -enum arm_perf_pmu_ids -armpmu_get_pmu_id(void) -{ - int id = -ENODEV; - - if (cpu_pmu != NULL) - id = cpu_pmu->id; - - return id; -} -EXPORT_SYMBOL_GPL(armpmu_get_pmu_id); - -int perf_num_counters(void) -{ - int max_events = 0; - - if (cpu_pmu != NULL) - max_events = cpu_pmu->num_events; - - return max_events; -} -EXPORT_SYMBOL_GPL(perf_num_counters); - -#define HW_OP_UNSUPPORTED 0xFFFF - -#define C(_x) \ - PERF_COUNT_HW_CACHE_##_x - -#define CACHE_OP_UNSUPPORTED 0xFFFF - -static int -armpmu_map_cache_event(const unsigned (*cache_map) - [PERF_COUNT_HW_CACHE_MAX] - [PERF_COUNT_HW_CACHE_OP_MAX] - [PERF_COUNT_HW_CACHE_RESULT_MAX], - u64 config) -{ - unsigned int cache_type, cache_op, cache_result, ret; - - cache_type = (config >> 0) & 0xff; - if (cache_type >= PERF_COUNT_HW_CACHE_MAX) - return -EINVAL; - - cache_op = (config >> 8) & 0xff; - if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX) - return -EINVAL; - - cache_result = (config >> 16) & 0xff; - if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX) - return -EINVAL; - - ret = (int)(*cache_map)[cache_type][cache_op][cache_result]; - - if (ret == CACHE_OP_UNSUPPORTED) - return -ENOENT; - - return ret; -} - -static int -armpmu_map_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config) -{ - int mapping = (*event_map)[config]; - return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping; -} - -static int -armpmu_map_raw_event(u32 raw_event_mask, u64 config) -{ - return (int)(config & raw_event_mask); -} - -static int map_cpu_event(struct perf_event *event, - const unsigned (*event_map)[PERF_COUNT_HW_MAX], - const unsigned (*cache_map) - [PERF_COUNT_HW_CACHE_MAX] - [PERF_COUNT_HW_CACHE_OP_MAX] - [PERF_COUNT_HW_CACHE_RESULT_MAX], - u32 raw_event_mask) -{ - u64 config = event->attr.config; - - switch (event->attr.type) { - case PERF_TYPE_HARDWARE: - return armpmu_map_event(event_map, config); - case PERF_TYPE_HW_CACHE: - return armpmu_map_cache_event(cache_map, config); - case PERF_TYPE_RAW: - return armpmu_map_raw_event(raw_event_mask, config); - } - - return -ENOENT; -} - -int -armpmu_event_set_period(struct perf_event *event, - struct hw_perf_event *hwc, - int idx) -{ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - s64 left = local64_read(&hwc->period_left); - s64 period = hwc->sample_period; - int ret = 0; - - if (unlikely(left <= -period)) { - left = period; - local64_set(&hwc->period_left, left); - hwc->last_period = period; - ret = 1; - } - - if (unlikely(left <= 0)) { - left += period; - local64_set(&hwc->period_left, left); - hwc->last_period = period; - ret = 1; - } - - if (left > (s64)armpmu->max_period) - left = armpmu->max_period; - - local64_set(&hwc->prev_count, (u64)-left); - - armpmu->write_counter(idx, (u64)(-left) & 0xffffffff); - - perf_event_update_userpage(event); - - return ret; -} - -u64 -armpmu_event_update(struct perf_event *event, - struct hw_perf_event *hwc, - int idx) -{ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - u64 delta, prev_raw_count, new_raw_count; - -again: - prev_raw_count = local64_read(&hwc->prev_count); - new_raw_count = armpmu->read_counter(idx); - - if (local64_cmpxchg(&hwc->prev_count, prev_raw_count, - new_raw_count) != prev_raw_count) - goto again; - - delta = (new_raw_count - prev_raw_count) & armpmu->max_period; - - local64_add(delta, &event->count); - local64_sub(delta, &hwc->period_left); - - return new_raw_count; -} - -static void -armpmu_read(struct perf_event *event) -{ - struct hw_perf_event *hwc = &event->hw; - - /* Don't read disabled counters! */ - if (hwc->idx < 0) - return; - - armpmu_event_update(event, hwc, hwc->idx); -} - -static void -armpmu_stop(struct perf_event *event, int flags) -{ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - struct hw_perf_event *hwc = &event->hw; - - /* - * ARM pmu always has to update the counter, so ignore - * PERF_EF_UPDATE, see comments in armpmu_start(). - */ - if (!(hwc->state & PERF_HES_STOPPED)) { - armpmu->disable(hwc, hwc->idx); - barrier(); /* why? */ - armpmu_event_update(event, hwc, hwc->idx); - hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE; - } -} - -static void -armpmu_start(struct perf_event *event, int flags) -{ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - struct hw_perf_event *hwc = &event->hw; - - /* - * ARM pmu always has to reprogram the period, so ignore - * PERF_EF_RELOAD, see the comment below. - */ - if (flags & PERF_EF_RELOAD) - WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE)); - - hwc->state = 0; - /* - * Set the period again. Some counters can't be stopped, so when we - * were stopped we simply disabled the IRQ source and the counter - * may have been left counting. If we don't do this step then we may - * get an interrupt too soon or *way* too late if the overflow has - * happened since disabling. - */ - armpmu_event_set_period(event, hwc, hwc->idx); - armpmu->enable(hwc, hwc->idx); -} - -static void -armpmu_del(struct perf_event *event, int flags) -{ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - struct pmu_hw_events *hw_events = armpmu->get_hw_events(); - struct hw_perf_event *hwc = &event->hw; - int idx = hwc->idx; - - WARN_ON(idx < 0); - - armpmu_stop(event, PERF_EF_UPDATE); - hw_events->events[idx] = NULL; - clear_bit(idx, hw_events->used_mask); - - perf_event_update_userpage(event); -} - -static int -armpmu_add(struct perf_event *event, int flags) -{ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - struct pmu_hw_events *hw_events = armpmu->get_hw_events(); - struct hw_perf_event *hwc = &event->hw; - int idx; - int err = 0; - - perf_pmu_disable(event->pmu); - - /* If we don't have a space for the counter then finish early. */ - idx = armpmu->get_event_idx(hw_events, hwc); - if (idx < 0) { - err = idx; - goto out; - } - - /* - * If there is an event in the counter we are going to use then make - * sure it is disabled. - */ - event->hw.idx = idx; - armpmu->disable(hwc, idx); - hw_events->events[idx] = event; - - hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE; - if (flags & PERF_EF_START) - armpmu_start(event, PERF_EF_RELOAD); - - /* Propagate our changes to the userspace mapping. */ - perf_event_update_userpage(event); - -out: - perf_pmu_enable(event->pmu); - return err; -} - -static int -validate_event(struct pmu_hw_events *hw_events, - struct perf_event *event) -{ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - struct hw_perf_event fake_event = event->hw; - struct pmu *leader_pmu = event->group_leader->pmu; - - if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF) - return 1; - - return armpmu->get_event_idx(hw_events, &fake_event) >= 0; -} - -static int -validate_group(struct perf_event *event) -{ - struct perf_event *sibling, *leader = event->group_leader; - struct pmu_hw_events fake_pmu; - DECLARE_BITMAP(fake_used_mask, ARMPMU_MAX_HWEVENTS); - - /* - * Initialise the fake PMU. We only need to populate the - * used_mask for the purposes of validation. - */ - memset(fake_used_mask, 0, sizeof(fake_used_mask)); - fake_pmu.used_mask = fake_used_mask; - - if (!validate_event(&fake_pmu, leader)) - return -EINVAL; - - list_for_each_entry(sibling, &leader->sibling_list, group_entry) { - if (!validate_event(&fake_pmu, sibling)) - return -EINVAL; - } - - if (!validate_event(&fake_pmu, event)) - return -EINVAL; - - return 0; -} - -static irqreturn_t armpmu_platform_irq(int irq, void *dev) -{ - struct arm_pmu *armpmu = (struct arm_pmu *) dev; - struct platform_device *plat_device = armpmu->plat_device; - struct arm_pmu_platdata *plat = dev_get_platdata(&plat_device->dev); - - return plat->handle_irq(irq, dev, armpmu->handle_irq); -} - -static void -armpmu_release_hardware(struct arm_pmu *armpmu) -{ - int i, irq, irqs; - struct platform_device *pmu_device = armpmu->plat_device; - struct arm_pmu_platdata *plat = - dev_get_platdata(&pmu_device->dev); - - irqs = min(pmu_device->num_resources, num_possible_cpus()); - - for (i = 0; i < irqs; ++i) { - if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs)) - continue; - irq = platform_get_irq(pmu_device, i); - if (irq >= 0) { - if (plat && plat->disable_irq) - plat->disable_irq(irq); - free_irq(irq, armpmu); - } - } - - release_pmu(armpmu->type); -} - -static int -armpmu_reserve_hardware(struct arm_pmu *armpmu) -{ - struct arm_pmu_platdata *plat; - irq_handler_t handle_irq; - int i, err, irq, irqs; - struct platform_device *pmu_device = armpmu->plat_device; - - if (!pmu_device) - return -ENODEV; - - err = reserve_pmu(armpmu->type); - if (err) { - pr_warning("unable to reserve pmu\n"); - return err; - } - - plat = dev_get_platdata(&pmu_device->dev); - if (plat && plat->handle_irq) - handle_irq = armpmu_platform_irq; - else - handle_irq = armpmu->handle_irq; - - irqs = min(pmu_device->num_resources, num_possible_cpus()); - if (irqs < 1) { - pr_err("no irqs for PMUs defined\n"); - return -ENODEV; - } - - for (i = 0; i < irqs; ++i) { - err = 0; - irq = platform_get_irq(pmu_device, i); - if (irq < 0) - continue; - - /* - * If we have a single PMU interrupt that we can't shift, - * assume that we're running on a uniprocessor machine and - * continue. Otherwise, continue without this interrupt. - */ - if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) { - pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n", - irq, i); - continue; - } - - err = request_irq(irq, handle_irq, - IRQF_DISABLED | IRQF_NOBALANCING, - "arm-pmu", armpmu); - if (err) { - pr_err("unable to request IRQ%d for ARM PMU counters\n", - irq); - armpmu_release_hardware(armpmu); - return err; - } else if (plat && plat->enable_irq) - plat->enable_irq(irq); - - cpumask_set_cpu(i, &armpmu->active_irqs); - } - - return 0; -} - -static void -hw_perf_event_destroy(struct perf_event *event) -{ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - atomic_t *active_events = &armpmu->active_events; - struct mutex *pmu_reserve_mutex = &armpmu->reserve_mutex; - - if (atomic_dec_and_mutex_lock(active_events, pmu_reserve_mutex)) { - armpmu_release_hardware(armpmu); - mutex_unlock(pmu_reserve_mutex); - } -} - -static int -event_requires_mode_exclusion(struct perf_event_attr *attr) -{ - return attr->exclude_idle || attr->exclude_user || - attr->exclude_kernel || attr->exclude_hv; -} - -static int -__hw_perf_event_init(struct perf_event *event) -{ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - struct hw_perf_event *hwc = &event->hw; - int mapping, err; - - mapping = armpmu->map_event(event); - - if (mapping < 0) { - pr_debug("event %x:%llx not supported\n", event->attr.type, - event->attr.config); - return mapping; - } - - /* - * We don't assign an index until we actually place the event onto - * hardware. Use -1 to signify that we haven't decided where to put it - * yet. For SMP systems, each core has it's own PMU so we can't do any - * clever allocation or constraints checking at this point. - */ - hwc->idx = -1; - hwc->config_base = 0; - hwc->config = 0; - hwc->event_base = 0; - - /* - * Check whether we need to exclude the counter from certain modes. - */ - if ((!armpmu->set_event_filter || - armpmu->set_event_filter(hwc, &event->attr)) && - event_requires_mode_exclusion(&event->attr)) { - pr_debug("ARM performance counters do not support " - "mode exclusion\n"); - return -EPERM; - } - - /* - * Store the event encoding into the config_base field. - */ - hwc->config_base |= (unsigned long)mapping; - - if (!hwc->sample_period) { - /* - * For non-sampling runs, limit the sample_period to half - * of the counter width. That way, the new counter value - * is far less likely to overtake the previous one unless - * you have some serious IRQ latency issues. - */ - hwc->sample_period = armpmu->max_period >> 1; - hwc->last_period = hwc->sample_period; - local64_set(&hwc->period_left, hwc->sample_period); - } - - err = 0; - if (event->group_leader != event) { - err = validate_group(event); - if (err) - return -EINVAL; - } - - return err; -} - -static int armpmu_event_init(struct perf_event *event) -{ - struct arm_pmu *armpmu = to_arm_pmu(event->pmu); - int err = 0; - atomic_t *active_events = &armpmu->active_events; - - /* does not support taken branch sampling */ - if (has_branch_stack(event)) - return -EOPNOTSUPP; - - if (armpmu->map_event(event) == -ENOENT) - return -ENOENT; - - event->destroy = hw_perf_event_destroy; - - if (!atomic_inc_not_zero(active_events)) { - mutex_lock(&armpmu->reserve_mutex); - if (atomic_read(active_events) == 0) - err = armpmu_reserve_hardware(armpmu); - - if (!err) - atomic_inc(active_events); - mutex_unlock(&armpmu->reserve_mutex); - } - - if (err) - return err; - - err = __hw_perf_event_init(event); - if (err) - hw_perf_event_destroy(event); - - return err; -} - -static void armpmu_enable(struct pmu *pmu) -{ - struct arm_pmu *armpmu = to_arm_pmu(pmu); - struct pmu_hw_events *hw_events = armpmu->get_hw_events(); - int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events); - - if (enabled) - armpmu->start(); -} - -static void armpmu_disable(struct pmu *pmu) -{ - struct arm_pmu *armpmu = to_arm_pmu(pmu); - armpmu->stop(); -} - -static void __init armpmu_init(struct arm_pmu *armpmu) -{ - atomic_set(&armpmu->active_events, 0); - mutex_init(&armpmu->reserve_mutex); - - armpmu->pmu = (struct pmu) { - .pmu_enable = armpmu_enable, - .pmu_disable = armpmu_disable, - .event_init = armpmu_event_init, - .add = armpmu_add, - .del = armpmu_del, - .start = armpmu_start, - .stop = armpmu_stop, - .read = armpmu_read, - }; -} - -int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type) -{ - armpmu_init(armpmu); - return perf_pmu_register(&armpmu->pmu, name, type); -} - -/* Include the PMU-specific implementations. */ -#include "perf_event_xscale.c" -#include "perf_event_v6.c" -#include "perf_event_v7.c" - -/* - * Ensure the PMU has sane values out of reset. - * This requires SMP to be available, so exists as a separate initcall. - */ -static int __init -cpu_pmu_reset(void) -{ - if (cpu_pmu && cpu_pmu->reset) - return on_each_cpu(cpu_pmu->reset, NULL, 1); - return 0; -} -arch_initcall(cpu_pmu_reset); - -/* - * PMU platform driver and devicetree bindings. - */ -static struct of_device_id armpmu_of_device_ids[] = { - {.compatible = "arm,cortex-a9-pmu"}, - {.compatible = "arm,cortex-a8-pmu"}, - {.compatible = "arm,arm1136-pmu"}, - {.compatible = "arm,arm1176-pmu"}, - {}, -}; - -static struct platform_device_id armpmu_plat_device_ids[] = { - {.name = "arm-pmu"}, - {}, -}; - -static int __devinit armpmu_device_probe(struct platform_device *pdev) -{ - if (!cpu_pmu) - return -ENODEV; - - cpu_pmu->plat_device = pdev; - return 0; -} - -static struct platform_driver armpmu_driver = { - .driver = { - .name = "arm-pmu", - .of_match_table = armpmu_of_device_ids, - }, - .probe = armpmu_device_probe, - .id_table = armpmu_plat_device_ids, -}; - -static int __init register_pmu_driver(void) -{ - return platform_driver_register(&armpmu_driver); -} -device_initcall(register_pmu_driver); - -static struct pmu_hw_events *armpmu_get_cpu_events(void) -{ - return &__get_cpu_var(cpu_hw_events); -} - -static void __init cpu_pmu_init(struct arm_pmu *armpmu) -{ - int cpu; - for_each_possible_cpu(cpu) { - struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu); - events->events = per_cpu(hw_events, cpu); - events->used_mask = per_cpu(used_mask, cpu); - raw_spin_lock_init(&events->pmu_lock); - } - armpmu->get_hw_events = armpmu_get_cpu_events; - armpmu->type = ARM_PMU_DEVICE_CPU; -} - -/* - * PMU hardware loses all context when a CPU goes offline. - * When a CPU is hotplugged back in, since some hardware registers are - * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading - * junk values out of them. - */ -static int __cpuinit pmu_cpu_notify(struct notifier_block *b, - unsigned long action, void *hcpu) -{ - if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING) - return NOTIFY_DONE; - - if (cpu_pmu && cpu_pmu->reset) - cpu_pmu->reset(NULL); - - return NOTIFY_OK; -} - -static struct notifier_block __cpuinitdata pmu_cpu_notifier = { - .notifier_call = pmu_cpu_notify, -}; - -/* - * CPU PMU identification and registration. - */ -static int __init -init_hw_perf_events(void) -{ - unsigned long cpuid = read_cpuid_id(); - unsigned long implementor = (cpuid & 0xFF000000) >> 24; - unsigned long part_number = (cpuid & 0xFFF0); - - /* ARM Ltd CPUs. */ - if (0x41 == implementor) { - switch (part_number) { - case 0xB360: /* ARM1136 */ - case 0xB560: /* ARM1156 */ - case 0xB760: /* ARM1176 */ - cpu_pmu = armv6pmu_init(); - break; - case 0xB020: /* ARM11mpcore */ - cpu_pmu = armv6mpcore_pmu_init(); - break; - case 0xC080: /* Cortex-A8 */ - cpu_pmu = armv7_a8_pmu_init(); - break; - case 0xC090: /* Cortex-A9 */ - cpu_pmu = armv7_a9_pmu_init(); - break; - case 0xC050: /* Cortex-A5 */ - cpu_pmu = armv7_a5_pmu_init(); - break; - case 0xC0F0: /* Cortex-A15 */ - cpu_pmu = armv7_a15_pmu_init(); - break; - case 0xC070: /* Cortex-A7 */ - cpu_pmu = armv7_a7_pmu_init(); - break; - } - /* Intel CPUs [xscale]. */ - } else if (0x69 == implementor) { - part_number = (cpuid >> 13) & 0x7; - switch (part_number) { - case 1: - cpu_pmu = xscale1pmu_init(); - break; - case 2: - cpu_pmu = xscale2pmu_init(); - break; - } - } - - if (cpu_pmu) { - pr_info("enabled with %s PMU driver, %d counters available\n", - cpu_pmu->name, cpu_pmu->num_events); - cpu_pmu_init(cpu_pmu); - register_cpu_notifier(&pmu_cpu_notifier); - armpmu_register(cpu_pmu, "cpu", PERF_TYPE_RAW); - } else { - pr_info("no hardware support available\n"); - } - - return 0; -} -early_initcall(init_hw_perf_events); - -/* - * Callchain handling code. - */ - -/* - * The registers we're interested in are at the end of the variable - * length saved register structure. The fp points at the end of this - * structure so the address of this struct is: - * (struct frame_tail *)(xxx->fp)-1 - * - * This code has been adapted from the ARM OProfile support. - */ -struct frame_tail { - struct frame_tail __user *fp; - unsigned long sp; - unsigned long lr; -} __attribute__((packed)); - -/* - * Get the return address for a single stackframe and return a pointer to the - * next frame tail. - */ -static struct frame_tail __user * -user_backtrace(struct frame_tail __user *tail, - struct perf_callchain_entry *entry) -{ - struct frame_tail buftail; - - /* Also check accessibility of one struct frame_tail beyond */ - if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) - return NULL; - if (__copy_from_user_inatomic(&buftail, tail, sizeof(buftail))) - return NULL; - - perf_callchain_store(entry, buftail.lr); - - /* - * Frame pointers should strictly progress back up the stack - * (towards higher addresses). - */ - if (tail + 1 >= buftail.fp) - return NULL; - - return buftail.fp - 1; -} - -void -perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) -{ - struct frame_tail __user *tail; - - - tail = (struct frame_tail __user *)regs->ARM_fp - 1; - - while ((entry->nr < PERF_MAX_STACK_DEPTH) && - tail && !((unsigned long)tail & 0x3)) - tail = user_backtrace(tail, entry); -} - -/* - * Gets called by walk_stackframe() for every stackframe. This will be called - * whist unwinding the stackframe and is like a subroutine return so we use - * the PC. - */ -static int -callchain_trace(struct stackframe *fr, - void *data) -{ - struct perf_callchain_entry *entry = data; - perf_callchain_store(entry, fr->pc); - return 0; -} - -void -perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs) -{ - struct stackframe fr; - - fr.fp = regs->ARM_fp; - fr.sp = regs->ARM_sp; - fr.lr = regs->ARM_lr; - fr.pc = regs->ARM_pc; - walk_stackframe(&fr, callchain_trace, entry); -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/perf_event_v6.c b/ANDROID_3.4.5/arch/arm/kernel/perf_event_v6.c deleted file mode 100644 index b78af0cc..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/perf_event_v6.c +++ /dev/null @@ -1,719 +0,0 @@ -/* - * ARMv6 Performance counter handling code. - * - * Copyright (C) 2009 picoChip Designs, Ltd., Jamie Iles - * - * ARMv6 has 2 configurable performance counters and a single cycle counter. - * They all share a single reset bit but can be written to zero so we can use - * that for a reset. - * - * The counters can't be individually enabled or disabled so when we remove - * one event and replace it with another we could get spurious counts from the - * wrong event. However, we can take advantage of the fact that the - * performance counters can export events to the event bus, and the event bus - * itself can be monitored. This requires that we *don't* export the events to - * the event bus. The procedure for disabling a configurable counter is: - * - change the counter to count the ETMEXTOUT[0] signal (0x20). This - * effectively stops the counter from counting. - * - disable the counter's interrupt generation (each counter has it's - * own interrupt enable bit). - * Once stopped, the counter value can be written as 0 to reset. - * - * To enable a counter: - * - enable the counter's interrupt generation. - * - set the new event type. - * - * Note: the dedicated cycle counter only counts cycles and can't be - * enabled/disabled independently of the others. When we want to disable the - * cycle counter, we have to just disable the interrupt reporting and start - * ignoring that counter. When re-enabling, we have to reset the value and - * enable the interrupt. - */ - -#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) -enum armv6_perf_types { - ARMV6_PERFCTR_ICACHE_MISS = 0x0, - ARMV6_PERFCTR_IBUF_STALL = 0x1, - ARMV6_PERFCTR_DDEP_STALL = 0x2, - ARMV6_PERFCTR_ITLB_MISS = 0x3, - ARMV6_PERFCTR_DTLB_MISS = 0x4, - ARMV6_PERFCTR_BR_EXEC = 0x5, - ARMV6_PERFCTR_BR_MISPREDICT = 0x6, - ARMV6_PERFCTR_INSTR_EXEC = 0x7, - ARMV6_PERFCTR_DCACHE_HIT = 0x9, - ARMV6_PERFCTR_DCACHE_ACCESS = 0xA, - ARMV6_PERFCTR_DCACHE_MISS = 0xB, - ARMV6_PERFCTR_DCACHE_WBACK = 0xC, - ARMV6_PERFCTR_SW_PC_CHANGE = 0xD, - ARMV6_PERFCTR_MAIN_TLB_MISS = 0xF, - ARMV6_PERFCTR_EXPL_D_ACCESS = 0x10, - ARMV6_PERFCTR_LSU_FULL_STALL = 0x11, - ARMV6_PERFCTR_WBUF_DRAINED = 0x12, - ARMV6_PERFCTR_CPU_CYCLES = 0xFF, - ARMV6_PERFCTR_NOP = 0x20, -}; - -enum armv6_counters { - ARMV6_CYCLE_COUNTER = 0, - ARMV6_COUNTER0, - ARMV6_COUNTER1, -}; - -/* - * The hardware events that we support. We do support cache operations but - * we have harvard caches and no way to combine instruction and data - * accesses/misses in hardware. - */ -static const unsigned armv6_perf_map[PERF_COUNT_HW_MAX] = { - [PERF_COUNT_HW_CPU_CYCLES] = ARMV6_PERFCTR_CPU_CYCLES, - [PERF_COUNT_HW_INSTRUCTIONS] = ARMV6_PERFCTR_INSTR_EXEC, - [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED, - [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED, - [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV6_PERFCTR_BR_EXEC, - [PERF_COUNT_HW_BRANCH_MISSES] = ARMV6_PERFCTR_BR_MISPREDICT, - [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED, - [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = ARMV6_PERFCTR_IBUF_STALL, - [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = ARMV6_PERFCTR_LSU_FULL_STALL, -}; - -static const unsigned armv6_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] - [PERF_COUNT_HW_CACHE_OP_MAX] - [PERF_COUNT_HW_CACHE_RESULT_MAX] = { - [C(L1D)] = { - /* - * The performance counters don't differentiate between read - * and write accesses/misses so this isn't strictly correct, - * but it's the best we can do. Writes and reads get - * combined. - */ - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = ARMV6_PERFCTR_DCACHE_ACCESS, - [C(RESULT_MISS)] = ARMV6_PERFCTR_DCACHE_MISS, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV6_PERFCTR_DCACHE_ACCESS, - [C(RESULT_MISS)] = ARMV6_PERFCTR_DCACHE_MISS, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(L1I)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV6_PERFCTR_ICACHE_MISS, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV6_PERFCTR_ICACHE_MISS, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(LL)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(DTLB)] = { - /* - * The ARM performance counters can count micro DTLB misses, - * micro ITLB misses and main TLB misses. There isn't an event - * for TLB misses, so use the micro misses here and if users - * want the main TLB misses they can use a raw counter. - */ - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV6_PERFCTR_DTLB_MISS, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV6_PERFCTR_DTLB_MISS, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(ITLB)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV6_PERFCTR_ITLB_MISS, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV6_PERFCTR_ITLB_MISS, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(BPU)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(NODE)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, -}; - -enum armv6mpcore_perf_types { - ARMV6MPCORE_PERFCTR_ICACHE_MISS = 0x0, - ARMV6MPCORE_PERFCTR_IBUF_STALL = 0x1, - ARMV6MPCORE_PERFCTR_DDEP_STALL = 0x2, - ARMV6MPCORE_PERFCTR_ITLB_MISS = 0x3, - ARMV6MPCORE_PERFCTR_DTLB_MISS = 0x4, - ARMV6MPCORE_PERFCTR_BR_EXEC = 0x5, - ARMV6MPCORE_PERFCTR_BR_NOTPREDICT = 0x6, - ARMV6MPCORE_PERFCTR_BR_MISPREDICT = 0x7, - ARMV6MPCORE_PERFCTR_INSTR_EXEC = 0x8, - ARMV6MPCORE_PERFCTR_DCACHE_RDACCESS = 0xA, - ARMV6MPCORE_PERFCTR_DCACHE_RDMISS = 0xB, - ARMV6MPCORE_PERFCTR_DCACHE_WRACCESS = 0xC, - ARMV6MPCORE_PERFCTR_DCACHE_WRMISS = 0xD, - ARMV6MPCORE_PERFCTR_DCACHE_EVICTION = 0xE, - ARMV6MPCORE_PERFCTR_SW_PC_CHANGE = 0xF, - ARMV6MPCORE_PERFCTR_MAIN_TLB_MISS = 0x10, - ARMV6MPCORE_PERFCTR_EXPL_MEM_ACCESS = 0x11, - ARMV6MPCORE_PERFCTR_LSU_FULL_STALL = 0x12, - ARMV6MPCORE_PERFCTR_WBUF_DRAINED = 0x13, - ARMV6MPCORE_PERFCTR_CPU_CYCLES = 0xFF, -}; - -/* - * The hardware events that we support. We do support cache operations but - * we have harvard caches and no way to combine instruction and data - * accesses/misses in hardware. - */ -static const unsigned armv6mpcore_perf_map[PERF_COUNT_HW_MAX] = { - [PERF_COUNT_HW_CPU_CYCLES] = ARMV6MPCORE_PERFCTR_CPU_CYCLES, - [PERF_COUNT_HW_INSTRUCTIONS] = ARMV6MPCORE_PERFCTR_INSTR_EXEC, - [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED, - [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED, - [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV6MPCORE_PERFCTR_BR_EXEC, - [PERF_COUNT_HW_BRANCH_MISSES] = ARMV6MPCORE_PERFCTR_BR_MISPREDICT, - [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED, - [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = ARMV6MPCORE_PERFCTR_IBUF_STALL, - [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = ARMV6MPCORE_PERFCTR_LSU_FULL_STALL, -}; - -static const unsigned armv6mpcore_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] - [PERF_COUNT_HW_CACHE_OP_MAX] - [PERF_COUNT_HW_CACHE_RESULT_MAX] = { - [C(L1D)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = - ARMV6MPCORE_PERFCTR_DCACHE_RDACCESS, - [C(RESULT_MISS)] = - ARMV6MPCORE_PERFCTR_DCACHE_RDMISS, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = - ARMV6MPCORE_PERFCTR_DCACHE_WRACCESS, - [C(RESULT_MISS)] = - ARMV6MPCORE_PERFCTR_DCACHE_WRMISS, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(L1I)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV6MPCORE_PERFCTR_ICACHE_MISS, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV6MPCORE_PERFCTR_ICACHE_MISS, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(LL)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(DTLB)] = { - /* - * The ARM performance counters can count micro DTLB misses, - * micro ITLB misses and main TLB misses. There isn't an event - * for TLB misses, so use the micro misses here and if users - * want the main TLB misses they can use a raw counter. - */ - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV6MPCORE_PERFCTR_DTLB_MISS, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV6MPCORE_PERFCTR_DTLB_MISS, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(ITLB)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV6MPCORE_PERFCTR_ITLB_MISS, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV6MPCORE_PERFCTR_ITLB_MISS, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(BPU)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(NODE)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, -}; - -static inline unsigned long -armv6_pmcr_read(void) -{ - u32 val; - asm volatile("mrc p15, 0, %0, c15, c12, 0" : "=r"(val)); - return val; -} - -static inline void -armv6_pmcr_write(unsigned long val) -{ - asm volatile("mcr p15, 0, %0, c15, c12, 0" : : "r"(val)); -} - -#define ARMV6_PMCR_ENABLE (1 << 0) -#define ARMV6_PMCR_CTR01_RESET (1 << 1) -#define ARMV6_PMCR_CCOUNT_RESET (1 << 2) -#define ARMV6_PMCR_CCOUNT_DIV (1 << 3) -#define ARMV6_PMCR_COUNT0_IEN (1 << 4) -#define ARMV6_PMCR_COUNT1_IEN (1 << 5) -#define ARMV6_PMCR_CCOUNT_IEN (1 << 6) -#define ARMV6_PMCR_COUNT0_OVERFLOW (1 << 8) -#define ARMV6_PMCR_COUNT1_OVERFLOW (1 << 9) -#define ARMV6_PMCR_CCOUNT_OVERFLOW (1 << 10) -#define ARMV6_PMCR_EVT_COUNT0_SHIFT 20 -#define ARMV6_PMCR_EVT_COUNT0_MASK (0xFF << ARMV6_PMCR_EVT_COUNT0_SHIFT) -#define ARMV6_PMCR_EVT_COUNT1_SHIFT 12 -#define ARMV6_PMCR_EVT_COUNT1_MASK (0xFF << ARMV6_PMCR_EVT_COUNT1_SHIFT) - -#define ARMV6_PMCR_OVERFLOWED_MASK \ - (ARMV6_PMCR_COUNT0_OVERFLOW | ARMV6_PMCR_COUNT1_OVERFLOW | \ - ARMV6_PMCR_CCOUNT_OVERFLOW) - -static inline int -armv6_pmcr_has_overflowed(unsigned long pmcr) -{ - return pmcr & ARMV6_PMCR_OVERFLOWED_MASK; -} - -static inline int -armv6_pmcr_counter_has_overflowed(unsigned long pmcr, - enum armv6_counters counter) -{ - int ret = 0; - - if (ARMV6_CYCLE_COUNTER == counter) - ret = pmcr & ARMV6_PMCR_CCOUNT_OVERFLOW; - else if (ARMV6_COUNTER0 == counter) - ret = pmcr & ARMV6_PMCR_COUNT0_OVERFLOW; - else if (ARMV6_COUNTER1 == counter) - ret = pmcr & ARMV6_PMCR_COUNT1_OVERFLOW; - else - WARN_ONCE(1, "invalid counter number (%d)\n", counter); - - return ret; -} - -static inline u32 -armv6pmu_read_counter(int counter) -{ - unsigned long value = 0; - - if (ARMV6_CYCLE_COUNTER == counter) - asm volatile("mrc p15, 0, %0, c15, c12, 1" : "=r"(value)); - else if (ARMV6_COUNTER0 == counter) - asm volatile("mrc p15, 0, %0, c15, c12, 2" : "=r"(value)); - else if (ARMV6_COUNTER1 == counter) - asm volatile("mrc p15, 0, %0, c15, c12, 3" : "=r"(value)); - else - WARN_ONCE(1, "invalid counter number (%d)\n", counter); - - return value; -} - -static inline void -armv6pmu_write_counter(int counter, - u32 value) -{ - if (ARMV6_CYCLE_COUNTER == counter) - asm volatile("mcr p15, 0, %0, c15, c12, 1" : : "r"(value)); - else if (ARMV6_COUNTER0 == counter) - asm volatile("mcr p15, 0, %0, c15, c12, 2" : : "r"(value)); - else if (ARMV6_COUNTER1 == counter) - asm volatile("mcr p15, 0, %0, c15, c12, 3" : : "r"(value)); - else - WARN_ONCE(1, "invalid counter number (%d)\n", counter); -} - -static void -armv6pmu_enable_event(struct hw_perf_event *hwc, - int idx) -{ - unsigned long val, mask, evt, flags; - struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - - if (ARMV6_CYCLE_COUNTER == idx) { - mask = 0; - evt = ARMV6_PMCR_CCOUNT_IEN; - } else if (ARMV6_COUNTER0 == idx) { - mask = ARMV6_PMCR_EVT_COUNT0_MASK; - evt = (hwc->config_base << ARMV6_PMCR_EVT_COUNT0_SHIFT) | - ARMV6_PMCR_COUNT0_IEN; - } else if (ARMV6_COUNTER1 == idx) { - mask = ARMV6_PMCR_EVT_COUNT1_MASK; - evt = (hwc->config_base << ARMV6_PMCR_EVT_COUNT1_SHIFT) | - ARMV6_PMCR_COUNT1_IEN; - } else { - WARN_ONCE(1, "invalid counter number (%d)\n", idx); - return; - } - - /* - * Mask out the current event and set the counter to count the event - * that we're interested in. - */ - raw_spin_lock_irqsave(&events->pmu_lock, flags); - val = armv6_pmcr_read(); - val &= ~mask; - val |= evt; - armv6_pmcr_write(val); - raw_spin_unlock_irqrestore(&events->pmu_lock, flags); -} - -static irqreturn_t -armv6pmu_handle_irq(int irq_num, - void *dev) -{ - unsigned long pmcr = armv6_pmcr_read(); - struct perf_sample_data data; - struct pmu_hw_events *cpuc; - struct pt_regs *regs; - int idx; - - if (!armv6_pmcr_has_overflowed(pmcr)) - return IRQ_NONE; - - regs = get_irq_regs(); - - /* - * The interrupts are cleared by writing the overflow flags back to - * the control register. All of the other bits don't have any effect - * if they are rewritten, so write the whole value back. - */ - armv6_pmcr_write(pmcr); - - perf_sample_data_init(&data, 0); - - cpuc = &__get_cpu_var(cpu_hw_events); - for (idx = 0; idx < cpu_pmu->num_events; ++idx) { - struct perf_event *event = cpuc->events[idx]; - struct hw_perf_event *hwc; - - /* Ignore if we don't have an event. */ - if (!event) - continue; - - /* - * We have a single interrupt for all counters. Check that - * each counter has overflowed before we process it. - */ - if (!armv6_pmcr_counter_has_overflowed(pmcr, idx)) - continue; - - hwc = &event->hw; - armpmu_event_update(event, hwc, idx); - data.period = event->hw.last_period; - if (!armpmu_event_set_period(event, hwc, idx)) - continue; - - if (perf_event_overflow(event, &data, regs)) - cpu_pmu->disable(hwc, idx); - } - - /* - * Handle the pending perf events. - * - * Note: this call *must* be run with interrupts disabled. For - * platforms that can have the PMU interrupts raised as an NMI, this - * will not work. - */ - irq_work_run(); - - return IRQ_HANDLED; -} - -static void -armv6pmu_start(void) -{ - unsigned long flags, val; - struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - - raw_spin_lock_irqsave(&events->pmu_lock, flags); - val = armv6_pmcr_read(); - val |= ARMV6_PMCR_ENABLE; - armv6_pmcr_write(val); - raw_spin_unlock_irqrestore(&events->pmu_lock, flags); -} - -static void -armv6pmu_stop(void) -{ - unsigned long flags, val; - struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - - raw_spin_lock_irqsave(&events->pmu_lock, flags); - val = armv6_pmcr_read(); - val &= ~ARMV6_PMCR_ENABLE; - armv6_pmcr_write(val); - raw_spin_unlock_irqrestore(&events->pmu_lock, flags); -} - -static int -armv6pmu_get_event_idx(struct pmu_hw_events *cpuc, - struct hw_perf_event *event) -{ - /* Always place a cycle counter into the cycle counter. */ - if (ARMV6_PERFCTR_CPU_CYCLES == event->config_base) { - if (test_and_set_bit(ARMV6_CYCLE_COUNTER, cpuc->used_mask)) - return -EAGAIN; - - return ARMV6_CYCLE_COUNTER; - } else { - /* - * For anything other than a cycle counter, try and use - * counter0 and counter1. - */ - if (!test_and_set_bit(ARMV6_COUNTER1, cpuc->used_mask)) - return ARMV6_COUNTER1; - - if (!test_and_set_bit(ARMV6_COUNTER0, cpuc->used_mask)) - return ARMV6_COUNTER0; - - /* The counters are all in use. */ - return -EAGAIN; - } -} - -static void -armv6pmu_disable_event(struct hw_perf_event *hwc, - int idx) -{ - unsigned long val, mask, evt, flags; - struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - - if (ARMV6_CYCLE_COUNTER == idx) { - mask = ARMV6_PMCR_CCOUNT_IEN; - evt = 0; - } else if (ARMV6_COUNTER0 == idx) { - mask = ARMV6_PMCR_COUNT0_IEN | ARMV6_PMCR_EVT_COUNT0_MASK; - evt = ARMV6_PERFCTR_NOP << ARMV6_PMCR_EVT_COUNT0_SHIFT; - } else if (ARMV6_COUNTER1 == idx) { - mask = ARMV6_PMCR_COUNT1_IEN | ARMV6_PMCR_EVT_COUNT1_MASK; - evt = ARMV6_PERFCTR_NOP << ARMV6_PMCR_EVT_COUNT1_SHIFT; - } else { - WARN_ONCE(1, "invalid counter number (%d)\n", idx); - return; - } - - /* - * Mask out the current event and set the counter to count the number - * of ETM bus signal assertion cycles. The external reporting should - * be disabled and so this should never increment. - */ - raw_spin_lock_irqsave(&events->pmu_lock, flags); - val = armv6_pmcr_read(); - val &= ~mask; - val |= evt; - armv6_pmcr_write(val); - raw_spin_unlock_irqrestore(&events->pmu_lock, flags); -} - -static void -armv6mpcore_pmu_disable_event(struct hw_perf_event *hwc, - int idx) -{ - unsigned long val, mask, flags, evt = 0; - struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - - if (ARMV6_CYCLE_COUNTER == idx) { - mask = ARMV6_PMCR_CCOUNT_IEN; - } else if (ARMV6_COUNTER0 == idx) { - mask = ARMV6_PMCR_COUNT0_IEN; - } else if (ARMV6_COUNTER1 == idx) { - mask = ARMV6_PMCR_COUNT1_IEN; - } else { - WARN_ONCE(1, "invalid counter number (%d)\n", idx); - return; - } - - /* - * Unlike UP ARMv6, we don't have a way of stopping the counters. We - * simply disable the interrupt reporting. - */ - raw_spin_lock_irqsave(&events->pmu_lock, flags); - val = armv6_pmcr_read(); - val &= ~mask; - val |= evt; - armv6_pmcr_write(val); - raw_spin_unlock_irqrestore(&events->pmu_lock, flags); -} - -static int armv6_map_event(struct perf_event *event) -{ - return map_cpu_event(event, &armv6_perf_map, - &armv6_perf_cache_map, 0xFF); -} - -static struct arm_pmu armv6pmu = { - .id = ARM_PERF_PMU_ID_V6, - .name = "v6", - .handle_irq = armv6pmu_handle_irq, - .enable = armv6pmu_enable_event, - .disable = armv6pmu_disable_event, - .read_counter = armv6pmu_read_counter, - .write_counter = armv6pmu_write_counter, - .get_event_idx = armv6pmu_get_event_idx, - .start = armv6pmu_start, - .stop = armv6pmu_stop, - .map_event = armv6_map_event, - .num_events = 3, - .max_period = (1LLU << 32) - 1, -}; - -static struct arm_pmu *__init armv6pmu_init(void) -{ - return &armv6pmu; -} - -/* - * ARMv6mpcore is almost identical to single core ARMv6 with the exception - * that some of the events have different enumerations and that there is no - * *hack* to stop the programmable counters. To stop the counters we simply - * disable the interrupt reporting and update the event. When unthrottling we - * reset the period and enable the interrupt reporting. - */ - -static int armv6mpcore_map_event(struct perf_event *event) -{ - return map_cpu_event(event, &armv6mpcore_perf_map, - &armv6mpcore_perf_cache_map, 0xFF); -} - -static struct arm_pmu armv6mpcore_pmu = { - .id = ARM_PERF_PMU_ID_V6MP, - .name = "v6mpcore", - .handle_irq = armv6pmu_handle_irq, - .enable = armv6pmu_enable_event, - .disable = armv6mpcore_pmu_disable_event, - .read_counter = armv6pmu_read_counter, - .write_counter = armv6pmu_write_counter, - .get_event_idx = armv6pmu_get_event_idx, - .start = armv6pmu_start, - .stop = armv6pmu_stop, - .map_event = armv6mpcore_map_event, - .num_events = 3, - .max_period = (1LLU << 32) - 1, -}; - -static struct arm_pmu *__init armv6mpcore_pmu_init(void) -{ - return &armv6mpcore_pmu; -} -#else -static struct arm_pmu *__init armv6pmu_init(void) -{ - return NULL; -} - -static struct arm_pmu *__init armv6mpcore_pmu_init(void) -{ - return NULL; -} -#endif /* CONFIG_CPU_V6 || CONFIG_CPU_V6K */ diff --git a/ANDROID_3.4.5/arch/arm/kernel/perf_event_v7.c b/ANDROID_3.4.5/arch/arm/kernel/perf_event_v7.c deleted file mode 100644 index 00755d82..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/perf_event_v7.c +++ /dev/null @@ -1,1332 +0,0 @@ -/* - * ARMv7 Cortex-A8 and Cortex-A9 Performance Events handling code. - * - * ARMv7 support: Jean Pihet <jpihet@mvista.com> - * 2010 (c) MontaVista Software, LLC. - * - * Copied from ARMv6 code, with the low level code inspired - * by the ARMv7 Oprofile code. - * - * Cortex-A8 has up to 4 configurable performance counters and - * a single cycle counter. - * Cortex-A9 has up to 31 configurable performance counters and - * a single cycle counter. - * - * All counters can be enabled/disabled and IRQ masked separately. The cycle - * counter and all 4 performance counters together can be reset separately. - */ - -#ifdef CONFIG_CPU_V7 - -static struct arm_pmu armv7pmu; - -/* - * Common ARMv7 event types - * - * Note: An implementation may not be able to count all of these events - * but the encodings are considered to be `reserved' in the case that - * they are not available. - */ -enum armv7_perf_types { - ARMV7_PERFCTR_PMNC_SW_INCR = 0x00, - ARMV7_PERFCTR_L1_ICACHE_REFILL = 0x01, - ARMV7_PERFCTR_ITLB_REFILL = 0x02, - ARMV7_PERFCTR_L1_DCACHE_REFILL = 0x03, - ARMV7_PERFCTR_L1_DCACHE_ACCESS = 0x04, - ARMV7_PERFCTR_DTLB_REFILL = 0x05, - ARMV7_PERFCTR_MEM_READ = 0x06, - ARMV7_PERFCTR_MEM_WRITE = 0x07, - ARMV7_PERFCTR_INSTR_EXECUTED = 0x08, - ARMV7_PERFCTR_EXC_TAKEN = 0x09, - ARMV7_PERFCTR_EXC_EXECUTED = 0x0A, - ARMV7_PERFCTR_CID_WRITE = 0x0B, - - /* - * ARMV7_PERFCTR_PC_WRITE is equivalent to HW_BRANCH_INSTRUCTIONS. - * It counts: - * - all (taken) branch instructions, - * - instructions that explicitly write the PC, - * - exception generating instructions. - */ - ARMV7_PERFCTR_PC_WRITE = 0x0C, - ARMV7_PERFCTR_PC_IMM_BRANCH = 0x0D, - ARMV7_PERFCTR_PC_PROC_RETURN = 0x0E, - ARMV7_PERFCTR_MEM_UNALIGNED_ACCESS = 0x0F, - ARMV7_PERFCTR_PC_BRANCH_MIS_PRED = 0x10, - ARMV7_PERFCTR_CLOCK_CYCLES = 0x11, - ARMV7_PERFCTR_PC_BRANCH_PRED = 0x12, - - /* These events are defined by the PMUv2 supplement (ARM DDI 0457A). */ - ARMV7_PERFCTR_MEM_ACCESS = 0x13, - ARMV7_PERFCTR_L1_ICACHE_ACCESS = 0x14, - ARMV7_PERFCTR_L1_DCACHE_WB = 0x15, - ARMV7_PERFCTR_L2_CACHE_ACCESS = 0x16, - ARMV7_PERFCTR_L2_CACHE_REFILL = 0x17, - ARMV7_PERFCTR_L2_CACHE_WB = 0x18, - ARMV7_PERFCTR_BUS_ACCESS = 0x19, - ARMV7_PERFCTR_MEM_ERROR = 0x1A, - ARMV7_PERFCTR_INSTR_SPEC = 0x1B, - ARMV7_PERFCTR_TTBR_WRITE = 0x1C, - ARMV7_PERFCTR_BUS_CYCLES = 0x1D, - - ARMV7_PERFCTR_CPU_CYCLES = 0xFF -}; - -/* ARMv7 Cortex-A8 specific event types */ -enum armv7_a8_perf_types { - ARMV7_A8_PERFCTR_L2_CACHE_ACCESS = 0x43, - ARMV7_A8_PERFCTR_L2_CACHE_REFILL = 0x44, - ARMV7_A8_PERFCTR_L1_ICACHE_ACCESS = 0x50, - ARMV7_A8_PERFCTR_STALL_ISIDE = 0x56, -}; - -/* ARMv7 Cortex-A9 specific event types */ -enum armv7_a9_perf_types { - ARMV7_A9_PERFCTR_INSTR_CORE_RENAME = 0x68, - ARMV7_A9_PERFCTR_STALL_ICACHE = 0x60, - ARMV7_A9_PERFCTR_STALL_DISPATCH = 0x66, -}; - -/* ARMv7 Cortex-A5 specific event types */ -enum armv7_a5_perf_types { - ARMV7_A5_PERFCTR_PREFETCH_LINEFILL = 0xc2, - ARMV7_A5_PERFCTR_PREFETCH_LINEFILL_DROP = 0xc3, -}; - -/* ARMv7 Cortex-A15 specific event types */ -enum armv7_a15_perf_types { - ARMV7_A15_PERFCTR_L1_DCACHE_ACCESS_READ = 0x40, - ARMV7_A15_PERFCTR_L1_DCACHE_ACCESS_WRITE = 0x41, - ARMV7_A15_PERFCTR_L1_DCACHE_REFILL_READ = 0x42, - ARMV7_A15_PERFCTR_L1_DCACHE_REFILL_WRITE = 0x43, - - ARMV7_A15_PERFCTR_DTLB_REFILL_L1_READ = 0x4C, - ARMV7_A15_PERFCTR_DTLB_REFILL_L1_WRITE = 0x4D, - - ARMV7_A15_PERFCTR_L2_CACHE_ACCESS_READ = 0x50, - ARMV7_A15_PERFCTR_L2_CACHE_ACCESS_WRITE = 0x51, - ARMV7_A15_PERFCTR_L2_CACHE_REFILL_READ = 0x52, - ARMV7_A15_PERFCTR_L2_CACHE_REFILL_WRITE = 0x53, - - ARMV7_A15_PERFCTR_PC_WRITE_SPEC = 0x76, -}; - -/* - * Cortex-A8 HW events mapping - * - * The hardware events that we support. We do support cache operations but - * we have harvard caches and no way to combine instruction and data - * accesses/misses in hardware. - */ -static const unsigned armv7_a8_perf_map[PERF_COUNT_HW_MAX] = { - [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES, - [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED, - [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, - [PERF_COUNT_HW_CACHE_MISSES] = ARMV7_PERFCTR_L1_DCACHE_REFILL, - [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE, - [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, - [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED, - [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = ARMV7_A8_PERFCTR_STALL_ISIDE, - [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = HW_OP_UNSUPPORTED, -}; - -static const unsigned armv7_a8_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] - [PERF_COUNT_HW_CACHE_OP_MAX] - [PERF_COUNT_HW_CACHE_RESULT_MAX] = { - [C(L1D)] = { - /* - * The performance counters don't differentiate between read - * and write accesses/misses so this isn't strictly correct, - * but it's the best we can do. Writes and reads get - * combined. - */ - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(L1I)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = ARMV7_A8_PERFCTR_L1_ICACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV7_A8_PERFCTR_L1_ICACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(LL)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = ARMV7_A8_PERFCTR_L2_CACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_A8_PERFCTR_L2_CACHE_REFILL, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV7_A8_PERFCTR_L2_CACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_A8_PERFCTR_L2_CACHE_REFILL, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(DTLB)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(ITLB)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(BPU)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(NODE)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, -}; - -/* - * Cortex-A9 HW events mapping - */ -static const unsigned armv7_a9_perf_map[PERF_COUNT_HW_MAX] = { - [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES, - [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_A9_PERFCTR_INSTR_CORE_RENAME, - [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, - [PERF_COUNT_HW_CACHE_MISSES] = ARMV7_PERFCTR_L1_DCACHE_REFILL, - [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE, - [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, - [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED, - [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = ARMV7_A9_PERFCTR_STALL_ICACHE, - [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = ARMV7_A9_PERFCTR_STALL_DISPATCH, -}; - -static const unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] - [PERF_COUNT_HW_CACHE_OP_MAX] - [PERF_COUNT_HW_CACHE_RESULT_MAX] = { - [C(L1D)] = { - /* - * The performance counters don't differentiate between read - * and write accesses/misses so this isn't strictly correct, - * but it's the best we can do. Writes and reads get - * combined. - */ - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(L1I)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(LL)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(DTLB)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(ITLB)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(BPU)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(NODE)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, -}; - -/* - * Cortex-A5 HW events mapping - */ -static const unsigned armv7_a5_perf_map[PERF_COUNT_HW_MAX] = { - [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES, - [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED, - [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, - [PERF_COUNT_HW_CACHE_MISSES] = ARMV7_PERFCTR_L1_DCACHE_REFILL, - [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE, - [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, - [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED, - [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = HW_OP_UNSUPPORTED, - [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = HW_OP_UNSUPPORTED, -}; - -static const unsigned armv7_a5_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] - [PERF_COUNT_HW_CACHE_OP_MAX] - [PERF_COUNT_HW_CACHE_RESULT_MAX] = { - [C(L1D)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = ARMV7_A5_PERFCTR_PREFETCH_LINEFILL, - [C(RESULT_MISS)] = ARMV7_A5_PERFCTR_PREFETCH_LINEFILL_DROP, - }, - }, - [C(L1I)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, - }, - /* - * The prefetch counters don't differentiate between the I - * side and the D side. - */ - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = ARMV7_A5_PERFCTR_PREFETCH_LINEFILL, - [C(RESULT_MISS)] = ARMV7_A5_PERFCTR_PREFETCH_LINEFILL_DROP, - }, - }, - [C(LL)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(DTLB)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(ITLB)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(BPU)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(NODE)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, -}; - -/* - * Cortex-A15 HW events mapping - */ -static const unsigned armv7_a15_perf_map[PERF_COUNT_HW_MAX] = { - [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES, - [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED, - [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, - [PERF_COUNT_HW_CACHE_MISSES] = ARMV7_PERFCTR_L1_DCACHE_REFILL, - [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_A15_PERFCTR_PC_WRITE_SPEC, - [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, - [PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_BUS_CYCLES, - [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = HW_OP_UNSUPPORTED, - [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = HW_OP_UNSUPPORTED, -}; - -static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] - [PERF_COUNT_HW_CACHE_OP_MAX] - [PERF_COUNT_HW_CACHE_RESULT_MAX] = { - [C(L1D)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = ARMV7_A15_PERFCTR_L1_DCACHE_ACCESS_READ, - [C(RESULT_MISS)] = ARMV7_A15_PERFCTR_L1_DCACHE_REFILL_READ, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV7_A15_PERFCTR_L1_DCACHE_ACCESS_WRITE, - [C(RESULT_MISS)] = ARMV7_A15_PERFCTR_L1_DCACHE_REFILL_WRITE, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(L1I)] = { - /* - * Not all performance counters differentiate between read - * and write accesses/misses so we're not always strictly - * correct, but it's the best we can do. Writes and reads get - * combined in these cases. - */ - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(LL)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = ARMV7_A15_PERFCTR_L2_CACHE_ACCESS_READ, - [C(RESULT_MISS)] = ARMV7_A15_PERFCTR_L2_CACHE_REFILL_READ, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV7_A15_PERFCTR_L2_CACHE_ACCESS_WRITE, - [C(RESULT_MISS)] = ARMV7_A15_PERFCTR_L2_CACHE_REFILL_WRITE, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(DTLB)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_A15_PERFCTR_DTLB_REFILL_L1_READ, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_A15_PERFCTR_DTLB_REFILL_L1_WRITE, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(ITLB)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(BPU)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(NODE)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, -}; - -/* - * Cortex-A7 HW events mapping - */ -static const unsigned armv7_a7_perf_map[PERF_COUNT_HW_MAX] = { - [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES, - [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED, - [PERF_COUNT_HW_CACHE_REFERENCES] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, - [PERF_COUNT_HW_CACHE_MISSES] = ARMV7_PERFCTR_L1_DCACHE_REFILL, - [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE, - [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, - [PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_BUS_CYCLES, - [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = HW_OP_UNSUPPORTED, - [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = HW_OP_UNSUPPORTED, -}; - -static const unsigned armv7_a7_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] - [PERF_COUNT_HW_CACHE_OP_MAX] - [PERF_COUNT_HW_CACHE_RESULT_MAX] = { - [C(L1D)] = { - /* - * The performance counters don't differentiate between read - * and write accesses/misses so this isn't strictly correct, - * but it's the best we can do. Writes and reads get - * combined. - */ - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_DCACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_DCACHE_REFILL, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(L1I)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L1_ICACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L1_ICACHE_REFILL, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(LL)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L2_CACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L2_CACHE_REFILL, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_L2_CACHE_ACCESS, - [C(RESULT_MISS)] = ARMV7_PERFCTR_L2_CACHE_REFILL, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(DTLB)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_DTLB_REFILL, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(ITLB)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_ITLB_REFILL, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(BPU)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = ARMV7_PERFCTR_PC_BRANCH_PRED, - [C(RESULT_MISS)] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(NODE)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, -}; - -/* - * Perf Events' indices - */ -#define ARMV7_IDX_CYCLE_COUNTER 0 -#define ARMV7_IDX_COUNTER0 1 -#define ARMV7_IDX_COUNTER_LAST (ARMV7_IDX_CYCLE_COUNTER + cpu_pmu->num_events - 1) - -#define ARMV7_MAX_COUNTERS 32 -#define ARMV7_COUNTER_MASK (ARMV7_MAX_COUNTERS - 1) - -/* - * ARMv7 low level PMNC access - */ - -/* - * Perf Event to low level counters mapping - */ -#define ARMV7_IDX_TO_COUNTER(x) \ - (((x) - ARMV7_IDX_COUNTER0) & ARMV7_COUNTER_MASK) - -/* - * Per-CPU PMNC: config reg - */ -#define ARMV7_PMNC_E (1 << 0) /* Enable all counters */ -#define ARMV7_PMNC_P (1 << 1) /* Reset all counters */ -#define ARMV7_PMNC_C (1 << 2) /* Cycle counter reset */ -#define ARMV7_PMNC_D (1 << 3) /* CCNT counts every 64th cpu cycle */ -#define ARMV7_PMNC_X (1 << 4) /* Export to ETM */ -#define ARMV7_PMNC_DP (1 << 5) /* Disable CCNT if non-invasive debug*/ -#define ARMV7_PMNC_N_SHIFT 11 /* Number of counters supported */ -#define ARMV7_PMNC_N_MASK 0x1f -#define ARMV7_PMNC_MASK 0x3f /* Mask for writable bits */ - -/* - * FLAG: counters overflow flag status reg - */ -#define ARMV7_FLAG_MASK 0xffffffff /* Mask for writable bits */ -#define ARMV7_OVERFLOWED_MASK ARMV7_FLAG_MASK - -/* - * PMXEVTYPER: Event selection reg - */ -#define ARMV7_EVTYPE_MASK 0xc00000ff /* Mask for writable bits */ -#define ARMV7_EVTYPE_EVENT 0xff /* Mask for EVENT bits */ - -/* - * Event filters for PMUv2 - */ -#define ARMV7_EXCLUDE_PL1 (1 << 31) -#define ARMV7_EXCLUDE_USER (1 << 30) -#define ARMV7_INCLUDE_HYP (1 << 27) - -static inline u32 armv7_pmnc_read(void) -{ - u32 val; - asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r"(val)); - return val; -} - -static inline void armv7_pmnc_write(u32 val) -{ - val &= ARMV7_PMNC_MASK; - isb(); - asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r"(val)); -} - -static inline int armv7_pmnc_has_overflowed(u32 pmnc) -{ - return pmnc & ARMV7_OVERFLOWED_MASK; -} - -static inline int armv7_pmnc_counter_valid(int idx) -{ - return idx >= ARMV7_IDX_CYCLE_COUNTER && idx <= ARMV7_IDX_COUNTER_LAST; -} - -static inline int armv7_pmnc_counter_has_overflowed(u32 pmnc, int idx) -{ - int ret = 0; - u32 counter; - - if (!armv7_pmnc_counter_valid(idx)) { - pr_err("CPU%u checking wrong counter %d overflow status\n", - smp_processor_id(), idx); - } else { - counter = ARMV7_IDX_TO_COUNTER(idx); - ret = pmnc & BIT(counter); - } - - return ret; -} - -static inline int armv7_pmnc_select_counter(int idx) -{ - u32 counter; - - if (!armv7_pmnc_counter_valid(idx)) { - pr_err("CPU%u selecting wrong PMNC counter %d\n", - smp_processor_id(), idx); - return -EINVAL; - } - - counter = ARMV7_IDX_TO_COUNTER(idx); - asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (counter)); - isb(); - - return idx; -} - -static inline u32 armv7pmu_read_counter(int idx) -{ - u32 value = 0; - - if (!armv7_pmnc_counter_valid(idx)) - pr_err("CPU%u reading wrong counter %d\n", - smp_processor_id(), idx); - else if (idx == ARMV7_IDX_CYCLE_COUNTER) - asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (value)); - else if (armv7_pmnc_select_counter(idx) == idx) - asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (value)); - - return value; -} - -static inline void armv7pmu_write_counter(int idx, u32 value) -{ - if (!armv7_pmnc_counter_valid(idx)) - pr_err("CPU%u writing wrong counter %d\n", - smp_processor_id(), idx); - else if (idx == ARMV7_IDX_CYCLE_COUNTER) - asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value)); - else if (armv7_pmnc_select_counter(idx) == idx) - asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (value)); -} - -static inline void armv7_pmnc_write_evtsel(int idx, u32 val) -{ - if (armv7_pmnc_select_counter(idx) == idx) { - val &= ARMV7_EVTYPE_MASK; - asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val)); - } -} - -static inline int armv7_pmnc_enable_counter(int idx) -{ - u32 counter; - - if (!armv7_pmnc_counter_valid(idx)) { - pr_err("CPU%u enabling wrong PMNC counter %d\n", - smp_processor_id(), idx); - return -EINVAL; - } - - counter = ARMV7_IDX_TO_COUNTER(idx); - asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (BIT(counter))); - return idx; -} - -static inline int armv7_pmnc_disable_counter(int idx) -{ - u32 counter; - - if (!armv7_pmnc_counter_valid(idx)) { - pr_err("CPU%u disabling wrong PMNC counter %d\n", - smp_processor_id(), idx); - return -EINVAL; - } - - counter = ARMV7_IDX_TO_COUNTER(idx); - asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (BIT(counter))); - return idx; -} - -static inline int armv7_pmnc_enable_intens(int idx) -{ - u32 counter; - - if (!armv7_pmnc_counter_valid(idx)) { - pr_err("CPU%u enabling wrong PMNC counter IRQ enable %d\n", - smp_processor_id(), idx); - return -EINVAL; - } - - counter = ARMV7_IDX_TO_COUNTER(idx); - asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (BIT(counter))); - return idx; -} - -static inline int armv7_pmnc_disable_intens(int idx) -{ - u32 counter; - - if (!armv7_pmnc_counter_valid(idx)) { - pr_err("CPU%u disabling wrong PMNC counter IRQ enable %d\n", - smp_processor_id(), idx); - return -EINVAL; - } - - counter = ARMV7_IDX_TO_COUNTER(idx); - asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (BIT(counter))); - isb(); - /* Clear the overflow flag in case an interrupt is pending. */ - asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (BIT(counter))); - isb(); - - return idx; -} - -static inline u32 armv7_pmnc_getreset_flags(void) -{ - u32 val; - - /* Read */ - asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val)); - - /* Write to clear flags */ - val &= ARMV7_FLAG_MASK; - asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (val)); - - return val; -} - -#ifdef DEBUG -static void armv7_pmnc_dump_regs(void) -{ - u32 val; - unsigned int cnt; - - printk(KERN_INFO "PMNC registers dump:\n"); - - asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val)); - printk(KERN_INFO "PMNC =0x%08x\n", val); - - asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r" (val)); - printk(KERN_INFO "CNTENS=0x%08x\n", val); - - asm volatile("mrc p15, 0, %0, c9, c14, 1" : "=r" (val)); - printk(KERN_INFO "INTENS=0x%08x\n", val); - - asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val)); - printk(KERN_INFO "FLAGS =0x%08x\n", val); - - asm volatile("mrc p15, 0, %0, c9, c12, 5" : "=r" (val)); - printk(KERN_INFO "SELECT=0x%08x\n", val); - - asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val)); - printk(KERN_INFO "CCNT =0x%08x\n", val); - - for (cnt = ARMV7_IDX_COUNTER0; cnt <= ARMV7_IDX_COUNTER_LAST; cnt++) { - armv7_pmnc_select_counter(cnt); - asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val)); - printk(KERN_INFO "CNT[%d] count =0x%08x\n", - ARMV7_IDX_TO_COUNTER(cnt), val); - asm volatile("mrc p15, 0, %0, c9, c13, 1" : "=r" (val)); - printk(KERN_INFO "CNT[%d] evtsel=0x%08x\n", - ARMV7_IDX_TO_COUNTER(cnt), val); - } -} -#endif - -static void armv7pmu_enable_event(struct hw_perf_event *hwc, int idx) -{ - unsigned long flags; - struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - - /* - * Enable counter and interrupt, and set the counter to count - * the event that we're interested in. - */ - raw_spin_lock_irqsave(&events->pmu_lock, flags); - - /* - * Disable counter - */ - armv7_pmnc_disable_counter(idx); - - /* - * Set event (if destined for PMNx counters) - * We only need to set the event for the cycle counter if we - * have the ability to perform event filtering. - */ - if (armv7pmu.set_event_filter || idx != ARMV7_IDX_CYCLE_COUNTER) - armv7_pmnc_write_evtsel(idx, hwc->config_base); - - /* - * Enable interrupt for this counter - */ - armv7_pmnc_enable_intens(idx); - - /* - * Enable counter - */ - armv7_pmnc_enable_counter(idx); - - raw_spin_unlock_irqrestore(&events->pmu_lock, flags); -} - -static void armv7pmu_disable_event(struct hw_perf_event *hwc, int idx) -{ - unsigned long flags; - struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - - /* - * Disable counter and interrupt - */ - raw_spin_lock_irqsave(&events->pmu_lock, flags); - - /* - * Disable counter - */ - armv7_pmnc_disable_counter(idx); - - /* - * Disable interrupt for this counter - */ - armv7_pmnc_disable_intens(idx); - - raw_spin_unlock_irqrestore(&events->pmu_lock, flags); -} - -static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev) -{ - u32 pmnc; - struct perf_sample_data data; - struct pmu_hw_events *cpuc; - struct pt_regs *regs; - int idx; - - /* - * Get and reset the IRQ flags - */ - pmnc = armv7_pmnc_getreset_flags(); - - /* - * Did an overflow occur? - */ - if (!armv7_pmnc_has_overflowed(pmnc)) - return IRQ_NONE; - - /* - * Handle the counter(s) overflow(s) - */ - regs = get_irq_regs(); - - perf_sample_data_init(&data, 0); - - cpuc = &__get_cpu_var(cpu_hw_events); - for (idx = 0; idx < cpu_pmu->num_events; ++idx) { - struct perf_event *event = cpuc->events[idx]; - struct hw_perf_event *hwc; - - /* Ignore if we don't have an event. */ - if (!event) - continue; - - /* - * We have a single interrupt for all counters. Check that - * each counter has overflowed before we process it. - */ - if (!armv7_pmnc_counter_has_overflowed(pmnc, idx)) - continue; - - hwc = &event->hw; - armpmu_event_update(event, hwc, idx); - data.period = event->hw.last_period; - if (!armpmu_event_set_period(event, hwc, idx)) - continue; - - if (perf_event_overflow(event, &data, regs)) - cpu_pmu->disable(hwc, idx); - } - - /* - * Handle the pending perf events. - * - * Note: this call *must* be run with interrupts disabled. For - * platforms that can have the PMU interrupts raised as an NMI, this - * will not work. - */ - irq_work_run(); - - return IRQ_HANDLED; -} - -static void armv7pmu_start(void) -{ - unsigned long flags; - struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - - raw_spin_lock_irqsave(&events->pmu_lock, flags); - /* Enable all counters */ - armv7_pmnc_write(armv7_pmnc_read() | ARMV7_PMNC_E); - raw_spin_unlock_irqrestore(&events->pmu_lock, flags); -} - -static void armv7pmu_stop(void) -{ - unsigned long flags; - struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - - raw_spin_lock_irqsave(&events->pmu_lock, flags); - /* Disable all counters */ - armv7_pmnc_write(armv7_pmnc_read() & ~ARMV7_PMNC_E); - raw_spin_unlock_irqrestore(&events->pmu_lock, flags); -} - -static int armv7pmu_get_event_idx(struct pmu_hw_events *cpuc, - struct hw_perf_event *event) -{ - int idx; - unsigned long evtype = event->config_base & ARMV7_EVTYPE_EVENT; - - /* Always place a cycle counter into the cycle counter. */ - if (evtype == ARMV7_PERFCTR_CPU_CYCLES) { - if (test_and_set_bit(ARMV7_IDX_CYCLE_COUNTER, cpuc->used_mask)) - return -EAGAIN; - - return ARMV7_IDX_CYCLE_COUNTER; - } - - /* - * For anything other than a cycle counter, try and use - * the events counters - */ - for (idx = ARMV7_IDX_COUNTER0; idx < cpu_pmu->num_events; ++idx) { - if (!test_and_set_bit(idx, cpuc->used_mask)) - return idx; - } - - /* The counters are all in use. */ - return -EAGAIN; -} - -/* - * Add an event filter to a given event. This will only work for PMUv2 PMUs. - */ -static int armv7pmu_set_event_filter(struct hw_perf_event *event, - struct perf_event_attr *attr) -{ - unsigned long config_base = 0; - - if (attr->exclude_idle) - return -EPERM; - if (attr->exclude_user) - config_base |= ARMV7_EXCLUDE_USER; - if (attr->exclude_kernel) - config_base |= ARMV7_EXCLUDE_PL1; - if (!attr->exclude_hv) - config_base |= ARMV7_INCLUDE_HYP; - - /* - * Install the filter into config_base as this is used to - * construct the event type. - */ - event->config_base = config_base; - - return 0; -} - -static void armv7pmu_reset(void *info) -{ - u32 idx, nb_cnt = cpu_pmu->num_events; - - /* The counter and interrupt enable registers are unknown at reset. */ - for (idx = ARMV7_IDX_CYCLE_COUNTER; idx < nb_cnt; ++idx) - armv7pmu_disable_event(NULL, idx); - - /* Initialize & Reset PMNC: C and P bits */ - armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C); -} - -static int armv7_a8_map_event(struct perf_event *event) -{ - return map_cpu_event(event, &armv7_a8_perf_map, - &armv7_a8_perf_cache_map, 0xFF); -} - -static int armv7_a9_map_event(struct perf_event *event) -{ - return map_cpu_event(event, &armv7_a9_perf_map, - &armv7_a9_perf_cache_map, 0xFF); -} - -static int armv7_a5_map_event(struct perf_event *event) -{ - return map_cpu_event(event, &armv7_a5_perf_map, - &armv7_a5_perf_cache_map, 0xFF); -} - -static int armv7_a15_map_event(struct perf_event *event) -{ - return map_cpu_event(event, &armv7_a15_perf_map, - &armv7_a15_perf_cache_map, 0xFF); -} - -static int armv7_a7_map_event(struct perf_event *event) -{ - return map_cpu_event(event, &armv7_a7_perf_map, - &armv7_a7_perf_cache_map, 0xFF); -} - -static struct arm_pmu armv7pmu = { - .handle_irq = armv7pmu_handle_irq, - .enable = armv7pmu_enable_event, - .disable = armv7pmu_disable_event, - .read_counter = armv7pmu_read_counter, - .write_counter = armv7pmu_write_counter, - .get_event_idx = armv7pmu_get_event_idx, - .start = armv7pmu_start, - .stop = armv7pmu_stop, - .reset = armv7pmu_reset, - .max_period = (1LLU << 32) - 1, -}; - -static u32 __init armv7_read_num_pmnc_events(void) -{ - u32 nb_cnt; - - /* Read the nb of CNTx counters supported from PMNC */ - nb_cnt = (armv7_pmnc_read() >> ARMV7_PMNC_N_SHIFT) & ARMV7_PMNC_N_MASK; - - /* Add the CPU cycles counter and return */ - return nb_cnt + 1; -} - -static struct arm_pmu *__init armv7_a8_pmu_init(void) -{ - armv7pmu.id = ARM_PERF_PMU_ID_CA8; - armv7pmu.name = "ARMv7 Cortex-A8"; - armv7pmu.map_event = armv7_a8_map_event; - armv7pmu.num_events = armv7_read_num_pmnc_events(); - return &armv7pmu; -} - -static struct arm_pmu *__init armv7_a9_pmu_init(void) -{ - armv7pmu.id = ARM_PERF_PMU_ID_CA9; - armv7pmu.name = "ARMv7 Cortex-A9"; - armv7pmu.map_event = armv7_a9_map_event; - armv7pmu.num_events = armv7_read_num_pmnc_events(); - return &armv7pmu; -} - -static struct arm_pmu *__init armv7_a5_pmu_init(void) -{ - armv7pmu.id = ARM_PERF_PMU_ID_CA5; - armv7pmu.name = "ARMv7 Cortex-A5"; - armv7pmu.map_event = armv7_a5_map_event; - armv7pmu.num_events = armv7_read_num_pmnc_events(); - return &armv7pmu; -} - -static struct arm_pmu *__init armv7_a15_pmu_init(void) -{ - armv7pmu.id = ARM_PERF_PMU_ID_CA15; - armv7pmu.name = "ARMv7 Cortex-A15"; - armv7pmu.map_event = armv7_a15_map_event; - armv7pmu.num_events = armv7_read_num_pmnc_events(); - armv7pmu.set_event_filter = armv7pmu_set_event_filter; - return &armv7pmu; -} - -static struct arm_pmu *__init armv7_a7_pmu_init(void) -{ - armv7pmu.id = ARM_PERF_PMU_ID_CA7; - armv7pmu.name = "ARMv7 Cortex-A7"; - armv7pmu.map_event = armv7_a7_map_event; - armv7pmu.num_events = armv7_read_num_pmnc_events(); - armv7pmu.set_event_filter = armv7pmu_set_event_filter; - return &armv7pmu; -} -#else -static struct arm_pmu *__init armv7_a8_pmu_init(void) -{ - return NULL; -} - -static struct arm_pmu *__init armv7_a9_pmu_init(void) -{ - return NULL; -} - -static struct arm_pmu *__init armv7_a5_pmu_init(void) -{ - return NULL; -} - -static struct arm_pmu *__init armv7_a15_pmu_init(void) -{ - return NULL; -} - -static struct arm_pmu *__init armv7_a7_pmu_init(void) -{ - return NULL; -} -#endif /* CONFIG_CPU_V7 */ diff --git a/ANDROID_3.4.5/arch/arm/kernel/perf_event_xscale.c b/ANDROID_3.4.5/arch/arm/kernel/perf_event_xscale.c deleted file mode 100644 index 71a21e67..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/perf_event_xscale.c +++ /dev/null @@ -1,839 +0,0 @@ -/* - * ARMv5 [xscale] Performance counter handling code. - * - * Copyright (C) 2010, ARM Ltd., Will Deacon <will.deacon@arm.com> - * - * Based on the previous xscale OProfile code. - * - * There are two variants of the xscale PMU that we support: - * - xscale1pmu: 2 event counters and a cycle counter - * - xscale2pmu: 4 event counters and a cycle counter - * The two variants share event definitions, but have different - * PMU structures. - */ - -#ifdef CONFIG_CPU_XSCALE -enum xscale_perf_types { - XSCALE_PERFCTR_ICACHE_MISS = 0x00, - XSCALE_PERFCTR_ICACHE_NO_DELIVER = 0x01, - XSCALE_PERFCTR_DATA_STALL = 0x02, - XSCALE_PERFCTR_ITLB_MISS = 0x03, - XSCALE_PERFCTR_DTLB_MISS = 0x04, - XSCALE_PERFCTR_BRANCH = 0x05, - XSCALE_PERFCTR_BRANCH_MISS = 0x06, - XSCALE_PERFCTR_INSTRUCTION = 0x07, - XSCALE_PERFCTR_DCACHE_FULL_STALL = 0x08, - XSCALE_PERFCTR_DCACHE_FULL_STALL_CONTIG = 0x09, - XSCALE_PERFCTR_DCACHE_ACCESS = 0x0A, - XSCALE_PERFCTR_DCACHE_MISS = 0x0B, - XSCALE_PERFCTR_DCACHE_WRITE_BACK = 0x0C, - XSCALE_PERFCTR_PC_CHANGED = 0x0D, - XSCALE_PERFCTR_BCU_REQUEST = 0x10, - XSCALE_PERFCTR_BCU_FULL = 0x11, - XSCALE_PERFCTR_BCU_DRAIN = 0x12, - XSCALE_PERFCTR_BCU_ECC_NO_ELOG = 0x14, - XSCALE_PERFCTR_BCU_1_BIT_ERR = 0x15, - XSCALE_PERFCTR_RMW = 0x16, - /* XSCALE_PERFCTR_CCNT is not hardware defined */ - XSCALE_PERFCTR_CCNT = 0xFE, - XSCALE_PERFCTR_UNUSED = 0xFF, -}; - -enum xscale_counters { - XSCALE_CYCLE_COUNTER = 0, - XSCALE_COUNTER0, - XSCALE_COUNTER1, - XSCALE_COUNTER2, - XSCALE_COUNTER3, -}; - -static const unsigned xscale_perf_map[PERF_COUNT_HW_MAX] = { - [PERF_COUNT_HW_CPU_CYCLES] = XSCALE_PERFCTR_CCNT, - [PERF_COUNT_HW_INSTRUCTIONS] = XSCALE_PERFCTR_INSTRUCTION, - [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED, - [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED, - [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = XSCALE_PERFCTR_BRANCH, - [PERF_COUNT_HW_BRANCH_MISSES] = XSCALE_PERFCTR_BRANCH_MISS, - [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED, - [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = XSCALE_PERFCTR_ICACHE_NO_DELIVER, - [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = HW_OP_UNSUPPORTED, -}; - -static const unsigned xscale_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] - [PERF_COUNT_HW_CACHE_OP_MAX] - [PERF_COUNT_HW_CACHE_RESULT_MAX] = { - [C(L1D)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = XSCALE_PERFCTR_DCACHE_ACCESS, - [C(RESULT_MISS)] = XSCALE_PERFCTR_DCACHE_MISS, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = XSCALE_PERFCTR_DCACHE_ACCESS, - [C(RESULT_MISS)] = XSCALE_PERFCTR_DCACHE_MISS, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(L1I)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = XSCALE_PERFCTR_ICACHE_MISS, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = XSCALE_PERFCTR_ICACHE_MISS, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(LL)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(DTLB)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = XSCALE_PERFCTR_DTLB_MISS, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = XSCALE_PERFCTR_DTLB_MISS, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(ITLB)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = XSCALE_PERFCTR_ITLB_MISS, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = XSCALE_PERFCTR_ITLB_MISS, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(BPU)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, - [C(NODE)] = { - [C(OP_READ)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_WRITE)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - [C(OP_PREFETCH)] = { - [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, - [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, - }, - }, -}; - -#define XSCALE_PMU_ENABLE 0x001 -#define XSCALE_PMN_RESET 0x002 -#define XSCALE_CCNT_RESET 0x004 -#define XSCALE_PMU_RESET (CCNT_RESET | PMN_RESET) -#define XSCALE_PMU_CNT64 0x008 - -#define XSCALE1_OVERFLOWED_MASK 0x700 -#define XSCALE1_CCOUNT_OVERFLOW 0x400 -#define XSCALE1_COUNT0_OVERFLOW 0x100 -#define XSCALE1_COUNT1_OVERFLOW 0x200 -#define XSCALE1_CCOUNT_INT_EN 0x040 -#define XSCALE1_COUNT0_INT_EN 0x010 -#define XSCALE1_COUNT1_INT_EN 0x020 -#define XSCALE1_COUNT0_EVT_SHFT 12 -#define XSCALE1_COUNT0_EVT_MASK (0xff << XSCALE1_COUNT0_EVT_SHFT) -#define XSCALE1_COUNT1_EVT_SHFT 20 -#define XSCALE1_COUNT1_EVT_MASK (0xff << XSCALE1_COUNT1_EVT_SHFT) - -static inline u32 -xscale1pmu_read_pmnc(void) -{ - u32 val; - asm volatile("mrc p14, 0, %0, c0, c0, 0" : "=r" (val)); - return val; -} - -static inline void -xscale1pmu_write_pmnc(u32 val) -{ - /* upper 4bits and 7, 11 are write-as-0 */ - val &= 0xffff77f; - asm volatile("mcr p14, 0, %0, c0, c0, 0" : : "r" (val)); -} - -static inline int -xscale1_pmnc_counter_has_overflowed(unsigned long pmnc, - enum xscale_counters counter) -{ - int ret = 0; - - switch (counter) { - case XSCALE_CYCLE_COUNTER: - ret = pmnc & XSCALE1_CCOUNT_OVERFLOW; - break; - case XSCALE_COUNTER0: - ret = pmnc & XSCALE1_COUNT0_OVERFLOW; - break; - case XSCALE_COUNTER1: - ret = pmnc & XSCALE1_COUNT1_OVERFLOW; - break; - default: - WARN_ONCE(1, "invalid counter number (%d)\n", counter); - } - - return ret; -} - -static irqreturn_t -xscale1pmu_handle_irq(int irq_num, void *dev) -{ - unsigned long pmnc; - struct perf_sample_data data; - struct pmu_hw_events *cpuc; - struct pt_regs *regs; - int idx; - - /* - * NOTE: there's an A stepping erratum that states if an overflow - * bit already exists and another occurs, the previous - * Overflow bit gets cleared. There's no workaround. - * Fixed in B stepping or later. - */ - pmnc = xscale1pmu_read_pmnc(); - - /* - * Write the value back to clear the overflow flags. Overflow - * flags remain in pmnc for use below. We also disable the PMU - * while we process the interrupt. - */ - xscale1pmu_write_pmnc(pmnc & ~XSCALE_PMU_ENABLE); - - if (!(pmnc & XSCALE1_OVERFLOWED_MASK)) - return IRQ_NONE; - - regs = get_irq_regs(); - - perf_sample_data_init(&data, 0); - - cpuc = &__get_cpu_var(cpu_hw_events); - for (idx = 0; idx < cpu_pmu->num_events; ++idx) { - struct perf_event *event = cpuc->events[idx]; - struct hw_perf_event *hwc; - - if (!event) - continue; - - if (!xscale1_pmnc_counter_has_overflowed(pmnc, idx)) - continue; - - hwc = &event->hw; - armpmu_event_update(event, hwc, idx); - data.period = event->hw.last_period; - if (!armpmu_event_set_period(event, hwc, idx)) - continue; - - if (perf_event_overflow(event, &data, regs)) - cpu_pmu->disable(hwc, idx); - } - - irq_work_run(); - - /* - * Re-enable the PMU. - */ - pmnc = xscale1pmu_read_pmnc() | XSCALE_PMU_ENABLE; - xscale1pmu_write_pmnc(pmnc); - - return IRQ_HANDLED; -} - -static void -xscale1pmu_enable_event(struct hw_perf_event *hwc, int idx) -{ - unsigned long val, mask, evt, flags; - struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - - switch (idx) { - case XSCALE_CYCLE_COUNTER: - mask = 0; - evt = XSCALE1_CCOUNT_INT_EN; - break; - case XSCALE_COUNTER0: - mask = XSCALE1_COUNT0_EVT_MASK; - evt = (hwc->config_base << XSCALE1_COUNT0_EVT_SHFT) | - XSCALE1_COUNT0_INT_EN; - break; - case XSCALE_COUNTER1: - mask = XSCALE1_COUNT1_EVT_MASK; - evt = (hwc->config_base << XSCALE1_COUNT1_EVT_SHFT) | - XSCALE1_COUNT1_INT_EN; - break; - default: - WARN_ONCE(1, "invalid counter number (%d)\n", idx); - return; - } - - raw_spin_lock_irqsave(&events->pmu_lock, flags); - val = xscale1pmu_read_pmnc(); - val &= ~mask; - val |= evt; - xscale1pmu_write_pmnc(val); - raw_spin_unlock_irqrestore(&events->pmu_lock, flags); -} - -static void -xscale1pmu_disable_event(struct hw_perf_event *hwc, int idx) -{ - unsigned long val, mask, evt, flags; - struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - - switch (idx) { - case XSCALE_CYCLE_COUNTER: - mask = XSCALE1_CCOUNT_INT_EN; - evt = 0; - break; - case XSCALE_COUNTER0: - mask = XSCALE1_COUNT0_INT_EN | XSCALE1_COUNT0_EVT_MASK; - evt = XSCALE_PERFCTR_UNUSED << XSCALE1_COUNT0_EVT_SHFT; - break; - case XSCALE_COUNTER1: - mask = XSCALE1_COUNT1_INT_EN | XSCALE1_COUNT1_EVT_MASK; - evt = XSCALE_PERFCTR_UNUSED << XSCALE1_COUNT1_EVT_SHFT; - break; - default: - WARN_ONCE(1, "invalid counter number (%d)\n", idx); - return; - } - - raw_spin_lock_irqsave(&events->pmu_lock, flags); - val = xscale1pmu_read_pmnc(); - val &= ~mask; - val |= evt; - xscale1pmu_write_pmnc(val); - raw_spin_unlock_irqrestore(&events->pmu_lock, flags); -} - -static int -xscale1pmu_get_event_idx(struct pmu_hw_events *cpuc, - struct hw_perf_event *event) -{ - if (XSCALE_PERFCTR_CCNT == event->config_base) { - if (test_and_set_bit(XSCALE_CYCLE_COUNTER, cpuc->used_mask)) - return -EAGAIN; - - return XSCALE_CYCLE_COUNTER; - } else { - if (!test_and_set_bit(XSCALE_COUNTER1, cpuc->used_mask)) - return XSCALE_COUNTER1; - - if (!test_and_set_bit(XSCALE_COUNTER0, cpuc->used_mask)) - return XSCALE_COUNTER0; - - return -EAGAIN; - } -} - -static void -xscale1pmu_start(void) -{ - unsigned long flags, val; - struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - - raw_spin_lock_irqsave(&events->pmu_lock, flags); - val = xscale1pmu_read_pmnc(); - val |= XSCALE_PMU_ENABLE; - xscale1pmu_write_pmnc(val); - raw_spin_unlock_irqrestore(&events->pmu_lock, flags); -} - -static void -xscale1pmu_stop(void) -{ - unsigned long flags, val; - struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - - raw_spin_lock_irqsave(&events->pmu_lock, flags); - val = xscale1pmu_read_pmnc(); - val &= ~XSCALE_PMU_ENABLE; - xscale1pmu_write_pmnc(val); - raw_spin_unlock_irqrestore(&events->pmu_lock, flags); -} - -static inline u32 -xscale1pmu_read_counter(int counter) -{ - u32 val = 0; - - switch (counter) { - case XSCALE_CYCLE_COUNTER: - asm volatile("mrc p14, 0, %0, c1, c0, 0" : "=r" (val)); - break; - case XSCALE_COUNTER0: - asm volatile("mrc p14, 0, %0, c2, c0, 0" : "=r" (val)); - break; - case XSCALE_COUNTER1: - asm volatile("mrc p14, 0, %0, c3, c0, 0" : "=r" (val)); - break; - } - - return val; -} - -static inline void -xscale1pmu_write_counter(int counter, u32 val) -{ - switch (counter) { - case XSCALE_CYCLE_COUNTER: - asm volatile("mcr p14, 0, %0, c1, c0, 0" : : "r" (val)); - break; - case XSCALE_COUNTER0: - asm volatile("mcr p14, 0, %0, c2, c0, 0" : : "r" (val)); - break; - case XSCALE_COUNTER1: - asm volatile("mcr p14, 0, %0, c3, c0, 0" : : "r" (val)); - break; - } -} - -static int xscale_map_event(struct perf_event *event) -{ - return map_cpu_event(event, &xscale_perf_map, - &xscale_perf_cache_map, 0xFF); -} - -static struct arm_pmu xscale1pmu = { - .id = ARM_PERF_PMU_ID_XSCALE1, - .name = "xscale1", - .handle_irq = xscale1pmu_handle_irq, - .enable = xscale1pmu_enable_event, - .disable = xscale1pmu_disable_event, - .read_counter = xscale1pmu_read_counter, - .write_counter = xscale1pmu_write_counter, - .get_event_idx = xscale1pmu_get_event_idx, - .start = xscale1pmu_start, - .stop = xscale1pmu_stop, - .map_event = xscale_map_event, - .num_events = 3, - .max_period = (1LLU << 32) - 1, -}; - -static struct arm_pmu *__init xscale1pmu_init(void) -{ - return &xscale1pmu; -} - -#define XSCALE2_OVERFLOWED_MASK 0x01f -#define XSCALE2_CCOUNT_OVERFLOW 0x001 -#define XSCALE2_COUNT0_OVERFLOW 0x002 -#define XSCALE2_COUNT1_OVERFLOW 0x004 -#define XSCALE2_COUNT2_OVERFLOW 0x008 -#define XSCALE2_COUNT3_OVERFLOW 0x010 -#define XSCALE2_CCOUNT_INT_EN 0x001 -#define XSCALE2_COUNT0_INT_EN 0x002 -#define XSCALE2_COUNT1_INT_EN 0x004 -#define XSCALE2_COUNT2_INT_EN 0x008 -#define XSCALE2_COUNT3_INT_EN 0x010 -#define XSCALE2_COUNT0_EVT_SHFT 0 -#define XSCALE2_COUNT0_EVT_MASK (0xff << XSCALE2_COUNT0_EVT_SHFT) -#define XSCALE2_COUNT1_EVT_SHFT 8 -#define XSCALE2_COUNT1_EVT_MASK (0xff << XSCALE2_COUNT1_EVT_SHFT) -#define XSCALE2_COUNT2_EVT_SHFT 16 -#define XSCALE2_COUNT2_EVT_MASK (0xff << XSCALE2_COUNT2_EVT_SHFT) -#define XSCALE2_COUNT3_EVT_SHFT 24 -#define XSCALE2_COUNT3_EVT_MASK (0xff << XSCALE2_COUNT3_EVT_SHFT) - -static inline u32 -xscale2pmu_read_pmnc(void) -{ - u32 val; - asm volatile("mrc p14, 0, %0, c0, c1, 0" : "=r" (val)); - /* bits 1-2 and 4-23 are read-unpredictable */ - return val & 0xff000009; -} - -static inline void -xscale2pmu_write_pmnc(u32 val) -{ - /* bits 4-23 are write-as-0, 24-31 are write ignored */ - val &= 0xf; - asm volatile("mcr p14, 0, %0, c0, c1, 0" : : "r" (val)); -} - -static inline u32 -xscale2pmu_read_overflow_flags(void) -{ - u32 val; - asm volatile("mrc p14, 0, %0, c5, c1, 0" : "=r" (val)); - return val; -} - -static inline void -xscale2pmu_write_overflow_flags(u32 val) -{ - asm volatile("mcr p14, 0, %0, c5, c1, 0" : : "r" (val)); -} - -static inline u32 -xscale2pmu_read_event_select(void) -{ - u32 val; - asm volatile("mrc p14, 0, %0, c8, c1, 0" : "=r" (val)); - return val; -} - -static inline void -xscale2pmu_write_event_select(u32 val) -{ - asm volatile("mcr p14, 0, %0, c8, c1, 0" : : "r"(val)); -} - -static inline u32 -xscale2pmu_read_int_enable(void) -{ - u32 val; - asm volatile("mrc p14, 0, %0, c4, c1, 0" : "=r" (val)); - return val; -} - -static void -xscale2pmu_write_int_enable(u32 val) -{ - asm volatile("mcr p14, 0, %0, c4, c1, 0" : : "r" (val)); -} - -static inline int -xscale2_pmnc_counter_has_overflowed(unsigned long of_flags, - enum xscale_counters counter) -{ - int ret = 0; - - switch (counter) { - case XSCALE_CYCLE_COUNTER: - ret = of_flags & XSCALE2_CCOUNT_OVERFLOW; - break; - case XSCALE_COUNTER0: - ret = of_flags & XSCALE2_COUNT0_OVERFLOW; - break; - case XSCALE_COUNTER1: - ret = of_flags & XSCALE2_COUNT1_OVERFLOW; - break; - case XSCALE_COUNTER2: - ret = of_flags & XSCALE2_COUNT2_OVERFLOW; - break; - case XSCALE_COUNTER3: - ret = of_flags & XSCALE2_COUNT3_OVERFLOW; - break; - default: - WARN_ONCE(1, "invalid counter number (%d)\n", counter); - } - - return ret; -} - -static irqreturn_t -xscale2pmu_handle_irq(int irq_num, void *dev) -{ - unsigned long pmnc, of_flags; - struct perf_sample_data data; - struct pmu_hw_events *cpuc; - struct pt_regs *regs; - int idx; - - /* Disable the PMU. */ - pmnc = xscale2pmu_read_pmnc(); - xscale2pmu_write_pmnc(pmnc & ~XSCALE_PMU_ENABLE); - - /* Check the overflow flag register. */ - of_flags = xscale2pmu_read_overflow_flags(); - if (!(of_flags & XSCALE2_OVERFLOWED_MASK)) - return IRQ_NONE; - - /* Clear the overflow bits. */ - xscale2pmu_write_overflow_flags(of_flags); - - regs = get_irq_regs(); - - perf_sample_data_init(&data, 0); - - cpuc = &__get_cpu_var(cpu_hw_events); - for (idx = 0; idx < cpu_pmu->num_events; ++idx) { - struct perf_event *event = cpuc->events[idx]; - struct hw_perf_event *hwc; - - if (!event) - continue; - - if (!xscale2_pmnc_counter_has_overflowed(of_flags, idx)) - continue; - - hwc = &event->hw; - armpmu_event_update(event, hwc, idx); - data.period = event->hw.last_period; - if (!armpmu_event_set_period(event, hwc, idx)) - continue; - - if (perf_event_overflow(event, &data, regs)) - cpu_pmu->disable(hwc, idx); - } - - irq_work_run(); - - /* - * Re-enable the PMU. - */ - pmnc = xscale2pmu_read_pmnc() | XSCALE_PMU_ENABLE; - xscale2pmu_write_pmnc(pmnc); - - return IRQ_HANDLED; -} - -static void -xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx) -{ - unsigned long flags, ien, evtsel; - struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - - ien = xscale2pmu_read_int_enable(); - evtsel = xscale2pmu_read_event_select(); - - switch (idx) { - case XSCALE_CYCLE_COUNTER: - ien |= XSCALE2_CCOUNT_INT_EN; - break; - case XSCALE_COUNTER0: - ien |= XSCALE2_COUNT0_INT_EN; - evtsel &= ~XSCALE2_COUNT0_EVT_MASK; - evtsel |= hwc->config_base << XSCALE2_COUNT0_EVT_SHFT; - break; - case XSCALE_COUNTER1: - ien |= XSCALE2_COUNT1_INT_EN; - evtsel &= ~XSCALE2_COUNT1_EVT_MASK; - evtsel |= hwc->config_base << XSCALE2_COUNT1_EVT_SHFT; - break; - case XSCALE_COUNTER2: - ien |= XSCALE2_COUNT2_INT_EN; - evtsel &= ~XSCALE2_COUNT2_EVT_MASK; - evtsel |= hwc->config_base << XSCALE2_COUNT2_EVT_SHFT; - break; - case XSCALE_COUNTER3: - ien |= XSCALE2_COUNT3_INT_EN; - evtsel &= ~XSCALE2_COUNT3_EVT_MASK; - evtsel |= hwc->config_base << XSCALE2_COUNT3_EVT_SHFT; - break; - default: - WARN_ONCE(1, "invalid counter number (%d)\n", idx); - return; - } - - raw_spin_lock_irqsave(&events->pmu_lock, flags); - xscale2pmu_write_event_select(evtsel); - xscale2pmu_write_int_enable(ien); - raw_spin_unlock_irqrestore(&events->pmu_lock, flags); -} - -static void -xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx) -{ - unsigned long flags, ien, evtsel, of_flags; - struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - - ien = xscale2pmu_read_int_enable(); - evtsel = xscale2pmu_read_event_select(); - - switch (idx) { - case XSCALE_CYCLE_COUNTER: - ien &= ~XSCALE2_CCOUNT_INT_EN; - of_flags = XSCALE2_CCOUNT_OVERFLOW; - break; - case XSCALE_COUNTER0: - ien &= ~XSCALE2_COUNT0_INT_EN; - evtsel &= ~XSCALE2_COUNT0_EVT_MASK; - evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT0_EVT_SHFT; - of_flags = XSCALE2_COUNT0_OVERFLOW; - break; - case XSCALE_COUNTER1: - ien &= ~XSCALE2_COUNT1_INT_EN; - evtsel &= ~XSCALE2_COUNT1_EVT_MASK; - evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT1_EVT_SHFT; - of_flags = XSCALE2_COUNT1_OVERFLOW; - break; - case XSCALE_COUNTER2: - ien &= ~XSCALE2_COUNT2_INT_EN; - evtsel &= ~XSCALE2_COUNT2_EVT_MASK; - evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT2_EVT_SHFT; - of_flags = XSCALE2_COUNT2_OVERFLOW; - break; - case XSCALE_COUNTER3: - ien &= ~XSCALE2_COUNT3_INT_EN; - evtsel &= ~XSCALE2_COUNT3_EVT_MASK; - evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT3_EVT_SHFT; - of_flags = XSCALE2_COUNT3_OVERFLOW; - break; - default: - WARN_ONCE(1, "invalid counter number (%d)\n", idx); - return; - } - - raw_spin_lock_irqsave(&events->pmu_lock, flags); - xscale2pmu_write_event_select(evtsel); - xscale2pmu_write_int_enable(ien); - xscale2pmu_write_overflow_flags(of_flags); - raw_spin_unlock_irqrestore(&events->pmu_lock, flags); -} - -static int -xscale2pmu_get_event_idx(struct pmu_hw_events *cpuc, - struct hw_perf_event *event) -{ - int idx = xscale1pmu_get_event_idx(cpuc, event); - if (idx >= 0) - goto out; - - if (!test_and_set_bit(XSCALE_COUNTER3, cpuc->used_mask)) - idx = XSCALE_COUNTER3; - else if (!test_and_set_bit(XSCALE_COUNTER2, cpuc->used_mask)) - idx = XSCALE_COUNTER2; -out: - return idx; -} - -static void -xscale2pmu_start(void) -{ - unsigned long flags, val; - struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - - raw_spin_lock_irqsave(&events->pmu_lock, flags); - val = xscale2pmu_read_pmnc() & ~XSCALE_PMU_CNT64; - val |= XSCALE_PMU_ENABLE; - xscale2pmu_write_pmnc(val); - raw_spin_unlock_irqrestore(&events->pmu_lock, flags); -} - -static void -xscale2pmu_stop(void) -{ - unsigned long flags, val; - struct pmu_hw_events *events = cpu_pmu->get_hw_events(); - - raw_spin_lock_irqsave(&events->pmu_lock, flags); - val = xscale2pmu_read_pmnc(); - val &= ~XSCALE_PMU_ENABLE; - xscale2pmu_write_pmnc(val); - raw_spin_unlock_irqrestore(&events->pmu_lock, flags); -} - -static inline u32 -xscale2pmu_read_counter(int counter) -{ - u32 val = 0; - - switch (counter) { - case XSCALE_CYCLE_COUNTER: - asm volatile("mrc p14, 0, %0, c1, c1, 0" : "=r" (val)); - break; - case XSCALE_COUNTER0: - asm volatile("mrc p14, 0, %0, c0, c2, 0" : "=r" (val)); - break; - case XSCALE_COUNTER1: - asm volatile("mrc p14, 0, %0, c1, c2, 0" : "=r" (val)); - break; - case XSCALE_COUNTER2: - asm volatile("mrc p14, 0, %0, c2, c2, 0" : "=r" (val)); - break; - case XSCALE_COUNTER3: - asm volatile("mrc p14, 0, %0, c3, c2, 0" : "=r" (val)); - break; - } - - return val; -} - -static inline void -xscale2pmu_write_counter(int counter, u32 val) -{ - switch (counter) { - case XSCALE_CYCLE_COUNTER: - asm volatile("mcr p14, 0, %0, c1, c1, 0" : : "r" (val)); - break; - case XSCALE_COUNTER0: - asm volatile("mcr p14, 0, %0, c0, c2, 0" : : "r" (val)); - break; - case XSCALE_COUNTER1: - asm volatile("mcr p14, 0, %0, c1, c2, 0" : : "r" (val)); - break; - case XSCALE_COUNTER2: - asm volatile("mcr p14, 0, %0, c2, c2, 0" : : "r" (val)); - break; - case XSCALE_COUNTER3: - asm volatile("mcr p14, 0, %0, c3, c2, 0" : : "r" (val)); - break; - } -} - -static struct arm_pmu xscale2pmu = { - .id = ARM_PERF_PMU_ID_XSCALE2, - .name = "xscale2", - .handle_irq = xscale2pmu_handle_irq, - .enable = xscale2pmu_enable_event, - .disable = xscale2pmu_disable_event, - .read_counter = xscale2pmu_read_counter, - .write_counter = xscale2pmu_write_counter, - .get_event_idx = xscale2pmu_get_event_idx, - .start = xscale2pmu_start, - .stop = xscale2pmu_stop, - .map_event = xscale_map_event, - .num_events = 5, - .max_period = (1LLU << 32) - 1, -}; - -static struct arm_pmu *__init xscale2pmu_init(void) -{ - return &xscale2pmu; -} -#else -static struct arm_pmu *__init xscale1pmu_init(void) -{ - return NULL; -} - -static struct arm_pmu *__init xscale2pmu_init(void) -{ - return NULL; -} -#endif /* CONFIG_CPU_XSCALE */ diff --git a/ANDROID_3.4.5/arch/arm/kernel/pj4-cp0.c b/ANDROID_3.4.5/arch/arm/kernel/pj4-cp0.c deleted file mode 100644 index 679cf4d1..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/pj4-cp0.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * linux/arch/arm/kernel/pj4-cp0.c - * - * PJ4 iWMMXt coprocessor context switching and handling - * - * Copyright (c) 2010 Marvell International Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/signal.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/io.h> -#include <asm/thread_notify.h> - -static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t) -{ - struct thread_info *thread = t; - - switch (cmd) { - case THREAD_NOTIFY_FLUSH: - /* - * flush_thread() zeroes thread->fpstate, so no need - * to do anything here. - * - * FALLTHROUGH: Ensure we don't try to overwrite our newly - * initialised state information on the first fault. - */ - - case THREAD_NOTIFY_EXIT: - iwmmxt_task_release(thread); - break; - - case THREAD_NOTIFY_SWITCH: - iwmmxt_task_switch(thread); - break; - } - - return NOTIFY_DONE; -} - -static struct notifier_block iwmmxt_notifier_block = { - .notifier_call = iwmmxt_do, -}; - - -static u32 __init pj4_cp_access_read(void) -{ - u32 value; - - __asm__ __volatile__ ( - "mrc p15, 0, %0, c1, c0, 2\n\t" - : "=r" (value)); - return value; -} - -static void __init pj4_cp_access_write(u32 value) -{ - u32 temp; - - __asm__ __volatile__ ( - "mcr p15, 0, %1, c1, c0, 2\n\t" - "mrc p15, 0, %0, c1, c0, 2\n\t" - "mov %0, %0\n\t" - "sub pc, pc, #4\n\t" - : "=r" (temp) : "r" (value)); -} - - -/* - * Disable CP0/CP1 on boot, and let call_fpe() and the iWMMXt lazy - * switch code handle iWMMXt context switching. - */ -static int __init pj4_cp0_init(void) -{ - u32 cp_access; - - cp_access = pj4_cp_access_read() & ~0xf; - pj4_cp_access_write(cp_access); - - printk(KERN_INFO "PJ4 iWMMXt coprocessor enabled.\n"); - elf_hwcap |= HWCAP_IWMMXT; - thread_register_notifier(&iwmmxt_notifier_block); - - return 0; -} - -late_initcall(pj4_cp0_init); diff --git a/ANDROID_3.4.5/arch/arm/kernel/pmu.c b/ANDROID_3.4.5/arch/arm/kernel/pmu.c deleted file mode 100644 index 2334bf8a..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/pmu.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * linux/arch/arm/kernel/pmu.c - * - * Copyright (C) 2009 picoChip Designs Ltd, Jamie Iles - * Copyright (C) 2010 ARM Ltd, Will Deacon - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include <linux/err.h> -#include <linux/kernel.h> -#include <linux/module.h> - -#include <asm/pmu.h> - -/* - * PMU locking to ensure mutual exclusion between different subsystems. - */ -static unsigned long pmu_lock[BITS_TO_LONGS(ARM_NUM_PMU_DEVICES)]; - -int -reserve_pmu(enum arm_pmu_type type) -{ - return test_and_set_bit_lock(type, pmu_lock) ? -EBUSY : 0; -} -EXPORT_SYMBOL_GPL(reserve_pmu); - -void -release_pmu(enum arm_pmu_type type) -{ - clear_bit_unlock(type, pmu_lock); -} -EXPORT_SYMBOL_GPL(release_pmu); diff --git a/ANDROID_3.4.5/arch/arm/kernel/process.c b/ANDROID_3.4.5/arch/arm/kernel/process.c deleted file mode 100644 index df0dec8e..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/process.c +++ /dev/null @@ -1,704 +0,0 @@ -/* - * linux/arch/arm/kernel/process.c - * - * Copyright (C) 1996-2000 Russell King - Converted to ARM. - * Original Copyright (C) 1995 Linus Torvalds - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <stdarg.h> - -#include <linux/export.h> -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/stddef.h> -#include <linux/unistd.h> -#include <linux/user.h> -#include <linux/delay.h> -#include <linux/reboot.h> -#include <linux/interrupt.h> -#include <linux/kallsyms.h> -#include <linux/init.h> -#include <linux/cpu.h> -#include <linux/elfcore.h> -#include <linux/pm.h> -#include <linux/tick.h> -#include <linux/utsname.h> -#include <linux/uaccess.h> -#include <linux/random.h> -#include <linux/hw_breakpoint.h> -#include <linux/cpuidle.h> -#include <linux/console.h> - -#include <asm/cacheflush.h> -#include <asm/processor.h> -#include <asm/thread_notify.h> -#include <asm/stacktrace.h> -#include <asm/mach/time.h> - -#ifdef CONFIG_CC_STACKPROTECTOR -#include <linux/stackprotector.h> -unsigned long __stack_chk_guard __read_mostly; -EXPORT_SYMBOL(__stack_chk_guard); -#endif - -static const char *processor_modes[] = { - "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , - "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26", - "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" , - "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32" -}; - -static const char *isa_modes[] = { - "ARM" , "Thumb" , "Jazelle", "ThumbEE" -}; - -extern void setup_mm_for_reboot(void); - -static volatile int hlt_counter; - -#ifdef CONFIG_SMP -void arch_trigger_all_cpu_backtrace(void) -{ - smp_send_all_cpu_backtrace(); -} -#else -void arch_trigger_all_cpu_backtrace(void) -{ - dump_stack(); -} -#endif - -void disable_hlt(void) -{ - hlt_counter++; -} - -EXPORT_SYMBOL(disable_hlt); - -void enable_hlt(void) -{ - hlt_counter--; -} - -EXPORT_SYMBOL(enable_hlt); - -static int __init nohlt_setup(char *__unused) -{ - hlt_counter = 1; - return 1; -} - -static int __init hlt_setup(char *__unused) -{ - hlt_counter = 0; - return 1; -} - -__setup("nohlt", nohlt_setup); -__setup("hlt", hlt_setup); - -extern void call_with_stack(void (*fn)(void *), void *arg, void *sp); -typedef void (*phys_reset_t)(unsigned long); - -#ifdef CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART -void arm_machine_flush_console(void) -{ - printk("\n"); - pr_emerg("Restarting %s\n", linux_banner); - if (console_trylock()) { - console_unlock(); - return; - } - - mdelay(50); - - local_irq_disable(); - if (!console_trylock()) - pr_emerg("arm_restart: Console was locked! Busting\n"); - else - pr_emerg("arm_restart: Console was locked!\n"); - console_unlock(); -} -#else -void arm_machine_flush_console(void) -{ -} -#endif - -/* - * A temporary stack to use for CPU reset. This is static so that we - * don't clobber it with the identity mapping. When running with this - * stack, any references to the current task *will not work* so you - * should really do as little as possible before jumping to your reset - * code. - */ -static u64 soft_restart_stack[16]; - -static void __soft_restart(void *addr) -{ - phys_reset_t phys_reset; - - /* Take out a flat memory mapping. */ - setup_mm_for_reboot(); - - /* Clean and invalidate caches */ - flush_cache_all(); - - /* Turn off caching */ - cpu_proc_fin(); - - /* Push out any further dirty data, and ensure cache is empty */ - flush_cache_all(); - - /* Switch to the identity mapping. */ - phys_reset = (phys_reset_t)(unsigned long)virt_to_phys(cpu_reset); - phys_reset((unsigned long)addr); - - /* Should never get here. */ - BUG(); -} - -void soft_restart_noirq(unsigned long addr)/*add by roger.*/
-{
- u64 *stack = soft_restart_stack + ARRAY_SIZE(soft_restart_stack);
-
- /* Disable the L2 if we're the last man standing. */
- if (num_online_cpus() == 1)
- outer_disable();
-
- /* Change to the new stack and continue with the reset. */
- call_with_stack(__soft_restart, (void *)addr, (void *)stack);
-
- /* Should never get here. */
- BUG();
-} - -void soft_restart(unsigned long addr) -{ - u64 *stack = soft_restart_stack + ARRAY_SIZE(soft_restart_stack); - - /* Disable interrupts first */ - local_irq_disable(); - local_fiq_disable(); - - /* Disable the L2 if we're the last man standing. */ - if (num_online_cpus() == 1) - outer_disable(); - - /* Change to the new stack and continue with the reset. */ - call_with_stack(__soft_restart, (void *)addr, (void *)stack); - - /* Should never get here. */ - BUG(); -} - -static void null_restart(char mode, const char *cmd) -{ -} - -/* - * Function pointers to optional machine specific functions - */ -void (*pm_power_off)(void); -EXPORT_SYMBOL(pm_power_off); - -void (*arm_pm_restart)(char str, const char *cmd) = null_restart; -EXPORT_SYMBOL_GPL(arm_pm_restart); - -static void do_nothing(void *unused) -{ -} - -/* - * cpu_idle_wait - Used to ensure that all the CPUs discard old value of - * pm_idle and update to new pm_idle value. Required while changing pm_idle - * handler on SMP systems. - * - * Caller must have changed pm_idle to the new value before the call. Old - * pm_idle value will not be used by any CPU after the return of this function. - */ -void cpu_idle_wait(void) -{ - smp_mb(); - /* kick all the CPUs so that they exit out of pm_idle */ - smp_call_function(do_nothing, NULL, 1); -} -EXPORT_SYMBOL_GPL(cpu_idle_wait); - -/* - * This is our default idle handler. - */ - -void (*arm_pm_idle)(void); - -static void default_idle(void) -{ - if (arm_pm_idle) - arm_pm_idle(); - else - cpu_do_idle(); - local_irq_enable(); -} - -void (*pm_idle)(void) = default_idle; -EXPORT_SYMBOL(pm_idle); - -/* - * The idle thread, has rather strange semantics for calling pm_idle, - * but this is what x86 does and we need to do the same, so that - * things like cpuidle get called in the same way. The only difference - * is that we always respect 'hlt_counter' to prevent low power idle. - */ -void cpu_idle(void) -{ - local_fiq_enable(); - - /* endless idle loop with no priority at all */ - while (1) { - idle_notifier_call_chain(IDLE_START); - tick_nohz_idle_enter(); - rcu_idle_enter(); - while (!need_resched()) { -#ifdef CONFIG_HOTPLUG_CPU - if (cpu_is_offline(smp_processor_id())) - cpu_die(); -#endif - - /* - * We need to disable interrupts here - * to ensure we don't miss a wakeup call. - */ - local_irq_disable(); -#ifdef CONFIG_PL310_ERRATA_769419 - wmb(); -#endif - if (hlt_counter) { - local_irq_enable(); - cpu_relax(); - } else if (!need_resched()) { - stop_critical_timings(); - if (cpuidle_idle_call()) - pm_idle(); - start_critical_timings(); - /* - * pm_idle functions must always - * return with IRQs enabled. - */ - WARN_ON(irqs_disabled()); - } else - local_irq_enable(); - } - rcu_idle_exit(); - tick_nohz_idle_exit(); - idle_notifier_call_chain(IDLE_END); - schedule_preempt_disabled(); - } -} - -static char reboot_mode = 'h'; - -int __init reboot_setup(char *str) -{ - reboot_mode = str[0]; - return 1; -} - -__setup("reboot=", reboot_setup); - -void machine_shutdown(void) -{ -#ifdef CONFIG_SMP - /* - * Disable preemption so we're guaranteed to - * run to power off or reboot and prevent - * the possibility of switching to another - * thread that might wind up blocking on - * one of the stopped CPUs. - */ - preempt_disable(); - - smp_send_stop(); -#endif -} - -void machine_halt(void) -{ - machine_shutdown(); - while (1); -} - -void machine_power_off(void) -{ - machine_shutdown(); - if (pm_power_off) - pm_power_off(); -} - -void machine_restart(char *cmd) -{ - machine_shutdown(); - - /* Flush the console to make sure all the relevant messages make it - * out to the console drivers */ - arm_machine_flush_console(); - - arm_pm_restart(reboot_mode, cmd); - - /* Give a grace period for failure to restart of 1s */ - mdelay(1000); - - /* Whoops - the platform was unable to reboot. Tell the user! */ - printk("Reboot failed -- System halted\n"); - while (1); -} - -/* - * dump a block of kernel memory from around the given address - */ -static void show_data(unsigned long addr, int nbytes, const char *name) -{ - int i, j; - int nlines; - u32 *p; - - /* - * don't attempt to dump non-kernel addresses or - * values that are probably just small negative numbers - */ - if (addr < PAGE_OFFSET || addr > -256UL) - return; - - printk("\n%s: %#lx:\n", name, addr); - - /* - * round address down to a 32 bit boundary - * and always dump a multiple of 32 bytes - */ - p = (u32 *)(addr & ~(sizeof(u32) - 1)); - nbytes += (addr & (sizeof(u32) - 1)); - nlines = (nbytes + 31) / 32; - - - for (i = 0; i < nlines; i++) { - /* - * just display low 16 bits of address to keep - * each line of the dump < 80 characters - */ - printk("%04lx ", (unsigned long)p & 0xffff); - for (j = 0; j < 8; j++) { - u32 data; - if (probe_kernel_address(p, data)) { - printk(" ********"); - } else { - printk(" %08x", data); - } - ++p; - } - printk("\n"); - } -} - -static void show_extra_register_data(struct pt_regs *regs, int nbytes) -{ - mm_segment_t fs; - - fs = get_fs(); - set_fs(KERNEL_DS); - show_data(regs->ARM_pc - nbytes, nbytes * 2, "PC"); - show_data(regs->ARM_lr - nbytes, nbytes * 2, "LR"); - show_data(regs->ARM_sp - nbytes, nbytes * 2, "SP"); - show_data(regs->ARM_ip - nbytes, nbytes * 2, "IP"); - show_data(regs->ARM_fp - nbytes, nbytes * 2, "FP"); - show_data(regs->ARM_r0 - nbytes, nbytes * 2, "R0"); - show_data(regs->ARM_r1 - nbytes, nbytes * 2, "R1"); - show_data(regs->ARM_r2 - nbytes, nbytes * 2, "R2"); - show_data(regs->ARM_r3 - nbytes, nbytes * 2, "R3"); - show_data(regs->ARM_r4 - nbytes, nbytes * 2, "R4"); - show_data(regs->ARM_r5 - nbytes, nbytes * 2, "R5"); - show_data(regs->ARM_r6 - nbytes, nbytes * 2, "R6"); - show_data(regs->ARM_r7 - nbytes, nbytes * 2, "R7"); - show_data(regs->ARM_r8 - nbytes, nbytes * 2, "R8"); - show_data(regs->ARM_r9 - nbytes, nbytes * 2, "R9"); - show_data(regs->ARM_r10 - nbytes, nbytes * 2, "R10"); - set_fs(fs); -} - -void __show_regs(struct pt_regs *regs) -{ - unsigned long flags; - char buf[64]; - - printk("CPU: %d %s (%s %.*s)\n", - raw_smp_processor_id(), print_tainted(), - init_utsname()->release, - (int)strcspn(init_utsname()->version, " "), - init_utsname()->version); - print_symbol("PC is at %s\n", instruction_pointer(regs)); - print_symbol("LR is at %s\n", regs->ARM_lr); - printk("pc : [<%08lx>] lr : [<%08lx>] psr: %08lx\n" - "sp : %08lx ip : %08lx fp : %08lx\n", - regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr, - regs->ARM_sp, regs->ARM_ip, regs->ARM_fp); - printk("r10: %08lx r9 : %08lx r8 : %08lx\n", - regs->ARM_r10, regs->ARM_r9, - regs->ARM_r8); - printk("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", - regs->ARM_r7, regs->ARM_r6, - regs->ARM_r5, regs->ARM_r4); - printk("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", - regs->ARM_r3, regs->ARM_r2, - regs->ARM_r1, regs->ARM_r0); - - flags = regs->ARM_cpsr; - buf[0] = flags & PSR_N_BIT ? 'N' : 'n'; - buf[1] = flags & PSR_Z_BIT ? 'Z' : 'z'; - buf[2] = flags & PSR_C_BIT ? 'C' : 'c'; - buf[3] = flags & PSR_V_BIT ? 'V' : 'v'; - buf[4] = '\0'; - - printk("Flags: %s IRQs o%s FIQs o%s Mode %s ISA %s Segment %s\n", - buf, interrupts_enabled(regs) ? "n" : "ff", - fast_interrupts_enabled(regs) ? "n" : "ff", - processor_modes[processor_mode(regs)], - isa_modes[isa_mode(regs)], - get_fs() == get_ds() ? "kernel" : "user"); -#ifdef CONFIG_CPU_CP15 - { - unsigned int ctrl; - - buf[0] = '\0'; -#ifdef CONFIG_CPU_CP15_MMU - { - unsigned int transbase, dac; - asm("mrc p15, 0, %0, c2, c0\n\t" - "mrc p15, 0, %1, c3, c0\n" - : "=r" (transbase), "=r" (dac)); - snprintf(buf, sizeof(buf), " Table: %08x DAC: %08x", - transbase, dac); - } -#endif - asm("mrc p15, 0, %0, c1, c0\n" : "=r" (ctrl)); - - printk("Control: %08x%s\n", ctrl, buf); - } -#endif - - show_extra_register_data(regs, 128); -} - -void show_regs(struct pt_regs * regs) -{ - printk("\n"); - printk("Pid: %d, comm: %20s\n", task_pid_nr(current), current->comm); - __show_regs(regs); - dump_stack(); -} - -ATOMIC_NOTIFIER_HEAD(thread_notify_head); - -EXPORT_SYMBOL_GPL(thread_notify_head); - -/* - * Free current thread data structures etc.. - */ -void exit_thread(void) -{ - thread_notify(THREAD_NOTIFY_EXIT, current_thread_info()); -} - -void flush_thread(void) -{ - struct thread_info *thread = current_thread_info(); - struct task_struct *tsk = current; - - flush_ptrace_hw_breakpoint(tsk); - - memset(thread->used_cp, 0, sizeof(thread->used_cp)); - memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); - memset(&thread->fpstate, 0, sizeof(union fp_state)); - - thread_notify(THREAD_NOTIFY_FLUSH, thread); -} - -void release_thread(struct task_struct *dead_task) -{ -} - -asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); - -int -copy_thread(unsigned long clone_flags, unsigned long stack_start, - unsigned long stk_sz, struct task_struct *p, struct pt_regs *regs) -{ - struct thread_info *thread = task_thread_info(p); - struct pt_regs *childregs = task_pt_regs(p); - - *childregs = *regs; - childregs->ARM_r0 = 0; - childregs->ARM_sp = stack_start; - - memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save)); - thread->cpu_context.sp = (unsigned long)childregs; - thread->cpu_context.pc = (unsigned long)ret_from_fork; - - clear_ptrace_hw_breakpoint(p); - - if (clone_flags & CLONE_SETTLS) - thread->tp_value = regs->ARM_r3; - - thread_notify(THREAD_NOTIFY_COPY, thread); - - return 0; -} - -/* - * Fill in the task's elfregs structure for a core dump. - */ -int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs) -{ - elf_core_copy_regs(elfregs, task_pt_regs(t)); - return 1; -} - -/* - * fill in the fpe structure for a core dump... - */ -int dump_fpu (struct pt_regs *regs, struct user_fp *fp) -{ - struct thread_info *thread = current_thread_info(); - int used_math = thread->used_cp[1] | thread->used_cp[2]; - - if (used_math) - memcpy(fp, &thread->fpstate.soft, sizeof (*fp)); - - return used_math != 0; -} -EXPORT_SYMBOL(dump_fpu); - -/* - * Shuffle the argument into the correct register before calling the - * thread function. r4 is the thread argument, r5 is the pointer to - * the thread function, and r6 points to the exit function. - */ -extern void kernel_thread_helper(void); -asm( ".pushsection .text\n" -" .align\n" -" .type kernel_thread_helper, #function\n" -"kernel_thread_helper:\n" -#ifdef CONFIG_TRACE_IRQFLAGS -" bl trace_hardirqs_on\n" -#endif -" msr cpsr_c, r7\n" -" mov r0, r4\n" -" mov lr, r6\n" -" mov pc, r5\n" -" .size kernel_thread_helper, . - kernel_thread_helper\n" -" .popsection"); - -#ifdef CONFIG_ARM_UNWIND -extern void kernel_thread_exit(long code); -asm( ".pushsection .text\n" -" .align\n" -" .type kernel_thread_exit, #function\n" -"kernel_thread_exit:\n" -" .fnstart\n" -" .cantunwind\n" -" bl do_exit\n" -" nop\n" -" .fnend\n" -" .size kernel_thread_exit, . - kernel_thread_exit\n" -" .popsection"); -#else -#define kernel_thread_exit do_exit -#endif - -/* - * Create a kernel thread. - */ -pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - - regs.ARM_r4 = (unsigned long)arg; - regs.ARM_r5 = (unsigned long)fn; - regs.ARM_r6 = (unsigned long)kernel_thread_exit; - regs.ARM_r7 = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE; - regs.ARM_pc = (unsigned long)kernel_thread_helper; - regs.ARM_cpsr = regs.ARM_r7 | PSR_I_BIT; - - return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); -} -EXPORT_SYMBOL(kernel_thread); - -unsigned long get_wchan(struct task_struct *p) -{ - struct stackframe frame; - int count = 0; - if (!p || p == current || p->state == TASK_RUNNING) - return 0; - - frame.fp = thread_saved_fp(p); - frame.sp = thread_saved_sp(p); - frame.lr = 0; /* recovered from the stack */ - frame.pc = thread_saved_pc(p); - do { - int ret = unwind_frame(&frame); - if (ret < 0) - return 0; - if (!in_sched_functions(frame.pc)) - return frame.pc; - } while (count ++ < 16); - return 0; -} - -unsigned long arch_randomize_brk(struct mm_struct *mm) -{ - unsigned long range_end = mm->brk + 0x02000000; - return randomize_range(mm->brk, range_end, 0) ? : mm->brk; -} - -#ifdef CONFIG_MMU -/* - * The vectors page is always readable from user space for the - * atomic helpers and the signal restart code. Insert it into the - * gate_vma so that it is visible through ptrace and /proc/<pid>/mem. - */ -static struct vm_area_struct gate_vma; - -static int __init gate_vma_init(void) -{ - gate_vma.vm_start = 0xffff0000; - gate_vma.vm_end = 0xffff0000 + PAGE_SIZE; - gate_vma.vm_page_prot = PAGE_READONLY_EXEC; - gate_vma.vm_flags = VM_READ | VM_EXEC | - VM_MAYREAD | VM_MAYEXEC; - return 0; -} -arch_initcall(gate_vma_init); - -struct vm_area_struct *get_gate_vma(struct mm_struct *mm) -{ - return &gate_vma; -} - -int in_gate_area(struct mm_struct *mm, unsigned long addr) -{ - return (addr >= gate_vma.vm_start) && (addr < gate_vma.vm_end); -} - -int in_gate_area_no_mm(unsigned long addr) -{ - return in_gate_area(NULL, addr); -} - -const char *arch_vma_name(struct vm_area_struct *vma) -{ - return (vma == &gate_vma) ? "[vectors]" : NULL; -} -#endif diff --git a/ANDROID_3.4.5/arch/arm/kernel/ptrace.c b/ANDROID_3.4.5/arch/arm/kernel/ptrace.c deleted file mode 100644 index 9650c143..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/ptrace.c +++ /dev/null @@ -1,949 +0,0 @@ -/* - * linux/arch/arm/kernel/ptrace.c - * - * By Ross Biro 1/23/92 - * edited by Linus Torvalds - * ARM modifications Copyright (C) 2000 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/elf.h> -#include <linux/smp.h> -#include <linux/ptrace.h> -#include <linux/user.h> -#include <linux/security.h> -#include <linux/init.h> -#include <linux/signal.h> -#include <linux/uaccess.h> -#include <linux/perf_event.h> -#include <linux/hw_breakpoint.h> -#include <linux/regset.h> -#include <linux/audit.h> - -#include <asm/pgtable.h> -#include <asm/traps.h> - -#define REG_PC 15 -#define REG_PSR 16 -/* - * does not yet catch signals sent when the child dies. - * in exit.c or in signal.c. - */ - -#if 0 -/* - * Breakpoint SWI instruction: SWI &9F0001 - */ -#define BREAKINST_ARM 0xef9f0001 -#define BREAKINST_THUMB 0xdf00 /* fill this in later */ -#else -/* - * New breakpoints - use an undefined instruction. The ARM architecture - * reference manual guarantees that the following instruction space - * will produce an undefined instruction exception on all CPUs: - * - * ARM: xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx - * Thumb: 1101 1110 xxxx xxxx - */ -#define BREAKINST_ARM 0xe7f001f0 -#define BREAKINST_THUMB 0xde01 -#endif - -struct pt_regs_offset { - const char *name; - int offset; -}; - -#define REG_OFFSET_NAME(r) \ - {.name = #r, .offset = offsetof(struct pt_regs, ARM_##r)} -#define REG_OFFSET_END {.name = NULL, .offset = 0} - -static const struct pt_regs_offset regoffset_table[] = { - REG_OFFSET_NAME(r0), - REG_OFFSET_NAME(r1), - REG_OFFSET_NAME(r2), - REG_OFFSET_NAME(r3), - REG_OFFSET_NAME(r4), - REG_OFFSET_NAME(r5), - REG_OFFSET_NAME(r6), - REG_OFFSET_NAME(r7), - REG_OFFSET_NAME(r8), - REG_OFFSET_NAME(r9), - REG_OFFSET_NAME(r10), - REG_OFFSET_NAME(fp), - REG_OFFSET_NAME(ip), - REG_OFFSET_NAME(sp), - REG_OFFSET_NAME(lr), - REG_OFFSET_NAME(pc), - REG_OFFSET_NAME(cpsr), - REG_OFFSET_NAME(ORIG_r0), - REG_OFFSET_END, -}; - -/** - * regs_query_register_offset() - query register offset from its name - * @name: the name of a register - * - * regs_query_register_offset() returns the offset of a register in struct - * pt_regs from its name. If the name is invalid, this returns -EINVAL; - */ -int regs_query_register_offset(const char *name) -{ - const struct pt_regs_offset *roff; - for (roff = regoffset_table; roff->name != NULL; roff++) - if (!strcmp(roff->name, name)) - return roff->offset; - return -EINVAL; -} - -/** - * regs_query_register_name() - query register name from its offset - * @offset: the offset of a register in struct pt_regs. - * - * regs_query_register_name() returns the name of a register from its - * offset in struct pt_regs. If the @offset is invalid, this returns NULL; - */ -const char *regs_query_register_name(unsigned int offset) -{ - const struct pt_regs_offset *roff; - for (roff = regoffset_table; roff->name != NULL; roff++) - if (roff->offset == offset) - return roff->name; - return NULL; -} - -/** - * regs_within_kernel_stack() - check the address in the stack - * @regs: pt_regs which contains kernel stack pointer. - * @addr: address which is checked. - * - * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). - * If @addr is within the kernel stack, it returns true. If not, returns false. - */ -bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr) -{ - return ((addr & ~(THREAD_SIZE - 1)) == - (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1))); -} - -/** - * regs_get_kernel_stack_nth() - get Nth entry of the stack - * @regs: pt_regs which contains kernel stack pointer. - * @n: stack entry number. - * - * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which - * is specified by @regs. If the @n th entry is NOT in the kernel stack, - * this returns 0. - */ -unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) -{ - unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); - addr += n; - if (regs_within_kernel_stack(regs, (unsigned long)addr)) - return *addr; - else - return 0; -} - -/* - * this routine will get a word off of the processes privileged stack. - * the offset is how far from the base addr as stored in the THREAD. - * this routine assumes that all the privileged stacks are in our - * data space. - */ -static inline long get_user_reg(struct task_struct *task, int offset) -{ - return task_pt_regs(task)->uregs[offset]; -} - -/* - * this routine will put a word on the processes privileged stack. - * the offset is how far from the base addr as stored in the THREAD. - * this routine assumes that all the privileged stacks are in our - * data space. - */ -static inline int -put_user_reg(struct task_struct *task, int offset, long data) -{ - struct pt_regs newregs, *regs = task_pt_regs(task); - int ret = -EINVAL; - - newregs = *regs; - newregs.uregs[offset] = data; - - if (valid_user_regs(&newregs)) { - regs->uregs[offset] = data; - ret = 0; - } - - return ret; -} - -/* - * Called by kernel/ptrace.c when detaching.. - */ -void ptrace_disable(struct task_struct *child) -{ - /* Nothing to do. */ -} - -/* - * Handle hitting a breakpoint. - */ -void ptrace_break(struct task_struct *tsk, struct pt_regs *regs) -{ - siginfo_t info; - - info.si_signo = SIGTRAP; - info.si_errno = 0; - info.si_code = TRAP_BRKPT; - info.si_addr = (void __user *)instruction_pointer(regs); - - force_sig_info(SIGTRAP, &info, tsk); -} - -static int break_trap(struct pt_regs *regs, unsigned int instr) -{ - ptrace_break(current, regs); - return 0; -} - -static struct undef_hook arm_break_hook = { - .instr_mask = 0x0fffffff, - .instr_val = 0x07f001f0, - .cpsr_mask = PSR_T_BIT, - .cpsr_val = 0, - .fn = break_trap, -}; - -static struct undef_hook thumb_break_hook = { - .instr_mask = 0xffff, - .instr_val = 0xde01, - .cpsr_mask = PSR_T_BIT, - .cpsr_val = PSR_T_BIT, - .fn = break_trap, -}; - -static struct undef_hook thumb2_break_hook = { - .instr_mask = 0xffffffff, - .instr_val = 0xf7f0a000, - .cpsr_mask = PSR_T_BIT, - .cpsr_val = PSR_T_BIT, - .fn = break_trap, -}; - -static int __init ptrace_break_init(void) -{ - register_undef_hook(&arm_break_hook); - register_undef_hook(&thumb_break_hook); - register_undef_hook(&thumb2_break_hook); - return 0; -} - -core_initcall(ptrace_break_init); - -/* - * Read the word at offset "off" into the "struct user". We - * actually access the pt_regs stored on the kernel stack. - */ -static int ptrace_read_user(struct task_struct *tsk, unsigned long off, - unsigned long __user *ret) -{ - unsigned long tmp; - - if (off & 3) - return -EIO; - - tmp = 0; - if (off == PT_TEXT_ADDR) - tmp = tsk->mm->start_code; - else if (off == PT_DATA_ADDR) - tmp = tsk->mm->start_data; - else if (off == PT_TEXT_END_ADDR) - tmp = tsk->mm->end_code; - else if (off < sizeof(struct pt_regs)) - tmp = get_user_reg(tsk, off >> 2); - else if (off >= sizeof(struct user)) - return -EIO; - - return put_user(tmp, ret); -} - -/* - * Write the word at offset "off" into "struct user". We - * actually access the pt_regs stored on the kernel stack. - */ -static int ptrace_write_user(struct task_struct *tsk, unsigned long off, - unsigned long val) -{ - if (off & 3 || off >= sizeof(struct user)) - return -EIO; - - if (off >= sizeof(struct pt_regs)) - return 0; - - return put_user_reg(tsk, off >> 2, val); -} - -#ifdef CONFIG_IWMMXT - -/* - * Get the child iWMMXt state. - */ -static int ptrace_getwmmxregs(struct task_struct *tsk, void __user *ufp) -{ - struct thread_info *thread = task_thread_info(tsk); - - if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT)) - return -ENODATA; - iwmmxt_task_disable(thread); /* force it to ram */ - return copy_to_user(ufp, &thread->fpstate.iwmmxt, IWMMXT_SIZE) - ? -EFAULT : 0; -} - -/* - * Set the child iWMMXt state. - */ -static int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp) -{ - struct thread_info *thread = task_thread_info(tsk); - - if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT)) - return -EACCES; - iwmmxt_task_release(thread); /* force a reload */ - return copy_from_user(&thread->fpstate.iwmmxt, ufp, IWMMXT_SIZE) - ? -EFAULT : 0; -} - -#endif - -#ifdef CONFIG_CRUNCH -/* - * Get the child Crunch state. - */ -static int ptrace_getcrunchregs(struct task_struct *tsk, void __user *ufp) -{ - struct thread_info *thread = task_thread_info(tsk); - - crunch_task_disable(thread); /* force it to ram */ - return copy_to_user(ufp, &thread->crunchstate, CRUNCH_SIZE) - ? -EFAULT : 0; -} - -/* - * Set the child Crunch state. - */ -static int ptrace_setcrunchregs(struct task_struct *tsk, void __user *ufp) -{ - struct thread_info *thread = task_thread_info(tsk); - - crunch_task_release(thread); /* force a reload */ - return copy_from_user(&thread->crunchstate, ufp, CRUNCH_SIZE) - ? -EFAULT : 0; -} -#endif - -#ifdef CONFIG_HAVE_HW_BREAKPOINT -/* - * Convert a virtual register number into an index for a thread_info - * breakpoint array. Breakpoints are identified using positive numbers - * whilst watchpoints are negative. The registers are laid out as pairs - * of (address, control), each pair mapping to a unique hw_breakpoint struct. - * Register 0 is reserved for describing resource information. - */ -static int ptrace_hbp_num_to_idx(long num) -{ - if (num < 0) - num = (ARM_MAX_BRP << 1) - num; - return (num - 1) >> 1; -} - -/* - * Returns the virtual register number for the address of the - * breakpoint at index idx. - */ -static long ptrace_hbp_idx_to_num(int idx) -{ - long mid = ARM_MAX_BRP << 1; - long num = (idx << 1) + 1; - return num > mid ? mid - num : num; -} - -/* - * Handle hitting a HW-breakpoint. - */ -static void ptrace_hbptriggered(struct perf_event *bp, - struct perf_sample_data *data, - struct pt_regs *regs) -{ - struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp); - long num; - int i; - siginfo_t info; - - for (i = 0; i < ARM_MAX_HBP_SLOTS; ++i) - if (current->thread.debug.hbp[i] == bp) - break; - - num = (i == ARM_MAX_HBP_SLOTS) ? 0 : ptrace_hbp_idx_to_num(i); - - info.si_signo = SIGTRAP; - info.si_errno = (int)num; - info.si_code = TRAP_HWBKPT; - info.si_addr = (void __user *)(bkpt->trigger); - - force_sig_info(SIGTRAP, &info, current); -} - -/* - * Set ptrace breakpoint pointers to zero for this task. - * This is required in order to prevent child processes from unregistering - * breakpoints held by their parent. - */ -void clear_ptrace_hw_breakpoint(struct task_struct *tsk) -{ - memset(tsk->thread.debug.hbp, 0, sizeof(tsk->thread.debug.hbp)); -} - -/* - * Unregister breakpoints from this task and reset the pointers in - * the thread_struct. - */ -void flush_ptrace_hw_breakpoint(struct task_struct *tsk) -{ - int i; - struct thread_struct *t = &tsk->thread; - - for (i = 0; i < ARM_MAX_HBP_SLOTS; i++) { - if (t->debug.hbp[i]) { - unregister_hw_breakpoint(t->debug.hbp[i]); - t->debug.hbp[i] = NULL; - } - } -} - -static u32 ptrace_get_hbp_resource_info(void) -{ - u8 num_brps, num_wrps, debug_arch, wp_len; - u32 reg = 0; - - num_brps = hw_breakpoint_slots(TYPE_INST); - num_wrps = hw_breakpoint_slots(TYPE_DATA); - debug_arch = arch_get_debug_arch(); - wp_len = arch_get_max_wp_len(); - - reg |= debug_arch; - reg <<= 8; - reg |= wp_len; - reg <<= 8; - reg |= num_wrps; - reg <<= 8; - reg |= num_brps; - - return reg; -} - -static struct perf_event *ptrace_hbp_create(struct task_struct *tsk, int type) -{ - struct perf_event_attr attr; - - ptrace_breakpoint_init(&attr); - - /* Initialise fields to sane defaults. */ - attr.bp_addr = 0; - attr.bp_len = HW_BREAKPOINT_LEN_4; - attr.bp_type = type; - attr.disabled = 1; - - return register_user_hw_breakpoint(&attr, ptrace_hbptriggered, NULL, - tsk); -} - -static int ptrace_gethbpregs(struct task_struct *tsk, long num, - unsigned long __user *data) -{ - u32 reg; - int idx, ret = 0; - struct perf_event *bp; - struct arch_hw_breakpoint_ctrl arch_ctrl; - - if (num == 0) { - reg = ptrace_get_hbp_resource_info(); - } else { - idx = ptrace_hbp_num_to_idx(num); - if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) { - ret = -EINVAL; - goto out; - } - - bp = tsk->thread.debug.hbp[idx]; - if (!bp) { - reg = 0; - goto put; - } - - arch_ctrl = counter_arch_bp(bp)->ctrl; - - /* - * Fix up the len because we may have adjusted it - * to compensate for an unaligned address. - */ - while (!(arch_ctrl.len & 0x1)) - arch_ctrl.len >>= 1; - - if (num & 0x1) - reg = bp->attr.bp_addr; - else - reg = encode_ctrl_reg(arch_ctrl); - } - -put: - if (put_user(reg, data)) - ret = -EFAULT; - -out: - return ret; -} - -static int ptrace_sethbpregs(struct task_struct *tsk, long num, - unsigned long __user *data) -{ - int idx, gen_len, gen_type, implied_type, ret = 0; - u32 user_val; - struct perf_event *bp; - struct arch_hw_breakpoint_ctrl ctrl; - struct perf_event_attr attr; - - if (num == 0) - goto out; - else if (num < 0) - implied_type = HW_BREAKPOINT_RW; - else - implied_type = HW_BREAKPOINT_X; - - idx = ptrace_hbp_num_to_idx(num); - if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) { - ret = -EINVAL; - goto out; - } - - if (get_user(user_val, data)) { - ret = -EFAULT; - goto out; - } - - bp = tsk->thread.debug.hbp[idx]; - if (!bp) { - bp = ptrace_hbp_create(tsk, implied_type); - if (IS_ERR(bp)) { - ret = PTR_ERR(bp); - goto out; - } - tsk->thread.debug.hbp[idx] = bp; - } - - attr = bp->attr; - - if (num & 0x1) { - /* Address */ - attr.bp_addr = user_val; - } else { - /* Control */ - decode_ctrl_reg(user_val, &ctrl); - ret = arch_bp_generic_fields(ctrl, &gen_len, &gen_type); - if (ret) - goto out; - - if ((gen_type & implied_type) != gen_type) { - ret = -EINVAL; - goto out; - } - - attr.bp_len = gen_len; - attr.bp_type = gen_type; - attr.disabled = !ctrl.enabled; - } - - ret = modify_user_hw_breakpoint(bp, &attr); -out: - return ret; -} -#endif - -/* regset get/set implementations */ - -static int gpr_get(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf) -{ - struct pt_regs *regs = task_pt_regs(target); - - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, - regs, - 0, sizeof(*regs)); -} - -static int gpr_set(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - int ret; - struct pt_regs newregs; - - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, - &newregs, - 0, sizeof(newregs)); - if (ret) - return ret; - - if (!valid_user_regs(&newregs)) - return -EINVAL; - - *task_pt_regs(target) = newregs; - return 0; -} - -static int fpa_get(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf) -{ - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &task_thread_info(target)->fpstate, - 0, sizeof(struct user_fp)); -} - -static int fpa_set(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - struct thread_info *thread = task_thread_info(target); - - thread->used_cp[1] = thread->used_cp[2] = 1; - - return user_regset_copyin(&pos, &count, &kbuf, &ubuf, - &thread->fpstate, - 0, sizeof(struct user_fp)); -} - -#ifdef CONFIG_VFP -/* - * VFP register get/set implementations. - * - * With respect to the kernel, struct user_fp is divided into three chunks: - * 16 or 32 real VFP registers (d0-d15 or d0-31) - * These are transferred to/from the real registers in the task's - * vfp_hard_struct. The number of registers depends on the kernel - * configuration. - * - * 16 or 0 fake VFP registers (d16-d31 or empty) - * i.e., the user_vfp structure has space for 32 registers even if - * the kernel doesn't have them all. - * - * vfp_get() reads this chunk as zero where applicable - * vfp_set() ignores this chunk - * - * 1 word for the FPSCR - * - * The bounds-checking logic built into user_regset_copyout and friends - * means that we can make a simple sequence of calls to map the relevant data - * to/from the specified slice of the user regset structure. - */ -static int vfp_get(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - void *kbuf, void __user *ubuf) -{ - int ret; - struct thread_info *thread = task_thread_info(target); - struct vfp_hard_struct const *vfp = &thread->vfpstate.hard; - const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs); - const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr); - - vfp_sync_hwstate(thread); - - ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &vfp->fpregs, - user_fpregs_offset, - user_fpregs_offset + sizeof(vfp->fpregs)); - if (ret) - return ret; - - ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, - user_fpregs_offset + sizeof(vfp->fpregs), - user_fpscr_offset); - if (ret) - return ret; - - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &vfp->fpscr, - user_fpscr_offset, - user_fpscr_offset + sizeof(vfp->fpscr)); -} - -/* - * For vfp_set() a read-modify-write is done on the VFP registers, - * in order to avoid writing back a half-modified set of registers on - * failure. - */ -static int vfp_set(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - int ret; - struct thread_info *thread = task_thread_info(target); - struct vfp_hard_struct new_vfp; - const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs); - const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr); - - vfp_sync_hwstate(thread); - new_vfp = thread->vfpstate.hard; - - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, - &new_vfp.fpregs, - user_fpregs_offset, - user_fpregs_offset + sizeof(new_vfp.fpregs)); - if (ret) - return ret; - - ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, - user_fpregs_offset + sizeof(new_vfp.fpregs), - user_fpscr_offset); - if (ret) - return ret; - - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, - &new_vfp.fpscr, - user_fpscr_offset, - user_fpscr_offset + sizeof(new_vfp.fpscr)); - if (ret) - return ret; - - vfp_flush_hwstate(thread); - thread->vfpstate.hard = new_vfp; - - return 0; -} -#endif /* CONFIG_VFP */ - -enum arm_regset { - REGSET_GPR, - REGSET_FPR, -#ifdef CONFIG_VFP - REGSET_VFP, -#endif -}; - -static const struct user_regset arm_regsets[] = { - [REGSET_GPR] = { - .core_note_type = NT_PRSTATUS, - .n = ELF_NGREG, - .size = sizeof(u32), - .align = sizeof(u32), - .get = gpr_get, - .set = gpr_set - }, - [REGSET_FPR] = { - /* - * For the FPA regs in fpstate, the real fields are a mixture - * of sizes, so pretend that the registers are word-sized: - */ - .core_note_type = NT_PRFPREG, - .n = sizeof(struct user_fp) / sizeof(u32), - .size = sizeof(u32), - .align = sizeof(u32), - .get = fpa_get, - .set = fpa_set - }, -#ifdef CONFIG_VFP - [REGSET_VFP] = { - /* - * Pretend that the VFP regs are word-sized, since the FPSCR is - * a single word dangling at the end of struct user_vfp: - */ - .core_note_type = NT_ARM_VFP, - .n = ARM_VFPREGS_SIZE / sizeof(u32), - .size = sizeof(u32), - .align = sizeof(u32), - .get = vfp_get, - .set = vfp_set - }, -#endif /* CONFIG_VFP */ -}; - -static const struct user_regset_view user_arm_view = { - .name = "arm", .e_machine = ELF_ARCH, .ei_osabi = ELF_OSABI, - .regsets = arm_regsets, .n = ARRAY_SIZE(arm_regsets) -}; - -const struct user_regset_view *task_user_regset_view(struct task_struct *task) -{ - return &user_arm_view; -} - -long arch_ptrace(struct task_struct *child, long request, - unsigned long addr, unsigned long data) -{ - int ret; - unsigned long __user *datap = (unsigned long __user *) data; - - switch (request) { - case PTRACE_PEEKUSR: - ret = ptrace_read_user(child, addr, datap); - break; - - case PTRACE_POKEUSR: - ret = ptrace_write_user(child, addr, data); - break; - - case PTRACE_GETREGS: - ret = copy_regset_to_user(child, - &user_arm_view, REGSET_GPR, - 0, sizeof(struct pt_regs), - datap); - break; - - case PTRACE_SETREGS: - ret = copy_regset_from_user(child, - &user_arm_view, REGSET_GPR, - 0, sizeof(struct pt_regs), - datap); - break; - - case PTRACE_GETFPREGS: - ret = copy_regset_to_user(child, - &user_arm_view, REGSET_FPR, - 0, sizeof(union fp_state), - datap); - break; - - case PTRACE_SETFPREGS: - ret = copy_regset_from_user(child, - &user_arm_view, REGSET_FPR, - 0, sizeof(union fp_state), - datap); - break; - -#ifdef CONFIG_IWMMXT - case PTRACE_GETWMMXREGS: - ret = ptrace_getwmmxregs(child, datap); - break; - - case PTRACE_SETWMMXREGS: - ret = ptrace_setwmmxregs(child, datap); - break; -#endif - - case PTRACE_GET_THREAD_AREA: - ret = put_user(task_thread_info(child)->tp_value, - datap); - break; - - case PTRACE_SET_SYSCALL: - task_thread_info(child)->syscall = data; - ret = 0; - break; - -#ifdef CONFIG_CRUNCH - case PTRACE_GETCRUNCHREGS: - ret = ptrace_getcrunchregs(child, datap); - break; - - case PTRACE_SETCRUNCHREGS: - ret = ptrace_setcrunchregs(child, datap); - break; -#endif - -#ifdef CONFIG_VFP - case PTRACE_GETVFPREGS: - ret = copy_regset_to_user(child, - &user_arm_view, REGSET_VFP, - 0, ARM_VFPREGS_SIZE, - datap); - break; - - case PTRACE_SETVFPREGS: - ret = copy_regset_from_user(child, - &user_arm_view, REGSET_VFP, - 0, ARM_VFPREGS_SIZE, - datap); - break; -#endif - -#ifdef CONFIG_HAVE_HW_BREAKPOINT - case PTRACE_GETHBPREGS: - if (ptrace_get_breakpoints(child) < 0) - return -ESRCH; - - ret = ptrace_gethbpregs(child, addr, - (unsigned long __user *)data); - ptrace_put_breakpoints(child); - break; - case PTRACE_SETHBPREGS: - if (ptrace_get_breakpoints(child) < 0) - return -ESRCH; - - ret = ptrace_sethbpregs(child, addr, - (unsigned long __user *)data); - ptrace_put_breakpoints(child); - break; -#endif - - default: - ret = ptrace_request(child, request, addr, data); - break; - } - - return ret; -} - -asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno) -{ - unsigned long ip; - - if (why) - audit_syscall_exit(regs); - else - audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0, - regs->ARM_r1, regs->ARM_r2, regs->ARM_r3); - - if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return scno; - if (!(current->ptrace & PT_PTRACED)) - return scno; - - current_thread_info()->syscall = scno; - - /* - * IP is used to denote syscall entry/exit: - * IP = 0 -> entry, =1 -> exit - */ - ip = regs->ARM_ip; - regs->ARM_ip = why; - - /* the 0x80 provides a way for the tracing parent to distinguish - between a syscall stop and SIGTRAP delivery */ - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0)); - /* - * this isn't the same as continuing with a signal, but it will do - * for normal use. strace only continues with a signal if the - * stopping signal is not SIGTRAP. -brl - */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; - } - regs->ARM_ip = ip; - - return current_thread_info()->syscall; -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/relocate_kernel.S b/ANDROID_3.4.5/arch/arm/kernel/relocate_kernel.S deleted file mode 100644 index d0cdedf4..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/relocate_kernel.S +++ /dev/null @@ -1,88 +0,0 @@ -/* - * relocate_kernel.S - put the kernel image in place to boot - */ - -#include <asm/kexec.h> - - .globl relocate_new_kernel -relocate_new_kernel: - - ldr r0,kexec_indirection_page - ldr r1,kexec_start_address - - /* - * If there is no indirection page (we are doing crashdumps) - * skip any relocation. - */ - cmp r0, #0 - beq 2f - -0: /* top, read another word for the indirection page */ - ldr r3, [r0],#4 - - /* Is it a destination page. Put destination address to r4 */ - tst r3,#1,0 - beq 1f - bic r4,r3,#1 - b 0b -1: - /* Is it an indirection page */ - tst r3,#2,0 - beq 1f - bic r0,r3,#2 - b 0b -1: - - /* are we done ? */ - tst r3,#4,0 - beq 1f - b 2f - -1: - /* is it source ? */ - tst r3,#8,0 - beq 0b - bic r3,r3,#8 - mov r6,#1024 -9: - ldr r5,[r3],#4 - str r5,[r4],#4 - subs r6,r6,#1 - bne 9b - b 0b - -2: - /* Jump to relocated kernel */ - mov lr,r1 - mov r0,#0 - ldr r1,kexec_mach_type - ldr r2,kexec_boot_atags - ARM( mov pc, lr ) - THUMB( bx lr ) - - .align - - .globl kexec_start_address -kexec_start_address: - .long 0x0 - - .globl kexec_indirection_page -kexec_indirection_page: - .long 0x0 - - .globl kexec_mach_type -kexec_mach_type: - .long 0x0 - - /* phy addr of the atags for the new kernel */ - .globl kexec_boot_atags -kexec_boot_atags: - .long 0x0 - -relocate_new_kernel_end: - - .globl relocate_new_kernel_size -relocate_new_kernel_size: - .long relocate_new_kernel_end - relocate_new_kernel - - diff --git a/ANDROID_3.4.5/arch/arm/kernel/return_address.c b/ANDROID_3.4.5/arch/arm/kernel/return_address.c deleted file mode 100644 index 80854175..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/return_address.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * arch/arm/kernel/return_address.c - * - * Copyright (C) 2009 Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> - * for Pengutronix - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ -#include <linux/export.h> -#include <linux/ftrace.h> - -#if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) -#include <linux/sched.h> - -#include <asm/stacktrace.h> - -struct return_address_data { - unsigned int level; - void *addr; -}; - -static int save_return_addr(struct stackframe *frame, void *d) -{ - struct return_address_data *data = d; - - if (!data->level) { - data->addr = (void *)frame->lr; - - return 1; - } else { - --data->level; - return 0; - } -} - -void *return_address(unsigned int level) -{ - struct return_address_data data; - struct stackframe frame; - register unsigned long current_sp asm ("sp"); - - data.level = level + 1; - - frame.fp = (unsigned long)__builtin_frame_address(0); - frame.sp = current_sp; - frame.lr = (unsigned long)__builtin_return_address(0); - frame.pc = (unsigned long)return_address; - - walk_stackframe(&frame, save_return_addr, &data); - - if (!data.level) - return data.addr; - else - return NULL; -} - -#else /* if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) */ - -#if defined(CONFIG_ARM_UNWIND) -#warning "TODO: return_address should use unwind tables" -#endif - -void *return_address(unsigned int level) -{ - return NULL; -} - -#endif /* if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) / else */ - -EXPORT_SYMBOL_GPL(return_address); diff --git a/ANDROID_3.4.5/arch/arm/kernel/sched_clock.c b/ANDROID_3.4.5/arch/arm/kernel/sched_clock.c deleted file mode 100644 index 69d63e56..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/sched_clock.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * sched_clock.c: support for extending counters to full 64-bit ns counter - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/clocksource.h> -#include <linux/init.h> -#include <linux/jiffies.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/syscore_ops.h> -#include <linux/timer.h> - -#include <asm/sched_clock.h> - -struct clock_data { - u64 epoch_ns; - u32 epoch_cyc; - u32 epoch_cyc_copy; - u32 mult; - u32 shift; - bool suspended; - bool needs_suspend; -}; - -static void sched_clock_poll(unsigned long wrap_ticks); -static DEFINE_TIMER(sched_clock_timer, sched_clock_poll, 0, 0); - -static struct clock_data cd = { - .mult = NSEC_PER_SEC / HZ, -}; - -static u32 __read_mostly sched_clock_mask = 0xffffffff; - -static u32 notrace jiffy_sched_clock_read(void) -{ - return (u32)(jiffies - INITIAL_JIFFIES); -} - -static u32 __read_mostly (*read_sched_clock)(void) = jiffy_sched_clock_read; - -static inline u64 cyc_to_ns(u64 cyc, u32 mult, u32 shift) -{ - return (cyc * mult) >> shift; -} - -static unsigned long long cyc_to_sched_clock(u32 cyc, u32 mask) -{ - u64 epoch_ns; - u32 epoch_cyc; - - if (cd.suspended) - return cd.epoch_ns; - - /* - * Load the epoch_cyc and epoch_ns atomically. We do this by - * ensuring that we always write epoch_cyc, epoch_ns and - * epoch_cyc_copy in strict order, and read them in strict order. - * If epoch_cyc and epoch_cyc_copy are not equal, then we're in - * the middle of an update, and we should repeat the load. - */ - do { - epoch_cyc = cd.epoch_cyc; - smp_rmb(); - epoch_ns = cd.epoch_ns; - smp_rmb(); - } while (epoch_cyc != cd.epoch_cyc_copy); - - return epoch_ns + cyc_to_ns((cyc - epoch_cyc) & mask, cd.mult, cd.shift); -} - -/* - * Atomically update the sched_clock epoch. - */ -static void notrace update_sched_clock(void) -{ - unsigned long flags; - u32 cyc; - u64 ns; - - cyc = read_sched_clock(); - ns = cd.epoch_ns + - cyc_to_ns((cyc - cd.epoch_cyc) & sched_clock_mask, - cd.mult, cd.shift); - /* - * Write epoch_cyc and epoch_ns in a way that the update is - * detectable in cyc_to_fixed_sched_clock(). - */ - raw_local_irq_save(flags); - cd.epoch_cyc = cyc; - smp_wmb(); - cd.epoch_ns = ns; - smp_wmb(); - cd.epoch_cyc_copy = cyc; - raw_local_irq_restore(flags); -} - -static void sched_clock_poll(unsigned long wrap_ticks) -{ - mod_timer(&sched_clock_timer, round_jiffies(jiffies + wrap_ticks)); - update_sched_clock(); -} - -void __init setup_sched_clock_needs_suspend(u32 (*read)(void), int bits, - unsigned long rate) -{ - setup_sched_clock(read, bits, rate); - cd.needs_suspend = true; -} - -void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) -{ - unsigned long r, w; - u64 res, wrap; - char r_unit; - - BUG_ON(bits > 32); - WARN_ON(!irqs_disabled()); - WARN_ON(read_sched_clock != jiffy_sched_clock_read); - read_sched_clock = read; - sched_clock_mask = (1 << bits) - 1; - - /* calculate the mult/shift to convert counter ticks to ns. */ - clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 0); - - r = rate; - if (r >= 4000000) { - r /= 1000000; - r_unit = 'M'; - } else if (r >= 1000) { - r /= 1000; - r_unit = 'k'; - } else - r_unit = ' '; - - /* calculate how many ns until we wrap */ - wrap = cyc_to_ns((1ULL << bits) - 1, cd.mult, cd.shift); - do_div(wrap, NSEC_PER_MSEC); - w = wrap; - - /* calculate the ns resolution of this counter */ - res = cyc_to_ns(1ULL, cd.mult, cd.shift); - pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lums\n", - bits, r, r_unit, res, w); - - /* - * Start the timer to keep sched_clock() properly updated and - * sets the initial epoch. - */ - sched_clock_timer.data = msecs_to_jiffies((w - (w / 10))/2); - update_sched_clock(); - - /* - * Ensure that sched_clock() starts off at 0ns - */ - cd.epoch_ns = 0; - - pr_debug("Registered %pF as sched_clock source\n", read); -} - -unsigned long long notrace sched_clock(void) -{ - u32 cyc = read_sched_clock(); - return cyc_to_sched_clock(cyc, sched_clock_mask); -} - -void __init sched_clock_postinit(void) -{ - /* - * If no sched_clock function has been provided at that point, - * make it the final one one. - */ - if (read_sched_clock == jiffy_sched_clock_read) - setup_sched_clock(jiffy_sched_clock_read, 32, HZ); - - sched_clock_poll(sched_clock_timer.data); -} - -static int sched_clock_suspend(void) -{ - sched_clock_poll(sched_clock_timer.data); - if (cd.needs_suspend) - cd.suspended = true; - return 0; -} - -static void sched_clock_resume(void) -{ - if (cd.needs_suspend) { - cd.epoch_cyc = read_sched_clock(); - cd.epoch_cyc_copy = cd.epoch_cyc; - cd.suspended = false; - } -} - -static struct syscore_ops sched_clock_ops = { - .suspend = sched_clock_suspend, - .resume = sched_clock_resume, -}; - -static int __init sched_clock_syscore_init(void) -{ - register_syscore_ops(&sched_clock_ops); - return 0; -} -device_initcall(sched_clock_syscore_init); diff --git a/ANDROID_3.4.5/arch/arm/kernel/setup.c b/ANDROID_3.4.5/arch/arm/kernel/setup.c deleted file mode 100644 index ebfac782..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/setup.c +++ /dev/null @@ -1,1132 +0,0 @@ -/* - * linux/arch/arm/kernel/setup.c - * - * Copyright (C) 1995-2001 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/export.h> -#include <linux/kernel.h> -#include <linux/stddef.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/utsname.h> -#include <linux/initrd.h> -#include <linux/console.h> -#include <linux/bootmem.h> -#include <linux/seq_file.h> -#include <linux/screen_info.h> -#include <linux/init.h> -#include <linux/kexec.h> -#include <linux/of_fdt.h> -#include <linux/root_dev.h> -#include <linux/cpu.h> -#include <linux/interrupt.h> -#include <linux/smp.h> -#include <linux/fs.h> -#include <linux/proc_fs.h> -#include <linux/memblock.h> -#include <linux/bug.h> -#include <linux/compiler.h> -#include <linux/sort.h> - -#include <asm/unified.h> -#include <asm/cp15.h> -#include <asm/cpu.h> -#include <asm/cputype.h> -#include <asm/elf.h> -#include <asm/procinfo.h> -#include <asm/sections.h> -#include <asm/setup.h> -#include <asm/smp_plat.h> -#include <asm/mach-types.h> -#include <asm/cacheflush.h> -#include <asm/cachetype.h> -#include <asm/tlbflush.h> - -#include <asm/prom.h> -#include <asm/mach/arch.h> -#include <asm/mach/irq.h> -#include <asm/mach/time.h> -#include <asm/system_info.h> -#include <asm/system_misc.h> -#include <asm/traps.h> -#include <asm/unwind.h> -#include <asm/memblock.h> - -#if defined(CONFIG_DEPRECATED_PARAM_STRUCT) -#include "compat.h" -#endif -#include "atags.h" -#include "tcm.h" - -#ifndef MEM_SIZE -#define MEM_SIZE (16*1024*1024) -#endif - -#if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE) -char fpe_type[8]; - -static int __init fpe_setup(char *line) -{ - memcpy(fpe_type, line, 8); - return 1; -} - -__setup("fpe=", fpe_setup); -#endif - -extern void paging_init(struct machine_desc *desc); -extern void sanity_check_meminfo(void); -extern void reboot_setup(char *str); - -unsigned int processor_id; -EXPORT_SYMBOL(processor_id); -unsigned int __machine_arch_type __read_mostly; -EXPORT_SYMBOL(__machine_arch_type); -unsigned int cacheid __read_mostly; -EXPORT_SYMBOL(cacheid); - -unsigned int __atags_pointer __initdata; - -unsigned int system_rev; -EXPORT_SYMBOL(system_rev); - -unsigned int system_serial_low; -EXPORT_SYMBOL(system_serial_low); - -unsigned int system_serial_high; -EXPORT_SYMBOL(system_serial_high); - -unsigned int elf_hwcap __read_mostly; -EXPORT_SYMBOL(elf_hwcap); - - -#ifdef MULTI_CPU -struct processor processor __read_mostly; -#endif -#ifdef MULTI_TLB -struct cpu_tlb_fns cpu_tlb __read_mostly; -#endif -#ifdef MULTI_USER -struct cpu_user_fns cpu_user __read_mostly; -#endif -#ifdef MULTI_CACHE -struct cpu_cache_fns cpu_cache __read_mostly; -#endif -#ifdef CONFIG_OUTER_CACHE -struct outer_cache_fns outer_cache __read_mostly; -EXPORT_SYMBOL(outer_cache); -#endif - -/* - * Cached cpu_architecture() result for use by assembler code. - * C code should use the cpu_architecture() function instead of accessing this - * variable directly. - */ -int __cpu_architecture __read_mostly = CPU_ARCH_UNKNOWN; - -struct stack { - u32 irq[3]; - u32 abt[3]; - u32 und[3]; -} ____cacheline_aligned; - -static struct stack stacks[NR_CPUS]; - -char elf_platform[ELF_PLATFORM_SIZE]; -EXPORT_SYMBOL(elf_platform); - -static const char *cpu_name; -static const char *machine_name; -static char __initdata cmd_line[COMMAND_LINE_SIZE]; -struct machine_desc *machine_desc __initdata; - -static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; -static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } }; -#define ENDIANNESS ((char)endian_test.l) - -DEFINE_PER_CPU(struct cpuinfo_arm, cpu_data); - -/* - * Standard memory resources - */ -static struct resource mem_res[] = { - { - .name = "Video RAM", - .start = 0, - .end = 0, - .flags = IORESOURCE_MEM - }, - { - .name = "Kernel code", - .start = 0, - .end = 0, - .flags = IORESOURCE_MEM - }, - { - .name = "Kernel data", - .start = 0, - .end = 0, - .flags = IORESOURCE_MEM - } -}; - -#define video_ram mem_res[0] -#define kernel_code mem_res[1] -#define kernel_data mem_res[2] - -static struct resource io_res[] = { - { - .name = "reserved", - .start = 0x3bc, - .end = 0x3be, - .flags = IORESOURCE_IO | IORESOURCE_BUSY - }, - { - .name = "reserved", - .start = 0x378, - .end = 0x37f, - .flags = IORESOURCE_IO | IORESOURCE_BUSY - }, - { - .name = "reserved", - .start = 0x278, - .end = 0x27f, - .flags = IORESOURCE_IO | IORESOURCE_BUSY - } -}; - -#define lp0 io_res[0] -#define lp1 io_res[1] -#define lp2 io_res[2] - -static const char *proc_arch[] = { - "undefined/unknown", - "3", - "4", - "4T", - "5", - "5T", - "5TE", - "5TEJ", - "6TEJ", - "7", - "?(11)", - "?(12)", - "?(13)", - "?(14)", - "?(15)", - "?(16)", - "?(17)", -}; - -static int __get_cpu_architecture(void) -{ - int cpu_arch; - - if ((read_cpuid_id() & 0x0008f000) == 0) { - cpu_arch = CPU_ARCH_UNKNOWN; - } else if ((read_cpuid_id() & 0x0008f000) == 0x00007000) { - cpu_arch = (read_cpuid_id() & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3; - } else if ((read_cpuid_id() & 0x00080000) == 0x00000000) { - cpu_arch = (read_cpuid_id() >> 16) & 7; - if (cpu_arch) - cpu_arch += CPU_ARCH_ARMv3; - } else if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) { - unsigned int mmfr0; - - /* Revised CPUID format. Read the Memory Model Feature - * Register 0 and check for VMSAv7 or PMSAv7 */ - asm("mrc p15, 0, %0, c0, c1, 4" - : "=r" (mmfr0)); - if ((mmfr0 & 0x0000000f) >= 0x00000003 || - (mmfr0 & 0x000000f0) >= 0x00000030) - cpu_arch = CPU_ARCH_ARMv7; - else if ((mmfr0 & 0x0000000f) == 0x00000002 || - (mmfr0 & 0x000000f0) == 0x00000020) - cpu_arch = CPU_ARCH_ARMv6; - else - cpu_arch = CPU_ARCH_UNKNOWN; - } else - cpu_arch = CPU_ARCH_UNKNOWN; - - return cpu_arch; -} - -int __pure cpu_architecture(void) -{ - BUG_ON(__cpu_architecture == CPU_ARCH_UNKNOWN); - - return __cpu_architecture; -} - -static int cpu_has_aliasing_icache(unsigned int arch) -{ - int aliasing_icache; - unsigned int id_reg, num_sets, line_size; - - /* PIPT caches never alias. */ - if (icache_is_pipt()) - return 0; - - /* arch specifies the register format */ - switch (arch) { - case CPU_ARCH_ARMv7: - asm("mcr p15, 2, %0, c0, c0, 0 @ set CSSELR" - : /* No output operands */ - : "r" (1)); - isb(); - asm("mrc p15, 1, %0, c0, c0, 0 @ read CCSIDR" - : "=r" (id_reg)); - line_size = 4 << ((id_reg & 0x7) + 2); - num_sets = ((id_reg >> 13) & 0x7fff) + 1; - aliasing_icache = (line_size * num_sets) > PAGE_SIZE; - break; - case CPU_ARCH_ARMv6: - aliasing_icache = read_cpuid_cachetype() & (1 << 11); - break; - default: - /* I-cache aliases will be handled by D-cache aliasing code */ - aliasing_icache = 0; - } - - return aliasing_icache; -} - -static void __init cacheid_init(void) -{ - unsigned int cachetype = read_cpuid_cachetype(); - unsigned int arch = cpu_architecture(); - - if (arch >= CPU_ARCH_ARMv6) { - if ((cachetype & (7 << 29)) == 4 << 29) { - /* ARMv7 register format */ - arch = CPU_ARCH_ARMv7; - cacheid = CACHEID_VIPT_NONALIASING; - switch (cachetype & (3 << 14)) { - case (1 << 14): - cacheid |= CACHEID_ASID_TAGGED; - break; - case (3 << 14): - cacheid |= CACHEID_PIPT; - break; - } - } else { - arch = CPU_ARCH_ARMv6; - if (cachetype & (1 << 23)) - cacheid = CACHEID_VIPT_ALIASING; - else - cacheid = CACHEID_VIPT_NONALIASING; - } - if (cpu_has_aliasing_icache(arch)) - cacheid |= CACHEID_VIPT_I_ALIASING; - } else { - cacheid = CACHEID_VIVT; - } - - printk("CPU: %s data cache, %s instruction cache\n", - cache_is_vivt() ? "VIVT" : - cache_is_vipt_aliasing() ? "VIPT aliasing" : - cache_is_vipt_nonaliasing() ? "PIPT / VIPT nonaliasing" : "unknown", - cache_is_vivt() ? "VIVT" : - icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" : - icache_is_vipt_aliasing() ? "VIPT aliasing" : - icache_is_pipt() ? "PIPT" : - cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown"); -} - -/* - * These functions re-use the assembly code in head.S, which - * already provide the required functionality. - */ -extern struct proc_info_list *lookup_processor_type(unsigned int); - -void __init early_print(const char *str, ...) -{ - extern void printascii(const char *); - char buf[256]; - va_list ap; - - va_start(ap, str); - vsnprintf(buf, sizeof(buf), str, ap); - va_end(ap); - -#ifdef CONFIG_DEBUG_LL - printascii(buf); -#endif - printk("%s", buf); -} - -static void __init feat_v6_fixup(void) -{ - int id = read_cpuid_id(); - - if ((id & 0xff0f0000) != 0x41070000) - return; - - /* - * HWCAP_TLS is available only on 1136 r1p0 and later, - * see also kuser_get_tls_init. - */ - if ((((id >> 4) & 0xfff) == 0xb36) && (((id >> 20) & 3) == 0)) - elf_hwcap &= ~HWCAP_TLS; -} - -/* - * cpu_init - initialise one CPU. - * - * cpu_init sets up the per-CPU stacks. - */ -void cpu_init(void) -{ - unsigned int cpu = smp_processor_id(); - struct stack *stk = &stacks[cpu]; - - if (cpu >= NR_CPUS) { - printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu); - BUG(); - } - - cpu_proc_init(); - - /* - * Define the placement constraint for the inline asm directive below. - * In Thumb-2, msr with an immediate value is not allowed. - */ -#ifdef CONFIG_THUMB2_KERNEL -#define PLC "r" -#else -#define PLC "I" -#endif - - /* - * setup stacks for re-entrant exception handlers - */ - __asm__ ( - "msr cpsr_c, %1\n\t" - "add r14, %0, %2\n\t" - "mov sp, r14\n\t" - "msr cpsr_c, %3\n\t" - "add r14, %0, %4\n\t" - "mov sp, r14\n\t" - "msr cpsr_c, %5\n\t" - "add r14, %0, %6\n\t" - "mov sp, r14\n\t" - "msr cpsr_c, %7" - : - : "r" (stk), - PLC (PSR_F_BIT | PSR_I_BIT | IRQ_MODE), - "I" (offsetof(struct stack, irq[0])), - PLC (PSR_F_BIT | PSR_I_BIT | ABT_MODE), - "I" (offsetof(struct stack, abt[0])), - PLC (PSR_F_BIT | PSR_I_BIT | UND_MODE), - "I" (offsetof(struct stack, und[0])), - PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE) - : "r14"); -} - -int __cpu_logical_map[NR_CPUS]; - -void __init smp_setup_processor_id(void) -{ - int i; - u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0; - - cpu_logical_map(0) = cpu; - for (i = 1; i < NR_CPUS; ++i) - cpu_logical_map(i) = i == cpu ? 0 : i; - - printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu); -} - -static void __init setup_processor(void) -{ - struct proc_info_list *list; - - /* - * locate processor in the list of supported processor - * types. The linker builds this table for us from the - * entries in arch/arm/mm/proc-*.S - */ - list = lookup_processor_type(read_cpuid_id()); - if (!list) { - printk("CPU configuration botched (ID %08x), unable " - "to continue.\n", read_cpuid_id()); - while (1); - } - - cpu_name = list->cpu_name; - __cpu_architecture = __get_cpu_architecture(); - -#ifdef MULTI_CPU - processor = *list->proc; -#endif -#ifdef MULTI_TLB - cpu_tlb = *list->tlb; -#endif -#ifdef MULTI_USER - cpu_user = *list->user; -#endif -#ifdef MULTI_CACHE - cpu_cache = *list->cache; -#endif - - printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n", - cpu_name, read_cpuid_id(), read_cpuid_id() & 15, - proc_arch[cpu_architecture()], cr_alignment); - - snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c", - list->arch_name, ENDIANNESS); - snprintf(elf_platform, ELF_PLATFORM_SIZE, "%s%c", - list->elf_name, ENDIANNESS); - elf_hwcap = list->elf_hwcap; -#ifndef CONFIG_ARM_THUMB - elf_hwcap &= ~HWCAP_THUMB; -#endif - - feat_v6_fixup(); - - cacheid_init(); - cpu_init(); -} - -void __init dump_machine_table(void) -{ - struct machine_desc *p; - - early_print("Available machine support:\n\nID (hex)\tNAME\n"); - for_each_machine_desc(p) - early_print("%08x\t%s\n", p->nr, p->name); - - early_print("\nPlease check your kernel config and/or bootloader.\n"); - - while (true) - /* can't use cpu_relax() here as it may require MMU setup */; -} - -int __init arm_add_memory(phys_addr_t start, unsigned long size) -{ - struct membank *bank = &meminfo.bank[meminfo.nr_banks]; - - if (meminfo.nr_banks >= NR_BANKS) { - printk(KERN_CRIT "NR_BANKS too low, " - "ignoring memory at 0x%08llx\n", (long long)start); - return -EINVAL; - } - - /* - * Ensure that start/size are aligned to a page boundary. - * Size is appropriately rounded down, start is rounded up. - */ - size -= start & ~PAGE_MASK; - bank->start = PAGE_ALIGN(start); - -#ifndef CONFIG_LPAE - if (bank->start + size < bank->start) { - printk(KERN_CRIT "Truncating memory at 0x%08llx to fit in " - "32-bit physical address space\n", (long long)start); - /* - * To ensure bank->start + bank->size is representable in - * 32 bits, we use ULONG_MAX as the upper limit rather than 4GB. - * This means we lose a page after masking. - */ - size = ULONG_MAX - bank->start; - } -#endif - - bank->size = size & PAGE_MASK; - - /* - * Check whether this memory region has non-zero size or - * invalid node number. - */ - if (bank->size == 0) - return -EINVAL; - - meminfo.nr_banks++; - return 0; -} - -/* - * Pick out the memory size. We look for mem=size@start, - * where start and size are "size[KkMm]" - */ -static int __init early_mem(char *p) -{ - static int usermem __initdata = 0; - unsigned long size; - phys_addr_t start; - char *endp; - - /* - * If the user specifies memory size, we - * blow away any automatically generated - * size. - */ - if (usermem == 0) { - usermem = 1; - meminfo.nr_banks = 0; - } - - start = PHYS_OFFSET; - size = memparse(p, &endp); - if (*endp == '@') - start = memparse(endp + 1, NULL); - - arm_add_memory(start, size); - - return 0; -} -early_param("mem", early_mem); - -static void __init -setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz) -{ -#ifdef CONFIG_BLK_DEV_RAM - extern int rd_size, rd_image_start, rd_prompt, rd_doload; - - rd_image_start = image_start; - rd_prompt = prompt; - rd_doload = doload; - - if (rd_sz) - rd_size = rd_sz; -#endif -} - -static void __init request_standard_resources(struct machine_desc *mdesc) -{ - struct memblock_region *region; - struct resource *res; - - kernel_code.start = virt_to_phys(_text); - kernel_code.end = virt_to_phys(_etext - 1); - kernel_data.start = virt_to_phys(_sdata); - kernel_data.end = virt_to_phys(_end - 1); - - for_each_memblock(memory, region) { - res = alloc_bootmem_low(sizeof(*res)); - res->name = "System RAM"; - res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region)); - res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1; - res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; - - request_resource(&iomem_resource, res); - - if (kernel_code.start >= res->start && - kernel_code.end <= res->end) - request_resource(res, &kernel_code); - if (kernel_data.start >= res->start && - kernel_data.end <= res->end) - request_resource(res, &kernel_data); - } - - if (mdesc->video_start) { - video_ram.start = mdesc->video_start; - video_ram.end = mdesc->video_end; - request_resource(&iomem_resource, &video_ram); - } - - /* - * Some machines don't have the possibility of ever - * possessing lp0, lp1 or lp2 - */ - if (mdesc->reserve_lp0) - request_resource(&ioport_resource, &lp0); - if (mdesc->reserve_lp1) - request_resource(&ioport_resource, &lp1); - if (mdesc->reserve_lp2) - request_resource(&ioport_resource, &lp2); -} - -/* - * Tag parsing. - * - * This is the new way of passing data to the kernel at boot time. Rather - * than passing a fixed inflexible structure to the kernel, we pass a list - * of variable-sized tags to the kernel. The first tag must be a ATAG_CORE - * tag for the list to be recognised (to distinguish the tagged list from - * a param_struct). The list is terminated with a zero-length tag (this tag - * is not parsed in any way). - */ -static int __init parse_tag_core(const struct tag *tag) -{ - if (tag->hdr.size > 2) { - if ((tag->u.core.flags & 1) == 0) - root_mountflags &= ~MS_RDONLY; - ROOT_DEV = old_decode_dev(tag->u.core.rootdev); - } - return 0; -} - -__tagtable(ATAG_CORE, parse_tag_core); - -static int __init parse_tag_mem32(const struct tag *tag) -{ - return arm_add_memory(tag->u.mem.start, tag->u.mem.size); -} - -__tagtable(ATAG_MEM, parse_tag_mem32); - -#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE) -struct screen_info screen_info = { - .orig_video_lines = 30, - .orig_video_cols = 80, - .orig_video_mode = 0, - .orig_video_ega_bx = 0, - .orig_video_isVGA = 1, - .orig_video_points = 8 -}; - -static int __init parse_tag_videotext(const struct tag *tag) -{ - screen_info.orig_x = tag->u.videotext.x; - screen_info.orig_y = tag->u.videotext.y; - screen_info.orig_video_page = tag->u.videotext.video_page; - screen_info.orig_video_mode = tag->u.videotext.video_mode; - screen_info.orig_video_cols = tag->u.videotext.video_cols; - screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx; - screen_info.orig_video_lines = tag->u.videotext.video_lines; - screen_info.orig_video_isVGA = tag->u.videotext.video_isvga; - screen_info.orig_video_points = tag->u.videotext.video_points; - return 0; -} - -__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext); -#endif - -static int __init parse_tag_ramdisk(const struct tag *tag) -{ - setup_ramdisk((tag->u.ramdisk.flags & 1) == 0, - (tag->u.ramdisk.flags & 2) == 0, - tag->u.ramdisk.start, tag->u.ramdisk.size); - return 0; -} - -__tagtable(ATAG_RAMDISK, parse_tag_ramdisk); - -static int __init parse_tag_serialnr(const struct tag *tag) -{ - system_serial_low = tag->u.serialnr.low; - system_serial_high = tag->u.serialnr.high; - return 0; -} - -__tagtable(ATAG_SERIAL, parse_tag_serialnr); - -static int __init parse_tag_revision(const struct tag *tag) -{ - system_rev = tag->u.revision.rev; - return 0; -} - -__tagtable(ATAG_REVISION, parse_tag_revision); - -static int __init parse_tag_cmdline(const struct tag *tag) -{ -#if defined(CONFIG_CMDLINE_EXTEND) - strlcat(default_command_line, " ", COMMAND_LINE_SIZE); - strlcat(default_command_line, tag->u.cmdline.cmdline, - COMMAND_LINE_SIZE); -#elif defined(CONFIG_CMDLINE_FORCE) - pr_warning("Ignoring tag cmdline (using the default kernel command line)\n"); -#else - strlcpy(default_command_line, tag->u.cmdline.cmdline, - COMMAND_LINE_SIZE); -#endif - return 0; -} - -__tagtable(ATAG_CMDLINE, parse_tag_cmdline); - -/* - * Scan the tag table for this tag, and call its parse function. - * The tag table is built by the linker from all the __tagtable - * declarations. - */ -static int __init parse_tag(const struct tag *tag) -{ - extern struct tagtable __tagtable_begin, __tagtable_end; - struct tagtable *t; - - for (t = &__tagtable_begin; t < &__tagtable_end; t++) - if (tag->hdr.tag == t->tag) { - t->parse(tag); - break; - } - - return t < &__tagtable_end; -} - -/* - * Parse all tags in the list, checking both the global and architecture - * specific tag tables. - */ -static void __init parse_tags(const struct tag *t) -{ - for (; t->hdr.size; t = tag_next(t)) - if (!parse_tag(t)) - printk(KERN_WARNING - "Ignoring unrecognised tag 0x%08x\n", - t->hdr.tag); -} - -/* - * This holds our defaults. - */ -static struct init_tags { - struct tag_header hdr1; - struct tag_core core; - struct tag_header hdr2; - struct tag_mem32 mem; - struct tag_header hdr3; -} init_tags __initdata = { - { tag_size(tag_core), ATAG_CORE }, - { 1, PAGE_SIZE, 0xff }, - { tag_size(tag_mem32), ATAG_MEM }, - { MEM_SIZE }, - { 0, ATAG_NONE } -}; - -static int __init customize_machine(void) -{ - /* customizes platform devices, or adds new ones */ - if (machine_desc->init_machine) - machine_desc->init_machine(); - return 0; -} -arch_initcall(customize_machine); - -#ifdef CONFIG_KEXEC -static inline unsigned long long get_total_mem(void) -{ - unsigned long total; - - total = max_low_pfn - min_low_pfn; - return total << PAGE_SHIFT; -} - -/** - * reserve_crashkernel() - reserves memory are for crash kernel - * - * This function reserves memory area given in "crashkernel=" kernel command - * line parameter. The memory reserved is used by a dump capture kernel when - * primary kernel is crashing. - */ -static void __init reserve_crashkernel(void) -{ - unsigned long long crash_size, crash_base; - unsigned long long total_mem; - int ret; - - total_mem = get_total_mem(); - ret = parse_crashkernel(boot_command_line, total_mem, - &crash_size, &crash_base); - if (ret) - return; - - ret = reserve_bootmem(crash_base, crash_size, BOOTMEM_EXCLUSIVE); - if (ret < 0) { - printk(KERN_WARNING "crashkernel reservation failed - " - "memory is in use (0x%lx)\n", (unsigned long)crash_base); - return; - } - - printk(KERN_INFO "Reserving %ldMB of memory at %ldMB " - "for crashkernel (System RAM: %ldMB)\n", - (unsigned long)(crash_size >> 20), - (unsigned long)(crash_base >> 20), - (unsigned long)(total_mem >> 20)); - - crashk_res.start = crash_base; - crashk_res.end = crash_base + crash_size - 1; - insert_resource(&iomem_resource, &crashk_res); -} -#else -static inline void reserve_crashkernel(void) {} -#endif /* CONFIG_KEXEC */ - -static void __init squash_mem_tags(struct tag *tag) -{ - for (; tag->hdr.size; tag = tag_next(tag)) - if (tag->hdr.tag == ATAG_MEM) - tag->hdr.tag = ATAG_NONE; -} - -static struct machine_desc * __init setup_machine_tags(unsigned int nr) -{ - struct tag *tags = (struct tag *)&init_tags; - struct machine_desc *mdesc = NULL, *p; - char *from = default_command_line; - - init_tags.mem.start = PHYS_OFFSET; - - /* - * locate machine in the list of supported machines. - */ - for_each_machine_desc(p) - if (nr == p->nr) { - printk("Machine: %s\n", p->name); - mdesc = p; - break; - } - - if (!mdesc) { - early_print("\nError: unrecognized/unsupported machine ID" - " (r1 = 0x%08x).\n\n", nr); - dump_machine_table(); /* does not return */ - } - - if (__atags_pointer) - tags = phys_to_virt(__atags_pointer); - else if (mdesc->atag_offset) - tags = (void *)(PAGE_OFFSET + mdesc->atag_offset); - -#if defined(CONFIG_DEPRECATED_PARAM_STRUCT) - /* - * If we have the old style parameters, convert them to - * a tag list. - */ - if (tags->hdr.tag != ATAG_CORE) - convert_to_tag_list(tags); -#endif - - if (tags->hdr.tag != ATAG_CORE) { -#if defined(CONFIG_OF) - /* - * If CONFIG_OF is set, then assume this is a reasonably - * modern system that should pass boot parameters - */ - early_print("Warning: Neither atags nor dtb found\n"); -#endif - tags = (struct tag *)&init_tags; - } - - if (mdesc->fixup) - mdesc->fixup(tags, &from, &meminfo); - - if (tags->hdr.tag == ATAG_CORE) { - if (meminfo.nr_banks != 0) - squash_mem_tags(tags); - save_atags(tags); - parse_tags(tags); - } - - /* parse_early_param needs a boot_command_line */ - strlcpy(boot_command_line, from, COMMAND_LINE_SIZE); - - return mdesc; -} - -static int __init meminfo_cmp(const void *_a, const void *_b) -{ - const struct membank *a = _a, *b = _b; - long cmp = bank_pfn_start(a) - bank_pfn_start(b); - return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; -} - -void __init setup_arch(char **cmdline_p) -{ - struct machine_desc *mdesc; - - setup_processor(); - mdesc = setup_machine_fdt(__atags_pointer); - if (!mdesc) - mdesc = setup_machine_tags(machine_arch_type); - machine_desc = mdesc; - machine_name = mdesc->name; - -#ifdef CONFIG_ZONE_DMA - if (mdesc->dma_zone_size) { - extern unsigned long arm_dma_zone_size; - arm_dma_zone_size = mdesc->dma_zone_size; - } -#endif - if (mdesc->restart_mode) - reboot_setup(&mdesc->restart_mode); - - init_mm.start_code = (unsigned long) _text; - init_mm.end_code = (unsigned long) _etext; - init_mm.end_data = (unsigned long) _edata; - init_mm.brk = (unsigned long) _end; - - /* populate cmd_line too for later use, preserving boot_command_line */ - strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE); - *cmdline_p = cmd_line; - - parse_early_param(); - - sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL); - sanity_check_meminfo(); - arm_memblock_init(&meminfo, mdesc); - - paging_init(mdesc); - request_standard_resources(mdesc); - - if (mdesc->restart) - arm_pm_restart = mdesc->restart; - - unflatten_device_tree(); - -#ifdef CONFIG_SMP - if (is_smp()) - smp_init_cpus(); -#endif - reserve_crashkernel(); - - tcm_init(); - -#ifdef CONFIG_MULTI_IRQ_HANDLER - handle_arch_irq = mdesc->handle_irq; -#endif - -#ifdef CONFIG_VT -#if defined(CONFIG_VGA_CONSOLE) - conswitchp = &vga_con; -#elif defined(CONFIG_DUMMY_CONSOLE) - conswitchp = &dummy_con; -#endif -#endif - - if (mdesc->init_early) - mdesc->init_early(); -} - - -static int __init topology_init(void) -{ - int cpu; - - for_each_possible_cpu(cpu) { - struct cpuinfo_arm *cpuinfo = &per_cpu(cpu_data, cpu); - cpuinfo->cpu.hotpluggable = 1; - register_cpu(&cpuinfo->cpu, cpu); - } - - return 0; -} -subsys_initcall(topology_init); - -#ifdef CONFIG_HAVE_PROC_CPU -static int __init proc_cpu_init(void) -{ - struct proc_dir_entry *res; - - res = proc_mkdir("cpu", NULL); - if (!res) - return -ENOMEM; - return 0; -} -fs_initcall(proc_cpu_init); -#endif - -static const char *hwcap_str[] = { - "swp", - "half", - "thumb", - "26bit", - "fastmult", - "fpa", - "vfp", - "edsp", - "java", - "iwmmxt", - "crunch", - "thumbee", - "neon", - "vfpv3", - "vfpv3d16", - "tls", - "vfpv4", - "idiva", - "idivt", - NULL -}; - -static int c_show(struct seq_file *m, void *v) -{ - int i; - - seq_printf(m, "Processor\t: %s rev %d (%s)\n", - cpu_name, read_cpuid_id() & 15, elf_platform); - -#if defined(CONFIG_SMP) - for_each_online_cpu(i) { - /* - * glibc reads /proc/cpuinfo to determine the number of - * online processors, looking for lines beginning with - * "processor". Give glibc what it expects. - */ - seq_printf(m, "processor\t: %d\n", i); - seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n", - per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ), - (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100); - } -#else /* CONFIG_SMP */ - seq_printf(m, "BogoMIPS\t: %lu.%02lu\n", - loops_per_jiffy / (500000/HZ), - (loops_per_jiffy / (5000/HZ)) % 100); -#endif - - /* dump out the processor features */ - seq_puts(m, "Features\t: "); - - for (i = 0; hwcap_str[i]; i++) - if (elf_hwcap & (1 << i)) - seq_printf(m, "%s ", hwcap_str[i]); - - seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24); - seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]); - - if ((read_cpuid_id() & 0x0008f000) == 0x00000000) { - /* pre-ARM7 */ - seq_printf(m, "CPU part\t: %07x\n", read_cpuid_id() >> 4); - } else { - if ((read_cpuid_id() & 0x0008f000) == 0x00007000) { - /* ARM7 */ - seq_printf(m, "CPU variant\t: 0x%02x\n", - (read_cpuid_id() >> 16) & 127); - } else { - /* post-ARM7 */ - seq_printf(m, "CPU variant\t: 0x%x\n", - (read_cpuid_id() >> 20) & 15); - } - seq_printf(m, "CPU part\t: 0x%03x\n", - (read_cpuid_id() >> 4) & 0xfff); - } - seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15); - - seq_puts(m, "\n"); - - seq_printf(m, "Hardware\t: %s\n", machine_name); - seq_printf(m, "Revision\t: %04x\n", system_rev); - seq_printf(m, "Serial\t\t: %08x%08x\n", - system_serial_high, system_serial_low); - - return 0; -} - -static void *c_start(struct seq_file *m, loff_t *pos) -{ - return *pos < 1 ? (void *)1 : NULL; -} - -static void *c_next(struct seq_file *m, void *v, loff_t *pos) -{ - ++*pos; - return NULL; -} - -static void c_stop(struct seq_file *m, void *v) -{ -} - -const struct seq_operations cpuinfo_op = { - .start = c_start, - .next = c_next, - .stop = c_stop, - .show = c_show -}; diff --git a/ANDROID_3.4.5/arch/arm/kernel/signal.c b/ANDROID_3.4.5/arch/arm/kernel/signal.c deleted file mode 100644 index eb3a2912..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/signal.c +++ /dev/null @@ -1,741 +0,0 @@ -/* - * linux/arch/arm/kernel/signal.c - * - * Copyright (C) 1995-2009 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/errno.h> -#include <linux/signal.h> -#include <linux/personality.h> -#include <linux/freezer.h> -#include <linux/uaccess.h> -#include <linux/tracehook.h> - -#include <asm/elf.h> -#include <asm/cacheflush.h> -#include <asm/ucontext.h> -#include <asm/unistd.h> -#include <asm/vfp.h> - -#include "signal.h" - -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - -/* - * For ARM syscalls, we encode the syscall number into the instruction. - */ -#define SWI_SYS_SIGRETURN (0xef000000|(__NR_sigreturn)|(__NR_OABI_SYSCALL_BASE)) -#define SWI_SYS_RT_SIGRETURN (0xef000000|(__NR_rt_sigreturn)|(__NR_OABI_SYSCALL_BASE)) -#define SWI_SYS_RESTART (0xef000000|__NR_restart_syscall|__NR_OABI_SYSCALL_BASE) - -/* - * With EABI, the syscall number has to be loaded into r7. - */ -#define MOV_R7_NR_SIGRETURN (0xe3a07000 | (__NR_sigreturn - __NR_SYSCALL_BASE)) -#define MOV_R7_NR_RT_SIGRETURN (0xe3a07000 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE)) - -/* - * For Thumb syscalls, we pass the syscall number via r7. We therefore - * need two 16-bit instructions. - */ -#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE)) -#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE)) - -const unsigned long sigreturn_codes[7] = { - MOV_R7_NR_SIGRETURN, SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN, - MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN, -}; - -/* - * Either we support OABI only, or we have EABI with the OABI - * compat layer enabled. In the later case we don't know if - * user space is EABI or not, and if not we must not clobber r7. - * Always using the OABI syscall solves that issue and works for - * all those cases. - */ -const unsigned long syscall_restart_code[2] = { - SWI_SYS_RESTART, /* swi __NR_restart_syscall */ - 0xe49df004, /* ldr pc, [sp], #4 */ -}; - -/* - * atomically swap in the new signal mask, and wait for a signal. - */ -asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask) -{ - sigset_t blocked; - - current->saved_sigmask = current->blocked; - - mask &= _BLOCKABLE; - siginitset(&blocked, mask); - set_current_blocked(&blocked); - - current->state = TASK_INTERRUPTIBLE; - schedule(); - set_restore_sigmask(); - return -ERESTARTNOHAND; -} - -asmlinkage int -sys_sigaction(int sig, const struct old_sigaction __user *act, - struct old_sigaction __user *oact) -{ - struct k_sigaction new_ka, old_ka; - int ret; - - if (act) { - old_sigset_t mask; - if (!access_ok(VERIFY_READ, act, sizeof(*act)) || - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) - return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); - siginitset(&new_ka.sa.sa_mask, mask); - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) - return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); - } - - return ret; -} - -#ifdef CONFIG_CRUNCH -static int preserve_crunch_context(struct crunch_sigframe __user *frame) -{ - char kbuf[sizeof(*frame) + 8]; - struct crunch_sigframe *kframe; - - /* the crunch context must be 64 bit aligned */ - kframe = (struct crunch_sigframe *)((unsigned long)(kbuf + 8) & ~7); - kframe->magic = CRUNCH_MAGIC; - kframe->size = CRUNCH_STORAGE_SIZE; - crunch_task_copy(current_thread_info(), &kframe->storage); - return __copy_to_user(frame, kframe, sizeof(*frame)); -} - -static int restore_crunch_context(struct crunch_sigframe __user *frame) -{ - char kbuf[sizeof(*frame) + 8]; - struct crunch_sigframe *kframe; - - /* the crunch context must be 64 bit aligned */ - kframe = (struct crunch_sigframe *)((unsigned long)(kbuf + 8) & ~7); - if (__copy_from_user(kframe, frame, sizeof(*frame))) - return -1; - if (kframe->magic != CRUNCH_MAGIC || - kframe->size != CRUNCH_STORAGE_SIZE) - return -1; - crunch_task_restore(current_thread_info(), &kframe->storage); - return 0; -} -#endif - -#ifdef CONFIG_IWMMXT - -static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame) -{ - char kbuf[sizeof(*frame) + 8]; - struct iwmmxt_sigframe *kframe; - - /* the iWMMXt context must be 64 bit aligned */ - kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7); - kframe->magic = IWMMXT_MAGIC; - kframe->size = IWMMXT_STORAGE_SIZE; - iwmmxt_task_copy(current_thread_info(), &kframe->storage); - return __copy_to_user(frame, kframe, sizeof(*frame)); -} - -static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame) -{ - char kbuf[sizeof(*frame) + 8]; - struct iwmmxt_sigframe *kframe; - - /* the iWMMXt context must be 64 bit aligned */ - kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7); - if (__copy_from_user(kframe, frame, sizeof(*frame))) - return -1; - if (kframe->magic != IWMMXT_MAGIC || - kframe->size != IWMMXT_STORAGE_SIZE) - return -1; - iwmmxt_task_restore(current_thread_info(), &kframe->storage); - return 0; -} - -#endif - -#ifdef CONFIG_VFP - -static int preserve_vfp_context(struct vfp_sigframe __user *frame) -{ - const unsigned long magic = VFP_MAGIC; - const unsigned long size = VFP_STORAGE_SIZE; - int err = 0; - - __put_user_error(magic, &frame->magic, err); - __put_user_error(size, &frame->size, err); - - if (err) - return -EFAULT; - - return vfp_preserve_user_clear_hwstate(&frame->ufp, &frame->ufp_exc); -} - -static int restore_vfp_context(struct vfp_sigframe __user *frame) -{ - unsigned long magic; - unsigned long size; - int err = 0; - - __get_user_error(magic, &frame->magic, err); - __get_user_error(size, &frame->size, err); - - if (err) - return -EFAULT; - if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE) - return -EINVAL; - - return vfp_restore_user_hwstate(&frame->ufp, &frame->ufp_exc); -} - -#endif - -/* - * Do a signal return; undo the signal stack. These are aligned to 64-bit. - */ -struct sigframe { - struct ucontext uc; - unsigned long retcode[2]; -}; - -struct rt_sigframe { - struct siginfo info; - struct sigframe sig; -}; - -static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf) -{ - struct aux_sigframe __user *aux; - sigset_t set; - int err; - - err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set)); - if (err == 0) { - sigdelsetmask(&set, ~_BLOCKABLE); - set_current_blocked(&set); - } - - __get_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err); - __get_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err); - __get_user_error(regs->ARM_r2, &sf->uc.uc_mcontext.arm_r2, err); - __get_user_error(regs->ARM_r3, &sf->uc.uc_mcontext.arm_r3, err); - __get_user_error(regs->ARM_r4, &sf->uc.uc_mcontext.arm_r4, err); - __get_user_error(regs->ARM_r5, &sf->uc.uc_mcontext.arm_r5, err); - __get_user_error(regs->ARM_r6, &sf->uc.uc_mcontext.arm_r6, err); - __get_user_error(regs->ARM_r7, &sf->uc.uc_mcontext.arm_r7, err); - __get_user_error(regs->ARM_r8, &sf->uc.uc_mcontext.arm_r8, err); - __get_user_error(regs->ARM_r9, &sf->uc.uc_mcontext.arm_r9, err); - __get_user_error(regs->ARM_r10, &sf->uc.uc_mcontext.arm_r10, err); - __get_user_error(regs->ARM_fp, &sf->uc.uc_mcontext.arm_fp, err); - __get_user_error(regs->ARM_ip, &sf->uc.uc_mcontext.arm_ip, err); - __get_user_error(regs->ARM_sp, &sf->uc.uc_mcontext.arm_sp, err); - __get_user_error(regs->ARM_lr, &sf->uc.uc_mcontext.arm_lr, err); - __get_user_error(regs->ARM_pc, &sf->uc.uc_mcontext.arm_pc, err); - __get_user_error(regs->ARM_cpsr, &sf->uc.uc_mcontext.arm_cpsr, err); - - err |= !valid_user_regs(regs); - - aux = (struct aux_sigframe __user *) sf->uc.uc_regspace; -#ifdef CONFIG_CRUNCH - if (err == 0) - err |= restore_crunch_context(&aux->crunch); -#endif -#ifdef CONFIG_IWMMXT - if (err == 0 && test_thread_flag(TIF_USING_IWMMXT)) - err |= restore_iwmmxt_context(&aux->iwmmxt); -#endif -#ifdef CONFIG_VFP - if (err == 0) - err |= restore_vfp_context(&aux->vfp); -#endif - - return err; -} - -asmlinkage int sys_sigreturn(struct pt_regs *regs) -{ - struct sigframe __user *frame; - - /* Always make any pending restarted system calls return -EINTR */ - current_thread_info()->restart_block.fn = do_no_restart_syscall; - - /* - * Since we stacked the signal on a 64-bit boundary, - * then 'sp' should be word aligned here. If it's - * not, then the user is trying to mess with us. - */ - if (regs->ARM_sp & 7) - goto badframe; - - frame = (struct sigframe __user *)regs->ARM_sp; - - if (!access_ok(VERIFY_READ, frame, sizeof (*frame))) - goto badframe; - - if (restore_sigframe(regs, frame)) - goto badframe; - - return regs->ARM_r0; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - -asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) -{ - struct rt_sigframe __user *frame; - - /* Always make any pending restarted system calls return -EINTR */ - current_thread_info()->restart_block.fn = do_no_restart_syscall; - - /* - * Since we stacked the signal on a 64-bit boundary, - * then 'sp' should be word aligned here. If it's - * not, then the user is trying to mess with us. - */ - if (regs->ARM_sp & 7) - goto badframe; - - frame = (struct rt_sigframe __user *)regs->ARM_sp; - - if (!access_ok(VERIFY_READ, frame, sizeof (*frame))) - goto badframe; - - if (restore_sigframe(regs, &frame->sig)) - goto badframe; - - if (do_sigaltstack(&frame->sig.uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT) - goto badframe; - - return regs->ARM_r0; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - -static int -setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set) -{ - struct aux_sigframe __user *aux; - int err = 0; - - __put_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err); - __put_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err); - __put_user_error(regs->ARM_r2, &sf->uc.uc_mcontext.arm_r2, err); - __put_user_error(regs->ARM_r3, &sf->uc.uc_mcontext.arm_r3, err); - __put_user_error(regs->ARM_r4, &sf->uc.uc_mcontext.arm_r4, err); - __put_user_error(regs->ARM_r5, &sf->uc.uc_mcontext.arm_r5, err); - __put_user_error(regs->ARM_r6, &sf->uc.uc_mcontext.arm_r6, err); - __put_user_error(regs->ARM_r7, &sf->uc.uc_mcontext.arm_r7, err); - __put_user_error(regs->ARM_r8, &sf->uc.uc_mcontext.arm_r8, err); - __put_user_error(regs->ARM_r9, &sf->uc.uc_mcontext.arm_r9, err); - __put_user_error(regs->ARM_r10, &sf->uc.uc_mcontext.arm_r10, err); - __put_user_error(regs->ARM_fp, &sf->uc.uc_mcontext.arm_fp, err); - __put_user_error(regs->ARM_ip, &sf->uc.uc_mcontext.arm_ip, err); - __put_user_error(regs->ARM_sp, &sf->uc.uc_mcontext.arm_sp, err); - __put_user_error(regs->ARM_lr, &sf->uc.uc_mcontext.arm_lr, err); - __put_user_error(regs->ARM_pc, &sf->uc.uc_mcontext.arm_pc, err); - __put_user_error(regs->ARM_cpsr, &sf->uc.uc_mcontext.arm_cpsr, err); - - __put_user_error(current->thread.trap_no, &sf->uc.uc_mcontext.trap_no, err); - __put_user_error(current->thread.error_code, &sf->uc.uc_mcontext.error_code, err); - __put_user_error(current->thread.address, &sf->uc.uc_mcontext.fault_address, err); - __put_user_error(set->sig[0], &sf->uc.uc_mcontext.oldmask, err); - - err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set)); - - aux = (struct aux_sigframe __user *) sf->uc.uc_regspace; -#ifdef CONFIG_CRUNCH - if (err == 0) - err |= preserve_crunch_context(&aux->crunch); -#endif -#ifdef CONFIG_IWMMXT - if (err == 0 && test_thread_flag(TIF_USING_IWMMXT)) - err |= preserve_iwmmxt_context(&aux->iwmmxt); -#endif -#ifdef CONFIG_VFP - if (err == 0) - err |= preserve_vfp_context(&aux->vfp); -#endif - __put_user_error(0, &aux->end_magic, err); - - return err; -} - -static inline void __user * -get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize) -{ - unsigned long sp = regs->ARM_sp; - void __user *frame; - - /* - * This is the X/Open sanctioned signal stack switching. - */ - if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) - sp = current->sas_ss_sp + current->sas_ss_size; - - /* - * ATPCS B01 mandates 8-byte alignment - */ - frame = (void __user *)((sp - framesize) & ~7); - - /* - * Check that we can actually write to the signal frame. - */ - if (!access_ok(VERIFY_WRITE, frame, framesize)) - frame = NULL; - - return frame; -} - -static int -setup_return(struct pt_regs *regs, struct k_sigaction *ka, - unsigned long __user *rc, void __user *frame, int usig) -{ - unsigned long handler = (unsigned long)ka->sa.sa_handler; - unsigned long retcode; - int thumb = 0; - unsigned long cpsr = regs->ARM_cpsr & ~(PSR_f | PSR_E_BIT); - - cpsr |= PSR_ENDSTATE; - - /* - * Maybe we need to deliver a 32-bit signal to a 26-bit task. - */ - if (ka->sa.sa_flags & SA_THIRTYTWO) - cpsr = (cpsr & ~MODE_MASK) | USR_MODE; - -#ifdef CONFIG_ARM_THUMB - if (elf_hwcap & HWCAP_THUMB) { - /* - * The LSB of the handler determines if we're going to - * be using THUMB or ARM mode for this signal handler. - */ - thumb = handler & 1; - - if (thumb) { - cpsr |= PSR_T_BIT; -#if __LINUX_ARM_ARCH__ >= 7 - /* clear the If-Then Thumb-2 execution state */ - cpsr &= ~PSR_IT_MASK; -#endif - } else - cpsr &= ~PSR_T_BIT; - } -#endif - - if (ka->sa.sa_flags & SA_RESTORER) { - retcode = (unsigned long)ka->sa.sa_restorer; - } else { - unsigned int idx = thumb << 1; - - if (ka->sa.sa_flags & SA_SIGINFO) - idx += 3; - - if (__put_user(sigreturn_codes[idx], rc) || - __put_user(sigreturn_codes[idx+1], rc+1)) - return 1; - - if (cpsr & MODE32_BIT) { - /* - * 32-bit code can use the new high-page - * signal return code support. - */ - retcode = KERN_SIGRETURN_CODE + (idx << 2) + thumb; - } else { - /* - * Ensure that the instruction cache sees - * the return code written onto the stack. - */ - flush_icache_range((unsigned long)rc, - (unsigned long)(rc + 2)); - - retcode = ((unsigned long)rc) + thumb; - } - } - - regs->ARM_r0 = usig; - regs->ARM_sp = (unsigned long)frame; - regs->ARM_lr = retcode; - regs->ARM_pc = handler; - regs->ARM_cpsr = cpsr; - - return 0; -} - -static int -setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *regs) -{ - struct sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame)); - int err = 0; - - if (!frame) - return 1; - - /* - * Set uc.uc_flags to a value which sc.trap_no would never have. - */ - __put_user_error(0x5ac3c35a, &frame->uc.uc_flags, err); - - err |= setup_sigframe(frame, regs, set); - if (err == 0) - err = setup_return(regs, ka, frame->retcode, frame, usig); - - return err; -} - -static int -setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs *regs) -{ - struct rt_sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame)); - stack_t stack; - int err = 0; - - if (!frame) - return 1; - - err |= copy_siginfo_to_user(&frame->info, info); - - __put_user_error(0, &frame->sig.uc.uc_flags, err); - __put_user_error(NULL, &frame->sig.uc.uc_link, err); - - memset(&stack, 0, sizeof(stack)); - stack.ss_sp = (void __user *)current->sas_ss_sp; - stack.ss_flags = sas_ss_flags(regs->ARM_sp); - stack.ss_size = current->sas_ss_size; - err |= __copy_to_user(&frame->sig.uc.uc_stack, &stack, sizeof(stack)); - - err |= setup_sigframe(&frame->sig, regs, set); - if (err == 0) - err = setup_return(regs, ka, frame->sig.retcode, frame, usig); - - if (err == 0) { - /* - * For realtime signals we must also set the second and third - * arguments for the signal handler. - * -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06 - */ - regs->ARM_r1 = (unsigned long)&frame->info; - regs->ARM_r2 = (unsigned long)&frame->sig.uc; - } - - return err; -} - -/* - * OK, we're invoking a handler - */ -static int -handle_signal(unsigned long sig, struct k_sigaction *ka, - siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs) -{ - struct thread_info *thread = current_thread_info(); - struct task_struct *tsk = current; - int usig = sig; - int ret; - - /* - * translate the signal - */ - if (usig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap) - usig = thread->exec_domain->signal_invmap[usig]; - - /* - * Set up the stack frame - */ - if (ka->sa.sa_flags & SA_SIGINFO) - ret = setup_rt_frame(usig, ka, info, oldset, regs); - else - ret = setup_frame(usig, ka, oldset, regs); - - /* - * Check that the resulting registers are actually sane. - */ - ret |= !valid_user_regs(regs); - - if (ret != 0) { - force_sigsegv(sig, tsk); - return ret; - } - - /* - * Block the signal if we were successful. - */ - block_sigmask(ka, sig); - - return 0; -} - -/* - * Note that 'init' is a special process: it doesn't get signals it doesn't - * want to handle. Thus you cannot kill init even with a SIGKILL even by - * mistake. - * - * Note that we go through the signals twice: once to check the signals that - * the kernel can handle, and then we build all the user-level signal handling - * stack-frames in one go after that. - */ -static void do_signal(struct pt_regs *regs, int syscall) -{ - unsigned int retval = 0, continue_addr = 0, restart_addr = 0; - struct k_sigaction ka; - siginfo_t info; - int signr; - - /* - * We want the common case to go fast, which - * is why we may in certain cases get here from - * kernel mode. Just return without doing anything - * if so. - */ - if (!user_mode(regs)) - return; - - /* - * If we were from a system call, check for system call restarting... - */ - if (syscall) { - continue_addr = regs->ARM_pc; - restart_addr = continue_addr - (thumb_mode(regs) ? 2 : 4); - retval = regs->ARM_r0; - - /* - * Prepare for system call restart. We do this here so that a - * debugger will see the already changed PSW. - */ - switch (retval) { - case -ERESTARTNOHAND: - case -ERESTARTSYS: - case -ERESTARTNOINTR: - regs->ARM_r0 = regs->ARM_ORIG_r0; - regs->ARM_pc = restart_addr; - break; - case -ERESTART_RESTARTBLOCK: - regs->ARM_r0 = -EINTR; - break; - } - } - - if (try_to_freeze_nowarn()) - goto no_signal; - - /* - * Get the signal to deliver. When running under ptrace, at this - * point the debugger may change all our registers ... - */ - signr = get_signal_to_deliver(&info, &ka, regs, NULL); - if (signr > 0) { - sigset_t *oldset; - - /* - * Depending on the signal settings we may need to revert the - * decision to restart the system call. But skip this if a - * debugger has chosen to restart at a different PC. - */ - if (regs->ARM_pc == restart_addr) { - if (retval == -ERESTARTNOHAND - || (retval == -ERESTARTSYS - && !(ka.sa.sa_flags & SA_RESTART))) { - regs->ARM_r0 = -EINTR; - regs->ARM_pc = continue_addr; - } - } - - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - oldset = ¤t->saved_sigmask; - else - oldset = ¤t->blocked; - if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { - /* - * A signal was successfully delivered; the saved - * sigmask will have been stored in the signal frame, - * and will be restored by sigreturn, so we can simply - * clear the TIF_RESTORE_SIGMASK flag. - */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); - } - return; - } - - no_signal: - if (syscall) { - /* - * Handle restarting a different system call. As above, - * if a debugger has chosen to restart at a different PC, - * ignore the restart. - */ - if (retval == -ERESTART_RESTARTBLOCK - && regs->ARM_pc == continue_addr) { - if (thumb_mode(regs)) { - regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE; - regs->ARM_pc -= 2; - } else { -#if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT) - regs->ARM_r7 = __NR_restart_syscall; - regs->ARM_pc -= 4; -#else - u32 __user *usp; - - regs->ARM_sp -= 4; - usp = (u32 __user *)regs->ARM_sp; - - if (put_user(regs->ARM_pc, usp) == 0) { - regs->ARM_pc = KERN_RESTART_CODE; - } else { - regs->ARM_sp += 4; - force_sigsegv(0, current); - } -#endif - } - } - - /* If there's no signal to deliver, we just put the saved sigmask - * back. - */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) { - clear_thread_flag(TIF_RESTORE_SIGMASK); - sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); - } - } -} - -asmlinkage void -do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall) -{ - if (thread_flags & _TIF_SIGPENDING) - do_signal(regs, syscall); - - if (thread_flags & _TIF_NOTIFY_RESUME) { - clear_thread_flag(TIF_NOTIFY_RESUME); - tracehook_notify_resume(regs); - if (current->replacement_session_keyring) - key_replace_session_keyring(); - } -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/signal.h b/ANDROID_3.4.5/arch/arm/kernel/signal.h deleted file mode 100644 index 6fcfe839..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/signal.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * linux/arch/arm/kernel/signal.h - * - * Copyright (C) 2005-2009 Russell King. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#define KERN_SIGRETURN_CODE (CONFIG_VECTORS_BASE + 0x00000500) -#define KERN_RESTART_CODE (KERN_SIGRETURN_CODE + sizeof(sigreturn_codes)) - -extern const unsigned long sigreturn_codes[7]; -extern const unsigned long syscall_restart_code[2]; diff --git a/ANDROID_3.4.5/arch/arm/kernel/sleep.S b/ANDROID_3.4.5/arch/arm/kernel/sleep.S deleted file mode 100644 index 987dcf33..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/sleep.S +++ /dev/null @@ -1,104 +0,0 @@ -#include <linux/linkage.h> -#include <linux/threads.h> -#include <asm/asm-offsets.h> -#include <asm/assembler.h> -#include <asm/glue-cache.h> -#include <asm/glue-proc.h> - .text - -/* - * Save CPU state for a suspend. This saves the CPU general purpose - * registers, and allocates space on the kernel stack to save the CPU - * specific registers and some other data for resume. - * r0 = suspend function arg0 - * r1 = suspend function - */ -ENTRY(__cpu_suspend) - stmfd sp!, {r4 - r11, lr} -#ifdef MULTI_CPU - ldr r10, =processor - ldr r4, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state -#else - ldr r4, =cpu_suspend_size -#endif - mov r5, sp @ current virtual SP - add r4, r4, #12 @ Space for pgd, virt sp, phys resume fn - sub sp, sp, r4 @ allocate CPU state on stack - stmfd sp!, {r0, r1} @ save suspend func arg and pointer - add r0, sp, #8 @ save pointer to save block - mov r1, r4 @ size of save block - mov r2, r5 @ virtual SP - ldr r3, =sleep_save_sp -#ifdef CONFIG_SMP - ALT_SMP(mrc p15, 0, lr, c0, c0, 5) - ALT_UP(mov lr, #0) - and lr, lr, #15 - add r3, r3, lr, lsl #2 -#endif - bl __cpu_suspend_save - adr lr, BSYM(cpu_suspend_abort) - ldmfd sp!, {r0, pc} @ call suspend fn -ENDPROC(__cpu_suspend) - .ltorg - -cpu_suspend_abort: - ldmia sp!, {r1 - r3} @ pop phys pgd, virt SP, phys resume fn - teq r0, #0 - moveq r0, #1 @ force non-zero value - mov sp, r2 - ldmfd sp!, {r4 - r11, pc} -ENDPROC(cpu_suspend_abort) - -/* - * r0 = control register value - */ - .align 5 - .pushsection .idmap.text,"ax" -ENTRY(cpu_resume_mmu) - ldr r3, =cpu_resume_after_mmu - instr_sync - mcr p15, 0, r0, c1, c0, 0 @ turn on MMU, I-cache, etc - mrc p15, 0, r0, c0, c0, 0 @ read id reg - instr_sync - mov r0, r0 - mov r0, r0 - mov pc, r3 @ jump to virtual address -ENDPROC(cpu_resume_mmu) - .popsection -cpu_resume_after_mmu: - bl cpu_init @ restore the und/abt/irq banked regs - mov r0, #0 @ return zero on success - ldmfd sp!, {r4 - r11, pc} -ENDPROC(cpu_resume_after_mmu) - -/* - * Note: Yes, part of the following code is located into the .data section. - * This is to allow sleep_save_sp to be accessed with a relative load - * while we can't rely on any MMU translation. We could have put - * sleep_save_sp in the .text section as well, but some setups might - * insist on it to be truly read-only. - */ - .data - .align -ENTRY(cpu_resume) -#ifdef CONFIG_SMP - adr r0, sleep_save_sp - ALT_SMP(mrc p15, 0, r1, c0, c0, 5) - ALT_UP(mov r1, #0) - and r1, r1, #15 - ldr r0, [r0, r1, lsl #2] @ stack phys addr -#else - ldr r0, sleep_save_sp @ stack phys addr -#endif - setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1 @ set SVC, irqs off - @ load phys pgd, stack, resume fn - ARM( ldmia r0!, {r1, sp, pc} ) -THUMB( ldmia r0!, {r1, r2, r3} ) -THUMB( mov sp, r2 ) -THUMB( bx r3 ) -ENDPROC(cpu_resume) - -sleep_save_sp: - .rept CONFIG_NR_CPUS - .long 0 @ preserve stack phys ptr here - .endr diff --git a/ANDROID_3.4.5/arch/arm/kernel/smp.c b/ANDROID_3.4.5/arch/arm/kernel/smp.c deleted file mode 100644 index f30d6832..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/smp.c +++ /dev/null @@ -1,670 +0,0 @@ -/* - * linux/arch/arm/kernel/smp.c - * - * Copyright (C) 2002 ARM Limited, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <linux/cache.h> -#include <linux/profile.h> -#include <linux/errno.h> -#include <linux/mm.h> -#include <linux/err.h> -#include <linux/cpu.h> -#include <linux/smp.h> -#include <linux/seq_file.h> -#include <linux/irq.h> -#include <linux/percpu.h> -#include <linux/clockchips.h> -#include <linux/completion.h> - -#include <linux/atomic.h> -#include <asm/cacheflush.h> -#include <asm/cpu.h> -#include <asm/cputype.h> -#include <asm/exception.h> -#include <asm/idmap.h> -#include <asm/topology.h> -#include <asm/mmu_context.h> -#include <asm/pgtable.h> -#include <asm/pgalloc.h> -#include <asm/processor.h> -#include <asm/sections.h> -#include <asm/tlbflush.h> -#include <asm/ptrace.h> -#include <asm/localtimer.h> -#include <asm/smp_plat.h> - -/* - * as from 2.5, kernels no longer have an init_tasks structure - * so we need some other way of telling a new secondary core - * where to place its SVC stack - */ -struct secondary_data secondary_data; - -enum ipi_msg_type { - IPI_TIMER = 2, - IPI_RESCHEDULE, - IPI_CALL_FUNC, - IPI_CALL_FUNC_SINGLE, - IPI_CPU_STOP, - IPI_CPU_BACKTRACE, -}; - -static DECLARE_COMPLETION(cpu_running); - -int __cpuinit __cpu_up(unsigned int cpu) -{ - struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu); - struct task_struct *idle = ci->idle; - int ret; - - /* - * Spawn a new process manually, if not already done. - * Grab a pointer to its task struct so we can mess with it - */ - if (!idle) { - idle = fork_idle(cpu); - if (IS_ERR(idle)) { - printk(KERN_ERR "CPU%u: fork() failed\n", cpu); - return PTR_ERR(idle); - } - ci->idle = idle; - } else { - /* - * Since this idle thread is being re-used, call - * init_idle() to reinitialize the thread structure. - */ - init_idle(idle, cpu); - } - - /* - * We need to tell the secondary core where to find - * its stack and the page tables. - */ - secondary_data.stack = task_stack_page(idle) + THREAD_START_SP; - secondary_data.pgdir = virt_to_phys(idmap_pgd); - secondary_data.swapper_pg_dir = virt_to_phys(swapper_pg_dir); - __cpuc_flush_dcache_area(&secondary_data, sizeof(secondary_data)); - outer_clean_range(__pa(&secondary_data), __pa(&secondary_data + 1)); - - /* - * Now bring the CPU into our world. - */ - ret = boot_secondary(cpu, idle); - if (ret == 0) { - /* - * CPU was successfully started, wait for it - * to come online or time out. - */ - wait_for_completion_timeout(&cpu_running, - msecs_to_jiffies(1000)); - - if (!cpu_online(cpu)) { - pr_crit("CPU%u: failed to come online\n", cpu); - ret = -EIO; - } - } else { - pr_err("CPU%u: failed to boot: %d\n", cpu, ret); - } - - secondary_data.stack = NULL; - secondary_data.pgdir = 0; - - return ret; -} - -#ifdef CONFIG_HOTPLUG_CPU -static void percpu_timer_stop(void); - -/* - * __cpu_disable runs on the processor to be shutdown. - */ -int __cpu_disable(void) -{ - unsigned int cpu = smp_processor_id(); - struct task_struct *p; - int ret; - - ret = platform_cpu_disable(cpu); - if (ret) - return ret; - - /* - * Take this CPU offline. Once we clear this, we can't return, - * and we must not schedule until we're ready to give up the cpu. - */ - set_cpu_online(cpu, false); - - /* - * OK - migrate IRQs away from this CPU - */ - migrate_irqs(); - - /* - * Stop the local timer for this CPU. - */ - percpu_timer_stop(); - - /* - * Flush user cache and TLB mappings, and then remove this CPU - * from the vm mask set of all processes. - */ - flush_cache_all(); - local_flush_tlb_all(); - - read_lock(&tasklist_lock); - for_each_process(p) { - if (p->mm) - cpumask_clear_cpu(cpu, mm_cpumask(p->mm)); - } - read_unlock(&tasklist_lock); - - return 0; -} - -static DECLARE_COMPLETION(cpu_died); - -/* - * called on the thread which is asking for a CPU to be shutdown - - * waits until shutdown has completed, or it is timed out. - */ -void __cpu_die(unsigned int cpu) -{ - if (!wait_for_completion_timeout(&cpu_died, msecs_to_jiffies(5000))) { - pr_err("CPU%u: cpu didn't die\n", cpu); - return; - } - printk(KERN_NOTICE "CPU%u: shutdown\n", cpu); - - if (!platform_cpu_kill(cpu)) - printk("CPU%u: unable to kill\n", cpu); -} - -/* - * Called from the idle thread for the CPU which has been shutdown. - * - * Note that we disable IRQs here, but do not re-enable them - * before returning to the caller. This is also the behaviour - * of the other hotplug-cpu capable cores, so presumably coming - * out of idle fixes this. - */ -void __ref cpu_die(void) -{ - unsigned int cpu = smp_processor_id(); - - idle_task_exit(); - - local_irq_disable(); - mb(); - - /* Tell __cpu_die() that this CPU is now safe to dispose of */ - complete(&cpu_died); - - /* - * actual CPU shutdown procedure is at least platform (if not - * CPU) specific. - */ - platform_cpu_die(cpu); - - /* - * Do not return to the idle loop - jump back to the secondary - * cpu initialisation. There's some initialisation which needs - * to be repeated to undo the effects of taking the CPU offline. - */ - __asm__("mov sp, %0\n" - " mov fp, #0\n" - " b secondary_start_kernel" - : - : "r" (task_stack_page(current) + THREAD_SIZE - 8)); -} -#endif /* CONFIG_HOTPLUG_CPU */ - -/* - * Called by both boot and secondaries to move global data into - * per-processor storage. - */ -static void __cpuinit smp_store_cpu_info(unsigned int cpuid) -{ - struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid); - - cpu_info->loops_per_jiffy = loops_per_jiffy; - - store_cpu_topology(cpuid); -} - -static void percpu_timer_setup(void); - -/* - * This is the secondary CPU boot entry. We're using this CPUs - * idle thread stack, but a set of temporary page tables. - */ -asmlinkage void __cpuinit secondary_start_kernel(void) -{ - struct mm_struct *mm = &init_mm; - unsigned int cpu = smp_processor_id(); - - /* - * All kernel threads share the same mm context; grab a - * reference and switch to it. - */ - atomic_inc(&mm->mm_count); - current->active_mm = mm; - cpumask_set_cpu(cpu, mm_cpumask(mm)); - cpu_switch_mm(mm->pgd, mm); - enter_lazy_tlb(mm, current); - local_flush_tlb_all(); - - printk("CPU%u: Booted secondary processor\n", cpu); - - cpu_init(); - preempt_disable(); - trace_hardirqs_off(); - - /* - * Give the platform a chance to do its own initialisation. - */ - platform_secondary_init(cpu); - - notify_cpu_starting(cpu); - - calibrate_delay(); - - smp_store_cpu_info(cpu); - - /* - * OK, now it's safe to let the boot CPU continue. Wait for - * the CPU migration code to notice that the CPU is online - * before we continue - which happens after __cpu_up returns. - */ - set_cpu_online(cpu, true); - complete(&cpu_running); - - /* - * Setup the percpu timer for this CPU. - */ - percpu_timer_setup(); - - local_irq_enable(); - local_fiq_enable(); - - /* - * OK, it's off to the idle thread for us - */ - cpu_idle(); -} - -void __init smp_cpus_done(unsigned int max_cpus) -{ - int cpu; - unsigned long bogosum = 0; - - for_each_online_cpu(cpu) - bogosum += per_cpu(cpu_data, cpu).loops_per_jiffy; - - printk(KERN_INFO "SMP: Total of %d processors activated " - "(%lu.%02lu BogoMIPS).\n", - num_online_cpus(), - bogosum / (500000/HZ), - (bogosum / (5000/HZ)) % 100); -} - -void __init smp_prepare_boot_cpu(void) -{ - unsigned int cpu = smp_processor_id(); - - per_cpu(cpu_data, cpu).idle = current; -} - -void __init smp_prepare_cpus(unsigned int max_cpus) -{ - unsigned int ncores = num_possible_cpus(); - - init_cpu_topology(); - - smp_store_cpu_info(smp_processor_id()); - - /* - * are we trying to boot more cores than exist? - */ - if (max_cpus > ncores) - max_cpus = ncores; - if (ncores > 1 && max_cpus) { - /* - * Enable the local timer or broadcast device for the - * boot CPU, but only if we have more than one CPU. - */ - percpu_timer_setup(); - - /* - * Initialise the present map, which describes the set of CPUs - * actually populated at the present time. A platform should - * re-initialize the map in platform_smp_prepare_cpus() if - * present != possible (e.g. physical hotplug). - */ - init_cpu_present(cpu_possible_mask); - - /* - * Initialise the SCU if there are more than one CPU - * and let them know where to start. - */ - platform_smp_prepare_cpus(max_cpus); - } -} - -static void (*smp_cross_call)(const struct cpumask *, unsigned int); - -void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int)) -{ - smp_cross_call = fn; -} - -void arch_send_call_function_ipi_mask(const struct cpumask *mask) -{ - smp_cross_call(mask, IPI_CALL_FUNC); -} - -void arch_send_call_function_single_ipi(int cpu) -{ - smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE); -} - -static const char *ipi_types[NR_IPI] = { -#define S(x,s) [x - IPI_TIMER] = s - S(IPI_TIMER, "Timer broadcast interrupts"), - S(IPI_RESCHEDULE, "Rescheduling interrupts"), - S(IPI_CALL_FUNC, "Function call interrupts"), - S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"), - S(IPI_CPU_STOP, "CPU stop interrupts"), - S(IPI_CPU_BACKTRACE, "CPU backtrace"), -}; - -void show_ipi_list(struct seq_file *p, int prec) -{ - unsigned int cpu, i; - - for (i = 0; i < NR_IPI; i++) { - seq_printf(p, "%*s%u: ", prec - 1, "IPI", i); - - for_each_present_cpu(cpu) - seq_printf(p, "%10u ", - __get_irq_stat(cpu, ipi_irqs[i])); - - seq_printf(p, " %s\n", ipi_types[i]); - } -} - -u64 smp_irq_stat_cpu(unsigned int cpu) -{ - u64 sum = 0; - int i; - - for (i = 0; i < NR_IPI; i++) - sum += __get_irq_stat(cpu, ipi_irqs[i]); - - return sum; -} - -/* - * Timer (local or broadcast) support - */ -static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent); - -static void ipi_timer(void) -{ - struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent); - evt->event_handler(evt); -} - -#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST -static void smp_timer_broadcast(const struct cpumask *mask) -{ - smp_cross_call(mask, IPI_TIMER); -} -#else -#define smp_timer_broadcast NULL -#endif - -static void broadcast_timer_set_mode(enum clock_event_mode mode, - struct clock_event_device *evt) -{ -} - -static void __cpuinit broadcast_timer_setup(struct clock_event_device *evt) -{ - evt->name = "dummy_timer"; - evt->features = CLOCK_EVT_FEAT_ONESHOT | - CLOCK_EVT_FEAT_PERIODIC | - CLOCK_EVT_FEAT_DUMMY; - evt->rating = 400; - evt->mult = 1; - evt->set_mode = broadcast_timer_set_mode; - - clockevents_register_device(evt); -} - -static struct local_timer_ops *lt_ops; - -#ifdef CONFIG_LOCAL_TIMERS -int local_timer_register(struct local_timer_ops *ops) -{ - if (lt_ops) - return -EBUSY; - - lt_ops = ops; - return 0; -} -#endif - -static void __cpuinit percpu_timer_setup(void) -{ - unsigned int cpu = smp_processor_id(); - struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu); - - evt->cpumask = cpumask_of(cpu); - evt->broadcast = smp_timer_broadcast; - - if (!lt_ops || lt_ops->setup(evt)) - broadcast_timer_setup(evt); -} - -#ifdef CONFIG_HOTPLUG_CPU -/* - * The generic clock events code purposely does not stop the local timer - * on CPU_DEAD/CPU_DEAD_FROZEN hotplug events, so we have to do it - * manually here. - */ -static void percpu_timer_stop(void) -{ - unsigned int cpu = smp_processor_id(); - struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu); - - if (lt_ops) - lt_ops->stop(evt); -} -#endif - -static DEFINE_RAW_SPINLOCK(stop_lock); - -/* - * ipi_cpu_stop - handle IPI from smp_send_stop() - */ -static void ipi_cpu_stop(unsigned int cpu) -{ - if (system_state == SYSTEM_BOOTING || - system_state == SYSTEM_RUNNING) { - raw_spin_lock(&stop_lock); - printk(KERN_CRIT "CPU%u: stopping\n", cpu); - dump_stack(); - raw_spin_unlock(&stop_lock); - } - - set_cpu_online(cpu, false); - - local_fiq_disable(); - local_irq_disable(); - - while (1) - cpu_relax(); -} - -static cpumask_t backtrace_mask; -static DEFINE_RAW_SPINLOCK(backtrace_lock); - -/* "in progress" flag of arch_trigger_all_cpu_backtrace */ -static unsigned long backtrace_flag; - -void smp_send_all_cpu_backtrace(void) -{ - unsigned int this_cpu = smp_processor_id(); - int i; - - if (test_and_set_bit(0, &backtrace_flag)) - /* - * If there is already a trigger_all_cpu_backtrace() in progress - * (backtrace_flag == 1), don't output double cpu dump infos. - */ - return; - - cpumask_copy(&backtrace_mask, cpu_online_mask); - cpu_clear(this_cpu, backtrace_mask); - - pr_info("Backtrace for cpu %d (current):\n", this_cpu); - dump_stack(); - - pr_info("\nsending IPI to all other CPUs:\n"); - smp_cross_call(&backtrace_mask, IPI_CPU_BACKTRACE); - - /* Wait for up to 10 seconds for all other CPUs to do the backtrace */ - for (i = 0; i < 10 * 1000; i++) { - if (cpumask_empty(&backtrace_mask)) - break; - mdelay(1); - } - - clear_bit(0, &backtrace_flag); - smp_mb__after_clear_bit(); -} - -/* - * ipi_cpu_backtrace - handle IPI from smp_send_all_cpu_backtrace() - */ -static void ipi_cpu_backtrace(unsigned int cpu, struct pt_regs *regs) -{ - if (cpu_isset(cpu, backtrace_mask)) { - raw_spin_lock(&backtrace_lock); - pr_warning("IPI backtrace for cpu %d\n", cpu); - show_regs(regs); - raw_spin_unlock(&backtrace_lock); - cpu_clear(cpu, backtrace_mask); - } -} - -/* - * Main handler for inter-processor interrupts - */ -asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs) -{ - handle_IPI(ipinr, regs); -} - -void handle_IPI(int ipinr, struct pt_regs *regs) -{ - unsigned int cpu = smp_processor_id(); - struct pt_regs *old_regs = set_irq_regs(regs); - - if (ipinr >= IPI_TIMER && ipinr < IPI_TIMER + NR_IPI) - __inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_TIMER]); - - switch (ipinr) { - case IPI_TIMER: - irq_enter(); - ipi_timer(); - irq_exit(); - break; - - case IPI_RESCHEDULE: - scheduler_ipi(); - break; - - case IPI_CALL_FUNC: - irq_enter(); - generic_smp_call_function_interrupt(); - irq_exit(); - break; - - case IPI_CALL_FUNC_SINGLE: - irq_enter(); - generic_smp_call_function_single_interrupt(); - irq_exit(); - break; - - case IPI_CPU_STOP: - irq_enter(); - ipi_cpu_stop(cpu); - irq_exit(); - break; - - case IPI_CPU_BACKTRACE: - ipi_cpu_backtrace(cpu, regs); - break; - - default: - printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n", - cpu, ipinr); - break; - } - set_irq_regs(old_regs); -} - -void smp_send_reschedule(int cpu) -{ - smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE); -} - -#ifdef CONFIG_HOTPLUG_CPU -static void smp_kill_cpus(cpumask_t *mask) -{ - unsigned int cpu; - for_each_cpu(cpu, mask) - platform_cpu_kill(cpu); -} -#else -static void smp_kill_cpus(cpumask_t *mask) { } -#endif - -void smp_send_stop(void) -{ - unsigned long timeout; - struct cpumask mask; - - cpumask_copy(&mask, cpu_online_mask); - cpumask_clear_cpu(smp_processor_id(), &mask); - smp_cross_call(&mask, IPI_CPU_STOP); - - /* Wait up to one second for other CPUs to stop */ - timeout = USEC_PER_SEC; - while (num_online_cpus() > 1 && timeout--) - udelay(1); - - if (num_online_cpus() > 1) - pr_warning("SMP: failed to stop secondary CPUs\n"); - - smp_kill_cpus(&mask); -} - -/* - * not supported here - */ -int setup_profiling_timer(unsigned int multiplier) -{ - return -EINVAL; -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/smp_scu.c b/ANDROID_3.4.5/arch/arm/kernel/smp_scu.c deleted file mode 100644 index 8f5dd796..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/smp_scu.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * linux/arch/arm/kernel/smp_scu.c - * - * Copyright (C) 2002 ARM Ltd. - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/init.h> -#include <linux/io.h> - -#include <asm/smp_scu.h> -#include <asm/cacheflush.h> -#include <asm/cputype.h> - -#define SCU_CTRL 0x00 -#define SCU_CONFIG 0x04 -#define SCU_CPU_STATUS 0x08 -#define SCU_INVALIDATE 0x0c -#define SCU_FPGA_REVISION 0x10 - -#ifdef CONFIG_SMP -/* - * Get the number of CPU cores from the SCU configuration - */ -unsigned int __init scu_get_core_count(void __iomem *scu_base) -{ - unsigned int ncores = __raw_readl(scu_base + SCU_CONFIG); - return (ncores & 0x03) + 1; -} - -/* - * Enable the SCU - */ -void scu_enable(void __iomem *scu_base) -{ - u32 scu_ctrl; - -#ifdef CONFIG_ARM_ERRATA_764369 - /* Cortex-A9 only */ - if ((read_cpuid(CPUID_ID) & 0xff0ffff0) == 0x410fc090) { - scu_ctrl = __raw_readl(scu_base + 0x30); - if (!(scu_ctrl & 1)) - __raw_writel(scu_ctrl | 0x1, scu_base + 0x30); - } -#endif - - scu_ctrl = __raw_readl(scu_base + SCU_CTRL); - /* already enabled? */ - if (scu_ctrl & 1) - return; - - scu_ctrl |= 1; - __raw_writel(scu_ctrl, scu_base + SCU_CTRL); - - /* - * Ensure that the data accessed by CPU0 before the SCU was - * initialised is visible to the other CPUs. - */ - flush_cache_all(); -} -#endif - -/* - * Set the executing CPUs power mode as defined. This will be in - * preparation for it executing a WFI instruction. - * - * This function must be called with preemption disabled, and as it - * has the side effect of disabling coherency, caches must have been - * flushed. Interrupts must also have been disabled. - */ -int scu_power_mode(void __iomem *scu_base, unsigned int mode) -{ - unsigned int val; - int cpu = smp_processor_id(); - - if (mode > 3 || mode == 1 || cpu > 3) - return -EINVAL; - - val = __raw_readb(scu_base + SCU_CPU_STATUS + cpu) & ~0x03; - val |= mode; - __raw_writeb(val, scu_base + SCU_CPU_STATUS + cpu); - - return 0; -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/smp_tlb.c b/ANDROID_3.4.5/arch/arm/kernel/smp_tlb.c deleted file mode 100644 index 02c5d2ce..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/smp_tlb.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * linux/arch/arm/kernel/smp_tlb.c - * - * Copyright (C) 2002 ARM Limited, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/preempt.h> -#include <linux/smp.h> - -#include <asm/smp_plat.h> -#include <asm/tlbflush.h> - -/**********************************************************************/ - -/* - * TLB operations - */ -struct tlb_args { - struct vm_area_struct *ta_vma; - unsigned long ta_start; - unsigned long ta_end; -}; - -static inline void ipi_flush_tlb_all(void *ignored) -{ - local_flush_tlb_all(); -} - -static inline void ipi_flush_tlb_mm(void *arg) -{ - struct mm_struct *mm = (struct mm_struct *)arg; - - local_flush_tlb_mm(mm); -} - -static inline void ipi_flush_tlb_page(void *arg) -{ - struct tlb_args *ta = (struct tlb_args *)arg; - - local_flush_tlb_page(ta->ta_vma, ta->ta_start); -} - -static inline void ipi_flush_tlb_kernel_page(void *arg) -{ - struct tlb_args *ta = (struct tlb_args *)arg; - - local_flush_tlb_kernel_page(ta->ta_start); -} - -static inline void ipi_flush_tlb_range(void *arg) -{ - struct tlb_args *ta = (struct tlb_args *)arg; - - local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end); -} - -static inline void ipi_flush_tlb_kernel_range(void *arg) -{ - struct tlb_args *ta = (struct tlb_args *)arg; - - local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end); -} - -void flush_tlb_all(void) -{ - if (tlb_ops_need_broadcast()) - on_each_cpu(ipi_flush_tlb_all, NULL, 1); - else - local_flush_tlb_all(); -} - -void flush_tlb_mm(struct mm_struct *mm) -{ - if (tlb_ops_need_broadcast()) - on_each_cpu_mask(mm_cpumask(mm), ipi_flush_tlb_mm, mm, 1); - else - local_flush_tlb_mm(mm); -} - -void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) -{ - if (tlb_ops_need_broadcast()) { - struct tlb_args ta; - ta.ta_vma = vma; - ta.ta_start = uaddr; - on_each_cpu_mask(mm_cpumask(vma->vm_mm), ipi_flush_tlb_page, - &ta, 1); - } else - local_flush_tlb_page(vma, uaddr); -} - -void flush_tlb_kernel_page(unsigned long kaddr) -{ - if (tlb_ops_need_broadcast()) { - struct tlb_args ta; - ta.ta_start = kaddr; - on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1); - } else - local_flush_tlb_kernel_page(kaddr); -} - -void flush_tlb_range(struct vm_area_struct *vma, - unsigned long start, unsigned long end) -{ - if (tlb_ops_need_broadcast()) { - struct tlb_args ta; - ta.ta_vma = vma; - ta.ta_start = start; - ta.ta_end = end; - on_each_cpu_mask(mm_cpumask(vma->vm_mm), ipi_flush_tlb_range, - &ta, 1); - } else - local_flush_tlb_range(vma, start, end); -} - -void flush_tlb_kernel_range(unsigned long start, unsigned long end) -{ - if (tlb_ops_need_broadcast()) { - struct tlb_args ta; - ta.ta_start = start; - ta.ta_end = end; - on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1); - } else - local_flush_tlb_kernel_range(start, end); -} - diff --git a/ANDROID_3.4.5/arch/arm/kernel/smp_twd.c b/ANDROID_3.4.5/arch/arm/kernel/smp_twd.c deleted file mode 100644 index ad0ac9a0..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/smp_twd.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - * linux/arch/arm/kernel/smp_twd.c - * - * Copyright (C) 2002 ARM Ltd. - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/clk.h> -#include <linux/cpufreq.h> -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/err.h> -#include <linux/smp.h> -#include <linux/jiffies.h> -#include <linux/clockchips.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/of_irq.h> -#include <linux/of_address.h> - -#include <asm/smp_twd.h> -#include <asm/localtimer.h> -#include <asm/hardware/gic.h> -#include <mach/hardware.h> - -/* set up by the platform code */ -static void __iomem *twd_base; - -static struct clk *twd_clk; -static unsigned long twd_timer_rate; - -static struct clock_event_device __percpu **twd_evt; -static int twd_ppi; - -static void twd_set_mode(enum clock_event_mode mode, - struct clock_event_device *clk) -{ - unsigned long ctrl; - - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - /* timer load already set up */ - ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE - | TWD_TIMER_CONTROL_PERIODIC; - __raw_writel(twd_timer_rate / HZ, twd_base + TWD_TIMER_LOAD); - break; - case CLOCK_EVT_MODE_ONESHOT: - /* period set, and timer enabled in 'next_event' hook */ - ctrl = TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_ONESHOT; - break; - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - default: - ctrl = 0; - } - - __raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL); -} - -static int twd_set_next_event(unsigned long evt, - struct clock_event_device *unused) -{ - unsigned long ctrl = __raw_readl(twd_base + TWD_TIMER_CONTROL); - - ctrl |= TWD_TIMER_CONTROL_ENABLE; - - __raw_writel(evt, twd_base + TWD_TIMER_COUNTER); - __raw_writel(ctrl, twd_base + TWD_TIMER_CONTROL); - - return 0; -} - -/* - * local_timer_ack: checks for a local timer interrupt. - * - * If a local timer interrupt has occurred, acknowledge and return 1. - * Otherwise, return 0. - */ -static int twd_timer_ack(void) -{ - if (__raw_readl(twd_base + TWD_TIMER_INTSTAT)) { - __raw_writel(1, twd_base + TWD_TIMER_INTSTAT); - return 1; - } - - return 0; -} - -static void twd_timer_stop(struct clock_event_device *clk) -{ - twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk); - disable_percpu_irq(clk->irq); -} - -#ifdef CONFIG_CPU_FREQ - -/* - * Updates clockevent frequency when the cpu frequency changes. - * Called on the cpu that is changing frequency with interrupts disabled. - */ -static void twd_update_frequency(void *data) -{ - twd_timer_rate = (auto_pll_divisor(DEV_ARM, GET_CPUTIMER, 0, 0) / 2); - - clockevents_update_freq(*__this_cpu_ptr(twd_evt), twd_timer_rate); -} - -static int twd_cpufreq_transition(struct notifier_block *nb, - unsigned long state, void *data) -{ - struct cpufreq_freqs *freqs = data; - - /* - * The twd clock events must be reprogrammed to account for the new - * frequency. The timer is local to a cpu, so cross-call to the - * changing cpu. - */ - if (state == CPUFREQ_POSTCHANGE || state == CPUFREQ_RESUMECHANGE) - smp_call_function_single(freqs->cpu, twd_update_frequency, - data, 1); - - return NOTIFY_OK; -} - -static struct notifier_block twd_cpufreq_nb = { - .notifier_call = twd_cpufreq_transition, -}; - -static int twd_cpufreq_init(void) -{ - if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk)) - return cpufreq_register_notifier(&twd_cpufreq_nb, - CPUFREQ_TRANSITION_NOTIFIER); - - return 0; -} -core_initcall(twd_cpufreq_init); - -#endif - -static void __cpuinit twd_calibrate_rate(void) -{ - unsigned long count; - u64 waitjiffies; - - /* - * If this is the first time round, we need to work out how fast - * the timer ticks - */ - if (twd_timer_rate == 0) { - printk(KERN_INFO "Calibrating local timer... "); - - /* Wait for a tick to start */ - waitjiffies = get_jiffies_64() + 1; - - while (get_jiffies_64() < waitjiffies) - udelay(10); - - /* OK, now the tick has started, let's get the timer going */ - waitjiffies += 5; - - /* enable, no interrupt or reload */ - __raw_writel(0x1, twd_base + TWD_TIMER_CONTROL); - - /* maximum value */ - __raw_writel(0xFFFFFFFFU, twd_base + TWD_TIMER_COUNTER); - - while (get_jiffies_64() < waitjiffies) - udelay(10); - - count = __raw_readl(twd_base + TWD_TIMER_COUNTER); - - twd_timer_rate = (0xFFFFFFFFU - count) * (HZ / 5); - - printk("%lu.%02luMHz.\n", twd_timer_rate / 1000000, - (twd_timer_rate / 10000) % 100); - } -} - -static irqreturn_t twd_handler(int irq, void *dev_id) -{ - struct clock_event_device *evt = *(struct clock_event_device **)dev_id; - - if (twd_timer_ack()) { - evt->event_handler(evt); - return IRQ_HANDLED; - } - - return IRQ_NONE; -} - -static struct clk *twd_get_clock(void) -{ - struct clk *clk; - int err; - - clk = clk_get_sys("smp_twd", NULL); - if (IS_ERR(clk)) { - pr_err("smp_twd: clock not found: %d\n", (int)PTR_ERR(clk)); - return clk; - } - - err = clk_prepare(clk); - if (err) { - pr_err("smp_twd: clock failed to prepare: %d\n", err); - clk_put(clk); - return ERR_PTR(err); - } - - err = clk_enable(clk); - if (err) { - pr_err("smp_twd: clock failed to enable: %d\n", err); - clk_unprepare(clk); - clk_put(clk); - return ERR_PTR(err); - } - - return clk; -} - -/* - * Setup the local clock events for a CPU. - */ -static int __cpuinit twd_timer_setup(struct clock_event_device *clk) -{ - struct clock_event_device **this_cpu_clk; - - twd_calibrate_rate(); - __raw_writel(0, twd_base + TWD_TIMER_CONTROL); - - clk->name = "local_timer"; - clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | - CLOCK_EVT_FEAT_C3STOP; - clk->rating = 350; - clk->set_mode = twd_set_mode; - clk->set_next_event = twd_set_next_event; - clk->irq = twd_ppi; - - this_cpu_clk = __this_cpu_ptr(twd_evt); - *this_cpu_clk = clk; - - clockevents_config_and_register(clk, twd_timer_rate, - 0xf, 0xffffffff); - enable_percpu_irq(clk->irq, 0); - - return 0; -} - -static struct local_timer_ops twd_lt_ops __cpuinitdata = { - .setup = twd_timer_setup, - .stop = twd_timer_stop, -}; - -static int __init twd_local_timer_common_register(void) -{ - int err; - - twd_evt = alloc_percpu(struct clock_event_device *); - if (!twd_evt) { - err = -ENOMEM; - goto out_free; - } - - err = request_percpu_irq(twd_ppi, twd_handler, "twd", twd_evt); - if (err) { - pr_err("twd: can't register interrupt %d (%d)\n", twd_ppi, err); - goto out_free; - } - - err = local_timer_register(&twd_lt_ops); - if (err) - goto out_irq; - - if (!twd_clk) - twd_clk = twd_get_clock(); - - if (!IS_ERR_OR_NULL(twd_clk)) - twd_timer_rate = clk_get_rate(twd_clk); - else - twd_calibrate_rate(); - - return 0; - -out_irq: - free_percpu_irq(twd_ppi, twd_evt); -out_free: - iounmap(twd_base); - twd_base = NULL; - free_percpu(twd_evt); - - return err; -} - -int __init twd_local_timer_register(struct twd_local_timer *tlt) -{ - if (twd_base || twd_evt) - return -EBUSY; - - twd_ppi = tlt->res[1].start; - - twd_base = ioremap(tlt->res[0].start, resource_size(&tlt->res[0])); - if (!twd_base) - return -ENOMEM; - - return twd_local_timer_common_register(); -} - -#ifdef CONFIG_OF -const static struct of_device_id twd_of_match[] __initconst = { - { .compatible = "arm,cortex-a9-twd-timer", }, - { .compatible = "arm,cortex-a5-twd-timer", }, - { .compatible = "arm,arm11mp-twd-timer", }, - { }, -}; - -void __init twd_local_timer_of_register(void) -{ - struct device_node *np; - int err; - - np = of_find_matching_node(NULL, twd_of_match); - if (!np) { - err = -ENODEV; - goto out; - } - - twd_ppi = irq_of_parse_and_map(np, 0); - if (!twd_ppi) { - err = -EINVAL; - goto out; - } - - twd_base = of_iomap(np, 0); - if (!twd_base) { - err = -ENOMEM; - goto out; - } - - err = twd_local_timer_common_register(); - -out: - WARN(err, "twd_local_timer_of_register failed (%d)\n", err); -} -#endif diff --git a/ANDROID_3.4.5/arch/arm/kernel/stacktrace.c b/ANDROID_3.4.5/arch/arm/kernel/stacktrace.c deleted file mode 100644 index 00f79e59..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/stacktrace.c +++ /dev/null @@ -1,131 +0,0 @@ -#include <linux/export.h> -#include <linux/sched.h> -#include <linux/stacktrace.h> - -#include <asm/stacktrace.h> - -#if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) -/* - * Unwind the current stack frame and store the new register values in the - * structure passed as argument. Unwinding is equivalent to a function return, - * hence the new PC value rather than LR should be used for backtrace. - * - * With framepointer enabled, a simple function prologue looks like this: - * mov ip, sp - * stmdb sp!, {fp, ip, lr, pc} - * sub fp, ip, #4 - * - * A simple function epilogue looks like this: - * ldm sp, {fp, sp, pc} - * - * Note that with framepointer enabled, even the leaf functions have the same - * prologue and epilogue, therefore we can ignore the LR value in this case. - */ -int notrace unwind_frame(struct stackframe *frame) -{ - unsigned long high, low; - unsigned long fp = frame->fp; - - /* only go to a higher address on the stack */ - low = frame->sp; - high = ALIGN(low, THREAD_SIZE); - - /* check current frame pointer is within bounds */ - if (fp < (low + 12) || fp + 4 >= high) - return -EINVAL; - - /* restore the registers from the stack frame */ - frame->fp = *(unsigned long *)(fp - 12); - frame->sp = *(unsigned long *)(fp - 8); - frame->pc = *(unsigned long *)(fp - 4); - - return 0; -} -#endif - -void notrace walk_stackframe(struct stackframe *frame, - int (*fn)(struct stackframe *, void *), void *data) -{ - while (1) { - int ret; - - if (fn(frame, data)) - break; - ret = unwind_frame(frame); - if (ret < 0) - break; - } -} -EXPORT_SYMBOL(walk_stackframe); - -#ifdef CONFIG_STACKTRACE -struct stack_trace_data { - struct stack_trace *trace; - unsigned int no_sched_functions; - unsigned int skip; -}; - -static int save_trace(struct stackframe *frame, void *d) -{ - struct stack_trace_data *data = d; - struct stack_trace *trace = data->trace; - unsigned long addr = frame->pc; - - if (data->no_sched_functions && in_sched_functions(addr)) - return 0; - if (data->skip) { - data->skip--; - return 0; - } - - trace->entries[trace->nr_entries++] = addr; - - return trace->nr_entries >= trace->max_entries; -} - -void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) -{ - struct stack_trace_data data; - struct stackframe frame; - - data.trace = trace; - data.skip = trace->skip; - - if (tsk != current) { -#ifdef CONFIG_SMP - /* - * What guarantees do we have here that 'tsk' is not - * running on another CPU? For now, ignore it as we - * can't guarantee we won't explode. - */ - if (trace->nr_entries < trace->max_entries) - trace->entries[trace->nr_entries++] = ULONG_MAX; - return; -#else - data.no_sched_functions = 1; - frame.fp = thread_saved_fp(tsk); - frame.sp = thread_saved_sp(tsk); - frame.lr = 0; /* recovered from the stack */ - frame.pc = thread_saved_pc(tsk); -#endif - } else { - register unsigned long current_sp asm ("sp"); - - data.no_sched_functions = 0; - frame.fp = (unsigned long)__builtin_frame_address(0); - frame.sp = current_sp; - frame.lr = (unsigned long)__builtin_return_address(0); - frame.pc = (unsigned long)save_stack_trace_tsk; - } - - walk_stackframe(&frame, save_trace, &data); - if (trace->nr_entries < trace->max_entries) - trace->entries[trace->nr_entries++] = ULONG_MAX; -} - -void save_stack_trace(struct stack_trace *trace) -{ - save_stack_trace_tsk(current, trace); -} -EXPORT_SYMBOL_GPL(save_stack_trace); -#endif diff --git a/ANDROID_3.4.5/arch/arm/kernel/suspend.c b/ANDROID_3.4.5/arch/arm/kernel/suspend.c deleted file mode 100644 index 1794cc3b..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/suspend.c +++ /dev/null @@ -1,60 +0,0 @@ -#include <linux/init.h> - -#include <asm/idmap.h> -#include <asm/pgalloc.h> -#include <asm/pgtable.h> -#include <asm/memory.h> -#include <asm/suspend.h> -#include <asm/tlbflush.h> - -extern int __cpu_suspend(unsigned long, int (*)(unsigned long)); -extern void cpu_resume_mmu(void); - -/* - * This is called by __cpu_suspend() to save the state, and do whatever - * flushing is required to ensure that when the CPU goes to sleep we have - * the necessary data available when the caches are not searched. - */ -void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr) -{ - *save_ptr = virt_to_phys(ptr); - - /* This must correspond to the LDM in cpu_resume() assembly */ - *ptr++ = virt_to_phys(idmap_pgd); - *ptr++ = sp; - *ptr++ = virt_to_phys(cpu_do_resume); - - cpu_do_suspend(ptr); - - flush_cache_all(); - outer_clean_range(*save_ptr, *save_ptr + ptrsz); - outer_clean_range(virt_to_phys(save_ptr), - virt_to_phys(save_ptr) + sizeof(*save_ptr)); -} - -/* - * Hide the first two arguments to __cpu_suspend - these are an implementation - * detail which platform code shouldn't have to know about. - */ -int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) -{ - struct mm_struct *mm = current->active_mm; - int ret; - - if (!idmap_pgd) - return -EINVAL; - - /* - * Provide a temporary page table with an identity mapping for - * the MMU-enable code, required for resuming. On successful - * resume (indicated by a zero return code), we need to switch - * back to the correct page tables. - */ - ret = __cpu_suspend(arg, fn); - if (ret == 0) { - cpu_switch_mm(mm->pgd, mm); - local_flush_tlb_all(); - } - - return ret; -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/swp_emulate.c b/ANDROID_3.4.5/arch/arm/kernel/swp_emulate.c deleted file mode 100644 index df745188..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/swp_emulate.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * linux/arch/arm/kernel/swp_emulate.c - * - * Copyright (C) 2009 ARM Limited - * __user_* functions adapted from include/asm/uaccess.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Implements emulation of the SWP/SWPB instructions using load-exclusive and - * store-exclusive for processors that have them disabled (or future ones that - * might not implement them). - * - * Syntax of SWP{B} instruction: SWP{B}<c> <Rt>, <Rt2>, [<Rn>] - * Where: Rt = destination - * Rt2 = source - * Rn = address - */ - -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/proc_fs.h> -#include <linux/sched.h> -#include <linux/syscalls.h> -#include <linux/perf_event.h> - -#include <asm/opcodes.h> -#include <asm/traps.h> -#include <asm/uaccess.h> - -/* - * Error-checking SWP macros implemented using ldrex{b}/strex{b} - */ -#define __user_swpX_asm(data, addr, res, temp, B) \ - __asm__ __volatile__( \ - " mov %2, %1\n" \ - "0: ldrex"B" %1, [%3]\n" \ - "1: strex"B" %0, %2, [%3]\n" \ - " cmp %0, #0\n" \ - " movne %0, %4\n" \ - "2:\n" \ - " .section .fixup,\"ax\"\n" \ - " .align 2\n" \ - "3: mov %0, %5\n" \ - " b 2b\n" \ - " .previous\n" \ - " .section __ex_table,\"a\"\n" \ - " .align 3\n" \ - " .long 0b, 3b\n" \ - " .long 1b, 3b\n" \ - " .previous" \ - : "=&r" (res), "+r" (data), "=&r" (temp) \ - : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT) \ - : "cc", "memory") - -#define __user_swp_asm(data, addr, res, temp) \ - __user_swpX_asm(data, addr, res, temp, "") -#define __user_swpb_asm(data, addr, res, temp) \ - __user_swpX_asm(data, addr, res, temp, "b") - -/* - * Macros/defines for extracting register numbers from instruction. - */ -#define EXTRACT_REG_NUM(instruction, offset) \ - (((instruction) & (0xf << (offset))) >> (offset)) -#define RN_OFFSET 16 -#define RT_OFFSET 12 -#define RT2_OFFSET 0 -/* - * Bit 22 of the instruction encoding distinguishes between - * the SWP and SWPB variants (bit set means SWPB). - */ -#define TYPE_SWPB (1 << 22) - -static unsigned long swpcounter; -static unsigned long swpbcounter; -static unsigned long abtcounter; -static pid_t previous_pid; - -#ifdef CONFIG_PROC_FS -static int proc_read_status(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - char *p = page; - int len; - - p += sprintf(p, "Emulated SWP:\t\t%lu\n", swpcounter); - p += sprintf(p, "Emulated SWPB:\t\t%lu\n", swpbcounter); - p += sprintf(p, "Aborted SWP{B}:\t\t%lu\n", abtcounter); - if (previous_pid != 0) - p += sprintf(p, "Last process:\t\t%d\n", previous_pid); - - len = (p - page) - off; - if (len < 0) - len = 0; - - *eof = (len <= count) ? 1 : 0; - *start = page + off; - - return len; -} -#endif - -/* - * Set up process info to signal segmentation fault - called on access error. - */ -static void set_segfault(struct pt_regs *regs, unsigned long addr) -{ - siginfo_t info; - - if (find_vma(current->mm, addr) == NULL) - info.si_code = SEGV_MAPERR; - else - info.si_code = SEGV_ACCERR; - - info.si_signo = SIGSEGV; - info.si_errno = 0; - info.si_addr = (void *) instruction_pointer(regs); - - pr_debug("SWP{B} emulation: access caused memory abort!\n"); - arm_notify_die("Illegal memory access", regs, &info, 0, 0); - - abtcounter++; -} - -static int emulate_swpX(unsigned int address, unsigned int *data, - unsigned int type) -{ - unsigned int res = 0; - - if ((type != TYPE_SWPB) && (address & 0x3)) { - /* SWP to unaligned address not permitted */ - pr_debug("SWP instruction on unaligned pointer!\n"); - return -EFAULT; - } - - while (1) { - unsigned long temp; - - /* - * Barrier required between accessing protected resource and - * releasing a lock for it. Legacy code might not have done - * this, and we cannot determine that this is not the case - * being emulated, so insert always. - */ - smp_mb(); - - if (type == TYPE_SWPB) - __user_swpb_asm(*data, address, res, temp); - else - __user_swp_asm(*data, address, res, temp); - - if (likely(res != -EAGAIN) || signal_pending(current)) - break; - - cond_resched(); - } - - if (res == 0) { - /* - * Barrier also required between acquiring a lock for a - * protected resource and accessing the resource. Inserted for - * same reason as above. - */ - smp_mb(); - - if (type == TYPE_SWPB) - swpbcounter++; - else - swpcounter++; - } - - return res; -} - -/* - * swp_handler logs the id of calling process, dissects the instruction, sanity - * checks the memory location, calls emulate_swpX for the actual operation and - * deals with fixup/error handling before returning - */ -static int swp_handler(struct pt_regs *regs, unsigned int instr) -{ - unsigned int address, destreg, data, type; - unsigned int res = 0; - - perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->ARM_pc); - - res = arm_check_condition(instr, regs->ARM_cpsr); - switch (res) { - case ARM_OPCODE_CONDTEST_PASS: - break; - case ARM_OPCODE_CONDTEST_FAIL: - /* Condition failed - return to next instruction */ - regs->ARM_pc += 4; - return 0; - case ARM_OPCODE_CONDTEST_UNCOND: - /* If unconditional encoding - not a SWP, undef */ - return -EFAULT; - default: - return -EINVAL; - } - - if (current->pid != previous_pid) { - pr_debug("\"%s\" (%ld) uses deprecated SWP{B} instruction\n", - current->comm, (unsigned long)current->pid); - previous_pid = current->pid; - } - - address = regs->uregs[EXTRACT_REG_NUM(instr, RN_OFFSET)]; - data = regs->uregs[EXTRACT_REG_NUM(instr, RT2_OFFSET)]; - destreg = EXTRACT_REG_NUM(instr, RT_OFFSET); - - type = instr & TYPE_SWPB; - - pr_debug("addr in r%d->0x%08x, dest is r%d, source in r%d->0x%08x)\n", - EXTRACT_REG_NUM(instr, RN_OFFSET), address, - destreg, EXTRACT_REG_NUM(instr, RT2_OFFSET), data); - - /* Check access in reasonable access range for both SWP and SWPB */ - if (!access_ok(VERIFY_WRITE, (address & ~3), 4)) { - pr_debug("SWP{B} emulation: access to %p not allowed!\n", - (void *)address); - res = -EFAULT; - } else { - res = emulate_swpX(address, &data, type); - } - - if (res == 0) { - /* - * On successful emulation, revert the adjustment to the PC - * made in kernel/traps.c in order to resume execution at the - * instruction following the SWP{B}. - */ - regs->ARM_pc += 4; - regs->uregs[destreg] = data; - } else if (res == -EFAULT) { - /* - * Memory errors do not mean emulation failed. - * Set up signal info to return SEGV, then return OK - */ - set_segfault(regs, address); - } - - return 0; -} - -/* - * Only emulate SWP/SWPB executed in ARM state/User mode. - * The kernel must be SWP free and SWP{B} does not exist in Thumb/ThumbEE. - */ -static struct undef_hook swp_hook = { - .instr_mask = 0x0fb00ff0, - .instr_val = 0x01000090, - .cpsr_mask = MODE_MASK | PSR_T_BIT | PSR_J_BIT, - .cpsr_val = USR_MODE, - .fn = swp_handler -}; - -/* - * Register handler and create status file in /proc/cpu - * Invoked as late_initcall, since not needed before init spawned. - */ -static int __init swp_emulation_init(void) -{ -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *res; - - res = create_proc_entry("cpu/swp_emulation", S_IRUGO, NULL); - - if (!res) - return -ENOMEM; - - res->read_proc = proc_read_status; -#endif /* CONFIG_PROC_FS */ - - printk(KERN_NOTICE "Registering SWP/SWPB emulation handler\n"); - register_undef_hook(&swp_hook); - - return 0; -} - -late_initcall(swp_emulation_init); diff --git a/ANDROID_3.4.5/arch/arm/kernel/sys_arm.c b/ANDROID_3.4.5/arch/arm/kernel/sys_arm.c deleted file mode 100644 index 76cbb055..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/sys_arm.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * linux/arch/arm/kernel/sys_arm.c - * - * Copyright (C) People who wrote linux/arch/i386/kernel/sys_i386.c - * Copyright (C) 1995, 1996 Russell King. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This file contains various random system calls that - * have a non-standard calling sequence on the Linux/arm - * platform. - */ -#include <linux/export.h> -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/sem.h> -#include <linux/msg.h> -#include <linux/shm.h> -#include <linux/stat.h> -#include <linux/syscalls.h> -#include <linux/mman.h> -#include <linux/fs.h> -#include <linux/file.h> -#include <linux/ipc.h> -#include <linux/uaccess.h> -#include <linux/slab.h> - -/* Fork a new task - this creates a new program thread. - * This is called indirectly via a small wrapper - */ -asmlinkage int sys_fork(struct pt_regs *regs) -{ -#ifdef CONFIG_MMU - return do_fork(SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL); -#else - /* can not support in nommu mode */ - return(-EINVAL); -#endif -} - -/* Clone a task - this clones the calling program thread. - * This is called indirectly via a small wrapper - */ -asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, - int __user *parent_tidptr, int tls_val, - int __user *child_tidptr, struct pt_regs *regs) -{ - if (!newsp) - newsp = regs->ARM_sp; - - return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); -} - -asmlinkage int sys_vfork(struct pt_regs *regs) -{ - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL); -} - -/* sys_execve() executes a new program. - * This is called indirectly via a small wrapper - */ -asmlinkage int sys_execve(const char __user *filenamei, - const char __user *const __user *argv, - const char __user *const __user *envp, struct pt_regs *regs) -{ - int error; - char * filename; - - filename = getname(filenamei); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - error = do_execve(filename, argv, envp, regs); - putname(filename); -out: - return error; -} - -int kernel_execve(const char *filename, - const char *const argv[], - const char *const envp[]) -{ - struct pt_regs regs; - int ret; - - memset(®s, 0, sizeof(struct pt_regs)); - ret = do_execve(filename, - (const char __user *const __user *)argv, - (const char __user *const __user *)envp, ®s); - if (ret < 0) - goto out; - - /* - * Save argc to the register structure for userspace. - */ - regs.ARM_r0 = ret; - - /* - * We were successful. We won't be returning to our caller, but - * instead to user space by manipulating the kernel stack. - */ - asm( "add r0, %0, %1\n\t" - "mov r1, %2\n\t" - "mov r2, %3\n\t" - "bl memmove\n\t" /* copy regs to top of stack */ - "mov r8, #0\n\t" /* not a syscall */ - "mov r9, %0\n\t" /* thread structure */ - "mov sp, r0\n\t" /* reposition stack pointer */ - "b ret_to_user" - : - : "r" (current_thread_info()), - "Ir" (THREAD_START_SP - sizeof(regs)), - "r" (®s), - "Ir" (sizeof(regs)) - : "r0", "r1", "r2", "r3", "r8", "r9", "ip", "lr", "memory"); - - out: - return ret; -} -EXPORT_SYMBOL(kernel_execve); - -/* - * Since loff_t is a 64 bit type we avoid a lot of ABI hassle - * with a different argument ordering. - */ -asmlinkage long sys_arm_fadvise64_64(int fd, int advice, - loff_t offset, loff_t len) -{ - return sys_fadvise64_64(fd, offset, len, advice); -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/sys_oabi-compat.c b/ANDROID_3.4.5/arch/arm/kernel/sys_oabi-compat.c deleted file mode 100644 index af0aaebf..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/sys_oabi-compat.c +++ /dev/null @@ -1,453 +0,0 @@ -/* - * arch/arm/kernel/sys_oabi-compat.c - * - * Compatibility wrappers for syscalls that are used from - * old ABI user space binaries with an EABI kernel. - * - * Author: Nicolas Pitre - * Created: Oct 7, 2005 - * Copyright: MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* - * The legacy ABI and the new ARM EABI have different rules making some - * syscalls incompatible especially with structure arguments. - * Most notably, Eabi says 64-bit members should be 64-bit aligned instead of - * simply word aligned. EABI also pads structures to the size of the largest - * member it contains instead of the invariant 32-bit. - * - * The following syscalls are affected: - * - * sys_stat64: - * sys_lstat64: - * sys_fstat64: - * sys_fstatat64: - * - * struct stat64 has different sizes and some members are shifted - * Compatibility wrappers are needed for them and provided below. - * - * sys_fcntl64: - * - * struct flock64 has different sizes and some members are shifted - * A compatibility wrapper is needed and provided below. - * - * sys_statfs64: - * sys_fstatfs64: - * - * struct statfs64 has extra padding with EABI growing its size from - * 84 to 88. This struct is now __attribute__((packed,aligned(4))) - * with a small assembly wrapper to force the sz argument to 84 if it is 88 - * to avoid copying the extra padding over user space unexpecting it. - * - * sys_newuname: - * - * struct new_utsname has no padding with EABI. No problem there. - * - * sys_epoll_ctl: - * sys_epoll_wait: - * - * struct epoll_event has its second member shifted also affecting the - * structure size. Compatibility wrappers are needed and provided below. - * - * sys_ipc: - * sys_semop: - * sys_semtimedop: - * - * struct sembuf loses its padding with EABI. Since arrays of them are - * used they have to be copyed to remove the padding. Compatibility wrappers - * provided below. - * - * sys_bind: - * sys_connect: - * sys_sendmsg: - * sys_sendto: - * sys_socketcall: - * - * struct sockaddr_un loses its padding with EABI. Since the size of the - * structure is used as a validation test in unix_mkname(), we need to - * change the length argument to 110 whenever it is 112. Compatibility - * wrappers provided below. - */ - -#include <linux/syscalls.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/fcntl.h> -#include <linux/eventpoll.h> -#include <linux/sem.h> -#include <linux/socket.h> -#include <linux/net.h> -#include <linux/ipc.h> -#include <linux/uaccess.h> -#include <linux/slab.h> - -struct oldabi_stat64 { - unsigned long long st_dev; - unsigned int __pad1; - unsigned long __st_ino; - unsigned int st_mode; - unsigned int st_nlink; - - unsigned long st_uid; - unsigned long st_gid; - - unsigned long long st_rdev; - unsigned int __pad2; - - long long st_size; - unsigned long st_blksize; - unsigned long long st_blocks; - - unsigned long st_atime; - unsigned long st_atime_nsec; - - unsigned long st_mtime; - unsigned long st_mtime_nsec; - - unsigned long st_ctime; - unsigned long st_ctime_nsec; - - unsigned long long st_ino; -} __attribute__ ((packed,aligned(4))); - -static long cp_oldabi_stat64(struct kstat *stat, - struct oldabi_stat64 __user *statbuf) -{ - struct oldabi_stat64 tmp; - - tmp.st_dev = huge_encode_dev(stat->dev); - tmp.__pad1 = 0; - tmp.__st_ino = stat->ino; - tmp.st_mode = stat->mode; - tmp.st_nlink = stat->nlink; - tmp.st_uid = stat->uid; - tmp.st_gid = stat->gid; - tmp.st_rdev = huge_encode_dev(stat->rdev); - tmp.st_size = stat->size; - tmp.st_blocks = stat->blocks; - tmp.__pad2 = 0; - tmp.st_blksize = stat->blksize; - tmp.st_atime = stat->atime.tv_sec; - tmp.st_atime_nsec = stat->atime.tv_nsec; - tmp.st_mtime = stat->mtime.tv_sec; - tmp.st_mtime_nsec = stat->mtime.tv_nsec; - tmp.st_ctime = stat->ctime.tv_sec; - tmp.st_ctime_nsec = stat->ctime.tv_nsec; - tmp.st_ino = stat->ino; - return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; -} - -asmlinkage long sys_oabi_stat64(const char __user * filename, - struct oldabi_stat64 __user * statbuf) -{ - struct kstat stat; - int error = vfs_stat(filename, &stat); - if (!error) - error = cp_oldabi_stat64(&stat, statbuf); - return error; -} - -asmlinkage long sys_oabi_lstat64(const char __user * filename, - struct oldabi_stat64 __user * statbuf) -{ - struct kstat stat; - int error = vfs_lstat(filename, &stat); - if (!error) - error = cp_oldabi_stat64(&stat, statbuf); - return error; -} - -asmlinkage long sys_oabi_fstat64(unsigned long fd, - struct oldabi_stat64 __user * statbuf) -{ - struct kstat stat; - int error = vfs_fstat(fd, &stat); - if (!error) - error = cp_oldabi_stat64(&stat, statbuf); - return error; -} - -asmlinkage long sys_oabi_fstatat64(int dfd, - const char __user *filename, - struct oldabi_stat64 __user *statbuf, - int flag) -{ - struct kstat stat; - int error; - - error = vfs_fstatat(dfd, filename, &stat, flag); - if (error) - return error; - return cp_oldabi_stat64(&stat, statbuf); -} - -struct oabi_flock64 { - short l_type; - short l_whence; - loff_t l_start; - loff_t l_len; - pid_t l_pid; -} __attribute__ ((packed,aligned(4))); - -asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd, - unsigned long arg) -{ - struct oabi_flock64 user; - struct flock64 kernel; - mm_segment_t fs = USER_DS; /* initialized to kill a warning */ - unsigned long local_arg = arg; - int ret; - - switch (cmd) { - case F_GETLK64: - case F_SETLK64: - case F_SETLKW64: - if (copy_from_user(&user, (struct oabi_flock64 __user *)arg, - sizeof(user))) - return -EFAULT; - kernel.l_type = user.l_type; - kernel.l_whence = user.l_whence; - kernel.l_start = user.l_start; - kernel.l_len = user.l_len; - kernel.l_pid = user.l_pid; - local_arg = (unsigned long)&kernel; - fs = get_fs(); - set_fs(KERNEL_DS); - } - - ret = sys_fcntl64(fd, cmd, local_arg); - - switch (cmd) { - case F_GETLK64: - if (!ret) { - user.l_type = kernel.l_type; - user.l_whence = kernel.l_whence; - user.l_start = kernel.l_start; - user.l_len = kernel.l_len; - user.l_pid = kernel.l_pid; - if (copy_to_user((struct oabi_flock64 __user *)arg, - &user, sizeof(user))) - ret = -EFAULT; - } - case F_SETLK64: - case F_SETLKW64: - set_fs(fs); - } - - return ret; -} - -struct oabi_epoll_event { - __u32 events; - __u64 data; -} __attribute__ ((packed,aligned(4))); - -asmlinkage long sys_oabi_epoll_ctl(int epfd, int op, int fd, - struct oabi_epoll_event __user *event) -{ - struct oabi_epoll_event user; - struct epoll_event kernel; - mm_segment_t fs; - long ret; - - if (op == EPOLL_CTL_DEL) - return sys_epoll_ctl(epfd, op, fd, NULL); - if (copy_from_user(&user, event, sizeof(user))) - return -EFAULT; - kernel.events = user.events; - kernel.data = user.data; - fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_epoll_ctl(epfd, op, fd, &kernel); - set_fs(fs); - return ret; -} - -asmlinkage long sys_oabi_epoll_wait(int epfd, - struct oabi_epoll_event __user *events, - int maxevents, int timeout) -{ - struct epoll_event *kbuf; - mm_segment_t fs; - long ret, err, i; - - if (maxevents <= 0 || maxevents > (INT_MAX/sizeof(struct epoll_event))) - return -EINVAL; - kbuf = kmalloc(sizeof(*kbuf) * maxevents, GFP_KERNEL); - if (!kbuf) - return -ENOMEM; - fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_epoll_wait(epfd, kbuf, maxevents, timeout); - set_fs(fs); - err = 0; - for (i = 0; i < ret; i++) { - __put_user_error(kbuf[i].events, &events->events, err); - __put_user_error(kbuf[i].data, &events->data, err); - events++; - } - kfree(kbuf); - return err ? -EFAULT : ret; -} - -struct oabi_sembuf { - unsigned short sem_num; - short sem_op; - short sem_flg; - unsigned short __pad; -}; - -asmlinkage long sys_oabi_semtimedop(int semid, - struct oabi_sembuf __user *tsops, - unsigned nsops, - const struct timespec __user *timeout) -{ - struct sembuf *sops; - struct timespec local_timeout; - long err; - int i; - - if (nsops < 1 || nsops > SEMOPM) - return -EINVAL; - sops = kmalloc(sizeof(*sops) * nsops, GFP_KERNEL); - if (!sops) - return -ENOMEM; - err = 0; - for (i = 0; i < nsops; i++) { - __get_user_error(sops[i].sem_num, &tsops->sem_num, err); - __get_user_error(sops[i].sem_op, &tsops->sem_op, err); - __get_user_error(sops[i].sem_flg, &tsops->sem_flg, err); - tsops++; - } - if (timeout) { - /* copy this as well before changing domain protection */ - err |= copy_from_user(&local_timeout, timeout, sizeof(*timeout)); - timeout = &local_timeout; - } - if (err) { - err = -EFAULT; - } else { - mm_segment_t fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_semtimedop(semid, sops, nsops, timeout); - set_fs(fs); - } - kfree(sops); - return err; -} - -asmlinkage long sys_oabi_semop(int semid, struct oabi_sembuf __user *tsops, - unsigned nsops) -{ - return sys_oabi_semtimedop(semid, tsops, nsops, NULL); -} - -asmlinkage int sys_oabi_ipc(uint call, int first, int second, int third, - void __user *ptr, long fifth) -{ - switch (call & 0xffff) { - case SEMOP: - return sys_oabi_semtimedop(first, - (struct oabi_sembuf __user *)ptr, - second, NULL); - case SEMTIMEDOP: - return sys_oabi_semtimedop(first, - (struct oabi_sembuf __user *)ptr, - second, - (const struct timespec __user *)fifth); - default: - return sys_ipc(call, first, second, third, ptr, fifth); - } -} - -asmlinkage long sys_oabi_bind(int fd, struct sockaddr __user *addr, int addrlen) -{ - sa_family_t sa_family; - if (addrlen == 112 && - get_user(sa_family, &addr->sa_family) == 0 && - sa_family == AF_UNIX) - addrlen = 110; - return sys_bind(fd, addr, addrlen); -} - -asmlinkage long sys_oabi_connect(int fd, struct sockaddr __user *addr, int addrlen) -{ - sa_family_t sa_family; - if (addrlen == 112 && - get_user(sa_family, &addr->sa_family) == 0 && - sa_family == AF_UNIX) - addrlen = 110; - return sys_connect(fd, addr, addrlen); -} - -asmlinkage long sys_oabi_sendto(int fd, void __user *buff, - size_t len, unsigned flags, - struct sockaddr __user *addr, - int addrlen) -{ - sa_family_t sa_family; - if (addrlen == 112 && - get_user(sa_family, &addr->sa_family) == 0 && - sa_family == AF_UNIX) - addrlen = 110; - return sys_sendto(fd, buff, len, flags, addr, addrlen); -} - -asmlinkage long sys_oabi_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) -{ - struct sockaddr __user *addr; - int msg_namelen; - sa_family_t sa_family; - if (msg && - get_user(msg_namelen, &msg->msg_namelen) == 0 && - msg_namelen == 112 && - get_user(addr, &msg->msg_name) == 0 && - get_user(sa_family, &addr->sa_family) == 0 && - sa_family == AF_UNIX) - { - /* - * HACK ALERT: there is a limit to how much backward bending - * we should do for what is actually a transitional - * compatibility layer. This already has known flaws with - * a few ioctls that we don't intend to fix. Therefore - * consider this blatent hack as another one... and take care - * to run for cover. In most cases it will "just work fine". - * If it doesn't, well, tough. - */ - put_user(110, &msg->msg_namelen); - } - return sys_sendmsg(fd, msg, flags); -} - -asmlinkage long sys_oabi_socketcall(int call, unsigned long __user *args) -{ - unsigned long r = -EFAULT, a[6]; - - switch (call) { - case SYS_BIND: - if (copy_from_user(a, args, 3 * sizeof(long)) == 0) - r = sys_oabi_bind(a[0], (struct sockaddr __user *)a[1], a[2]); - break; - case SYS_CONNECT: - if (copy_from_user(a, args, 3 * sizeof(long)) == 0) - r = sys_oabi_connect(a[0], (struct sockaddr __user *)a[1], a[2]); - break; - case SYS_SENDTO: - if (copy_from_user(a, args, 6 * sizeof(long)) == 0) - r = sys_oabi_sendto(a[0], (void __user *)a[1], a[2], a[3], - (struct sockaddr __user *)a[4], a[5]); - break; - case SYS_SENDMSG: - if (copy_from_user(a, args, 3 * sizeof(long)) == 0) - r = sys_oabi_sendmsg(a[0], (struct msghdr __user *)a[1], a[2]); - break; - default: - r = sys_socketcall(call, args); - } - - return r; -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/tcm.c b/ANDROID_3.4.5/arch/arm/kernel/tcm.c deleted file mode 100644 index 30ae6bb4..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/tcm.c +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright (C) 2008-2009 ST-Ericsson AB - * License terms: GNU General Public License (GPL) version 2 - * TCM memory handling for ARM systems - * - * Author: Linus Walleij <linus.walleij@stericsson.com> - * Author: Rickard Andersson <rickard.andersson@stericsson.com> - */ -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/stddef.h> -#include <linux/ioport.h> -#include <linux/genalloc.h> -#include <linux/string.h> /* memcpy */ -#include <asm/cputype.h> -#include <asm/mach/map.h> -#include <asm/memory.h> -#include <asm/system_info.h> -#include "tcm.h" - -static struct gen_pool *tcm_pool; -static bool dtcm_present; -static bool itcm_present; - -/* TCM section definitions from the linker */ -extern char __itcm_start, __sitcm_text, __eitcm_text; -extern char __dtcm_start, __sdtcm_data, __edtcm_data; - -/* These will be increased as we run */ -u32 dtcm_end = DTCM_OFFSET; -u32 itcm_end = ITCM_OFFSET; - -/* - * TCM memory resources - */ -static struct resource dtcm_res = { - .name = "DTCM RAM", - .start = DTCM_OFFSET, - .end = DTCM_OFFSET, - .flags = IORESOURCE_MEM -}; - -static struct resource itcm_res = { - .name = "ITCM RAM", - .start = ITCM_OFFSET, - .end = ITCM_OFFSET, - .flags = IORESOURCE_MEM -}; - -static struct map_desc dtcm_iomap[] __initdata = { - { - .virtual = DTCM_OFFSET, - .pfn = __phys_to_pfn(DTCM_OFFSET), - .length = 0, - .type = MT_MEMORY_DTCM - } -}; - -static struct map_desc itcm_iomap[] __initdata = { - { - .virtual = ITCM_OFFSET, - .pfn = __phys_to_pfn(ITCM_OFFSET), - .length = 0, - .type = MT_MEMORY_ITCM - } -}; - -/* - * Allocate a chunk of TCM memory - */ -void *tcm_alloc(size_t len) -{ - unsigned long vaddr; - - if (!tcm_pool) - return NULL; - - vaddr = gen_pool_alloc(tcm_pool, len); - if (!vaddr) - return NULL; - - return (void *) vaddr; -} -EXPORT_SYMBOL(tcm_alloc); - -/* - * Free a chunk of TCM memory - */ -void tcm_free(void *addr, size_t len) -{ - gen_pool_free(tcm_pool, (unsigned long) addr, len); -} -EXPORT_SYMBOL(tcm_free); - -bool tcm_dtcm_present(void) -{ - return dtcm_present; -} -EXPORT_SYMBOL(tcm_dtcm_present); - -bool tcm_itcm_present(void) -{ - return itcm_present; -} -EXPORT_SYMBOL(tcm_itcm_present); - -static int __init setup_tcm_bank(u8 type, u8 bank, u8 banks, - u32 *offset) -{ - const int tcm_sizes[16] = { 0, -1, -1, 4, 8, 16, 32, 64, 128, - 256, 512, 1024, -1, -1, -1, -1 }; - u32 tcm_region; - int tcm_size; - - /* - * If there are more than one TCM bank of this type, - * select the TCM bank to operate on in the TCM selection - * register. - */ - if (banks > 1) - asm("mcr p15, 0, %0, c9, c2, 0" - : /* No output operands */ - : "r" (bank)); - - /* Read the special TCM region register c9, 0 */ - if (!type) - asm("mrc p15, 0, %0, c9, c1, 0" - : "=r" (tcm_region)); - else - asm("mrc p15, 0, %0, c9, c1, 1" - : "=r" (tcm_region)); - - tcm_size = tcm_sizes[(tcm_region >> 2) & 0x0f]; - if (tcm_size < 0) { - pr_err("CPU: %sTCM%d of unknown size\n", - type ? "I" : "D", bank); - return -EINVAL; - } else if (tcm_size > 32) { - pr_err("CPU: %sTCM%d larger than 32k found\n", - type ? "I" : "D", bank); - return -EINVAL; - } else { - pr_info("CPU: found %sTCM%d %dk @ %08x, %senabled\n", - type ? "I" : "D", - bank, - tcm_size, - (tcm_region & 0xfffff000U), - (tcm_region & 1) ? "" : "not "); - } - - /* Not much fun you can do with a size 0 bank */ - if (tcm_size == 0) - return 0; - - /* Force move the TCM bank to where we want it, enable */ - tcm_region = *offset | (tcm_region & 0x00000ffeU) | 1; - - if (!type) - asm("mcr p15, 0, %0, c9, c1, 0" - : /* No output operands */ - : "r" (tcm_region)); - else - asm("mcr p15, 0, %0, c9, c1, 1" - : /* No output operands */ - : "r" (tcm_region)); - - /* Increase offset */ - *offset += (tcm_size << 10); - - pr_info("CPU: moved %sTCM%d %dk to %08x, enabled\n", - type ? "I" : "D", - bank, - tcm_size, - (tcm_region & 0xfffff000U)); - return 0; -} - -/* - * This initializes the TCM memory - */ -void __init tcm_init(void) -{ - u32 tcm_status; - u8 dtcm_banks; - u8 itcm_banks; - size_t dtcm_code_sz = &__edtcm_data - &__sdtcm_data; - size_t itcm_code_sz = &__eitcm_text - &__sitcm_text; - char *start; - char *end; - char *ram; - int ret; - int i; - - /* - * Prior to ARMv5 there is no TCM, and trying to read the status - * register will hang the processor. - */ - if (cpu_architecture() < CPU_ARCH_ARMv5) { - if (dtcm_code_sz || itcm_code_sz) - pr_info("CPU TCM: %u bytes of DTCM and %u bytes of " - "ITCM code compiled in, but no TCM present " - "in pre-v5 CPU\n", dtcm_code_sz, itcm_code_sz); - return; - } - - tcm_status = read_cpuid_tcmstatus(); - dtcm_banks = (tcm_status >> 16) & 0x03; - itcm_banks = (tcm_status & 0x03); - - /* Values greater than 2 for D/ITCM banks are "reserved" */ - if (dtcm_banks > 2) - dtcm_banks = 0; - if (itcm_banks > 2) - itcm_banks = 0; - - /* Setup DTCM if present */ - if (dtcm_banks > 0) { - for (i = 0; i < dtcm_banks; i++) { - ret = setup_tcm_bank(0, i, dtcm_banks, &dtcm_end); - if (ret) - return; - } - /* This means you compiled more code than fits into DTCM */ - if (dtcm_code_sz > (dtcm_end - DTCM_OFFSET)) { - pr_info("CPU DTCM: %u bytes of code compiled to " - "DTCM but only %lu bytes of DTCM present\n", - dtcm_code_sz, (dtcm_end - DTCM_OFFSET)); - goto no_dtcm; - } - dtcm_res.end = dtcm_end - 1; - request_resource(&iomem_resource, &dtcm_res); - dtcm_iomap[0].length = dtcm_end - DTCM_OFFSET; - iotable_init(dtcm_iomap, 1); - /* Copy data from RAM to DTCM */ - start = &__sdtcm_data; - end = &__edtcm_data; - ram = &__dtcm_start; - memcpy(start, ram, dtcm_code_sz); - pr_debug("CPU DTCM: copied data from %p - %p\n", - start, end); - dtcm_present = true; - } else if (dtcm_code_sz) { - pr_info("CPU DTCM: %u bytes of code compiled to DTCM but no " - "DTCM banks present in CPU\n", dtcm_code_sz); - } - -no_dtcm: - /* Setup ITCM if present */ - if (itcm_banks > 0) { - for (i = 0; i < itcm_banks; i++) { - ret = setup_tcm_bank(1, i, itcm_banks, &itcm_end); - if (ret) - return; - } - /* This means you compiled more code than fits into ITCM */ - if (itcm_code_sz > (itcm_end - ITCM_OFFSET)) { - pr_info("CPU ITCM: %u bytes of code compiled to " - "ITCM but only %lu bytes of ITCM present\n", - itcm_code_sz, (itcm_end - ITCM_OFFSET)); - return; - } - itcm_res.end = itcm_end - 1; - request_resource(&iomem_resource, &itcm_res); - itcm_iomap[0].length = itcm_end - ITCM_OFFSET; - iotable_init(itcm_iomap, 1); - /* Copy code from RAM to ITCM */ - start = &__sitcm_text; - end = &__eitcm_text; - ram = &__itcm_start; - memcpy(start, ram, itcm_code_sz); - pr_debug("CPU ITCM: copied code from %p - %p\n", - start, end); - itcm_present = true; - } else if (itcm_code_sz) { - pr_info("CPU ITCM: %u bytes of code compiled to ITCM but no " - "ITCM banks present in CPU\n", itcm_code_sz); - } -} - -/* - * This creates the TCM memory pool and has to be done later, - * during the core_initicalls, since the allocator is not yet - * up and running when the first initialization runs. - */ -static int __init setup_tcm_pool(void) -{ - u32 dtcm_pool_start = (u32) &__edtcm_data; - u32 itcm_pool_start = (u32) &__eitcm_text; - int ret; - - /* - * Set up malloc pool, 2^2 = 4 bytes granularity since - * the TCM is sometimes just 4 KiB. NB: pages and cache - * line alignments does not matter in TCM! - */ - tcm_pool = gen_pool_create(2, -1); - - pr_debug("Setting up TCM memory pool\n"); - - /* Add the rest of DTCM to the TCM pool */ - if (dtcm_present) { - if (dtcm_pool_start < dtcm_end) { - ret = gen_pool_add(tcm_pool, dtcm_pool_start, - dtcm_end - dtcm_pool_start, -1); - if (ret) { - pr_err("CPU DTCM: could not add DTCM " \ - "remainder to pool!\n"); - return ret; - } - pr_debug("CPU DTCM: Added %08x bytes @ %08x to " \ - "the TCM memory pool\n", - dtcm_end - dtcm_pool_start, - dtcm_pool_start); - } - } - - /* Add the rest of ITCM to the TCM pool */ - if (itcm_present) { - if (itcm_pool_start < itcm_end) { - ret = gen_pool_add(tcm_pool, itcm_pool_start, - itcm_end - itcm_pool_start, -1); - if (ret) { - pr_err("CPU ITCM: could not add ITCM " \ - "remainder to pool!\n"); - return ret; - } - pr_debug("CPU ITCM: Added %08x bytes @ %08x to " \ - "the TCM memory pool\n", - itcm_end - itcm_pool_start, - itcm_pool_start); - } - } - return 0; -} - -core_initcall(setup_tcm_pool); diff --git a/ANDROID_3.4.5/arch/arm/kernel/tcm.h b/ANDROID_3.4.5/arch/arm/kernel/tcm.h deleted file mode 100644 index 8015ad43..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/tcm.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (C) 2008-2009 ST-Ericsson AB - * License terms: GNU General Public License (GPL) version 2 - * TCM memory handling for ARM systems - * - * Author: Linus Walleij <linus.walleij@stericsson.com> - * Author: Rickard Andersson <rickard.andersson@stericsson.com> - */ - -#ifdef CONFIG_HAVE_TCM -void __init tcm_init(void); -#else -/* No TCM support, just blank inlines to be optimized out */ -inline void tcm_init(void) -{ -} -#endif diff --git a/ANDROID_3.4.5/arch/arm/kernel/thumbee.c b/ANDROID_3.4.5/arch/arm/kernel/thumbee.c deleted file mode 100644 index aab89976..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/thumbee.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * arch/arm/kernel/thumbee.c - * - * Copyright (C) 2008 ARM Limited - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/kernel.h> -#include <linux/init.h> - -#include <asm/system_info.h> -#include <asm/thread_notify.h> - -/* - * Access to the ThumbEE Handler Base register - */ -static inline unsigned long teehbr_read(void) -{ - unsigned long v; - asm("mrc p14, 6, %0, c1, c0, 0\n" : "=r" (v)); - return v; -} - -static inline void teehbr_write(unsigned long v) -{ - asm("mcr p14, 6, %0, c1, c0, 0\n" : : "r" (v)); -} - -static int thumbee_notifier(struct notifier_block *self, unsigned long cmd, void *t) -{ - struct thread_info *thread = t; - - switch (cmd) { - case THREAD_NOTIFY_FLUSH: - thread->thumbee_state = 0; - break; - case THREAD_NOTIFY_SWITCH: - current_thread_info()->thumbee_state = teehbr_read(); - teehbr_write(thread->thumbee_state); - break; - } - - return NOTIFY_DONE; -} - -static struct notifier_block thumbee_notifier_block = { - .notifier_call = thumbee_notifier, -}; - -static int __init thumbee_init(void) -{ - unsigned long pfr0; - unsigned int cpu_arch = cpu_architecture(); - - if (cpu_arch < CPU_ARCH_ARMv7) - return 0; - - /* processor feature register 0 */ - asm("mrc p15, 0, %0, c0, c1, 0\n" : "=r" (pfr0)); - if ((pfr0 & 0x0000f000) != 0x00001000) - return 0; - - printk(KERN_INFO "ThumbEE CPU extension supported.\n"); - elf_hwcap |= HWCAP_THUMBEE; - thread_register_notifier(&thumbee_notifier_block); - - return 0; -} - -late_initcall(thumbee_init); diff --git a/ANDROID_3.4.5/arch/arm/kernel/time.c b/ANDROID_3.4.5/arch/arm/kernel/time.c deleted file mode 100644 index fe31b22f..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/time.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * linux/arch/arm/kernel/time.c - * - * Copyright (C) 1991, 1992, 1995 Linus Torvalds - * Modifications for ARM (C) 1994-2001 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This file contains the ARM-specific time handling details: - * reading the RTC at bootup, etc... - */ -#include <linux/export.h> -#include <linux/kernel.h> -#include <linux/interrupt.h> -#include <linux/time.h> -#include <linux/init.h> -#include <linux/sched.h> -#include <linux/smp.h> -#include <linux/timex.h> -#include <linux/errno.h> -#include <linux/profile.h> -#include <linux/syscore_ops.h> -#include <linux/timer.h> -#include <linux/irq.h> - -#include <asm/leds.h> -#include <asm/thread_info.h> -#include <asm/sched_clock.h> -#include <asm/stacktrace.h> -#include <asm/mach/arch.h> -#include <asm/mach/time.h> - -/* - * Our system timer. - */ -static struct sys_timer *system_timer; - -#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || \ - defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE) -/* this needs a better home */ -DEFINE_SPINLOCK(rtc_lock); -EXPORT_SYMBOL(rtc_lock); -#endif /* pc-style 'CMOS' RTC support */ - -/* change this if you have some constant time drift */ -#define USECS_PER_JIFFY (1000000/HZ) - -#ifdef CONFIG_SMP -unsigned long profile_pc(struct pt_regs *regs) -{ - struct stackframe frame; - - if (!in_lock_functions(regs->ARM_pc)) - return regs->ARM_pc; - - frame.fp = regs->ARM_fp; - frame.sp = regs->ARM_sp; - frame.lr = regs->ARM_lr; - frame.pc = regs->ARM_pc; - do { - int ret = unwind_frame(&frame); - if (ret < 0) - return 0; - } while (in_lock_functions(frame.pc)); - - return frame.pc; -} -EXPORT_SYMBOL(profile_pc); -#endif - -#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET -u32 arch_gettimeoffset(void) -{ - if (system_timer->offset != NULL) - return system_timer->offset() * 1000; - - return 0; -} -#endif /* CONFIG_ARCH_USES_GETTIMEOFFSET */ - -#ifdef CONFIG_LEDS_TIMER -static inline void do_leds(void) -{ - static unsigned int count = HZ/2; - - if (--count == 0) { - count = HZ/2; - leds_event(led_timer); - } -} -#else -#define do_leds() -#endif - - -#ifndef CONFIG_GENERIC_CLOCKEVENTS -/* - * Kernel system timer support. - */ -void timer_tick(void) -{ - profile_tick(CPU_PROFILING); - do_leds(); - xtime_update(1); -#ifndef CONFIG_SMP - update_process_times(user_mode(get_irq_regs())); -#endif -} -#endif - -#if defined(CONFIG_PM) && !defined(CONFIG_GENERIC_CLOCKEVENTS) -static int timer_suspend(void) -{ - if (system_timer->suspend) - system_timer->suspend(); - - return 0; -} - -static void timer_resume(void) -{ - if (system_timer->resume) - system_timer->resume(); -} -#else -#define timer_suspend NULL -#define timer_resume NULL -#endif - -static struct syscore_ops timer_syscore_ops = { - .suspend = timer_suspend, - .resume = timer_resume, -}; - -static int __init timer_init_syscore_ops(void) -{ - register_syscore_ops(&timer_syscore_ops); - - return 0; -} - -device_initcall(timer_init_syscore_ops); - -void __init time_init(void) -{ - system_timer = machine_desc->timer; - system_timer->init(); - sched_clock_postinit(); -} - diff --git a/ANDROID_3.4.5/arch/arm/kernel/topology.c b/ANDROID_3.4.5/arch/arm/kernel/topology.c deleted file mode 100644 index 8200deaa..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/topology.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * arch/arm/kernel/topology.c - * - * Copyright (C) 2011 Linaro Limited. - * Written by: Vincent Guittot - * - * based on arch/sh/kernel/topology.c - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#include <linux/cpu.h> -#include <linux/cpumask.h> -#include <linux/init.h> -#include <linux/percpu.h> -#include <linux/node.h> -#include <linux/nodemask.h> -#include <linux/sched.h> - -#include <asm/cputype.h> -#include <asm/topology.h> - -#define MPIDR_SMP_BITMASK (0x3 << 30) -#define MPIDR_SMP_VALUE (0x2 << 30) - -#define MPIDR_MT_BITMASK (0x1 << 24) - -/* - * These masks reflect the current use of the affinity levels. - * The affinity level can be up to 16 bits according to ARM ARM - */ - -#define MPIDR_LEVEL0_MASK 0x3 -#define MPIDR_LEVEL0_SHIFT 0 - -#define MPIDR_LEVEL1_MASK 0xF -#define MPIDR_LEVEL1_SHIFT 8 - -#define MPIDR_LEVEL2_MASK 0xFF -#define MPIDR_LEVEL2_SHIFT 16 - -struct cputopo_arm cpu_topology[NR_CPUS]; - -const struct cpumask *cpu_coregroup_mask(int cpu) -{ - return &cpu_topology[cpu].core_sibling; -} - -/* - * store_cpu_topology is called at boot when only one cpu is running - * and with the mutex cpu_hotplug.lock locked, when several cpus have booted, - * which prevents simultaneous write access to cpu_topology array - */ -void store_cpu_topology(unsigned int cpuid) -{ - struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid]; - unsigned int mpidr; - unsigned int cpu; - - /* If the cpu topology has been already set, just return */ - if (cpuid_topo->core_id != -1) - return; - - mpidr = read_cpuid_mpidr(); - - /* create cpu topology mapping */ - if ((mpidr & MPIDR_SMP_BITMASK) == MPIDR_SMP_VALUE) { - /* - * This is a multiprocessor system - * multiprocessor format & multiprocessor mode field are set - */ - - if (mpidr & MPIDR_MT_BITMASK) { - /* core performance interdependency */ - cpuid_topo->thread_id = (mpidr >> MPIDR_LEVEL0_SHIFT) - & MPIDR_LEVEL0_MASK; - cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL1_SHIFT) - & MPIDR_LEVEL1_MASK; - cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL2_SHIFT) - & MPIDR_LEVEL2_MASK; - } else { - /* largely independent cores */ - cpuid_topo->thread_id = -1; - cpuid_topo->core_id = (mpidr >> MPIDR_LEVEL0_SHIFT) - & MPIDR_LEVEL0_MASK; - cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL1_SHIFT) - & MPIDR_LEVEL1_MASK; - } - } else { - /* - * This is an uniprocessor system - * we are in multiprocessor format but uniprocessor system - * or in the old uniprocessor format - */ - cpuid_topo->thread_id = -1; - cpuid_topo->core_id = 0; - cpuid_topo->socket_id = -1; - } - - /* update core and thread sibling masks */ - for_each_possible_cpu(cpu) { - struct cputopo_arm *cpu_topo = &cpu_topology[cpu]; - - if (cpuid_topo->socket_id == cpu_topo->socket_id) { - cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); - if (cpu != cpuid) - cpumask_set_cpu(cpu, - &cpuid_topo->core_sibling); - - if (cpuid_topo->core_id == cpu_topo->core_id) { - cpumask_set_cpu(cpuid, - &cpu_topo->thread_sibling); - if (cpu != cpuid) - cpumask_set_cpu(cpu, - &cpuid_topo->thread_sibling); - } - } - } - smp_wmb(); - - printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", - cpuid, cpu_topology[cpuid].thread_id, - cpu_topology[cpuid].core_id, - cpu_topology[cpuid].socket_id, mpidr); -} - -/* - * init_cpu_topology is called at boot when only one cpu is running - * which prevent simultaneous write access to cpu_topology array - */ -void init_cpu_topology(void) -{ - unsigned int cpu; - - /* init core mask */ - for_each_possible_cpu(cpu) { - struct cputopo_arm *cpu_topo = &(cpu_topology[cpu]); - - cpu_topo->thread_id = -1; - cpu_topo->core_id = -1; - cpu_topo->socket_id = -1; - cpumask_clear(&cpu_topo->core_sibling); - cpumask_clear(&cpu_topo->thread_sibling); - } - smp_wmb(); -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/traps.c b/ANDROID_3.4.5/arch/arm/kernel/traps.c deleted file mode 100644 index 63d402f7..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/traps.c +++ /dev/null @@ -1,829 +0,0 @@ -/* - * linux/arch/arm/kernel/traps.c - * - * Copyright (C) 1995-2009 Russell King - * Fragments that appear the same as linux/arch/i386/kernel/traps.c (C) Linus Torvalds - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 'traps.c' handles hardware exceptions after we have saved some state in - * 'linux/arch/arm/lib/traps.S'. Mostly a debugging aid, but will probably - * kill the offending process. - */ -#include <linux/signal.h> -#include <linux/personality.h> -#include <linux/kallsyms.h> -#include <linux/spinlock.h> -#include <linux/uaccess.h> -#include <linux/hardirq.h> -#include <linux/kdebug.h> -#include <linux/module.h> -#include <linux/kexec.h> -#include <linux/bug.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/sched.h> - -#include <linux/atomic.h> -#include <asm/cacheflush.h> -#include <asm/exception.h> -#include <asm/unistd.h> -#include <asm/traps.h> -#include <asm/unwind.h> -#include <asm/tls.h> -#include <asm/system_misc.h> - -#include "signal.h" - -static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; - -void *vectors_page; - -#ifdef CONFIG_DEBUG_USER -unsigned int user_debug; - -static int __init user_debug_setup(char *str) -{ - get_option(&str, &user_debug); - return 1; -} -__setup("user_debug=", user_debug_setup); -#endif - -static void dump_mem(const char *, const char *, unsigned long, unsigned long); - -void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame) -{ -#ifdef CONFIG_KALLSYMS - printk("[<%08lx>] (%pS) from [<%08lx>] (%pS)\n", where, (void *)where, from, (void *)from); -#else - printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from); -#endif - - if (in_exception_text(where)) - dump_mem("", "Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs)); -} - -#ifndef CONFIG_ARM_UNWIND -/* - * Stack pointers should always be within the kernels view of - * physical memory. If it is not there, then we can't dump - * out any information relating to the stack. - */ -static int verify_stack(unsigned long sp) -{ - if (sp < PAGE_OFFSET || - (sp > (unsigned long)high_memory && high_memory != NULL)) - return -EFAULT; - - return 0; -} -#endif - -/* - * Dump out the contents of some memory nicely... - */ -static void dump_mem(const char *lvl, const char *str, unsigned long bottom, - unsigned long top) -{ - unsigned long first; - mm_segment_t fs; - int i; - - /* - * We need to switch to kernel mode so that we can use __get_user - * to safely read from kernel space. Note that we now dump the - * code first, just in case the backtrace kills us. - */ - fs = get_fs(); - set_fs(KERNEL_DS); - - printk("%s%s(0x%08lx to 0x%08lx)\n", lvl, str, bottom, top); - - for (first = bottom & ~31; first < top; first += 32) { - unsigned long p; - char str[sizeof(" 12345678") * 8 + 1]; - - memset(str, ' ', sizeof(str)); - str[sizeof(str) - 1] = '\0'; - - for (p = first, i = 0; i < 8 && p < top; i++, p += 4) { - if (p >= bottom && p < top) { - unsigned long val; - if (__get_user(val, (unsigned long *)p) == 0) - sprintf(str + i * 9, " %08lx", val); - else - sprintf(str + i * 9, " ????????"); - } - } - printk("%s%04lx:%s\n", lvl, first & 0xffff, str); - } - - set_fs(fs); -} - -static void dump_instr(const char *lvl, struct pt_regs *regs) -{ - unsigned long addr = instruction_pointer(regs); - const int thumb = thumb_mode(regs); - const int width = thumb ? 4 : 8; - mm_segment_t fs; - char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str; - int i; - - /* - * We need to switch to kernel mode so that we can use __get_user - * to safely read from kernel space. Note that we now dump the - * code first, just in case the backtrace kills us. - */ - fs = get_fs(); - set_fs(KERNEL_DS); - - for (i = -4; i < 1 + !!thumb; i++) { - unsigned int val, bad; - - if (thumb) - bad = __get_user(val, &((u16 *)addr)[i]); - else - bad = __get_user(val, &((u32 *)addr)[i]); - - if (!bad) - p += sprintf(p, i == 0 ? "(%0*x) " : "%0*x ", - width, val); - else { - p += sprintf(p, "bad PC value"); - break; - } - } - printk("%sCode: %s\n", lvl, str); - - set_fs(fs); -} - -#ifdef CONFIG_ARM_UNWIND -static inline void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) -{ - unwind_backtrace(regs, tsk); -} -#else -static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) -{ - unsigned int fp, mode; - int ok = 1; - - printk("Backtrace: "); - - if (!tsk) - tsk = current; - - if (regs) { - fp = regs->ARM_fp; - mode = processor_mode(regs); - } else if (tsk != current) { - fp = thread_saved_fp(tsk); - mode = 0x10; - } else { - asm("mov %0, fp" : "=r" (fp) : : "cc"); - mode = 0x10; - } - - if (!fp) { - printk("no frame pointer"); - ok = 0; - } else if (verify_stack(fp)) { - printk("invalid frame pointer 0x%08x", fp); - ok = 0; - } else if (fp < (unsigned long)end_of_stack(tsk)) - printk("frame pointer underflow"); - printk("\n"); - - if (ok) - c_backtrace(fp, mode); -} -#endif - -void dump_stack(void) -{ - dump_backtrace(NULL, NULL); -} - -EXPORT_SYMBOL(dump_stack); - -void show_stack(struct task_struct *tsk, unsigned long *sp) -{ - dump_backtrace(NULL, tsk); - barrier(); -} - -#ifdef CONFIG_PREEMPT -#define S_PREEMPT " PREEMPT" -#else -#define S_PREEMPT "" -#endif -#ifdef CONFIG_SMP -#define S_SMP " SMP" -#else -#define S_SMP "" -#endif -#ifdef CONFIG_THUMB2_KERNEL -#define S_ISA " THUMB2" -#else -#define S_ISA " ARM" -#endif - -static int __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs) -{ - struct task_struct *tsk = thread->task; - static int die_counter; - int ret; - - printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP - S_ISA "\n", str, err, ++die_counter); - - /* trap and error numbers are mostly meaningless on ARM */ - ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV); - if (ret == NOTIFY_STOP) - return ret; - - print_modules(); - __show_regs(regs); - printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n", - TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1); - - if (!user_mode(regs) || in_interrupt()) { - dump_mem(KERN_EMERG, "Stack: ", regs->ARM_sp, - THREAD_SIZE + (unsigned long)task_stack_page(tsk)); - dump_backtrace(regs, tsk); - dump_instr(KERN_EMERG, regs); - } - - return ret; -} - -static DEFINE_RAW_SPINLOCK(die_lock); - -/* - * This function is protected against re-entrancy. - */ -void die(const char *str, struct pt_regs *regs, int err) -{ - struct thread_info *thread = current_thread_info(); - int ret; - enum bug_trap_type bug_type = BUG_TRAP_TYPE_NONE; - - oops_enter(); - - raw_spin_lock_irq(&die_lock); - console_verbose(); - bust_spinlocks(1); - if (!user_mode(regs)) - bug_type = report_bug(regs->ARM_pc, regs); - if (bug_type != BUG_TRAP_TYPE_NONE) - str = "Oops - BUG"; - ret = __die(str, err, thread, regs); - - if (regs && kexec_should_crash(thread->task)) - crash_kexec(regs); - - bust_spinlocks(0); - add_taint(TAINT_DIE); - raw_spin_unlock_irq(&die_lock); - oops_exit(); - - if (in_interrupt()) - panic("Fatal exception in interrupt"); - if (panic_on_oops) - panic("Fatal exception"); - if (ret != NOTIFY_STOP) - do_exit(SIGSEGV); -} - -void arm_notify_die(const char *str, struct pt_regs *regs, - struct siginfo *info, unsigned long err, unsigned long trap) -{ - if (user_mode(regs)) { - current->thread.error_code = err; - current->thread.trap_no = trap; - - force_sig_info(info->si_signo, info, current); - } else { - die(str, regs, err); - } -} - -#ifdef CONFIG_GENERIC_BUG - -int is_valid_bugaddr(unsigned long pc) -{ -#ifdef CONFIG_THUMB2_KERNEL - unsigned short bkpt; -#else - unsigned long bkpt; -#endif - - if (probe_kernel_address((unsigned *)pc, bkpt)) - return 0; - - return bkpt == BUG_INSTR_VALUE; -} - -#endif - -static LIST_HEAD(undef_hook); -static DEFINE_RAW_SPINLOCK(undef_lock); - -void register_undef_hook(struct undef_hook *hook) -{ - unsigned long flags; - - raw_spin_lock_irqsave(&undef_lock, flags); - list_add(&hook->node, &undef_hook); - raw_spin_unlock_irqrestore(&undef_lock, flags); -} - -void unregister_undef_hook(struct undef_hook *hook) -{ - unsigned long flags; - - raw_spin_lock_irqsave(&undef_lock, flags); - list_del(&hook->node); - raw_spin_unlock_irqrestore(&undef_lock, flags); -} - -static int call_undef_hook(struct pt_regs *regs, unsigned int instr) -{ - struct undef_hook *hook; - unsigned long flags; - int (*fn)(struct pt_regs *regs, unsigned int instr) = NULL; - - raw_spin_lock_irqsave(&undef_lock, flags); - list_for_each_entry(hook, &undef_hook, node) - if ((instr & hook->instr_mask) == hook->instr_val && - (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) - fn = hook->fn; - raw_spin_unlock_irqrestore(&undef_lock, flags); - - return fn ? fn(regs, instr) : 1; -} - -asmlinkage void __exception do_undefinstr(struct pt_regs *regs) -{ - unsigned int correction = thumb_mode(regs) ? 2 : 4; - unsigned int instr; - siginfo_t info; - void __user *pc; - - /* - * According to the ARM ARM, PC is 2 or 4 bytes ahead, - * depending whether we're in Thumb mode or not. - * Correct this offset. - */ - regs->ARM_pc -= correction; - - pc = (void __user *)instruction_pointer(regs); - - if (processor_mode(regs) == SVC_MODE) { -#ifdef CONFIG_THUMB2_KERNEL - if (thumb_mode(regs)) { - instr = ((u16 *)pc)[0]; - if (is_wide_instruction(instr)) { - instr <<= 16; - instr |= ((u16 *)pc)[1]; - } - } else -#endif - instr = *(u32 *) pc; - } else if (thumb_mode(regs)) { - get_user(instr, (u16 __user *)pc); - if (is_wide_instruction(instr)) { - unsigned int instr2; - get_user(instr2, (u16 __user *)pc+1); - instr <<= 16; - instr |= instr2; - } - } else { - get_user(instr, (u32 __user *)pc); - } - - if (call_undef_hook(regs, instr) == 0) - return; - -#ifdef CONFIG_DEBUG_USER - if (user_debug & UDBG_UNDEFINED) { - printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n", - current->comm, task_pid_nr(current), pc); - dump_instr(KERN_INFO, regs); - } -#endif - - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_ILLOPC; - info.si_addr = pc; - - arm_notify_die("Oops - undefined instruction", regs, &info, 0, 6); -} - -asmlinkage void do_unexp_fiq (struct pt_regs *regs) -{ - printk("Hmm. Unexpected FIQ received, but trying to continue\n"); - printk("You may have a hardware problem...\n"); -} - -/* - * bad_mode handles the impossible case in the vectors. If you see one of - * these, then it's extremely serious, and could mean you have buggy hardware. - * It never returns, and never tries to sync. We hope that we can at least - * dump out some state information... - */ -asmlinkage void bad_mode(struct pt_regs *regs, int reason) -{ - console_verbose(); - - printk(KERN_CRIT "Bad mode in %s handler detected\n", handler[reason]); - - die("Oops - bad mode", regs, 0); - local_irq_disable(); - panic("bad mode"); -} - -static int bad_syscall(int n, struct pt_regs *regs) -{ - struct thread_info *thread = current_thread_info(); - siginfo_t info; - - if ((current->personality & PER_MASK) != PER_LINUX && - thread->exec_domain->handler) { - thread->exec_domain->handler(n, regs); - return regs->ARM_r0; - } - -#ifdef CONFIG_DEBUG_USER - if (user_debug & UDBG_SYSCALL) { - printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n", - task_pid_nr(current), current->comm, n); - dump_instr(KERN_ERR, regs); - } -#endif - - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_ILLTRP; - info.si_addr = (void __user *)instruction_pointer(regs) - - (thumb_mode(regs) ? 2 : 4); - - arm_notify_die("Oops - bad syscall", regs, &info, n, 0); - - return regs->ARM_r0; -} - -static inline void -do_cache_op(unsigned long start, unsigned long end, int flags) -{ - struct mm_struct *mm = current->active_mm; - struct vm_area_struct *vma; - - if (end < start || flags) - return; - - down_read(&mm->mmap_sem); - vma = find_vma(mm, start); - if (vma && vma->vm_start < end) { - if (start < vma->vm_start) - start = vma->vm_start; - if (end > vma->vm_end) - end = vma->vm_end; - - up_read(&mm->mmap_sem); - flush_cache_user_range(start, end); - return; - } - up_read(&mm->mmap_sem); -} - -/* - * Handle all unrecognised system calls. - * 0x9f0000 - 0x9fffff are some more esoteric system calls - */ -#define NR(x) ((__ARM_NR_##x) - __ARM_NR_BASE) -asmlinkage int arm_syscall(int no, struct pt_regs *regs) -{ - struct thread_info *thread = current_thread_info(); - siginfo_t info; - - if ((no >> 16) != (__ARM_NR_BASE>> 16)) - return bad_syscall(no, regs); - - switch (no & 0xffff) { - case 0: /* branch through 0 */ - info.si_signo = SIGSEGV; - info.si_errno = 0; - info.si_code = SEGV_MAPERR; - info.si_addr = NULL; - - arm_notify_die("branch through zero", regs, &info, 0, 0); - return 0; - - case NR(breakpoint): /* SWI BREAK_POINT */ - regs->ARM_pc -= thumb_mode(regs) ? 2 : 4; - ptrace_break(current, regs); - return regs->ARM_r0; - - /* - * Flush a region from virtual address 'r0' to virtual address 'r1' - * _exclusive_. There is no alignment requirement on either address; - * user space does not need to know the hardware cache layout. - * - * r2 contains flags. It should ALWAYS be passed as ZERO until it - * is defined to be something else. For now we ignore it, but may - * the fires of hell burn in your belly if you break this rule. ;) - * - * (at a later date, we may want to allow this call to not flush - * various aspects of the cache. Passing '0' will guarantee that - * everything necessary gets flushed to maintain consistency in - * the specified region). - */ - case NR(cacheflush): - do_cache_op(regs->ARM_r0, regs->ARM_r1, regs->ARM_r2); - return 0; - - case NR(usr26): - if (!(elf_hwcap & HWCAP_26BIT)) - break; - regs->ARM_cpsr &= ~MODE32_BIT; - return regs->ARM_r0; - - case NR(usr32): - if (!(elf_hwcap & HWCAP_26BIT)) - break; - regs->ARM_cpsr |= MODE32_BIT; - return regs->ARM_r0; - - case NR(set_tls): - thread->tp_value = regs->ARM_r0; - if (tls_emu) - return 0; - if (has_tls_reg) { - asm ("mcr p15, 0, %0, c13, c0, 3" - : : "r" (regs->ARM_r0)); - } else { - /* - * User space must never try to access this directly. - * Expect your app to break eventually if you do so. - * The user helper at 0xffff0fe0 must be used instead. - * (see entry-armv.S for details) - */ - *((unsigned int *)0xffff0ff0) = regs->ARM_r0; - } - return 0; - -#ifdef CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG - /* - * Atomically store r1 in *r2 if *r2 is equal to r0 for user space. - * Return zero in r0 if *MEM was changed or non-zero if no exchange - * happened. Also set the user C flag accordingly. - * If access permissions have to be fixed up then non-zero is - * returned and the operation has to be re-attempted. - * - * *NOTE*: This is a ghost syscall private to the kernel. Only the - * __kuser_cmpxchg code in entry-armv.S should be aware of its - * existence. Don't ever use this from user code. - */ - case NR(cmpxchg): - for (;;) { - extern void do_DataAbort(unsigned long addr, unsigned int fsr, - struct pt_regs *regs); - unsigned long val; - unsigned long addr = regs->ARM_r2; - struct mm_struct *mm = current->mm; - pgd_t *pgd; pmd_t *pmd; pte_t *pte; - spinlock_t *ptl; - - regs->ARM_cpsr &= ~PSR_C_BIT; - down_read(&mm->mmap_sem); - pgd = pgd_offset(mm, addr); - if (!pgd_present(*pgd)) - goto bad_access; - pmd = pmd_offset(pgd, addr); - if (!pmd_present(*pmd)) - goto bad_access; - pte = pte_offset_map_lock(mm, pmd, addr, &ptl); - if (!pte_present(*pte) || !pte_write(*pte) || !pte_dirty(*pte)) { - pte_unmap_unlock(pte, ptl); - goto bad_access; - } - val = *(unsigned long *)addr; - val -= regs->ARM_r0; - if (val == 0) { - *(unsigned long *)addr = regs->ARM_r1; - regs->ARM_cpsr |= PSR_C_BIT; - } - pte_unmap_unlock(pte, ptl); - up_read(&mm->mmap_sem); - return val; - - bad_access: - up_read(&mm->mmap_sem); - /* simulate a write access fault */ - do_DataAbort(addr, 15 + (1 << 11), regs); - } -#endif - - default: - /* Calls 9f00xx..9f07ff are defined to return -ENOSYS - if not implemented, rather than raising SIGILL. This - way the calling program can gracefully determine whether - a feature is supported. */ - if ((no & 0xffff) <= 0x7ff) - return -ENOSYS; - break; - } -#ifdef CONFIG_DEBUG_USER - /* - * experience shows that these seem to indicate that - * something catastrophic has happened - */ - if (user_debug & UDBG_SYSCALL) { - printk("[%d] %s: arm syscall %d\n", - task_pid_nr(current), current->comm, no); - dump_instr("", regs); - if (user_mode(regs)) { - __show_regs(regs); - c_backtrace(regs->ARM_fp, processor_mode(regs)); - } - } -#endif - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_ILLTRP; - info.si_addr = (void __user *)instruction_pointer(regs) - - (thumb_mode(regs) ? 2 : 4); - - arm_notify_die("Oops - bad syscall(2)", regs, &info, no, 0); - return 0; -} - -#ifdef CONFIG_TLS_REG_EMUL - -/* - * We might be running on an ARMv6+ processor which should have the TLS - * register but for some reason we can't use it, or maybe an SMP system - * using a pre-ARMv6 processor (there are apparently a few prototypes like - * that in existence) and therefore access to that register must be - * emulated. - */ - -static int get_tp_trap(struct pt_regs *regs, unsigned int instr) -{ - int reg = (instr >> 12) & 15; - if (reg == 15) - return 1; - regs->uregs[reg] = current_thread_info()->tp_value; - regs->ARM_pc += 4; - return 0; -} - -static struct undef_hook arm_mrc_hook = { - .instr_mask = 0x0fff0fff, - .instr_val = 0x0e1d0f70, - .cpsr_mask = PSR_T_BIT, - .cpsr_val = 0, - .fn = get_tp_trap, -}; - -static int __init arm_mrc_hook_init(void) -{ - register_undef_hook(&arm_mrc_hook); - return 0; -} - -late_initcall(arm_mrc_hook_init); - -#endif - -void __bad_xchg(volatile void *ptr, int size) -{ - printk("xchg: bad data size: pc 0x%p, ptr 0x%p, size %d\n", - __builtin_return_address(0), ptr, size); - BUG(); -} -EXPORT_SYMBOL(__bad_xchg); - -/* - * A data abort trap was taken, but we did not handle the instruction. - * Try to abort the user program, or panic if it was the kernel. - */ -asmlinkage void -baddataabort(int code, unsigned long instr, struct pt_regs *regs) -{ - unsigned long addr = instruction_pointer(regs); - siginfo_t info; - -#ifdef CONFIG_DEBUG_USER - if (user_debug & UDBG_BADABORT) { - printk(KERN_ERR "[%d] %s: bad data abort: code %d instr 0x%08lx\n", - task_pid_nr(current), current->comm, code, instr); - dump_instr(KERN_ERR, regs); - show_pte(current->mm, addr); - } -#endif - - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_ILLOPC; - info.si_addr = (void __user *)addr; - - arm_notify_die("unknown data abort code", regs, &info, instr, 0); -} - -void __readwrite_bug(const char *fn) -{ - printk("%s called, but not implemented\n", fn); - BUG(); -} -EXPORT_SYMBOL(__readwrite_bug); - -void __pte_error(const char *file, int line, pte_t pte) -{ - printk("%s:%d: bad pte %08llx.\n", file, line, (long long)pte_val(pte)); -} - -void __pmd_error(const char *file, int line, pmd_t pmd) -{ - printk("%s:%d: bad pmd %08llx.\n", file, line, (long long)pmd_val(pmd)); -} - -void __pgd_error(const char *file, int line, pgd_t pgd) -{ - printk("%s:%d: bad pgd %08llx.\n", file, line, (long long)pgd_val(pgd)); -} - -asmlinkage void __div0(void) -{ - printk("Division by zero in kernel.\n"); - dump_stack(); -} -EXPORT_SYMBOL(__div0); - -void abort(void) -{ - BUG(); - - /* if that doesn't kill us, halt */ - panic("Oops failed to kill thread"); -} -EXPORT_SYMBOL(abort); - -void __init trap_init(void) -{ - return; -} - -static void __init kuser_get_tls_init(unsigned long vectors) -{ - /* - * vectors + 0xfe0 = __kuser_get_tls - * vectors + 0xfe8 = hardware TLS instruction at 0xffff0fe8 - */ - if (tls_emu || has_tls_reg) - memcpy((void *)vectors + 0xfe0, (void *)vectors + 0xfe8, 4); -} - -void __init early_trap_init(void *vectors_base) -{ - unsigned long vectors = (unsigned long)vectors_base; - extern char __stubs_start[], __stubs_end[]; - extern char __vectors_start[], __vectors_end[]; - extern char __kuser_helper_start[], __kuser_helper_end[]; - int kuser_sz = __kuser_helper_end - __kuser_helper_start; - - vectors_page = vectors_base; - - /* - * Copy the vectors, stubs and kuser helpers (in entry-armv.S) - * into the vector page, mapped at 0xffff0000, and ensure these - * are visible to the instruction stream. - */ - memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start); - memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start); - memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz); - - /* - * Do processor specific fixups for the kuser helpers - */ - kuser_get_tls_init(vectors); - - /* - * Copy signal return handlers into the vector page, and - * set sigreturn to be a pointer to these. - */ - memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE), - sigreturn_codes, sizeof(sigreturn_codes)); - memcpy((void *)(vectors + KERN_RESTART_CODE - CONFIG_VECTORS_BASE), - syscall_restart_code, sizeof(syscall_restart_code)); - - flush_icache_range(vectors, vectors + PAGE_SIZE); - modify_domain(DOMAIN_USER, DOMAIN_CLIENT); -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/unwind.c b/ANDROID_3.4.5/arch/arm/kernel/unwind.c deleted file mode 100644 index 00df012c..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/unwind.c +++ /dev/null @@ -1,491 +0,0 @@ -/* - * arch/arm/kernel/unwind.c - * - * Copyright (C) 2008 ARM Limited - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * Stack unwinding support for ARM - * - * An ARM EABI version of gcc is required to generate the unwind - * tables. For information about the structure of the unwind tables, - * see "Exception Handling ABI for the ARM Architecture" at: - * - * http://infocenter.arm.com/help/topic/com.arm.doc.subset.swdev.abi/index.html - */ - -#ifndef __CHECKER__ -#if !defined (__ARM_EABI__) -#warning Your compiler does not have EABI support. -#warning ARM unwind is known to compile only with EABI compilers. -#warning Change compiler or disable ARM_UNWIND option. -#elif (__GNUC__ == 4 && __GNUC_MINOR__ <= 2) -#warning Your compiler is too buggy; it is known to not compile ARM unwind support. -#warning Change compiler or disable ARM_UNWIND option. -#endif -#endif /* __CHECKER__ */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/export.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/list.h> - -#include <asm/stacktrace.h> -#include <asm/traps.h> -#include <asm/unwind.h> - -/* Dummy functions to avoid linker complaints */ -void __aeabi_unwind_cpp_pr0(void) -{ -}; -EXPORT_SYMBOL(__aeabi_unwind_cpp_pr0); - -void __aeabi_unwind_cpp_pr1(void) -{ -}; -EXPORT_SYMBOL(__aeabi_unwind_cpp_pr1); - -void __aeabi_unwind_cpp_pr2(void) -{ -}; -EXPORT_SYMBOL(__aeabi_unwind_cpp_pr2); - -struct unwind_ctrl_block { - unsigned long vrs[16]; /* virtual register set */ - const unsigned long *insn; /* pointer to the current instructions word */ - int entries; /* number of entries left to interpret */ - int byte; /* current byte number in the instructions word */ -}; - -enum regs { -#ifdef CONFIG_THUMB2_KERNEL - FP = 7, -#else - FP = 11, -#endif - SP = 13, - LR = 14, - PC = 15 -}; - -extern const struct unwind_idx __start_unwind_idx[]; -static const struct unwind_idx *__origin_unwind_idx; -extern const struct unwind_idx __stop_unwind_idx[]; - -static DEFINE_SPINLOCK(unwind_lock); -static LIST_HEAD(unwind_tables); - -/* Convert a prel31 symbol to an absolute address */ -#define prel31_to_addr(ptr) \ -({ \ - /* sign-extend to 32 bits */ \ - long offset = (((long)*(ptr)) << 1) >> 1; \ - (unsigned long)(ptr) + offset; \ -}) - -/* - * Binary search in the unwind index. The entries are - * guaranteed to be sorted in ascending order by the linker. - * - * start = first entry - * origin = first entry with positive offset (or stop if there is no such entry) - * stop - 1 = last entry - */ -static const struct unwind_idx *search_index(unsigned long addr, - const struct unwind_idx *start, - const struct unwind_idx *origin, - const struct unwind_idx *stop) -{ - unsigned long addr_prel31; - - pr_debug("%s(%08lx, %p, %p, %p)\n", - __func__, addr, start, origin, stop); - - /* - * only search in the section with the matching sign. This way the - * prel31 numbers can be compared as unsigned longs. - */ - if (addr < (unsigned long)start) - /* negative offsets: [start; origin) */ - stop = origin; - else - /* positive offsets: [origin; stop) */ - start = origin; - - /* prel31 for address relavive to start */ - addr_prel31 = (addr - (unsigned long)start) & 0x7fffffff; - - while (start < stop - 1) { - const struct unwind_idx *mid = start + ((stop - start) >> 1); - - /* - * As addr_prel31 is relative to start an offset is needed to - * make it relative to mid. - */ - if (addr_prel31 - ((unsigned long)mid - (unsigned long)start) < - mid->addr_offset) - stop = mid; - else { - /* keep addr_prel31 relative to start */ - addr_prel31 -= ((unsigned long)mid - - (unsigned long)start); - start = mid; - } - } - - if (likely(start->addr_offset <= addr_prel31)) - return start; - else { - pr_warning("unwind: Unknown symbol address %08lx\n", addr); - return NULL; - } -} - -static const struct unwind_idx *unwind_find_origin( - const struct unwind_idx *start, const struct unwind_idx *stop) -{ - pr_debug("%s(%p, %p)\n", __func__, start, stop); - while (start < stop) { - const struct unwind_idx *mid = start + ((stop - start) >> 1); - - if (mid->addr_offset >= 0x40000000) - /* negative offset */ - start = mid + 1; - else - /* positive offset */ - stop = mid; - } - pr_debug("%s -> %p\n", __func__, stop); - return stop; -} - -static const struct unwind_idx *unwind_find_idx(unsigned long addr) -{ - const struct unwind_idx *idx = NULL; - unsigned long flags; - - pr_debug("%s(%08lx)\n", __func__, addr); - - if (core_kernel_text(addr)) { - if (unlikely(!__origin_unwind_idx)) - __origin_unwind_idx = - unwind_find_origin(__start_unwind_idx, - __stop_unwind_idx); - - /* main unwind table */ - idx = search_index(addr, __start_unwind_idx, - __origin_unwind_idx, - __stop_unwind_idx); - } else { - /* module unwind tables */ - struct unwind_table *table; - - spin_lock_irqsave(&unwind_lock, flags); - list_for_each_entry(table, &unwind_tables, list) { - if (addr >= table->begin_addr && - addr < table->end_addr) { - idx = search_index(addr, table->start, - table->origin, - table->stop); - /* Move-to-front to exploit common traces */ - list_move(&table->list, &unwind_tables); - break; - } - } - spin_unlock_irqrestore(&unwind_lock, flags); - } - - pr_debug("%s: idx = %p\n", __func__, idx); - return idx; -} - -static unsigned long unwind_get_byte(struct unwind_ctrl_block *ctrl) -{ - unsigned long ret; - - if (ctrl->entries <= 0) { - pr_warning("unwind: Corrupt unwind table\n"); - return 0; - } - - ret = (*ctrl->insn >> (ctrl->byte * 8)) & 0xff; - - if (ctrl->byte == 0) { - ctrl->insn++; - ctrl->entries--; - ctrl->byte = 3; - } else - ctrl->byte--; - - return ret; -} - -/* - * Execute the current unwind instruction. - */ -static int unwind_exec_insn(struct unwind_ctrl_block *ctrl) -{ - unsigned long insn = unwind_get_byte(ctrl); - - pr_debug("%s: insn = %08lx\n", __func__, insn); - - if ((insn & 0xc0) == 0x00) - ctrl->vrs[SP] += ((insn & 0x3f) << 2) + 4; - else if ((insn & 0xc0) == 0x40) - ctrl->vrs[SP] -= ((insn & 0x3f) << 2) + 4; - else if ((insn & 0xf0) == 0x80) { - unsigned long mask; - unsigned long *vsp = (unsigned long *)ctrl->vrs[SP]; - int load_sp, reg = 4; - - insn = (insn << 8) | unwind_get_byte(ctrl); - mask = insn & 0x0fff; - if (mask == 0) { - pr_warning("unwind: 'Refuse to unwind' instruction %04lx\n", - insn); - return -URC_FAILURE; - } - - /* pop R4-R15 according to mask */ - load_sp = mask & (1 << (13 - 4)); - while (mask) { - if (mask & 1) - ctrl->vrs[reg] = *vsp++; - mask >>= 1; - reg++; - } - if (!load_sp) - ctrl->vrs[SP] = (unsigned long)vsp; - } else if ((insn & 0xf0) == 0x90 && - (insn & 0x0d) != 0x0d) - ctrl->vrs[SP] = ctrl->vrs[insn & 0x0f]; - else if ((insn & 0xf0) == 0xa0) { - unsigned long *vsp = (unsigned long *)ctrl->vrs[SP]; - int reg; - - /* pop R4-R[4+bbb] */ - for (reg = 4; reg <= 4 + (insn & 7); reg++) - ctrl->vrs[reg] = *vsp++; - if (insn & 0x80) - ctrl->vrs[14] = *vsp++; - ctrl->vrs[SP] = (unsigned long)vsp; - } else if (insn == 0xb0) { - if (ctrl->vrs[PC] == 0) - ctrl->vrs[PC] = ctrl->vrs[LR]; - /* no further processing */ - ctrl->entries = 0; - } else if (insn == 0xb1) { - unsigned long mask = unwind_get_byte(ctrl); - unsigned long *vsp = (unsigned long *)ctrl->vrs[SP]; - int reg = 0; - - if (mask == 0 || mask & 0xf0) { - pr_warning("unwind: Spare encoding %04lx\n", - (insn << 8) | mask); - return -URC_FAILURE; - } - - /* pop R0-R3 according to mask */ - while (mask) { - if (mask & 1) - ctrl->vrs[reg] = *vsp++; - mask >>= 1; - reg++; - } - ctrl->vrs[SP] = (unsigned long)vsp; - } else if (insn == 0xb2) { - unsigned long uleb128 = unwind_get_byte(ctrl); - - ctrl->vrs[SP] += 0x204 + (uleb128 << 2); - } else { - pr_warning("unwind: Unhandled instruction %02lx\n", insn); - return -URC_FAILURE; - } - - pr_debug("%s: fp = %08lx sp = %08lx lr = %08lx pc = %08lx\n", __func__, - ctrl->vrs[FP], ctrl->vrs[SP], ctrl->vrs[LR], ctrl->vrs[PC]); - - return URC_OK; -} - -/* - * Unwind a single frame starting with *sp for the symbol at *pc. It - * updates the *pc and *sp with the new values. - */ -int unwind_frame(struct stackframe *frame) -{ - unsigned long high, low; - const struct unwind_idx *idx; - struct unwind_ctrl_block ctrl; - - /* only go to a higher address on the stack */ - low = frame->sp; - high = ALIGN(low, THREAD_SIZE); - - pr_debug("%s(pc = %08lx lr = %08lx sp = %08lx)\n", __func__, - frame->pc, frame->lr, frame->sp); - - if (!kernel_text_address(frame->pc)) - return -URC_FAILURE; - - idx = unwind_find_idx(frame->pc); - if (!idx) { - pr_warning("unwind: Index not found %08lx\n", frame->pc); - return -URC_FAILURE; - } - - ctrl.vrs[FP] = frame->fp; - ctrl.vrs[SP] = frame->sp; - ctrl.vrs[LR] = frame->lr; - ctrl.vrs[PC] = 0; - - if (idx->insn == 1) - /* can't unwind */ - return -URC_FAILURE; - else if ((idx->insn & 0x80000000) == 0) - /* prel31 to the unwind table */ - ctrl.insn = (unsigned long *)prel31_to_addr(&idx->insn); - else if ((idx->insn & 0xff000000) == 0x80000000) - /* only personality routine 0 supported in the index */ - ctrl.insn = &idx->insn; - else { - pr_warning("unwind: Unsupported personality routine %08lx in the index at %p\n", - idx->insn, idx); - return -URC_FAILURE; - } - - /* check the personality routine */ - if ((*ctrl.insn & 0xff000000) == 0x80000000) { - ctrl.byte = 2; - ctrl.entries = 1; - } else if ((*ctrl.insn & 0xff000000) == 0x81000000) { - ctrl.byte = 1; - ctrl.entries = 1 + ((*ctrl.insn & 0x00ff0000) >> 16); - } else { - pr_warning("unwind: Unsupported personality routine %08lx at %p\n", - *ctrl.insn, ctrl.insn); - return -URC_FAILURE; - } - - while (ctrl.entries > 0) { - int urc = unwind_exec_insn(&ctrl); - if (urc < 0) - return urc; - if (ctrl.vrs[SP] < low || ctrl.vrs[SP] >= high) - return -URC_FAILURE; - } - - if (ctrl.vrs[PC] == 0) - ctrl.vrs[PC] = ctrl.vrs[LR]; - - /* check for infinite loop */ - if (frame->pc == ctrl.vrs[PC]) - return -URC_FAILURE; - - frame->fp = ctrl.vrs[FP]; - frame->sp = ctrl.vrs[SP]; - frame->lr = ctrl.vrs[LR]; - frame->pc = ctrl.vrs[PC]; - - return URC_OK; -} - -void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) -{ - struct stackframe frame; - register unsigned long current_sp asm ("sp"); - - pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); - - if (!tsk) - tsk = current; - - if (regs) { - frame.fp = regs->ARM_fp; - frame.sp = regs->ARM_sp; - frame.lr = regs->ARM_lr; - /* PC might be corrupted, use LR in that case. */ - frame.pc = kernel_text_address(regs->ARM_pc) - ? regs->ARM_pc : regs->ARM_lr; - } else if (tsk == current) { - frame.fp = (unsigned long)__builtin_frame_address(0); - frame.sp = current_sp; - frame.lr = (unsigned long)__builtin_return_address(0); - frame.pc = (unsigned long)unwind_backtrace; - } else { - /* task blocked in __switch_to */ - frame.fp = thread_saved_fp(tsk); - frame.sp = thread_saved_sp(tsk); - /* - * The function calling __switch_to cannot be a leaf function - * so LR is recovered from the stack. - */ - frame.lr = 0; - frame.pc = thread_saved_pc(tsk); - } - - while (1) { - int urc; - unsigned long where = frame.pc; - - urc = unwind_frame(&frame); - if (urc < 0) - break; - dump_backtrace_entry(where, frame.pc, frame.sp - 4); - } -} - -struct unwind_table *unwind_table_add(unsigned long start, unsigned long size, - unsigned long text_addr, - unsigned long text_size) -{ - unsigned long flags; - struct unwind_table *tab = kmalloc(sizeof(*tab), GFP_KERNEL); - - pr_debug("%s(%08lx, %08lx, %08lx, %08lx)\n", __func__, start, size, - text_addr, text_size); - - if (!tab) - return tab; - - tab->start = (const struct unwind_idx *)start; - tab->stop = (const struct unwind_idx *)(start + size); - tab->origin = unwind_find_origin(tab->start, tab->stop); - tab->begin_addr = text_addr; - tab->end_addr = text_addr + text_size; - - spin_lock_irqsave(&unwind_lock, flags); - list_add_tail(&tab->list, &unwind_tables); - spin_unlock_irqrestore(&unwind_lock, flags); - - return tab; -} - -void unwind_table_del(struct unwind_table *tab) -{ - unsigned long flags; - - if (!tab) - return; - - spin_lock_irqsave(&unwind_lock, flags); - list_del(&tab->list); - spin_unlock_irqrestore(&unwind_lock, flags); - - kfree(tab); -} diff --git a/ANDROID_3.4.5/arch/arm/kernel/vmlinux.lds.S b/ANDROID_3.4.5/arch/arm/kernel/vmlinux.lds.S deleted file mode 100644 index 43a31fb0..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/vmlinux.lds.S +++ /dev/null @@ -1,312 +0,0 @@ -/* ld script to make ARM Linux kernel - * taken from the i386 version by Russell King - * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz> - */ - -#include <asm-generic/vmlinux.lds.h> -#include <asm/cache.h> -#include <asm/thread_info.h> -#include <asm/memory.h> -#include <asm/page.h> - -#define PROC_INFO \ - . = ALIGN(4); \ - VMLINUX_SYMBOL(__proc_info_begin) = .; \ - *(.proc.info.init) \ - VMLINUX_SYMBOL(__proc_info_end) = .; - -#define IDMAP_TEXT \ - ALIGN_FUNCTION(); \ - VMLINUX_SYMBOL(__idmap_text_start) = .; \ - *(.idmap.text) \ - VMLINUX_SYMBOL(__idmap_text_end) = .; - -#ifdef CONFIG_HOTPLUG_CPU -#define ARM_CPU_DISCARD(x) -#define ARM_CPU_KEEP(x) x -#else -#define ARM_CPU_DISCARD(x) x -#define ARM_CPU_KEEP(x) -#endif - -#if (defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)) || \ - defined(CONFIG_GENERIC_BUG) -#define ARM_EXIT_KEEP(x) x -#define ARM_EXIT_DISCARD(x) -#else -#define ARM_EXIT_KEEP(x) -#define ARM_EXIT_DISCARD(x) x -#endif - -OUTPUT_ARCH(arm) -ENTRY(stext) - -#ifndef __ARMEB__ -jiffies = jiffies_64; -#else -jiffies = jiffies_64 + 4; -#endif - -SECTIONS -{ - /* - * XXX: The linker does not define how output sections are - * assigned to input sections when there are multiple statements - * matching the same input section name. There is no documented - * order of matching. - * - * unwind exit sections must be discarded before the rest of the - * unwind sections get included. - */ - /DISCARD/ : { - *(.ARM.exidx.exit.text) - *(.ARM.extab.exit.text) - ARM_CPU_DISCARD(*(.ARM.exidx.cpuexit.text)) - ARM_CPU_DISCARD(*(.ARM.extab.cpuexit.text)) - ARM_EXIT_DISCARD(EXIT_TEXT) - ARM_EXIT_DISCARD(EXIT_DATA) - EXIT_CALL -#ifndef CONFIG_HOTPLUG - *(.ARM.exidx.devexit.text) - *(.ARM.extab.devexit.text) -#endif -#ifndef CONFIG_MMU - *(.fixup) - *(__ex_table) -#endif -#ifndef CONFIG_SMP_ON_UP - *(.alt.smp.init) -#endif - *(.discard) - *(.discard.*) - } - -#ifdef CONFIG_XIP_KERNEL - . = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR); -#else - . = PAGE_OFFSET + TEXT_OFFSET; -#endif - .head.text : { - _text = .; - HEAD_TEXT - } - .text : { /* Real text segment */ - _stext = .; /* Text and read-only data */ - __exception_text_start = .; - *(.exception.text) - __exception_text_end = .; - IRQENTRY_TEXT - TEXT_TEXT - SCHED_TEXT - LOCK_TEXT - KPROBES_TEXT - IDMAP_TEXT -#ifdef CONFIG_MMU - *(.fixup) -#endif - *(.gnu.warning) - *(.glue_7) - *(.glue_7t) - . = ALIGN(4); - *(.got) /* Global offset table */ - ARM_CPU_KEEP(PROC_INFO) - } - - RO_DATA(PAGE_SIZE) - -#ifdef CONFIG_ARM_UNWIND - /* - * Stack unwinding tables - */ - . = ALIGN(8); - .ARM.unwind_idx : { - __start_unwind_idx = .; - *(.ARM.exidx*) - __stop_unwind_idx = .; - } - .ARM.unwind_tab : { - __start_unwind_tab = .; - *(.ARM.extab*) - __stop_unwind_tab = .; - } -#endif - - _etext = .; /* End of text and rodata section */ - -#ifndef CONFIG_XIP_KERNEL - . = ALIGN(PAGE_SIZE); - __init_begin = .; -#endif - - INIT_TEXT_SECTION(8) - .exit.text : { - ARM_EXIT_KEEP(EXIT_TEXT) - } - .init.proc.info : { - ARM_CPU_DISCARD(PROC_INFO) - } - .init.arch.info : { - __arch_info_begin = .; - *(.arch.info.init) - __arch_info_end = .; - } - .init.tagtable : { - __tagtable_begin = .; - *(.taglist.init) - __tagtable_end = .; - } -#ifdef CONFIG_SMP_ON_UP - .init.smpalt : { - __smpalt_begin = .; - *(.alt.smp.init) - __smpalt_end = .; - } -#endif - .init.pv_table : { - __pv_table_begin = .; - *(.pv_table) - __pv_table_end = .; - } - .init.data : { -#ifndef CONFIG_XIP_KERNEL - INIT_DATA -#endif - INIT_SETUP(16) - INIT_CALLS - CON_INITCALL - SECURITY_INITCALL - INIT_RAM_FS - } -#ifndef CONFIG_XIP_KERNEL - .exit.data : { - ARM_EXIT_KEEP(EXIT_DATA) - } -#endif - - PERCPU_SECTION(L1_CACHE_BYTES) - -#ifdef CONFIG_XIP_KERNEL - __data_loc = ALIGN(4); /* location in binary */ - . = PAGE_OFFSET + TEXT_OFFSET; -#else - __init_end = .; - . = ALIGN(THREAD_SIZE); - __data_loc = .; -#endif - - .data : AT(__data_loc) { - _data = .; /* address in memory */ - _sdata = .; - - /* - * first, the init task union, aligned - * to an 8192 byte boundary. - */ - INIT_TASK_DATA(THREAD_SIZE) - -#ifdef CONFIG_XIP_KERNEL - . = ALIGN(PAGE_SIZE); - __init_begin = .; - INIT_DATA - ARM_EXIT_KEEP(EXIT_DATA) - . = ALIGN(PAGE_SIZE); - __init_end = .; -#endif - - NOSAVE_DATA - CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES) - READ_MOSTLY_DATA(L1_CACHE_BYTES) - - /* - * The exception fixup table (might need resorting at runtime) - */ - . = ALIGN(4); - __start___ex_table = .; -#ifdef CONFIG_MMU - *(__ex_table) -#endif - __stop___ex_table = .; - - /* - * and the usual data section - */ - DATA_DATA - CONSTRUCTORS - - _edata = .; - } - _edata_loc = __data_loc + SIZEOF(.data); - -#ifdef CONFIG_HAVE_TCM - /* - * We align everything to a page boundary so we can - * free it after init has commenced and TCM contents have - * been copied to its destination. - */ - .tcm_start : { - . = ALIGN(PAGE_SIZE); - __tcm_start = .; - __itcm_start = .; - } - - /* - * Link these to the ITCM RAM - * Put VMA to the TCM address and LMA to the common RAM - * and we'll upload the contents from RAM to TCM and free - * the used RAM after that. - */ - .text_itcm ITCM_OFFSET : AT(__itcm_start) - { - __sitcm_text = .; - *(.tcm.text) - *(.tcm.rodata) - . = ALIGN(4); - __eitcm_text = .; - } - - /* - * Reset the dot pointer, this is needed to create the - * relative __dtcm_start below (to be used as extern in code). - */ - . = ADDR(.tcm_start) + SIZEOF(.tcm_start) + SIZEOF(.text_itcm); - - .dtcm_start : { - __dtcm_start = .; - } - - /* TODO: add remainder of ITCM as well, that can be used for data! */ - .data_dtcm DTCM_OFFSET : AT(__dtcm_start) - { - . = ALIGN(4); - __sdtcm_data = .; - *(.tcm.data) - . = ALIGN(4); - __edtcm_data = .; - } - - /* Reset the dot pointer or the linker gets confused */ - . = ADDR(.dtcm_start) + SIZEOF(.data_dtcm); - - /* End marker for freeing TCM copy in linked object */ - .tcm_end : AT(ADDR(.dtcm_start) + SIZEOF(.data_dtcm)){ - . = ALIGN(PAGE_SIZE); - __tcm_end = .; - } -#endif - - NOTES - - BSS_SECTION(0, 0, 0) - _end = .; - - STABS_DEBUG - .comment 0 : { *(.comment) } -} - -/* - * These must never be empty - * If you have to comment these two assert statements out, your - * binutils is too old (for other reasons as well) - */ -ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support") -ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined") diff --git a/ANDROID_3.4.5/arch/arm/kernel/xscale-cp0.c b/ANDROID_3.4.5/arch/arm/kernel/xscale-cp0.c deleted file mode 100644 index e42adc6b..00000000 --- a/ANDROID_3.4.5/arch/arm/kernel/xscale-cp0.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * linux/arch/arm/kernel/xscale-cp0.c - * - * XScale DSP and iWMMXt coprocessor context switching and handling - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/signal.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/io.h> -#include <asm/thread_notify.h> - -static inline void dsp_save_state(u32 *state) -{ - __asm__ __volatile__ ( - "mrrc p0, 0, %0, %1, c0\n" - : "=r" (state[0]), "=r" (state[1])); -} - -static inline void dsp_load_state(u32 *state) -{ - __asm__ __volatile__ ( - "mcrr p0, 0, %0, %1, c0\n" - : : "r" (state[0]), "r" (state[1])); -} - -static int dsp_do(struct notifier_block *self, unsigned long cmd, void *t) -{ - struct thread_info *thread = t; - - switch (cmd) { - case THREAD_NOTIFY_FLUSH: - thread->cpu_context.extra[0] = 0; - thread->cpu_context.extra[1] = 0; - break; - - case THREAD_NOTIFY_SWITCH: - dsp_save_state(current_thread_info()->cpu_context.extra); - dsp_load_state(thread->cpu_context.extra); - break; - } - - return NOTIFY_DONE; -} - -static struct notifier_block dsp_notifier_block = { - .notifier_call = dsp_do, -}; - - -#ifdef CONFIG_IWMMXT -static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t) -{ - struct thread_info *thread = t; - - switch (cmd) { - case THREAD_NOTIFY_FLUSH: - /* - * flush_thread() zeroes thread->fpstate, so no need - * to do anything here. - * - * FALLTHROUGH: Ensure we don't try to overwrite our newly - * initialised state information on the first fault. - */ - - case THREAD_NOTIFY_EXIT: - iwmmxt_task_release(thread); - break; - - case THREAD_NOTIFY_SWITCH: - iwmmxt_task_switch(thread); - break; - } - - return NOTIFY_DONE; -} - -static struct notifier_block iwmmxt_notifier_block = { - .notifier_call = iwmmxt_do, -}; -#endif - - -static u32 __init xscale_cp_access_read(void) -{ - u32 value; - - __asm__ __volatile__ ( - "mrc p15, 0, %0, c15, c1, 0\n\t" - : "=r" (value)); - - return value; -} - -static void __init xscale_cp_access_write(u32 value) -{ - u32 temp; - - __asm__ __volatile__ ( - "mcr p15, 0, %1, c15, c1, 0\n\t" - "mrc p15, 0, %0, c15, c1, 0\n\t" - "mov %0, %0\n\t" - "sub pc, pc, #4\n\t" - : "=r" (temp) : "r" (value)); -} - -/* - * Detect whether we have a MAC coprocessor (40 bit register) or an - * iWMMXt coprocessor (64 bit registers) by loading 00000100:00000000 - * into a coprocessor register and reading it back, and checking - * whether the upper word survived intact. - */ -static int __init cpu_has_iwmmxt(void) -{ - u32 lo; - u32 hi; - - /* - * This sequence is interpreted by the DSP coprocessor as: - * mar acc0, %2, %3 - * mra %0, %1, acc0 - * - * And by the iWMMXt coprocessor as: - * tmcrr wR0, %2, %3 - * tmrrc %0, %1, wR0 - */ - __asm__ __volatile__ ( - "mcrr p0, 0, %2, %3, c0\n" - "mrrc p0, 0, %0, %1, c0\n" - : "=r" (lo), "=r" (hi) - : "r" (0), "r" (0x100)); - - return !!hi; -} - - -/* - * If we detect that the CPU has iWMMXt (and CONFIG_IWMMXT=y), we - * disable CP0/CP1 on boot, and let call_fpe() and the iWMMXt lazy - * switch code handle iWMMXt context switching. If on the other - * hand the CPU has a DSP coprocessor, we keep access to CP0 enabled - * all the time, and save/restore acc0 on context switch in non-lazy - * fashion. - */ -static int __init xscale_cp0_init(void) -{ - u32 cp_access; - - cp_access = xscale_cp_access_read() & ~3; - xscale_cp_access_write(cp_access | 1); - - if (cpu_has_iwmmxt()) { -#ifndef CONFIG_IWMMXT - printk(KERN_WARNING "CAUTION: XScale iWMMXt coprocessor " - "detected, but kernel support is missing.\n"); -#else - printk(KERN_INFO "XScale iWMMXt coprocessor detected.\n"); - elf_hwcap |= HWCAP_IWMMXT; - thread_register_notifier(&iwmmxt_notifier_block); -#endif - } else { - printk(KERN_INFO "XScale DSP coprocessor detected.\n"); - thread_register_notifier(&dsp_notifier_block); - cp_access |= 1; - } - - xscale_cp_access_write(cp_access); - - return 0; -} - -late_initcall(xscale_cp0_init); |