From d6d55f0b9d900673548515614b56ab55aa2c51f8 Mon Sep 17 00:00:00 2001 From: Jacob Shin Date: Thu, 29 May 2014 17:26:50 +0200 Subject: perf/x86/amd: AMD support for bp_len > HW_BREAKPOINT_LEN_8 Implement hardware breakpoint address mask for AMD Family 16h and above processors. CPUID feature bit indicates hardware support for DRn_ADDR_MASK MSRs. These masks further qualify DRn/DR7 hardware breakpoint addresses to allow matching of larger addresses ranges. Valuable advice and pseudo code from Oleg Nesterov Signed-off-by: Jacob Shin Signed-off-by: Suravee Suthikulpanit Acked-by: Jiri Olsa Reviewed-by: Oleg Nesterov Cc: Arnaldo Carvalho de Melo Cc: Ingo Molnar Cc: Namhyung Kim Cc: Peter Zijlstra Cc: xiakaixu Signed-off-by: Frederic Weisbecker --- arch/x86/include/asm/cpufeature.h | 2 ++ arch/x86/include/asm/debugreg.h | 5 +++++ arch/x86/include/asm/hw_breakpoint.h | 1 + arch/x86/include/uapi/asm/msr-index.h | 4 ++++ arch/x86/kernel/cpu/amd.c | 19 +++++++++++++++++++ arch/x86/kernel/hw_breakpoint.c | 20 ++++++++++++++++---- 6 files changed, 47 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 0bb1335313b2..53966d65591e 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -174,6 +174,7 @@ #define X86_FEATURE_TOPOEXT ( 6*32+22) /* topology extensions CPUID leafs */ #define X86_FEATURE_PERFCTR_CORE ( 6*32+23) /* core performance counter extensions */ #define X86_FEATURE_PERFCTR_NB ( 6*32+24) /* NB performance counter extensions */ +#define X86_FEATURE_BPEXT (6*32+26) /* data breakpoint extension */ #define X86_FEATURE_PERFCTR_L2 ( 6*32+28) /* L2 performance counter extensions */ /* @@ -383,6 +384,7 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; #define cpu_has_cx16 boot_cpu_has(X86_FEATURE_CX16) #define cpu_has_eager_fpu boot_cpu_has(X86_FEATURE_EAGER_FPU) #define cpu_has_topoext boot_cpu_has(X86_FEATURE_TOPOEXT) +#define cpu_has_bpext boot_cpu_has(X86_FEATURE_BPEXT) #if __GNUC__ >= 4 extern void warn_pre_alternatives(void); diff --git a/arch/x86/include/asm/debugreg.h b/arch/x86/include/asm/debugreg.h index 61fd18b83b6c..12cb66f6d3a5 100644 --- a/arch/x86/include/asm/debugreg.h +++ b/arch/x86/include/asm/debugreg.h @@ -114,5 +114,10 @@ static inline void debug_stack_usage_inc(void) { } static inline void debug_stack_usage_dec(void) { } #endif /* X86_64 */ +#ifdef CONFIG_CPU_SUP_AMD +extern void set_dr_addr_mask(unsigned long mask, int dr); +#else +static inline void set_dr_addr_mask(unsigned long mask, int dr) { } +#endif #endif /* _ASM_X86_DEBUGREG_H */ diff --git a/arch/x86/include/asm/hw_breakpoint.h b/arch/x86/include/asm/hw_breakpoint.h index ef1c4d2d41ec..6c98be864a75 100644 --- a/arch/x86/include/asm/hw_breakpoint.h +++ b/arch/x86/include/asm/hw_breakpoint.h @@ -12,6 +12,7 @@ */ struct arch_hw_breakpoint { unsigned long address; + unsigned long mask; u8 len; u8 type; }; diff --git a/arch/x86/include/uapi/asm/msr-index.h b/arch/x86/include/uapi/asm/msr-index.h index 8f02f6990759..b1fb4fae03d3 100644 --- a/arch/x86/include/uapi/asm/msr-index.h +++ b/arch/x86/include/uapi/asm/msr-index.h @@ -212,6 +212,10 @@ /* Fam 16h MSRs */ #define MSR_F16H_L2I_PERF_CTL 0xc0010230 #define MSR_F16H_L2I_PERF_CTR 0xc0010231 +#define MSR_F16H_DR1_ADDR_MASK 0xc0011019 +#define MSR_F16H_DR2_ADDR_MASK 0xc001101a +#define MSR_F16H_DR3_ADDR_MASK 0xc001101b +#define MSR_F16H_DR0_ADDR_MASK 0xc0011027 /* Fam 15h MSRs */ #define MSR_F15H_PERF_CTL 0xc0010200 diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 813d29d00a17..abe4ec760db3 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -870,3 +870,22 @@ static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum) return false; } + +void set_dr_addr_mask(unsigned long mask, int dr) +{ + if (!cpu_has_bpext) + return; + + switch (dr) { + case 0: + wrmsr(MSR_F16H_DR0_ADDR_MASK, mask, 0); + break; + case 1: + case 2: + case 3: + wrmsr(MSR_F16H_DR1_ADDR_MASK - 1 + dr, mask, 0); + break; + default: + break; + } +} diff --git a/arch/x86/kernel/hw_breakpoint.c b/arch/x86/kernel/hw_breakpoint.c index 3d5fb509bdeb..b5cb0c59ea87 100644 --- a/arch/x86/kernel/hw_breakpoint.c +++ b/arch/x86/kernel/hw_breakpoint.c @@ -126,6 +126,8 @@ int arch_install_hw_breakpoint(struct perf_event *bp) *dr7 |= encode_dr7(i, info->len, info->type); set_debugreg(*dr7, 7); + if (info->mask) + set_dr_addr_mask(info->mask, i); return 0; } @@ -161,6 +163,8 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp) *dr7 &= ~__encode_dr7(i, info->len, info->type); set_debugreg(*dr7, 7); + if (info->mask) + set_dr_addr_mask(0, i); } static int get_hbp_len(u8 hbp_len) @@ -277,6 +281,8 @@ static int arch_build_bp_info(struct perf_event *bp) } /* Len */ + info->mask = 0; + switch (bp->attr.bp_len) { case HW_BREAKPOINT_LEN_1: info->len = X86_BREAKPOINT_LEN_1; @@ -293,11 +299,17 @@ static int arch_build_bp_info(struct perf_event *bp) break; #endif default: - return -EINVAL; + if (!is_power_of_2(bp->attr.bp_len)) + return -EINVAL; + if (!cpu_has_bpext) + return -EOPNOTSUPP; + info->mask = bp->attr.bp_len - 1; + info->len = X86_BREAKPOINT_LEN_1; } return 0; } + /* * Validate the arch-specific HW Breakpoint register settings */ @@ -312,11 +324,11 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) if (ret) return ret; - ret = -EINVAL; - switch (info->len) { case X86_BREAKPOINT_LEN_1: align = 0; + if (info->mask) + align = info->mask; break; case X86_BREAKPOINT_LEN_2: align = 1; @@ -330,7 +342,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) break; #endif default: - return ret; + WARN_ON_ONCE(1); } /* -- cgit v1.2.3 From 36748b9518a2437beffe861b47dff6d12b736b3f Mon Sep 17 00:00:00 2001 From: Jacob Shin Date: Thu, 29 May 2014 17:26:53 +0200 Subject: perf/x86: Remove get_hbp_len and replace with bp_len Clean up the logic for determining the breakpoint length Signed-off-by: Jacob Shin Signed-off-by: Suravee Suthikulpanit Acked-by: Jiri Olsa Reviewed-by: Oleg Nesterov Cc: Arnaldo Carvalho de Melo Cc: Ingo Molnar Cc: Namhyung Kim Cc: Peter Zijlstra Cc: xiakaixu Signed-off-by: Frederic Weisbecker --- arch/x86/kernel/hw_breakpoint.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/hw_breakpoint.c b/arch/x86/kernel/hw_breakpoint.c index b5cb0c59ea87..7114ba220fd4 100644 --- a/arch/x86/kernel/hw_breakpoint.c +++ b/arch/x86/kernel/hw_breakpoint.c @@ -167,29 +167,6 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp) set_dr_addr_mask(0, i); } -static int get_hbp_len(u8 hbp_len) -{ - unsigned int len_in_bytes = 0; - - switch (hbp_len) { - case X86_BREAKPOINT_LEN_1: - len_in_bytes = 1; - break; - case X86_BREAKPOINT_LEN_2: - len_in_bytes = 2; - break; - case X86_BREAKPOINT_LEN_4: - len_in_bytes = 4; - break; -#ifdef CONFIG_X86_64 - case X86_BREAKPOINT_LEN_8: - len_in_bytes = 8; - break; -#endif - } - return len_in_bytes; -} - /* * Check for virtual address in kernel space. */ @@ -200,7 +177,7 @@ int arch_check_bp_in_kernelspace(struct perf_event *bp) struct arch_hw_breakpoint *info = counter_arch_bp(bp); va = info->address; - len = get_hbp_len(info->len); + len = bp->attr.bp_len; return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE); } -- cgit v1.2.3 From d91525eb8ee6a622ce476955fe1a2530ade87c83 Mon Sep 17 00:00:00 2001 From: "Chen, Gong" Date: Wed, 10 Dec 2014 13:53:26 -0800 Subject: ACPI, EINJ: Enhance error injection tolerance level Some BIOSes utilize PCI MMCFG space read/write opertion to trigger specific errors. EINJ will report errors as below when hitting such cases: APEI: Can not request [mem 0x83f990a0-0x83f990a3] for APEI EINJ Trigger registers It is because on x86 platform ACPI based PCI MMCFG logic has reserved all MMCFG spaces so that EINJ can't reserve it again. We already trust the ACPI/APEI code when using the EINJ interface so it is not a big leap to also trust it to access the right MMCFG addresses. Skip address checking to allow the access. Signed-off-by: Chen, Gong Signed-off-by: Tony Luck --- arch/x86/pci/mmconfig-shared.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'arch') diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 326198a4434e..676e5e04e4d4 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c @@ -610,6 +610,32 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header) return 0; } +#ifdef CONFIG_ACPI_APEI +extern int (*arch_apei_filter_addr)(int (*func)(__u64 start, __u64 size, + void *data), void *data); + +static int pci_mmcfg_for_each_region(int (*func)(__u64 start, __u64 size, + void *data), void *data) +{ + struct pci_mmcfg_region *cfg; + int rc; + + if (list_empty(&pci_mmcfg_list)) + return 0; + + list_for_each_entry(cfg, &pci_mmcfg_list, list) { + rc = func(cfg->res.start, resource_size(&cfg->res), data); + if (rc) + return rc; + } + + return 0; +} +#define set_apei_filter() (arch_apei_filter_addr = pci_mmcfg_for_each_region) +#else +#define set_apei_filter() +#endif + static void __init __pci_mmcfg_init(int early) { pci_mmcfg_reject_broken(early); @@ -644,6 +670,8 @@ void __init pci_mmcfg_early_init(void) else acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg); __pci_mmcfg_init(1); + + set_apei_filter(); } } -- cgit v1.2.3 From e7ddf4b7b3c5fe64902c4fb9edac92532c87cd75 Mon Sep 17 00:00:00 2001 From: Srinidhi Kasagar Date: Fri, 19 Dec 2014 23:13:51 +0530 Subject: cpufreq: Add SFI based cpufreq driver support This adds the SFI based cpu freq driver for some of the Intel's Silvermont based Atom architectures like Z34xx and Z35xx. Signed-off-by: Rudramuni, Vishwesh M Signed-off-by: Srinidhi Kasagar Acked-by: Viresh Kumar Signed-off-by: Len Brown --- arch/x86/include/uapi/asm/msr-index.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/x86/include/uapi/asm/msr-index.h b/arch/x86/include/uapi/asm/msr-index.h index e21331ce368f..4f6dae67dd10 100644 --- a/arch/x86/include/uapi/asm/msr-index.h +++ b/arch/x86/include/uapi/asm/msr-index.h @@ -318,6 +318,7 @@ #define MSR_IA32_PERF_STATUS 0x00000198 #define MSR_IA32_PERF_CTL 0x00000199 +#define INTEL_PERF_CTL_MASK 0xffff #define MSR_AMD_PSTATE_DEF_BASE 0xc0010064 #define MSR_AMD_PERF_STATUS 0xc0010063 #define MSR_AMD_PERF_CTL 0xc0010062 -- cgit v1.2.3 From ca8bfc97ca7795f86e5b25553dd19d96b252bb29 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 25 Nov 2014 16:24:59 +0100 Subject: ARM: shmobile: kzm9g_defconfig: Update AK8975 config option CONFIG_SENSORS_AK8975 was renamed to CONFIG_AK8975 in commit 2fc72cd8354e3e9c ("iio:magnetometer:ak8975 move driver out of staging") in v3.10. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/configs/kzm9g_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig index 5d63fc5d2d48..23e8d146dc16 100644 --- a/arch/arm/configs/kzm9g_defconfig +++ b/arch/arm/configs/kzm9g_defconfig @@ -126,8 +126,8 @@ CONFIG_DMADEVICES=y CONFIG_SH_DMAE=y CONFIG_ASYNC_TX_DMA=y CONFIG_STAGING=y -CONFIG_SENSORS_AK8975=y CONFIG_IIO=y +CONFIG_AK8975=y # CONFIG_DNOTIFY is not set CONFIG_VFAT_FS=y CONFIG_TMPFS=y -- cgit v1.2.3 From ff550a37cda1f8ef9f383b456a9403c9e636fc9e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 4 Dec 2014 03:57:36 +0000 Subject: ARM: shmobile: defconfig: cleanup by savedefconfig Current shmobile_defconfig is not created from savedefconfig. Therefore, next defconfig patch will be unreadable. this patch tidyup this issue by below command > make shmobile_defconfig > make savedefconfig > cp defconfig ${LINUX}/arch/arm/config/shmobile_defconfig Signed-off-by: Kuninori Morimoto Acked-by: Geert Uytterhoeven [horms: Resolved conflicts; in particular leaving CONFIG_CPUFREQ_DT enabled] Signed-off-by: Simon Horman --- arch/arm/configs/shmobile_defconfig | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig index 3df6ca0c1d1f..ad52868b4c2b 100644 --- a/arch/arm/configs/shmobile_defconfig +++ b/arch/arm/configs/shmobile_defconfig @@ -19,7 +19,6 @@ CONFIG_ARCH_R8A7791=y CONFIG_ARCH_R8A7794=y CONFIG_MACH_LAGER=y CONFIG_MACH_MARZEN=y -# CONFIG_SWP_EMULATE is not set CONFIG_CPU_BPREDICT_DISABLE=y CONFIG_PL310_ERRATA_588369=y CONFIG_ARM_ERRATA_754322=y @@ -36,6 +35,13 @@ CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_ARM_APPENDED_DTB=y CONFIG_KEXEC=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPUFREQ_DT=y CONFIG_VFP=y CONFIG_NEON=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set @@ -98,9 +104,10 @@ CONFIG_GPIO_EM=y CONFIG_GPIO_RCAR=y # CONFIG_HWMON is not set CONFIG_THERMAL=y +CONFIG_CPU_THERMAL=y CONFIG_RCAR_THERMAL=y CONFIG_REGULATOR=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_DA9210=y CONFIG_REGULATOR_GPIO=y CONFIG_MEDIA_SUPPORT=y CONFIG_MEDIA_CAMERA_SUPPORT=y @@ -154,7 +161,6 @@ CONFIG_PWM_RENESAS_TPU=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y -CONFIG_CONFIGFS_FS=y # CONFIG_MISC_FILESYSTEMS is not set CONFIG_NFS_FS=y CONFIG_NFS_V3_ACL=y @@ -166,16 +172,3 @@ CONFIG_NLS_ISO8859_1=y # CONFIG_ENABLE_WARN_DEPRECATED is not set # CONFIG_ENABLE_MUST_CHECK is not set # CONFIG_ARM_UNWIND is not set -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_GOV_COMMON=y -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_FREQ_STAT_DETAILS=y -CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPU_THERMAL=y -CONFIG_CPUFREQ_DT=y -CONFIG_REGULATOR_DA9210=y -- cgit v1.2.3 From 1df3396bd09baf4093f82a49f8a1a523277fdf82 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 4 Dec 2014 03:57:50 +0000 Subject: ARM: shmobile: defconfig: add MTD_BLOCK MTD_BLOOK is needed for accessing to SPI-FLASH Signed-off-by: Kuninori Morimoto Reported-by: Cao Minh Hiep Reported-by: Bui Duc Phuc ( Fukuda ) Reported-by: Nguyen Xuan Nui Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/configs/shmobile_defconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig index ad52868b4c2b..a936a2ea8621 100644 --- a/arch/arm/configs/shmobile_defconfig +++ b/arch/arm/configs/shmobile_defconfig @@ -56,6 +56,7 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_MTD=y +CONFIG_MTD_BLOCK=y CONFIG_MTD_M25P80=y CONFIG_MTD_SPI_NOR=y CONFIG_EEPROM_AT24=y -- cgit v1.2.3 From 174b7a54c925a068161222fadb45732453bd7efa Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 8 Dec 2014 12:35:24 +0100 Subject: ARM: shmobile: Enable MICREL_PHY in shmobile_defconfig commit 1c9106cb783cd227 ("ARM: shmobile: lager-reference: DTS-only board support"), dropped the MACH_LAGER Kconfig section, which did "select MICREL_PHY if SH_ETH". Hence we now have to enable MICREL_PHY explicitly in shmobile_defconfig. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/configs/shmobile_defconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig index a936a2ea8621..a9a1b0afc691 100644 --- a/arch/arm/configs/shmobile_defconfig +++ b/arch/arm/configs/shmobile_defconfig @@ -80,6 +80,7 @@ CONFIG_SMSC911X=y # CONFIG_NET_VENDOR_VIA is not set # CONFIG_NET_VENDOR_WIZNET is not set CONFIG_SMSC_PHY=y +CONFIG_MICREL_PHY=y # CONFIG_INPUT_MOUSEDEV_PSAUX is not set CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set -- cgit v1.2.3 From db54d850b686c2ca81c10dd3582e98ee089a0e3a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 9 Dec 2014 12:22:49 +0100 Subject: ARM: shmobile: Enable DA9063 watchdog in multiplatform defconfig This allows to restart koelsch on watchdog timeout or manual system restart request. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/configs/shmobile_defconfig | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig index a9a1b0afc691..99e122694f5e 100644 --- a/arch/arm/configs/shmobile_defconfig +++ b/arch/arm/configs/shmobile_defconfig @@ -108,6 +108,9 @@ CONFIG_GPIO_RCAR=y CONFIG_THERMAL=y CONFIG_CPU_THERMAL=y CONFIG_RCAR_THERMAL=y +CONFIG_WATCHDOG=y +CONFIG_DA9063_WATCHDOG=y +CONFIG_MFD_DA9063=y CONFIG_REGULATOR=y CONFIG_REGULATOR_DA9210=y CONFIG_REGULATOR_GPIO=y -- cgit v1.2.3 From 5f61ffb5cfd516c62bae69535e28b0085210b3ae Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 9 Dec 2014 12:24:59 +0100 Subject: ARM: shmobile: genmai dts: Replace status value "ok" by "okay" While the DT parsing code recognizes "ok" as a valid value for the "status" property, ePAPR v1.1 doesn't mention it in the list of valid values. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r7s72100-genmai.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r7s72100-genmai.dts b/arch/arm/boot/dts/r7s72100-genmai.dts index 1518c5bcca33..a9da7a89fc4b 100644 --- a/arch/arm/boot/dts/r7s72100-genmai.dts +++ b/arch/arm/boot/dts/r7s72100-genmai.dts @@ -45,7 +45,7 @@ }; &mtu2 { - status = "ok"; + status = "okay"; }; &i2c2 { -- cgit v1.2.3 From 16d3b8845ef3934a0586df5662254d54785d7741 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 9 Dec 2014 12:25:00 +0100 Subject: ARM: shmobile: armadillo800eva dts: Replace status value "ok" by "okay" While the DT parsing code recognizes "ok" as a valid value for the "status" property, ePAPR v1.1 doesn't mention it in the list of valid values. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7740-armadillo800eva.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts index d4af4d86c6b0..9bd0cb439f44 100644 --- a/arch/arm/boot/dts/r8a7740-armadillo800eva.dts +++ b/arch/arm/boot/dts/r8a7740-armadillo800eva.dts @@ -172,7 +172,7 @@ pinctrl-names = "default"; phy-handle = <&phy0>; - status = "ok"; + status = "okay"; phy0: ethernet-phy@0 { reg = <0>; @@ -193,7 +193,7 @@ }; &cmt1 { - status = "ok"; + status = "okay"; }; &i2c0 { -- cgit v1.2.3 From fd7a8cbf0eec4a4f4191a22c879e2f8258257ca6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 9 Dec 2014 12:25:01 +0100 Subject: ARM: shmobile: lager dts: Replace status value "ok" by "okay" While the DT parsing code recognizes "ok" as a valid value for the "status" property, ePAPR v1.1 doesn't mention it in the list of valid values. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790-lager.dts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts index 636d53bb87a2..56e66bb53657 100644 --- a/arch/arm/boot/dts/r8a7790-lager.dts +++ b/arch/arm/boot/dts/r8a7790-lager.dts @@ -355,7 +355,7 @@ phy-handle = <&phy1>; renesas,ether-link-active-low; - status = "ok"; + status = "okay"; phy1: ethernet-phy@1 { reg = <1>; @@ -366,7 +366,7 @@ }; &cmt0 { - status = "ok"; + status = "okay"; }; &mmcif1 { @@ -470,17 +470,17 @@ }; &iic0 { - status = "ok"; + status = "okay"; }; &iic1 { - status = "ok"; + status = "okay"; pinctrl-0 = <&iic1_pins>; pinctrl-names = "default"; }; &iic2 { - status = "ok"; + status = "okay"; pinctrl-0 = <&iic2_pins>; pinctrl-names = "default"; @@ -562,7 +562,7 @@ pinctrl-0 = <&vin1_pins>; pinctrl-names = "default"; - status = "ok"; + status = "okay"; port { #address-cells = <1>; -- cgit v1.2.3 From deb9eb3ea1e5fa685b53744f1ff291ee18118029 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 9 Dec 2014 12:25:02 +0100 Subject: ARM: shmobile: henninger dts: Replace status value "ok" by "okay" While the DT parsing code recognizes "ok" as a valid value for the "status" property, ePAPR v1.1 doesn't mention it in the list of valid values. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7791-henninger.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7791-henninger.dts b/arch/arm/boot/dts/r8a7791-henninger.dts index 740e38678032..d2ebf11f9881 100644 --- a/arch/arm/boot/dts/r8a7791-henninger.dts +++ b/arch/arm/boot/dts/r8a7791-henninger.dts @@ -156,7 +156,7 @@ phy-handle = <&phy1>; renesas,ether-link-active-low; - status = "ok"; + status = "okay"; phy1: ethernet-phy@1 { reg = <1>; @@ -293,7 +293,7 @@ /* composite video input */ &vin0 { - status = "ok"; + status = "okay"; pinctrl-0 = <&vin0_pins>; pinctrl-names = "default"; -- cgit v1.2.3 From 815446d624f692b197ec5dde00cf341196513e03 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 9 Dec 2014 12:25:03 +0100 Subject: ARM: shmobile: koelsch dts: Replace status value "ok" by "okay" While the DT parsing code recognizes "ok" as a valid value for the "status" property, ePAPR v1.1 doesn't mention it in the list of valid values. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7791-koelsch.dts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts index 990af167c551..e2faa6261058 100644 --- a/arch/arm/boot/dts/r8a7791-koelsch.dts +++ b/arch/arm/boot/dts/r8a7791-koelsch.dts @@ -366,7 +366,7 @@ phy-handle = <&phy1>; renesas,ether-link-active-low; - status = "ok"; + status = "okay"; phy1: ethernet-phy@1 { reg = <1>; @@ -377,7 +377,7 @@ }; &cmt0 { - status = "ok"; + status = "okay"; }; &sata0 { @@ -563,7 +563,7 @@ /* composite video input */ &vin1 { - status = "ok"; + status = "okay"; pinctrl-0 = <&vin1_pins>; pinctrl-names = "default"; -- cgit v1.2.3 From 38e02908f3a4bf261c618893649e88bc92197566 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 9 Dec 2014 12:25:04 +0100 Subject: ARM: shmobile: alt dts: Replace status value "ok" by "okay" While the DT parsing code recognizes "ok" as a valid value for the "status" property, ePAPR v1.1 doesn't mention it in the list of valid values. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7794-alt.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7794-alt.dts b/arch/arm/boot/dts/r8a7794-alt.dts index f2cf7576bf3f..0d848e605071 100644 --- a/arch/arm/boot/dts/r8a7794-alt.dts +++ b/arch/arm/boot/dts/r8a7794-alt.dts @@ -40,9 +40,9 @@ }; &cmt0 { - status = "ok"; + status = "okay"; }; &scif2 { - status = "ok"; + status = "okay"; }; -- cgit v1.2.3 From 338d1f0b5e877eae51c885da81d86b0efd6373e7 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 9 Dec 2014 12:25:05 +0100 Subject: ARM: shmobile: kzm9g-reference dts: Replace status value "ok" by "okay" While the DT parsing code recognizes "ok" as a valid value for the "status" property, ePAPR v1.1 doesn't mention it in the list of valid values. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/sh73a0-kzm9g-reference.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts index 939be1299ca6..863dc4c7d7f6 100644 --- a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts +++ b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts @@ -179,7 +179,7 @@ }; &cmt1 { - status = "ok"; + status = "okay"; }; &i2c0 { -- cgit v1.2.3 From b5c107f03b65e14a70d86654cf2427bdc7e4afe6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 2 Dec 2014 18:35:55 +0100 Subject: ARM: shmobile: ape6evm-reference: Correct BSC bus range The address space for the r8a73a4 Bus State Controller covers the first 512 MiB, not the first 2 GiB. Correct the size in the "ranges" property to reflect this, and to no longer overlap with PCI Express Memory. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts b/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts index 84e05f713c54..b3d8f844b57a 100644 --- a/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts +++ b/arch/arm/boot/dts/r8a73a4-ape6evm-reference.dts @@ -67,7 +67,7 @@ compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; - ranges = <0 0 0 0x80000000>; + ranges = <0 0 0 0x20000000>; }; }; -- cgit v1.2.3 From 9f04e56749bf6da4cb36a6bc703e584b496c26f4 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 10 Nov 2014 19:49:35 +0100 Subject: ARM: shmobile: r8a7740 dtsi: Change to using clock-indices With the addition of clock-indices in commit 8e33f91a0b84ae19 ("clk: shmobile: clk-mstp: change to using clock-indices"), we can change the DTSes to use the generic property instead of the deprecated vendor-specific property. Signed-off-by: Geert Uytterhoeven Acked-by: Kuninori Morimoto Acked-by: Laurent Pinchart Acked-by: Wolfram Sang Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7740.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7740.dtsi b/arch/arm/boot/dts/r8a7740.dtsi index a8a674bafa67..60ca62254536 100644 --- a/arch/arm/boot/dts/r8a7740.dtsi +++ b/arch/arm/boot/dts/r8a7740.dtsi @@ -453,7 +453,7 @@ reg = <0xe6150080 4>; clocks = <&sub_clk>, <&sub_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7740_CLK_SUBCK R8A7740_CLK_SUBCK2 >; clock-output-names = @@ -468,7 +468,7 @@ <&cpg_clocks R8A7740_CLK_HPP>, <&sub_clk>, <&cpg_clocks R8A7740_CLK_B>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7740_CLK_CEU21 R8A7740_CLK_CEU20 R8A7740_CLK_TMU0 R8A7740_CLK_LCDC1 R8A7740_CLK_IIC0 R8A7740_CLK_TMU1 R8A7740_CLK_LCDC0 @@ -489,7 +489,7 @@ <&sub_clk>, <&sub_clk>, <&sub_clk>, <&sub_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7740_CLK_SCIFA6 R8A7740_CLK_INTCA R8A7740_CLK_SCIFA7 R8A7740_CLK_DMAC1 R8A7740_CLK_DMAC2 @@ -518,7 +518,7 @@ <&cpg_clocks R8A7740_CLK_HP>, <&cpg_clocks R8A7740_CLK_HP>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7740_CLK_CMT1 R8A7740_CLK_FSI R8A7740_CLK_IIC1 R8A7740_CLK_USBF R8A7740_CLK_SDHI0 R8A7740_CLK_SDHI1 R8A7740_CLK_MMC R8A7740_CLK_GETHER R8A7740_CLK_TPU0 @@ -535,7 +535,7 @@ <&cpg_clocks R8A7740_CLK_HP>, <&cpg_clocks R8A7740_CLK_HP>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7740_CLK_USBH R8A7740_CLK_SDHI2 R8A7740_CLK_USBFUNC R8A7740_CLK_USBPHY >; -- cgit v1.2.3 From 64530fc2ce234e2ba227e24a149c73ef91dbfae5 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 10 Nov 2014 19:49:36 +0100 Subject: ARM: shmobile: r8a7779 dtsi: Change to using clock-indices With the addition of clock-indices in commit 8e33f91a0b84ae19 ("clk: shmobile: clk-mstp: change to using clock-indices"), we can change the DTSes to use the generic property instead of the deprecated vendor-specific property. Signed-off-by: Geert Uytterhoeven Acked-by: Kuninori Morimoto Acked-by: Laurent Pinchart Acked-by: Wolfram Sang Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7779.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi index ede9a29e4bc6..e3846af833e1 100644 --- a/arch/arm/boot/dts/r8a7779.dtsi +++ b/arch/arm/boot/dts/r8a7779.dtsi @@ -475,7 +475,7 @@ <&cpg_clocks R8A7779_CLK_P>, <&cpg_clocks R8A7779_CLK_P>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7779_CLK_HSPI R8A7779_CLK_TMU2 R8A7779_CLK_TMU1 R8A7779_CLK_TMU0 R8A7779_CLK_HSCIF1 R8A7779_CLK_HSCIF0 @@ -506,7 +506,7 @@ <&cpg_clocks R8A7779_CLK_P>, <&cpg_clocks R8A7779_CLK_S>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7779_CLK_USB01 R8A7779_CLK_USB2 R8A7779_CLK_DU R8A7779_CLK_VIN2 R8A7779_CLK_VIN1 R8A7779_CLK_VIN0 @@ -527,7 +527,7 @@ clocks = <&s4_clk>, <&s4_clk>, <&s4_clk>, <&s4_clk>, <&s4_clk>, <&s4_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7779_CLK_SDHI3 R8A7779_CLK_SDHI2 R8A7779_CLK_SDHI1 R8A7779_CLK_SDHI0 R8A7779_CLK_MMC1 R8A7779_CLK_MMC0 -- cgit v1.2.3 From b54010af0f248e238bb628ad40d0766bb9474ec6 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 10 Nov 2014 19:49:37 +0100 Subject: ARM: shmobile: r8a7790 dtsi: Change to using clock-indices With the addition of clock-indices in commit 8e33f91a0b84ae19 ("clk: shmobile: clk-mstp: change to using clock-indices"), we can change the DTSes to use the generic property instead of the deprecated vendor-specific property. Signed-off-by: Ben Dooks [geert: Extracted r8a7790-specific part, rebased, reworded] Signed-off-by: Geert Uytterhoeven Acked-by: Kuninori Morimoto Acked-by: Laurent Pinchart Acked-by: Wolfram Sang Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790.dtsi | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index af7e255f629e..ffeff98fa16e 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -1054,7 +1054,7 @@ reg = <0 0xe6150130 0 4>, <0 0xe6150030 0 4>; clocks = <&mp_clk>; #clock-cells = <1>; - renesas,clock-indices = ; + clock-indices = ; clock-output-names = "msiof0"; }; mstp1_clks: mstp1_clks@e6150134 { @@ -1065,7 +1065,7 @@ <&zs_clk>, <&zs_clk>, <&p_clk>, <&p_clk>, <&rclk_clk>, <&cp_clk>, <&zs_clk>, <&zs_clk>, <&zs_clk>, <&zs_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7790_CLK_VCP1 R8A7790_CLK_VCP0 R8A7790_CLK_VPC1 R8A7790_CLK_VPC0 R8A7790_CLK_JPU R8A7790_CLK_SSP1 R8A7790_CLK_TMU1 R8A7790_CLK_3DG R8A7790_CLK_2DDMAC @@ -1087,7 +1087,7 @@ <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>, <&zs_clk>, <&zs_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7790_CLK_SCIFA2 R8A7790_CLK_SCIFA1 R8A7790_CLK_SCIFA0 R8A7790_CLK_MSIOF2 R8A7790_CLK_SCIFB0 R8A7790_CLK_SCIFB1 R8A7790_CLK_MSIOF1 R8A7790_CLK_MSIOF3 R8A7790_CLK_SCIFB2 @@ -1106,7 +1106,7 @@ <&hp_clk>, <&mp_clk>, <&hp_clk>, <&mp_clk>, <&rclk_clk>, <&hp_clk>, <&hp_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7790_CLK_IIC2 R8A7790_CLK_TPU0 R8A7790_CLK_MMCIF1 R8A7790_CLK_SDHI3 R8A7790_CLK_SDHI2 R8A7790_CLK_SDHI1 R8A7790_CLK_SDHI0 R8A7790_CLK_MMCIF0 R8A7790_CLK_IIC0 R8A7790_CLK_PCIEC R8A7790_CLK_IIC1 R8A7790_CLK_SSUSB R8A7790_CLK_CMT1 @@ -1123,8 +1123,10 @@ reg = <0 0xe6150144 0 4>, <0 0xe615003c 0 4>; clocks = <&hp_clk>, <&hp_clk>, <&extal_clk>, <&p_clk>; #clock-cells = <1>; - renesas,clock-indices = ; + clock-indices = < + R8A7790_CLK_AUDIO_DMAC0 R8A7790_CLK_AUDIO_DMAC1 + R8A7790_CLK_THERMAL R8A7790_CLK_PWM + >; clock-output-names = "audmac0", "audmac1", "thermal", "pwm"; }; mstp7_clks: mstp7_clks@e615014c { @@ -1134,7 +1136,7 @@ <&p_clk>, <&zx_clk>, <&zx_clk>, <&zx_clk>, <&zx_clk>, <&zx_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7790_CLK_EHCI R8A7790_CLK_HSUSB R8A7790_CLK_HSCIF1 R8A7790_CLK_HSCIF0 R8A7790_CLK_SCIF1 R8A7790_CLK_SCIF0 R8A7790_CLK_DU2 R8A7790_CLK_DU1 R8A7790_CLK_DU0 @@ -1150,7 +1152,7 @@ clocks = <&zg_clk>, <&zg_clk>, <&zg_clk>, <&zg_clk>, <&p_clk>, <&zs_clk>, <&zs_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7790_CLK_VIN3 R8A7790_CLK_VIN2 R8A7790_CLK_VIN1 R8A7790_CLK_VIN0 R8A7790_CLK_ETHER R8A7790_CLK_SATA1 R8A7790_CLK_SATA0 @@ -1166,7 +1168,7 @@ <&p_clk>, <&p_clk>, <&cpg_clocks R8A7790_CLK_QSPI>, <&cp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7790_CLK_GPIO5 R8A7790_CLK_GPIO4 R8A7790_CLK_GPIO3 R8A7790_CLK_GPIO2 R8A7790_CLK_GPIO1 R8A7790_CLK_GPIO0 R8A7790_CLK_RCAN1 R8A7790_CLK_RCAN0 R8A7790_CLK_QSPI_MOD R8A7790_CLK_IICDVFS -- cgit v1.2.3 From cb0bf8512353aef2105e0ddfcc6da5bb4c91cf25 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 10 Nov 2014 19:49:38 +0100 Subject: ARM: shmobile: r8a7791 dtsi: Change to using clock-indices With the addition of clock-indices in commit 8e33f91a0b84ae19 ("clk: shmobile: clk-mstp: change to using clock-indices"), we can change the DTSes to use the generic property instead of the deprecated vendor-specific property. Signed-off-by: Ben Dooks [geert: Extracted r8a7791-specific part, rebased, reworded] Signed-off-by: Geert Uytterhoeven Acked-by: Kuninori Morimoto Acked-by: Laurent Pinchart Acked-by: Wolfram Sang Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7791.dtsi | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index 77c0beeb8d7c..7fabea23dd6c 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -1062,7 +1062,7 @@ reg = <0 0xe6150130 0 4>, <0 0xe6150030 0 4>; clocks = <&mp_clk>; #clock-cells = <1>; - renesas,clock-indices = ; + clock-indices = ; clock-output-names = "msiof0"; }; mstp1_clks: mstp1_clks@e6150134 { @@ -1073,7 +1073,7 @@ <&p_clk>, <&rclk_clk>, <&cp_clk>, <&zs_clk>, <&zs_clk>, <&zs_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7791_CLK_VCP0 R8A7791_CLK_VPC0 R8A7791_CLK_JPU R8A7791_CLK_SSP1 R8A7791_CLK_TMU1 R8A7791_CLK_3DG R8A7791_CLK_2DDMAC R8A7791_CLK_FDP1_1 R8A7791_CLK_FDP1_0 @@ -1093,7 +1093,7 @@ <&mp_clk>, <&mp_clk>, <&mp_clk>, <&zs_clk>, <&zs_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7791_CLK_SCIFA2 R8A7791_CLK_SCIFA1 R8A7791_CLK_SCIFA0 R8A7791_CLK_MSIOF2 R8A7791_CLK_SCIFB0 R8A7791_CLK_SCIFB1 R8A7791_CLK_MSIOF1 R8A7791_CLK_SCIFB2 @@ -1111,7 +1111,7 @@ <&mmc0_clk>, <&hp_clk>, <&mp_clk>, <&hp_clk>, <&mp_clk>, <&rclk_clk>, <&hp_clk>, <&hp_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7791_CLK_TPU0 R8A7791_CLK_SDHI2 R8A7791_CLK_SDHI1 R8A7791_CLK_SDHI0 R8A7791_CLK_MMCIF0 R8A7791_CLK_IIC0 R8A7791_CLK_PCIEC R8A7791_CLK_IIC1 R8A7791_CLK_SSUSB R8A7791_CLK_CMT1 @@ -1127,8 +1127,10 @@ reg = <0 0xe6150144 0 4>, <0 0xe615003c 0 4>; clocks = <&hp_clk>, <&hp_clk>, <&extal_clk>, <&p_clk>; #clock-cells = <1>; - renesas,clock-indices = ; + clock-indices = < + R8A7791_CLK_AUDIO_DMAC0 R8A7791_CLK_AUDIO_DMAC1 + R8A7791_CLK_THERMAL R8A7791_CLK_PWM + >; clock-output-names = "audmac0", "audmac1", "thermal", "pwm"; }; mstp7_clks: mstp7_clks@e615014c { @@ -1138,7 +1140,7 @@ <&zs_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&zx_clk>, <&zx_clk>, <&zx_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7791_CLK_EHCI R8A7791_CLK_HSUSB R8A7791_CLK_HSCIF2 R8A7791_CLK_SCIF5 R8A7791_CLK_SCIF4 R8A7791_CLK_HSCIF1 R8A7791_CLK_HSCIF0 R8A7791_CLK_SCIF3 R8A7791_CLK_SCIF2 R8A7791_CLK_SCIF1 @@ -1155,7 +1157,7 @@ clocks = <&zg_clk>, <&zg_clk>, <&zg_clk>, <&p_clk>, <&zs_clk>, <&zs_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7791_CLK_VIN2 R8A7791_CLK_VIN1 R8A7791_CLK_VIN0 R8A7791_CLK_ETHER R8A7791_CLK_SATA1 R8A7791_CLK_SATA0 >; @@ -1171,7 +1173,7 @@ <&cp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7791_CLK_GPIO7 R8A7791_CLK_GPIO6 R8A7791_CLK_GPIO5 R8A7791_CLK_GPIO4 R8A7791_CLK_GPIO3 R8A7791_CLK_GPIO2 R8A7791_CLK_GPIO1 R8A7791_CLK_GPIO0 R8A7791_CLK_RCAN1 R8A7791_CLK_RCAN0 R8A7791_CLK_QSPI_MOD R8A7791_CLK_I2C5 @@ -1221,7 +1223,7 @@ reg = <0 0xe615099c 0 4>, <0 0xe61509ac 0 4>; clocks = <&mp_clk>, <&mp_clk>, <&mp_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7791_CLK_SCIFA3 R8A7791_CLK_SCIFA4 R8A7791_CLK_SCIFA5 >; clock-output-names = "scifa3", "scifa4", "scifa5"; -- cgit v1.2.3 From 1045d0655704a16a736e001d3ae052829d5532b0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 10 Nov 2014 19:49:39 +0100 Subject: ARM: shmobile: r8a7794 dtsi: Change to using clock-indices With the addition of clock-indices in commit 8e33f91a0b84ae19 ("clk: shmobile: clk-mstp: change to using clock-indices"), we can change the DTSes to use the generic property instead of the deprecated vendor-specific property. Signed-off-by: Geert Uytterhoeven Acked-by: Kuninori Morimoto Acked-by: Laurent Pinchart Acked-by: Wolfram Sang Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7794.dtsi | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index 19c9de3f2a5a..1801bb417cf9 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -455,7 +455,7 @@ reg = <0 0xe6150130 0 4>, <0 0xe6150030 0 4>; clocks = <&mp_clk>; #clock-cells = <1>; - renesas,clock-indices = ; + clock-indices = ; clock-output-names = "msiof0"; }; mstp1_clks: mstp1_clks@e6150134 { @@ -465,7 +465,7 @@ <&zs_clk>, <&p_clk>, <&p_clk>, <&rclk_clk>, <&cp_clk>, <&zs_clk>, <&zs_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7794_CLK_VCP0 R8A7794_CLK_VPC0 R8A7794_CLK_TMU1 R8A7794_CLK_3DG R8A7794_CLK_2DDMAC R8A7794_CLK_FDP1_0 R8A7794_CLK_TMU3 R8A7794_CLK_TMU2 R8A7794_CLK_CMT0 @@ -481,7 +481,7 @@ clocks = <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7794_CLK_SCIFA2 R8A7794_CLK_SCIFA1 R8A7794_CLK_SCIFA0 R8A7794_CLK_MSIOF2 R8A7794_CLK_SCIFB0 R8A7794_CLK_SCIFB1 R8A7794_CLK_MSIOF1 R8A7794_CLK_SCIFB2 @@ -495,7 +495,7 @@ reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>; clocks = <&rclk_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7794_CLK_CMT1 >; clock-output-names = @@ -507,7 +507,7 @@ clocks = <&zs_clk>, <&p_clk>, <&p_clk>, <&zs_clk>, <&zs_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7794_CLK_HSCIF2 R8A7794_CLK_SCIF5 R8A7794_CLK_SCIF4 R8A7794_CLK_HSCIF1 R8A7794_CLK_HSCIF0 R8A7794_CLK_SCIF3 R8A7794_CLK_SCIF2 R8A7794_CLK_SCIF1 @@ -522,7 +522,7 @@ reg = <0 0xe6150990 0 4>, <0 0xe61509a0 0 4>; clocks = <&zg_clk>, <&zg_clk>, <&p_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7794_CLK_VIN1 R8A7794_CLK_VIN0 R8A7794_CLK_ETHER >; clock-output-names = @@ -533,7 +533,7 @@ reg = <0 0xe615099c 0 4>, <0 0xe61509ac 0 4>; clocks = <&mp_clk>, <&mp_clk>, <&mp_clk>; #clock-cells = <1>; - renesas,clock-indices = < + clock-indices = < R8A7794_CLK_SCIFA3 R8A7794_CLK_SCIFA4 R8A7794_CLK_SCIFA5 >; clock-output-names = "scifa3", "scifa4", "scifa5"; -- cgit v1.2.3 From c7bab9f929e5176169de2cee529ec203ca7f1584 Mon Sep 17 00:00:00 2001 From: Shinobu Uehara Date: Fri, 5 Dec 2014 12:01:12 +0900 Subject: ARM: shmobile: r8a7794: Add USB clocks to device tree Signed-off-by: Shinobu Uehara [horms: resolved conflicts] Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7794.dtsi | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index 1801bb417cf9..7fd40f374207 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -504,16 +504,19 @@ mstp7_clks: mstp7_clks@e615014c { compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe615014c 0 4>, <0 0xe61501c4 0 4>; - clocks = <&zs_clk>, <&p_clk>, <&p_clk>, <&zs_clk>, + clocks = <&mp_clk>, <&mp_clk>, + <&zs_clk>, <&p_clk>, <&p_clk>, <&zs_clk>, <&zs_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>; #clock-cells = <1>; clock-indices = < + R8A7794_CLK_EHCI R8A7794_CLK_HSUSB R8A7794_CLK_HSCIF2 R8A7794_CLK_SCIF5 R8A7794_CLK_SCIF4 R8A7794_CLK_HSCIF1 R8A7794_CLK_HSCIF0 R8A7794_CLK_SCIF3 R8A7794_CLK_SCIF2 R8A7794_CLK_SCIF1 R8A7794_CLK_SCIF0 >; clock-output-names = + "ehci", "hsusb", "hscif2", "scif5", "scif4", "hscif1", "hscif0", "scif3", "scif2", "scif1", "scif0"; }; -- cgit v1.2.3 From 5f950e62b476c62fd8a6549f3889e08e478252f3 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Fri, 5 Dec 2014 11:28:28 +0900 Subject: ARM: shmobile: dts: koelsch: Fix flash partition label and size Update the size and names of flash partitions to match the expectations of the loader which are as follows: "loader"---0x0000_0000-0x0008_0000 [loader program (readonly)] "user" ---0x0008_0000-0x0060_0000 [U-Boot + bootargs + dt + uImage (readonly)] "flash" ---0x0060_0000-0x0400_0000 [filesystem and free (read/write)] ["user"'s assumed breakdown] U-boot (0x0008_0000-0x000c_0000) 256KiB bootargs (0x000c_0000-0x0010_0000) 256KiB Device tree (0x0010_0000-0x0014_0000) 256KiB zImage (0x0014_0000-0x0060_0000) 4.75MiB Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7791-koelsch.dts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts index 990af167c551..1e5f8d2b74b9 100644 --- a/arch/arm/boot/dts/r8a7791-koelsch.dts +++ b/arch/arm/boot/dts/r8a7791-koelsch.dts @@ -452,13 +452,13 @@ read-only; }; partition@80000 { - label = "bootenv"; - reg = <0x00080000 0x00080000>; + label = "user"; + reg = <0x00080000 0x00580000>; read-only; }; - partition@100000 { - label = "data"; - reg = <0x00100000 0x03f00000>; + partition@600000 { + label = "flash"; + reg = <0x00600000 0x03a00000>; }; }; }; -- cgit v1.2.3 From aa5404fc74c31491c8087a9ed546a94dee60aac1 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 27 Nov 2014 11:57:16 +0100 Subject: ARM: shmobile: r8a7791: Correct mask for GIC PPI interrupts R-Car M2-W (r8a7791) contains two Cortex-A15 cores, hence the second interrupt specifier cell for Private Peripheral Interrupts should use "GIC_CPU_MASK_SIMPLE(2)". Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7791.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index 7fabea23dd6c..958a69b24ff4 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -78,7 +78,7 @@ <0 0xf1002000 0 0x1000>, <0 0xf1004000 0 0x2000>, <0 0xf1006000 0 0x2000>; - interrupts = <1 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; + interrupts = <1 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>; }; gpio0: gpio@e6050000 { @@ -186,10 +186,10 @@ timer { compatible = "arm,armv7-timer"; - interrupts = <1 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, - <1 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, - <1 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, - <1 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>; + interrupts = <1 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, + <1 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, + <1 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, + <1 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>; }; cmt0: timer@ffca0000 { -- cgit v1.2.3 From 00add867b802b3023b49433b9002fba79f042acc Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 27 Nov 2014 11:57:17 +0100 Subject: ARM: shmobile: r8a7794: Correct mask for GIC PPI interrupts R-Car E2 (r8a7794) contains two Cortex-A7 cores, hence the second interrupt specifier cell for Private Peripheral Interrupts should use "GIC_CPU_MASK_SIMPLE(2)". Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7794.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index 7fd40f374207..e53765493346 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -47,7 +47,7 @@ <0 0xf1002000 0 0x1000>, <0 0xf1004000 0 0x2000>, <0 0xf1006000 0 0x2000>; - interrupts = <1 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; + interrupts = <1 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>; }; cmt0: timer@ffca0000 { @@ -84,10 +84,10 @@ timer { compatible = "arm,armv7-timer"; - interrupts = <1 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, - <1 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, - <1 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>, - <1 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>; + interrupts = <1 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, + <1 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, + <1 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, + <1 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>; }; irqc0: interrupt-controller@e61c0000 { -- cgit v1.2.3 From 22a9b44fc17e83417fa890123a33164ea37fc10c Mon Sep 17 00:00:00 2001 From: Kazuya Mizuguchi Date: Mon, 8 Dec 2014 09:54:36 +0900 Subject: ARM: shmobile: r8a7794: Add USBDMAC[01] clocks to device tree Signed-off-by: Kazuya Mizuguchi [horms: merged per-clock patches] Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7794.dtsi | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index e53765493346..13e4a8d73029 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -493,13 +493,14 @@ mstp3_clks: mstp3_clks@e615013c { compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>; - clocks = <&rclk_clk>; + clocks = <&rclk_clk>, <&hp_clk>, <&hp_clk>; #clock-cells = <1>; clock-indices = < - R8A7794_CLK_CMT1 + R8A7794_CLK_CMT1 R8A7794_CLK_USBDMAC0 + R8A7794_CLK_USBDMAC1 >; clock-output-names = - "cmt1"; + "cmt1", "usbdmac0", "usbdmac1"; }; mstp7_clks: mstp7_clks@e615014c { compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; -- cgit v1.2.3 From 9c5becce21af35e59c7313d3603af1d620fffd05 Mon Sep 17 00:00:00 2001 From: Hisashi Nakamura Date: Tue, 9 Dec 2014 09:37:12 +0900 Subject: ARM: shmobile: koelsch: Fix QSPI mode of SPI-Flash into mode3 In order to change into mode3, CPOL and CPHA bit of SPCMD register of QSPI is changed. Mode3 can avoid intermediate voltage. Signed-off-by: Hisashi Nakamura [horms: Updated changelog and re-ordered properties] Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7791-koelsch.dts | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts index 1e5f8d2b74b9..691e4c635564 100644 --- a/arch/arm/boot/dts/r8a7791-koelsch.dts +++ b/arch/arm/boot/dts/r8a7791-koelsch.dts @@ -444,6 +444,8 @@ spi-max-frequency = <30000000>; spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; + spi-cpha; + spi-cpol; m25p,fast-read; partition@0 { -- cgit v1.2.3 From be2902416cc6f26d05a9b7308b78d093ad69062c Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 29 Oct 2014 16:46:56 +0900 Subject: ARM: shmobile: lager-reference: DTS-only board support Remove redundant C board code for Lager Multiplatform, everything is supported via DT these days anyway so it is fine to rely on the MACHINE_START in setup-r8a7790.c. Signed-off-by: Magnus Damm [Remove CONFIG_MACH_LAGER from shmobile_defconfig] Signed-off-by: Laurent Pinchart Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/configs/shmobile_defconfig | 1 - arch/arm/mach-shmobile/Kconfig | 5 ---- arch/arm/mach-shmobile/Makefile | 1 - arch/arm/mach-shmobile/board-lager-reference.c | 39 -------------------------- 4 files changed, 46 deletions(-) delete mode 100644 arch/arm/mach-shmobile/board-lager-reference.c (limited to 'arch') diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig index 3df6ca0c1d1f..e4a6c5e9174d 100644 --- a/arch/arm/configs/shmobile_defconfig +++ b/arch/arm/configs/shmobile_defconfig @@ -17,7 +17,6 @@ CONFIG_ARCH_R8A7779=y CONFIG_ARCH_R8A7790=y CONFIG_ARCH_R8A7791=y CONFIG_ARCH_R8A7794=y -CONFIG_MACH_LAGER=y CONFIG_MACH_MARZEN=y # CONFIG_SWP_EMULATE is not set CONFIG_CPU_BPREDICT_DISABLE=y diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 1b4fafe524ff..859f391aa6e1 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -74,11 +74,6 @@ config ARCH_R8A7794 comment "Renesas ARM SoCs Board Type" -config MACH_LAGER - bool "Lager board" - depends on ARCH_R8A7790 - select MICREL_PHY if SH_ETH - config MACH_MARZEN bool "MARZEN board" depends on ARCH_R8A7779 diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index b55cac0e5b2b..85692c9a1cef 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -57,7 +57,6 @@ obj-$(CONFIG_ARCH_SH7372) += entry-intc.o sleep-sh7372.o # Board objects ifdef CONFIG_ARCH_SHMOBILE_MULTI -obj-$(CONFIG_MACH_LAGER) += board-lager-reference.o obj-$(CONFIG_MACH_MARZEN) += board-marzen-reference.o else obj-$(CONFIG_MACH_APE6EVM) += board-ape6evm.o diff --git a/arch/arm/mach-shmobile/board-lager-reference.c b/arch/arm/mach-shmobile/board-lager-reference.c deleted file mode 100644 index fa06bdba61df..000000000000 --- a/arch/arm/mach-shmobile/board-lager-reference.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Lager board support - Reference DT implementation - * - * Copyright (C) 2013 Renesas Solutions Corp. - * Copyright (C) 2013 Simon Horman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * 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 -#include - -#include - -#include "common.h" -#include "r8a7790.h" -#include "rcar-gen2.h" - -static const char *lager_boards_compat_dt[] __initdata = { - "renesas,lager", - "renesas,lager-reference", - NULL, -}; - -DT_MACHINE_START(LAGER_DT, "lager") - .smp = smp_ops(r8a7790_smp_ops), - .init_early = shmobile_init_delay, - .init_time = rcar_gen2_timer_init, - .init_late = shmobile_init_late, - .reserve = rcar_gen2_reserve, - .dt_compat = lager_boards_compat_dt, -MACHINE_END -- cgit v1.2.3 From a483dcbfa21f919c7666cb897e293eff785e3bee Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 29 Oct 2014 16:47:07 +0900 Subject: ARM: shmobile: lager: Remove legacy board support Lager legacy support level is same as the DT case so remove the legacy code and force people to move over to using Multiplatform and DT. Signed-off-by: Magnus Damm [Remove lager_defconfig and don't build the dtb for legacy kernels] Signed-off-by: Laurent Pinchart Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/Makefile | 1 - arch/arm/configs/lager_defconfig | 150 ------- arch/arm/mach-shmobile/Kconfig | 7 - arch/arm/mach-shmobile/Makefile | 1 - arch/arm/mach-shmobile/Makefile.boot | 1 - arch/arm/mach-shmobile/board-lager.c | 827 ----------------------------------- 6 files changed, 987 deletions(-) delete mode 100644 arch/arm/configs/lager_defconfig delete mode 100644 arch/arm/mach-shmobile/board-lager.c (limited to 'arch') diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 91bd5bd62857..19cb6fcecf89 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -410,7 +410,6 @@ dtb-$(CONFIG_ARCH_SHMOBILE_LEGACY) += \ r8a7778-bockw.dtb \ r8a7778-bockw-reference.dtb \ r8a7779-marzen.dtb \ - r8a7790-lager.dtb \ sh7372-mackerel.dtb \ sh73a0-kzm9g.dtb \ sh73a0-kzm9g-reference.dtb diff --git a/arch/arm/configs/lager_defconfig b/arch/arm/configs/lager_defconfig deleted file mode 100644 index a82afc916a89..000000000000 --- a/arch/arm/configs/lager_defconfig +++ /dev/null @@ -1,150 +0,0 @@ -CONFIG_SYSVIPC=y -CONFIG_NO_HZ=y -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=16 -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_EMBEDDED=y -CONFIG_PERF_EVENTS=y -CONFIG_SLAB=y -# CONFIG_LBDAF is not set -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set -CONFIG_ARCH_SHMOBILE_LEGACY=y -CONFIG_ARCH_R8A7790=y -CONFIG_MACH_LAGER=y -# CONFIG_SH_TIMER_TMU is not set -# CONFIG_EM_TIMER_STI is not set -CONFIG_ARM_ERRATA_430973=y -CONFIG_ARM_ERRATA_458693=y -CONFIG_ARM_ERRATA_460075=y -CONFIG_ARM_ERRATA_743622=y -CONFIG_ARM_ERRATA_754322=y -CONFIG_PCI=y -CONFIG_PCI_RCAR_GEN2=y -CONFIG_PCI_RCAR_GEN2_PCIE=y -CONFIG_HAVE_ARM_ARCH_TIMER=y -CONFIG_AEABI=y -# CONFIG_OABI_COMPAT is not set -CONFIG_FORCE_MAX_ZONEORDER=13 -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_ARM_APPENDED_DTB=y -CONFIG_KEXEC=y -CONFIG_AUTO_ZRELADDR=y -CONFIG_VFP=y -CONFIG_NEON=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -CONFIG_PM=y -CONFIG_NET=y -CONFIG_PACKET=y -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_LRO is not set -# CONFIG_INET_DIAG is not set -# CONFIG_IPV6 is not set -# CONFIG_WIRELESS is not set -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_DEVTMPFS=y -CONFIG_DEVTMPFS_MOUNT=y -CONFIG_MTD=y -CONFIG_MTD_M25P80=y -CONFIG_MTD_SPI_NOR=y -CONFIG_BLK_DEV_SD=y -CONFIG_ATA=y -CONFIG_SATA_RCAR=y -CONFIG_NETDEVICES=y -# CONFIG_NET_CORE is not set -# CONFIG_NET_VENDOR_ARC is not set -# CONFIG_NET_CADENCE is not set -# CONFIG_NET_VENDOR_BROADCOM is not set -# CONFIG_NET_VENDOR_CIRRUS is not set -# CONFIG_NET_VENDOR_FARADAY is not set -# CONFIG_NET_VENDOR_INTEL is not set -# CONFIG_NET_VENDOR_MARVELL is not set -# CONFIG_NET_VENDOR_MICREL is not set -# CONFIG_NET_VENDOR_NATSEMI is not set -CONFIG_SH_ETH=y -# CONFIG_NET_VENDOR_SEEQ is not set -# CONFIG_NET_VENDOR_SMSC is not set -# CONFIG_NET_VENDOR_STMICRO is not set -# CONFIG_NET_VENDOR_VIA is not set -# CONFIG_NET_VENDOR_WIZNET is not set -# CONFIG_WLAN is not set -# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -CONFIG_INPUT_EVDEV=y -# CONFIG_KEYBOARD_ATKBD is not set -CONFIG_KEYBOARD_GPIO=y -# CONFIG_INPUT_MOUSE is not set -# CONFIG_SERIO is not set -# CONFIG_LEGACY_PTYS is not set -CONFIG_SERIAL_SH_SCI=y -CONFIG_SERIAL_SH_SCI_NR_UARTS=10 -CONFIG_SERIAL_SH_SCI_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_I2C_GPIO=y -CONFIG_I2C_SH_MOBILE=y -CONFIG_I2C_RCAR=y -CONFIG_SPI=y -CONFIG_SPI_RSPI=y -CONFIG_SPI_SH_MSIOF=y -CONFIG_GPIO_SH_PFC=y -CONFIG_GPIOLIB=y -CONFIG_GPIO_RCAR=y -# CONFIG_HWMON is not set -CONFIG_THERMAL=y -CONFIG_RCAR_THERMAL=y -CONFIG_REGULATOR=y -CONFIG_REGULATOR_FIXED_VOLTAGE=y -CONFIG_REGULATOR_DA9210=y -CONFIG_REGULATOR_GPIO=y -CONFIG_MEDIA_SUPPORT=y -CONFIG_MEDIA_CAMERA_SUPPORT=y -CONFIG_V4L_PLATFORM_DRIVERS=y -CONFIG_SOC_CAMERA=y -CONFIG_SOC_CAMERA_PLATFORM=y -CONFIG_VIDEO_RCAR_VIN=y -# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set -CONFIG_VIDEO_ADV7180=y -CONFIG_DRM=y -CONFIG_DRM_RCAR_DU=y -CONFIG_SOUND=y -CONFIG_SND=y -CONFIG_SND_SOC=y -CONFIG_SND_SOC_RCAR=y -# CONFIG_USB_SUPPORT is not set -CONFIG_MMC=y -CONFIG_MMC_SDHI=y -CONFIG_MMC_SH_MMCIF=y -CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_GPIO=y -CONFIG_RTC_CLASS=y -CONFIG_DMADEVICES=y -CONFIG_SH_DMAE=y -# CONFIG_IOMMU_SUPPORT is not set -# CONFIG_DNOTIFY is not set -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_TMPFS=y -CONFIG_CONFIGFS_FS=y -# CONFIG_MISC_FILESYSTEMS is not set -CONFIG_NFS_FS=y -CONFIG_NFS_V3_ACL=y -CONFIG_NFS_V4=y -CONFIG_NFS_V4_1=y -CONFIG_ROOT_NFS=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ISO8859_1=y -# CONFIG_ENABLE_WARN_DEPRECATED is not set -# CONFIG_ENABLE_MUST_CHECK is not set -# CONFIG_ARM_UNWIND is not set -# CONFIG_CRYPTO_ANSI_CPRNG is not set -# CONFIG_CRYPTO_HW is not set diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 859f391aa6e1..d4211cba3513 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -203,13 +203,6 @@ config MACH_MARZEN select REGULATOR_FIXED_VOLTAGE if REGULATOR select USE_OF -config MACH_LAGER - bool "Lager board" - depends on ARCH_R8A7790 - select USE_OF - select MICREL_PHY if SH_ETH - select SND_SOC_AK4642 if SND_SIMPLE_CARD - config MACH_KZM9G bool "KZM-A9-GT board" depends on ARCH_SH73A0 diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index 85692c9a1cef..3eefe7dc74b6 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -65,7 +65,6 @@ obj-$(CONFIG_MACH_MACKEREL) += board-mackerel.o obj-$(CONFIG_MACH_BOCKW) += board-bockw.o obj-$(CONFIG_MACH_BOCKW_REFERENCE) += board-bockw-reference.o obj-$(CONFIG_MACH_MARZEN) += board-marzen.o -obj-$(CONFIG_MACH_LAGER) += board-lager.o obj-$(CONFIG_MACH_ARMADILLO800EVA) += board-armadillo800eva.o obj-$(CONFIG_MACH_KZM9G) += board-kzm9g.o obj-$(CONFIG_MACH_KZM9G_REFERENCE) += board-kzm9g-reference.o diff --git a/arch/arm/mach-shmobile/Makefile.boot b/arch/arm/mach-shmobile/Makefile.boot index 57d00ed6ec0c..02532bea5300 100644 --- a/arch/arm/mach-shmobile/Makefile.boot +++ b/arch/arm/mach-shmobile/Makefile.boot @@ -7,7 +7,6 @@ loadaddr-$(CONFIG_MACH_BOCKW) += 0x60008000 loadaddr-$(CONFIG_MACH_BOCKW_REFERENCE) += 0x60008000 loadaddr-$(CONFIG_MACH_KZM9G) += 0x41008000 loadaddr-$(CONFIG_MACH_KZM9G_REFERENCE) += 0x41008000 -loadaddr-$(CONFIG_MACH_LAGER) += 0x40008000 loadaddr-$(CONFIG_MACH_MACKEREL) += 0x40008000 loadaddr-$(CONFIG_MACH_MARZEN) += 0x60008000 diff --git a/arch/arm/mach-shmobile/board-lager.c b/arch/arm/mach-shmobile/board-lager.c deleted file mode 100644 index f8197eb6e566..000000000000 --- a/arch/arm/mach-shmobile/board-lager.c +++ /dev/null @@ -1,827 +0,0 @@ -/* - * Lager board support - * - * Copyright (C) 2013-2014 Renesas Solutions Corp. - * Copyright (C) 2013 Magnus Damm - * Copyright (C) 2014 Cogent Embedded, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "common.h" -#include "irqs.h" -#include "r8a7790.h" -#include "rcar-gen2.h" - -/* - * SSI-AK4643 - * - * SW1: 1: AK4643 - * 2: CN22 - * 3: ADV7511 - * - * this command is required when playback. - * - * # amixer set "LINEOUT Mixer DACL" on - */ - -/* - * SDHI0 (CN8) - * - * JP3: pin1 - * SW20: pin1 - - * GP5_24: 1: VDD 3.3V (defult) - * 0: VDD 0.0V - * GP5_29: 1: VccQ 3.3V (defult) - * 0: VccQ 1.8V - * - */ - -/* LEDS */ -static struct gpio_led lager_leds[] = { - { - .name = "led8", - .gpio = RCAR_GP_PIN(5, 17), - .default_state = LEDS_GPIO_DEFSTATE_ON, - }, { - .name = "led7", - .gpio = RCAR_GP_PIN(4, 23), - .default_state = LEDS_GPIO_DEFSTATE_ON, - }, { - .name = "led6", - .gpio = RCAR_GP_PIN(4, 22), - .default_state = LEDS_GPIO_DEFSTATE_ON, - }, -}; - -static const struct gpio_led_platform_data lager_leds_pdata __initconst = { - .leds = lager_leds, - .num_leds = ARRAY_SIZE(lager_leds), -}; - -/* GPIO KEY */ -#define GPIO_KEY(c, g, d, ...) \ - { .code = c, .gpio = g, .desc = d, .active_low = 1, \ - .wakeup = 1, .debounce_interval = 20 } - -static struct gpio_keys_button gpio_buttons[] = { - GPIO_KEY(KEY_4, RCAR_GP_PIN(1, 28), "SW2-pin4"), - GPIO_KEY(KEY_3, RCAR_GP_PIN(1, 26), "SW2-pin3"), - GPIO_KEY(KEY_2, RCAR_GP_PIN(1, 24), "SW2-pin2"), - GPIO_KEY(KEY_1, RCAR_GP_PIN(1, 14), "SW2-pin1"), -}; - -static const struct gpio_keys_platform_data lager_keys_pdata __initconst = { - .buttons = gpio_buttons, - .nbuttons = ARRAY_SIZE(gpio_buttons), -}; - -/* Fixed 3.3V regulator to be used by MMCIF */ -static struct regulator_consumer_supply fixed3v3_power_consumers[] = -{ - REGULATOR_SUPPLY("vmmc", "sh_mmcif.1"), -}; - -/* - * SDHI regulator macro - * - ** FIXME** - * Lager board vqmmc is provided via DA9063 PMIC chip, - * and we should use ${LINK}/drivers/mfd/da9063-* driver for it. - * but, it doesn't have regulator support at this point. - * It uses gpio-regulator for vqmmc as quick-hack. - */ -#define SDHI_REGULATOR(idx, vdd_pin, vccq_pin) \ -static struct regulator_consumer_supply vcc_sdhi##idx##_consumer = \ - REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi." #idx); \ - \ -static struct regulator_init_data vcc_sdhi##idx##_init_data = { \ - .constraints = { \ - .valid_ops_mask = REGULATOR_CHANGE_STATUS, \ - }, \ - .consumer_supplies = &vcc_sdhi##idx##_consumer, \ - .num_consumer_supplies = 1, \ -}; \ - \ -static const struct fixed_voltage_config vcc_sdhi##idx##_info __initconst = {\ - .supply_name = "SDHI" #idx "Vcc", \ - .microvolts = 3300000, \ - .gpio = vdd_pin, \ - .enable_high = 1, \ - .init_data = &vcc_sdhi##idx##_init_data, \ -}; \ - \ -static struct regulator_consumer_supply vccq_sdhi##idx##_consumer = \ - REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi." #idx); \ - \ -static struct regulator_init_data vccq_sdhi##idx##_init_data = { \ - .constraints = { \ - .input_uV = 3300000, \ - .min_uV = 1800000, \ - .max_uV = 3300000, \ - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | \ - REGULATOR_CHANGE_STATUS, \ - }, \ - .consumer_supplies = &vccq_sdhi##idx##_consumer, \ - .num_consumer_supplies = 1, \ -}; \ - \ -static struct gpio vccq_sdhi##idx##_gpio = \ - { vccq_pin, GPIOF_OUT_INIT_HIGH, "vccq-sdhi" #idx }; \ - \ -static struct gpio_regulator_state vccq_sdhi##idx##_states[] = { \ - { .value = 1800000, .gpios = 0 }, \ - { .value = 3300000, .gpios = 1 }, \ -}; \ - \ -static const struct gpio_regulator_config vccq_sdhi##idx##_info __initconst = {\ - .supply_name = "vqmmc", \ - .gpios = &vccq_sdhi##idx##_gpio, \ - .nr_gpios = 1, \ - .states = vccq_sdhi##idx##_states, \ - .nr_states = ARRAY_SIZE(vccq_sdhi##idx##_states), \ - .type = REGULATOR_VOLTAGE, \ - .init_data = &vccq_sdhi##idx##_init_data, \ -}; - -SDHI_REGULATOR(0, RCAR_GP_PIN(5, 24), RCAR_GP_PIN(5, 29)); -SDHI_REGULATOR(2, RCAR_GP_PIN(5, 25), RCAR_GP_PIN(5, 30)); - -/* MMCIF */ -static const struct sh_mmcif_plat_data mmcif1_pdata __initconst = { - .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE, - .clk_ctrl2_present = true, - .ccs_unsupported = true, -}; - -static const struct resource mmcif1_resources[] __initconst = { - DEFINE_RES_MEM(0xee220000, 0x80), - DEFINE_RES_IRQ(gic_spi(170)), -}; - -/* Ether */ -static const struct sh_eth_plat_data ether_pdata __initconst = { - .phy = 0x1, - .phy_irq = irq_pin(0), - .edmac_endian = EDMAC_LITTLE_ENDIAN, - .phy_interface = PHY_INTERFACE_MODE_RMII, - .ether_link_active_low = 1, -}; - -static const struct resource ether_resources[] __initconst = { - DEFINE_RES_MEM(0xee700000, 0x400), - DEFINE_RES_IRQ(gic_spi(162)), -}; - -static const struct platform_device_info ether_info __initconst = { - .name = "r8a7790-ether", - .id = -1, - .res = ether_resources, - .num_res = ARRAY_SIZE(ether_resources), - .data = ðer_pdata, - .size_data = sizeof(ether_pdata), - .dma_mask = DMA_BIT_MASK(32), -}; - -/* SPI Flash memory (Spansion S25FL512SAGMFIG11 64Mb) */ -static struct mtd_partition spi_flash_part[] = { - /* Reserved for user loader program, read-only */ - { - .name = "loader", - .offset = 0, - .size = SZ_256K, - .mask_flags = MTD_WRITEABLE, - }, - /* Reserved for user program, read-only */ - { - .name = "user", - .offset = MTDPART_OFS_APPEND, - .size = SZ_4M, - .mask_flags = MTD_WRITEABLE, - }, - /* All else is writable (e.g. JFFS2) */ - { - .name = "flash", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - .mask_flags = 0, - }, -}; - -static const struct flash_platform_data spi_flash_data = { - .name = "m25p80", - .parts = spi_flash_part, - .nr_parts = ARRAY_SIZE(spi_flash_part), - .type = "s25fl512s", -}; - -static const struct rspi_plat_data qspi_pdata __initconst = { - .num_chipselect = 1, -}; - -static const struct spi_board_info spi_info[] __initconst = { - { - .modalias = "m25p80", - .platform_data = &spi_flash_data, - .mode = SPI_MODE_0 | SPI_TX_QUAD | SPI_RX_QUAD, - .max_speed_hz = 30000000, - .bus_num = 0, - .chip_select = 0, - }, -}; - -/* QSPI resource */ -static const struct resource qspi_resources[] __initconst = { - DEFINE_RES_MEM(0xe6b10000, 0x1000), - DEFINE_RES_IRQ_NAMED(gic_spi(184), "mux"), -}; - -/* VIN */ -static const struct resource vin_resources[] __initconst = { - /* VIN0 */ - DEFINE_RES_MEM(0xe6ef0000, 0x1000), - DEFINE_RES_IRQ(gic_spi(188)), - /* VIN1 */ - DEFINE_RES_MEM(0xe6ef1000, 0x1000), - DEFINE_RES_IRQ(gic_spi(189)), -}; - -static void __init lager_add_vin_device(unsigned idx, - struct rcar_vin_platform_data *pdata) -{ - struct platform_device_info vin_info = { - .name = "r8a7790-vin", - .id = idx, - .res = &vin_resources[idx * 2], - .num_res = 2, - .dma_mask = DMA_BIT_MASK(32), - .data = pdata, - .size_data = sizeof(*pdata), - }; - - BUG_ON(idx > 1); - - platform_device_register_full(&vin_info); -} - -#define LAGER_CAMERA(idx, name, addr, pdata, flag) \ -static struct i2c_board_info i2c_cam##idx##_device = { \ - I2C_BOARD_INFO(name, addr), \ -}; \ - \ -static struct rcar_vin_platform_data vin##idx##_pdata = { \ - .flags = flag, \ -}; \ - \ -static struct soc_camera_link cam##idx##_link = { \ - .bus_id = idx, \ - .board_info = &i2c_cam##idx##_device, \ - .i2c_adapter_id = 2, \ - .module_name = name, \ - .priv = pdata, \ -} - -/* Camera 0 is not currently supported due to adv7612 support missing */ -LAGER_CAMERA(1, "adv7180", 0x20, NULL, RCAR_VIN_BT656); - -static void __init lager_add_camera1_device(void) -{ - platform_device_register_data(NULL, "soc-camera-pdrv", 1, - &cam1_link, sizeof(cam1_link)); - lager_add_vin_device(1, &vin1_pdata); -} - -/* SATA1 */ -static const struct resource sata1_resources[] __initconst = { - DEFINE_RES_MEM(0xee500000, 0x2000), - DEFINE_RES_IRQ(gic_spi(106)), -}; - -static const struct platform_device_info sata1_info __initconst = { - .name = "sata-r8a7790", - .id = 1, - .res = sata1_resources, - .num_res = ARRAY_SIZE(sata1_resources), - .dma_mask = DMA_BIT_MASK(32), -}; - -/* USBHS */ -static const struct resource usbhs_resources[] __initconst = { - DEFINE_RES_MEM(0xe6590000, 0x100), - DEFINE_RES_IRQ(gic_spi(107)), -}; - -struct usbhs_private { - struct renesas_usbhs_platform_info info; - struct usb_phy *phy; -}; - -#define usbhs_get_priv(pdev) \ - container_of(renesas_usbhs_get_info(pdev), struct usbhs_private, info) - -static int usbhs_power_ctrl(struct platform_device *pdev, - void __iomem *base, int enable) -{ - struct usbhs_private *priv = usbhs_get_priv(pdev); - - if (!priv->phy) - return -ENODEV; - - if (enable) { - int retval = usb_phy_init(priv->phy); - - if (!retval) - retval = usb_phy_set_suspend(priv->phy, 0); - return retval; - } - - usb_phy_set_suspend(priv->phy, 1); - usb_phy_shutdown(priv->phy); - return 0; -} - -static int usbhs_hardware_init(struct platform_device *pdev) -{ - struct usbhs_private *priv = usbhs_get_priv(pdev); - struct usb_phy *phy; - int ret; - - /* USB0 Function - use PWEN as GPIO input to detect DIP Switch SW5 - * setting to avoid VBUS short circuit due to wrong cable. - * PWEN should be pulled up high if USB Function is selected by SW5 - */ - gpio_request_one(RCAR_GP_PIN(5, 18), GPIOF_IN, NULL); /* USB0_PWEN */ - if (!gpio_get_value(RCAR_GP_PIN(5, 18))) { - pr_warn("Error: USB Function not selected - check SW5 + SW6\n"); - ret = -ENOTSUPP; - goto error; - } - - phy = usb_get_phy_dev(&pdev->dev, 0); - if (IS_ERR(phy)) { - ret = PTR_ERR(phy); - goto error; - } - - priv->phy = phy; - return 0; - error: - gpio_free(RCAR_GP_PIN(5, 18)); - return ret; -} - -static int usbhs_hardware_exit(struct platform_device *pdev) -{ - struct usbhs_private *priv = usbhs_get_priv(pdev); - - if (!priv->phy) - return 0; - - usb_put_phy(priv->phy); - priv->phy = NULL; - - gpio_free(RCAR_GP_PIN(5, 18)); - return 0; -} - -static int usbhs_get_id(struct platform_device *pdev) -{ - return USBHS_GADGET; -} - -static u32 lager_usbhs_pipe_type[] = { - USB_ENDPOINT_XFER_CONTROL, - USB_ENDPOINT_XFER_ISOC, - USB_ENDPOINT_XFER_ISOC, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_INT, - USB_ENDPOINT_XFER_INT, - USB_ENDPOINT_XFER_INT, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, - USB_ENDPOINT_XFER_BULK, -}; - -static struct usbhs_private usbhs_priv __initdata = { - .info = { - .platform_callback = { - .power_ctrl = usbhs_power_ctrl, - .hardware_init = usbhs_hardware_init, - .hardware_exit = usbhs_hardware_exit, - .get_id = usbhs_get_id, - }, - .driver_param = { - .buswait_bwait = 4, - .pipe_type = lager_usbhs_pipe_type, - .pipe_size = ARRAY_SIZE(lager_usbhs_pipe_type), - }, - } -}; - -static void __init lager_register_usbhs(void) -{ - usb_bind_phy("renesas_usbhs", 0, "usb_phy_rcar_gen2"); - platform_device_register_resndata(NULL, - "renesas_usbhs", -1, - usbhs_resources, - ARRAY_SIZE(usbhs_resources), - &usbhs_priv.info, - sizeof(usbhs_priv.info)); -} - -/* USBHS PHY */ -static const struct rcar_gen2_phy_platform_data usbhs_phy_pdata __initconst = { - .chan0_pci = 0, /* Channel 0 is USBHS */ - .chan2_pci = 1, /* Channel 2 is PCI USB */ -}; - -static const struct resource usbhs_phy_resources[] __initconst = { - DEFINE_RES_MEM(0xe6590100, 0x100), -}; - -/* I2C */ -static struct i2c_board_info i2c2_devices[] = { - { - I2C_BOARD_INFO("ak4643", 0x12), - } -}; - -/* Sound */ -static struct resource rsnd_resources[] __initdata = { - [RSND_GEN2_SCU] = DEFINE_RES_MEM(0xec500000, 0x1000), - [RSND_GEN2_ADG] = DEFINE_RES_MEM(0xec5a0000, 0x100), - [RSND_GEN2_SSIU] = DEFINE_RES_MEM(0xec540000, 0x1000), - [RSND_GEN2_SSI] = DEFINE_RES_MEM(0xec541000, 0x1280), -}; - -static struct rsnd_ssi_platform_info rsnd_ssi[] = { - RSND_SSI(0, gic_spi(370), 0), - RSND_SSI(0, gic_spi(371), RSND_SSI_CLK_PIN_SHARE), -}; - -static struct rsnd_src_platform_info rsnd_src[2] = { - /* no member at this point */ -}; - -static struct rsnd_dai_platform_info rsnd_dai = { - .playback = { .ssi = &rsnd_ssi[0], }, - .capture = { .ssi = &rsnd_ssi[1], }, -}; - -static struct rcar_snd_info rsnd_info = { - .flags = RSND_GEN2, - .ssi_info = rsnd_ssi, - .ssi_info_nr = ARRAY_SIZE(rsnd_ssi), - .src_info = rsnd_src, - .src_info_nr = ARRAY_SIZE(rsnd_src), - .dai_info = &rsnd_dai, - .dai_info_nr = 1, -}; - -static struct asoc_simple_card_info rsnd_card_info = { - .name = "AK4643", - .card = "SSI01-AK4643", - .codec = "ak4642-codec.2-0012", - .platform = "rcar_sound", - .daifmt = SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM, - .cpu_dai = { - .name = "rcar_sound", - }, - .codec_dai = { - .name = "ak4642-hifi", - .sysclk = 11289600, - }, -}; - -static void __init lager_add_rsnd_device(void) -{ - struct platform_device_info cardinfo = { - .name = "asoc-simple-card", - .id = -1, - .data = &rsnd_card_info, - .size_data = sizeof(struct asoc_simple_card_info), - .dma_mask = DMA_BIT_MASK(32), - }; - - i2c_register_board_info(2, i2c2_devices, - ARRAY_SIZE(i2c2_devices)); - - platform_device_register_resndata( - NULL, "rcar_sound", -1, - rsnd_resources, ARRAY_SIZE(rsnd_resources), - &rsnd_info, sizeof(rsnd_info)); - - platform_device_register_full(&cardinfo); -} - -/* SDHI0 */ -static struct sh_mobile_sdhi_info sdhi0_info __initdata = { - .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | - MMC_CAP_POWER_OFF_CARD, - .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | - TMIO_MMC_WRPROTECT_DISABLE, -}; - -static struct resource sdhi0_resources[] __initdata = { - DEFINE_RES_MEM(0xee100000, 0x200), - DEFINE_RES_IRQ(gic_spi(165)), -}; - -/* SDHI2 */ -static struct sh_mobile_sdhi_info sdhi2_info __initdata = { - .tmio_caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | - MMC_CAP_POWER_OFF_CARD, - .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | - TMIO_MMC_WRPROTECT_DISABLE, -}; - -static struct resource sdhi2_resources[] __initdata = { - DEFINE_RES_MEM(0xee140000, 0x100), - DEFINE_RES_IRQ(gic_spi(167)), -}; - -/* Internal PCI1 */ -static const struct resource pci1_resources[] __initconst = { - DEFINE_RES_MEM(0xee0b0000, 0x10000), /* CFG */ - DEFINE_RES_MEM(0xee0a0000, 0x10000), /* MEM */ - DEFINE_RES_IRQ(gic_spi(112)), -}; - -static const struct platform_device_info pci1_info __initconst = { - .name = "pci-rcar-gen2", - .id = 1, - .res = pci1_resources, - .num_res = ARRAY_SIZE(pci1_resources), - .dma_mask = DMA_BIT_MASK(32), -}; - -static void __init lager_add_usb1_device(void) -{ - platform_device_register_full(&pci1_info); -} - -/* Internal PCI2 */ -static const struct resource pci2_resources[] __initconst = { - DEFINE_RES_MEM(0xee0d0000, 0x10000), /* CFG */ - DEFINE_RES_MEM(0xee0c0000, 0x10000), /* MEM */ - DEFINE_RES_IRQ(gic_spi(113)), -}; - -static const struct platform_device_info pci2_info __initconst = { - .name = "pci-rcar-gen2", - .id = 2, - .res = pci2_resources, - .num_res = ARRAY_SIZE(pci2_resources), - .dma_mask = DMA_BIT_MASK(32), -}; - -static void __init lager_add_usb2_device(void) -{ - platform_device_register_full(&pci2_info); -} - -static const struct pinctrl_map lager_pinctrl_map[] = { - /* DU (CN10: ARGB0, CN13: LVDS) */ - PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7790", "pfc-r8a7790", - "du_rgb666", "du"), - PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7790", "pfc-r8a7790", - "du_sync_1", "du"), - PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7790", "pfc-r8a7790", - "du_clk_out_0", "du"), - /* I2C2 */ - PIN_MAP_MUX_GROUP_DEFAULT("i2c-rcar.2", "pfc-r8a7790", - "i2c2", "i2c2"), - /* QSPI */ - PIN_MAP_MUX_GROUP_DEFAULT("qspi.0", "pfc-r8a7790", - "qspi_ctrl", "qspi"), - PIN_MAP_MUX_GROUP_DEFAULT("qspi.0", "pfc-r8a7790", - "qspi_data4", "qspi"), - /* SCIF0 (CN19: DEBUG SERIAL0) */ - PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.6", "pfc-r8a7790", - "scif0_data", "scif0"), - /* SCIF1 (CN20: DEBUG SERIAL1) */ - PIN_MAP_MUX_GROUP_DEFAULT("sh-sci.7", "pfc-r8a7790", - "scif1_data", "scif1"), - /* SDHI0 */ - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7790", - "sdhi0_data4", "sdhi0"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7790", - "sdhi0_ctrl", "sdhi0"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.0", "pfc-r8a7790", - "sdhi0_cd", "sdhi0"), - /* SDHI2 */ - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-r8a7790", - "sdhi2_data4", "sdhi2"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-r8a7790", - "sdhi2_ctrl", "sdhi2"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-r8a7790", - "sdhi2_cd", "sdhi2"), - /* SSI (CN17: sound) */ - PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7790", - "ssi0129_ctrl", "ssi"), - PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7790", - "ssi0_data", "ssi"), - PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7790", - "ssi1_data", "ssi"), - PIN_MAP_MUX_GROUP_DEFAULT("rcar_sound", "pfc-r8a7790", - "audio_clk_a", "audio_clk"), - /* MMCIF1 */ - PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.1", "pfc-r8a7790", - "mmc1_data8", "mmc1"), - PIN_MAP_MUX_GROUP_DEFAULT("sh_mmcif.1", "pfc-r8a7790", - "mmc1_ctrl", "mmc1"), - /* Ether */ - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-ether", "pfc-r8a7790", - "eth_link", "eth"), - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-ether", "pfc-r8a7790", - "eth_mdio", "eth"), - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-ether", "pfc-r8a7790", - "eth_rmii", "eth"), - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-ether", "pfc-r8a7790", - "intc_irq0", "intc"), - /* VIN0 */ - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.0", "pfc-r8a7790", - "vin0_data24", "vin0"), - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.0", "pfc-r8a7790", - "vin0_sync", "vin0"), - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.0", "pfc-r8a7790", - "vin0_field", "vin0"), - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.0", "pfc-r8a7790", - "vin0_clkenb", "vin0"), - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.0", "pfc-r8a7790", - "vin0_clk", "vin0"), - /* VIN1 */ - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.1", "pfc-r8a7790", - "vin1_data8", "vin1"), - PIN_MAP_MUX_GROUP_DEFAULT("r8a7790-vin.1", "pfc-r8a7790", - "vin1_clk", "vin1"), - /* USB0 */ - PIN_MAP_MUX_GROUP_DEFAULT("renesas_usbhs", "pfc-r8a7790", - "usb0_ovc_vbus", "usb0"), - /* USB1 */ - PIN_MAP_MUX_GROUP_DEFAULT("pci-rcar-gen2.1", "pfc-r8a7790", - "usb1", "usb1"), - /* USB2 */ - PIN_MAP_MUX_GROUP_DEFAULT("pci-rcar-gen2.2", "pfc-r8a7790", - "usb2", "usb2"), -}; - -static void __init lager_add_standard_devices(void) -{ - int fixed_regulator_idx = 0; - int gpio_regulator_idx = 0; - - r8a7790_clock_init(); - - pinctrl_register_mappings(lager_pinctrl_map, - ARRAY_SIZE(lager_pinctrl_map)); - r8a7790_pinmux_init(); - - r8a7790_add_standard_devices(); - platform_device_register_data(NULL, "leds-gpio", -1, - &lager_leds_pdata, - sizeof(lager_leds_pdata)); - platform_device_register_data(NULL, "gpio-keys", -1, - &lager_keys_pdata, - sizeof(lager_keys_pdata)); - regulator_register_always_on(fixed_regulator_idx++, - "fixed-3.3V", fixed3v3_power_consumers, - ARRAY_SIZE(fixed3v3_power_consumers), 3300000); - platform_device_register_resndata(NULL, "sh_mmcif", 1, - mmcif1_resources, ARRAY_SIZE(mmcif1_resources), - &mmcif1_pdata, sizeof(mmcif1_pdata)); - - platform_device_register_full(ðer_info); - - platform_device_register_resndata(NULL, "qspi", 0, - qspi_resources, - ARRAY_SIZE(qspi_resources), - &qspi_pdata, sizeof(qspi_pdata)); - spi_register_board_info(spi_info, ARRAY_SIZE(spi_info)); - - platform_device_register_data(NULL, "reg-fixed-voltage", fixed_regulator_idx++, - &vcc_sdhi0_info, sizeof(struct fixed_voltage_config)); - platform_device_register_data(NULL, "reg-fixed-voltage", fixed_regulator_idx++, - &vcc_sdhi2_info, sizeof(struct fixed_voltage_config)); - - platform_device_register_data(NULL, "gpio-regulator", gpio_regulator_idx++, - &vccq_sdhi0_info, sizeof(struct gpio_regulator_config)); - platform_device_register_data(NULL, "gpio-regulator", gpio_regulator_idx++, - &vccq_sdhi2_info, sizeof(struct gpio_regulator_config)); - - lager_add_camera1_device(); - - platform_device_register_full(&sata1_info); - - platform_device_register_resndata(NULL, "usb_phy_rcar_gen2", - -1, usbhs_phy_resources, - ARRAY_SIZE(usbhs_phy_resources), - &usbhs_phy_pdata, - sizeof(usbhs_phy_pdata)); - lager_register_usbhs(); - lager_add_usb1_device(); - lager_add_usb2_device(); - - lager_add_rsnd_device(); - - platform_device_register_resndata(NULL, "sh_mobile_sdhi", 0, - sdhi0_resources, ARRAY_SIZE(sdhi0_resources), - &sdhi0_info, sizeof(struct sh_mobile_sdhi_info)); - platform_device_register_resndata(NULL, "sh_mobile_sdhi", 2, - sdhi2_resources, ARRAY_SIZE(sdhi2_resources), - &sdhi2_info, sizeof(struct sh_mobile_sdhi_info)); -} - -/* - * Ether LEDs on the Lager board are named LINK and ACTIVE which corresponds - * to non-default 01 setting of the Micrel KSZ8041 PHY control register 1 bits - * 14-15. We have to set them back to 01 from the default 00 value each time - * the PHY is reset. It's also important because the PHY's LED0 signal is - * connected to SoC's ETH_LINK signal and in the PHY's default mode it will - * bounce on and off after each packet, which we apparently want to avoid. - */ -static int lager_ksz8041_fixup(struct phy_device *phydev) -{ - u16 phyctrl1 = phy_read(phydev, 0x1e); - - phyctrl1 &= ~0xc000; - phyctrl1 |= 0x4000; - return phy_write(phydev, 0x1e, phyctrl1); -} - -static void __init lager_init(void) -{ - lager_add_standard_devices(); - - irq_set_irq_type(irq_pin(0), IRQ_TYPE_LEVEL_LOW); - - if (IS_ENABLED(CONFIG_PHYLIB)) - phy_register_fixup_for_id("r8a7790-ether-ff:01", - lager_ksz8041_fixup); -} - -static const char * const lager_boards_compat_dt[] __initconst = { - "renesas,lager", - NULL, -}; - -DT_MACHINE_START(LAGER_DT, "lager") - .smp = smp_ops(r8a7790_smp_ops), - .init_early = shmobile_init_delay, - .init_time = rcar_gen2_timer_init, - .init_machine = lager_init, - .init_late = shmobile_init_late, - .reserve = rcar_gen2_reserve, - .dt_compat = lager_boards_compat_dt, -MACHINE_END -- cgit v1.2.3 From e042681894b62d60f3a8704999d7700ebcdb9117 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 2 Dec 2014 18:00:56 +0200 Subject: ARM: shmobile: r8a7790: Remove legacy code All r8a7790 boards are now used with multiplatform kernels only. We can remove all the unused r8a7790 legacy device and clock registration code. Signed-off-by: Laurent Pinchart Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/Kconfig | 8 - arch/arm/mach-shmobile/Makefile | 1 - arch/arm/mach-shmobile/clock-r8a7790.c | 459 --------------------------------- arch/arm/mach-shmobile/r8a7790.h | 28 -- arch/arm/mach-shmobile/setup-r8a7790.c | 284 +------------------- 5 files changed, 1 insertion(+), 779 deletions(-) delete mode 100644 arch/arm/mach-shmobile/clock-r8a7790.c (limited to 'arch') diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index d4211cba3513..bb3d07504d8b 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -128,14 +128,6 @@ config ARCH_R8A7779 select ARCH_WANT_OPTIONAL_GPIOLIB select ARM_GIC -config ARCH_R8A7790 - bool "R-Car H2 (R8A77900)" - select ARCH_RCAR_GEN2 - select ARCH_WANT_OPTIONAL_GPIOLIB - select ARM_GIC - select MIGHT_HAVE_PCI - select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE - comment "Renesas ARM SoCs Board Type" config MACH_APE6EVM diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index 3eefe7dc74b6..d53996e6da97 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -27,7 +27,6 @@ obj-$(CONFIG_ARCH_R8A73A4) += clock-r8a73a4.o obj-$(CONFIG_ARCH_R8A7740) += clock-r8a7740.o obj-$(CONFIG_ARCH_R8A7778) += clock-r8a7778.o obj-$(CONFIG_ARCH_R8A7779) += clock-r8a7779.o -obj-$(CONFIG_ARCH_R8A7790) += clock-r8a7790.o endif # CPU reset vector handling objects diff --git a/arch/arm/mach-shmobile/clock-r8a7790.c b/arch/arm/mach-shmobile/clock-r8a7790.c deleted file mode 100644 index f9bbc5f0a9a1..000000000000 --- a/arch/arm/mach-shmobile/clock-r8a7790.c +++ /dev/null @@ -1,459 +0,0 @@ -/* - * r8a7790 clock framework support - * - * Copyright (C) 2013 Renesas Solutions Corp. - * Copyright (C) 2013 Magnus Damm - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * 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 -#include -#include -#include -#include - -#include "clock.h" -#include "common.h" -#include "r8a7790.h" -#include "rcar-gen2.h" - -/* - * MD EXTAL PLL0 PLL1 PLL3 - * 14 13 19 (MHz) *1 *1 - *--------------------------------------------------- - * 0 0 0 15 x 1 x172/2 x208/2 x106 - * 0 0 1 15 x 1 x172/2 x208/2 x88 - * 0 1 0 20 x 1 x130/2 x156/2 x80 - * 0 1 1 20 x 1 x130/2 x156/2 x66 - * 1 0 0 26 / 2 x200/2 x240/2 x122 - * 1 0 1 26 / 2 x200/2 x240/2 x102 - * 1 1 0 30 / 2 x172/2 x208/2 x106 - * 1 1 1 30 / 2 x172/2 x208/2 x88 - * - * *1 : Table 7.6 indicates VCO ouput (PLLx = VCO/2) - * see "p1 / 2" on R8A7790_CLOCK_ROOT() below - */ - -#define CPG_BASE 0xe6150000 -#define CPG_LEN 0x1000 - -#define SMSTPCR1 0xe6150134 -#define SMSTPCR2 0xe6150138 -#define SMSTPCR3 0xe615013c -#define SMSTPCR5 0xe6150144 -#define SMSTPCR7 0xe615014c -#define SMSTPCR8 0xe6150990 -#define SMSTPCR9 0xe6150994 -#define SMSTPCR10 0xe6150998 - -#define MSTPSR1 IOMEM(0xe6150038) -#define MSTPSR2 IOMEM(0xe6150040) -#define MSTPSR3 IOMEM(0xe6150048) -#define MSTPSR5 IOMEM(0xe615003c) -#define MSTPSR7 IOMEM(0xe61501c4) -#define MSTPSR8 IOMEM(0xe61509a0) -#define MSTPSR9 IOMEM(0xe61509a4) -#define MSTPSR10 IOMEM(0xe61509a8) - -#define SDCKCR 0xE6150074 -#define SD2CKCR 0xE6150078 -#define SD3CKCR 0xE615026C -#define MMC0CKCR 0xE6150240 -#define MMC1CKCR 0xE6150244 -#define SSPCKCR 0xE6150248 -#define SSPRSCKCR 0xE615024C - -static struct clk_mapping cpg_mapping = { - .phys = CPG_BASE, - .len = CPG_LEN, -}; - -static struct clk extal_clk = { - /* .rate will be updated on r8a7790_clock_init() */ - .mapping = &cpg_mapping, -}; - -static struct sh_clk_ops followparent_clk_ops = { - .recalc = followparent_recalc, -}; - -static struct clk main_clk = { - /* .parent will be set r8a7790_clock_init */ - .ops = &followparent_clk_ops, -}; - -static struct clk audio_clk_a = { -}; - -static struct clk audio_clk_b = { -}; - -static struct clk audio_clk_c = { -}; - -/* - * clock ratio of these clock will be updated - * on r8a7790_clock_init() - */ -SH_FIXED_RATIO_CLK_SET(pll1_clk, main_clk, 1, 1); -SH_FIXED_RATIO_CLK_SET(pll3_clk, main_clk, 1, 1); -SH_FIXED_RATIO_CLK_SET(lb_clk, pll1_clk, 1, 1); -SH_FIXED_RATIO_CLK_SET(qspi_clk, pll1_clk, 1, 1); - -/* fixed ratio clock */ -SH_FIXED_RATIO_CLK_SET(extal_div2_clk, extal_clk, 1, 2); -SH_FIXED_RATIO_CLK_SET(cp_clk, extal_clk, 1, 2); - -SH_FIXED_RATIO_CLK_SET(pll1_div2_clk, pll1_clk, 1, 2); -SH_FIXED_RATIO_CLK_SET(zg_clk, pll1_clk, 1, 3); -SH_FIXED_RATIO_CLK_SET(zx_clk, pll1_clk, 1, 3); -SH_FIXED_RATIO_CLK_SET(zs_clk, pll1_clk, 1, 6); -SH_FIXED_RATIO_CLK_SET(hp_clk, pll1_clk, 1, 12); -SH_FIXED_RATIO_CLK_SET(i_clk, pll1_clk, 1, 2); -SH_FIXED_RATIO_CLK_SET(b_clk, pll1_clk, 1, 12); -SH_FIXED_RATIO_CLK_SET(p_clk, pll1_clk, 1, 24); -SH_FIXED_RATIO_CLK_SET(cl_clk, pll1_clk, 1, 48); -SH_FIXED_RATIO_CLK_SET(m2_clk, pll1_clk, 1, 8); -SH_FIXED_RATIO_CLK_SET(imp_clk, pll1_clk, 1, 4); -SH_FIXED_RATIO_CLK_SET(rclk_clk, pll1_clk, 1, (48 * 1024)); -SH_FIXED_RATIO_CLK_SET(oscclk_clk, pll1_clk, 1, (12 * 1024)); - -SH_FIXED_RATIO_CLK_SET(zb3_clk, pll3_clk, 1, 4); -SH_FIXED_RATIO_CLK_SET(zb3d2_clk, pll3_clk, 1, 8); -SH_FIXED_RATIO_CLK_SET(ddr_clk, pll3_clk, 1, 8); -SH_FIXED_RATIO_CLK_SET(mp_clk, pll1_div2_clk, 1, 15); - -static struct clk *main_clks[] = { - &audio_clk_a, - &audio_clk_b, - &audio_clk_c, - &extal_clk, - &extal_div2_clk, - &main_clk, - &pll1_clk, - &pll1_div2_clk, - &pll3_clk, - &lb_clk, - &qspi_clk, - &zg_clk, - &zx_clk, - &zs_clk, - &hp_clk, - &i_clk, - &b_clk, - &p_clk, - &cl_clk, - &m2_clk, - &imp_clk, - &rclk_clk, - &oscclk_clk, - &zb3_clk, - &zb3d2_clk, - &ddr_clk, - &mp_clk, - &cp_clk, -}; - -/* SDHI (DIV4) clock */ -static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 18, 24, 0, 36, 48, 10 }; - -static struct clk_div_mult_table div4_div_mult_table = { - .divisors = divisors, - .nr_divisors = ARRAY_SIZE(divisors), -}; - -static struct clk_div4_table div4_table = { - .div_mult_table = &div4_div_mult_table, -}; - -enum { - DIV4_SDH, DIV4_SD0, DIV4_SD1, DIV4_NR -}; - -static struct clk div4_clks[DIV4_NR] = { - [DIV4_SDH] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 8, 0x0dff, CLK_ENABLE_ON_INIT), - [DIV4_SD0] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 4, 0x1df0, CLK_ENABLE_ON_INIT), - [DIV4_SD1] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 0, 0x1df0, CLK_ENABLE_ON_INIT), -}; - -/* DIV6 clocks */ -enum { - DIV6_SD2, DIV6_SD3, - DIV6_MMC0, DIV6_MMC1, - DIV6_SSP, DIV6_SSPRS, - DIV6_NR -}; - -static struct clk div6_clks[DIV6_NR] = { - [DIV6_SD2] = SH_CLK_DIV6(&pll1_div2_clk, SD2CKCR, 0), - [DIV6_SD3] = SH_CLK_DIV6(&pll1_div2_clk, SD3CKCR, 0), - [DIV6_MMC0] = SH_CLK_DIV6(&pll1_div2_clk, MMC0CKCR, 0), - [DIV6_MMC1] = SH_CLK_DIV6(&pll1_div2_clk, MMC1CKCR, 0), - [DIV6_SSP] = SH_CLK_DIV6(&pll1_div2_clk, SSPCKCR, 0), - [DIV6_SSPRS] = SH_CLK_DIV6(&pll1_div2_clk, SSPRSCKCR, 0), -}; - -/* MSTP */ -enum { - MSTP1017, /* parent of SCU */ - - MSTP1031, MSTP1030, - MSTP1029, MSTP1028, MSTP1027, MSTP1026, MSTP1025, MSTP1024, MSTP1023, MSTP1022, - MSTP1015, MSTP1014, MSTP1013, MSTP1012, MSTP1011, MSTP1010, - MSTP1009, MSTP1008, MSTP1007, MSTP1006, MSTP1005, - MSTP931, MSTP930, MSTP929, MSTP928, - MSTP917, - MSTP815, MSTP814, - MSTP813, - MSTP811, MSTP810, MSTP809, MSTP808, - MSTP726, MSTP725, MSTP724, MSTP723, MSTP722, MSTP721, MSTP720, - MSTP717, MSTP716, - MSTP704, MSTP703, - MSTP522, - MSTP502, MSTP501, - MSTP315, MSTP314, MSTP313, MSTP312, MSTP311, MSTP305, MSTP304, - MSTP216, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, - MSTP124, - MSTP_NR -}; - -static struct clk mstp_clks[MSTP_NR] = { - [MSTP1031] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 31, MSTPSR10, 0), /* SCU0 */ - [MSTP1030] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 30, MSTPSR10, 0), /* SCU1 */ - [MSTP1029] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 29, MSTPSR10, 0), /* SCU2 */ - [MSTP1028] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 28, MSTPSR10, 0), /* SCU3 */ - [MSTP1027] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 27, MSTPSR10, 0), /* SCU4 */ - [MSTP1026] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 26, MSTPSR10, 0), /* SCU5 */ - [MSTP1025] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 25, MSTPSR10, 0), /* SCU6 */ - [MSTP1024] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 24, MSTPSR10, 0), /* SCU7 */ - [MSTP1023] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 23, MSTPSR10, 0), /* SCU8 */ - [MSTP1022] = SH_CLK_MSTP32_STS(&mstp_clks[MSTP1017], SMSTPCR10, 22, MSTPSR10, 0), /* SCU9 */ - [MSTP1017] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 17, MSTPSR10, 0), /* SCU */ - [MSTP1015] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 15, MSTPSR10, 0), /* SSI0 */ - [MSTP1014] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 14, MSTPSR10, 0), /* SSI1 */ - [MSTP1013] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 13, MSTPSR10, 0), /* SSI2 */ - [MSTP1012] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 12, MSTPSR10, 0), /* SSI3 */ - [MSTP1011] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 11, MSTPSR10, 0), /* SSI4 */ - [MSTP1010] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 10, MSTPSR10, 0), /* SSI5 */ - [MSTP1009] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 9, MSTPSR10, 0), /* SSI6 */ - [MSTP1008] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 8, MSTPSR10, 0), /* SSI7 */ - [MSTP1007] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 7, MSTPSR10, 0), /* SSI8 */ - [MSTP1006] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 6, MSTPSR10, 0), /* SSI9 */ - [MSTP1005] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR10, 5, MSTPSR10, 0), /* SSI ALL */ - [MSTP931] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 31, MSTPSR9, 0), /* I2C0 */ - [MSTP930] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 30, MSTPSR9, 0), /* I2C1 */ - [MSTP929] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 29, MSTPSR9, 0), /* I2C2 */ - [MSTP928] = SH_CLK_MSTP32_STS(&hp_clk, SMSTPCR9, 28, MSTPSR9, 0), /* I2C3 */ - [MSTP917] = SH_CLK_MSTP32_STS(&qspi_clk, SMSTPCR9, 17, MSTPSR9, 0), /* QSPI */ - [MSTP815] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR8, 15, MSTPSR8, 0), /* SATA0 */ - [MSTP814] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR8, 14, MSTPSR8, 0), /* SATA1 */ - [MSTP813] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR8, 13, MSTPSR8, 0), /* Ether */ - [MSTP811] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 11, MSTPSR8, 0), /* VIN0 */ - [MSTP810] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 10, MSTPSR8, 0), /* VIN1 */ - [MSTP809] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 9, MSTPSR8, 0), /* VIN2 */ - [MSTP808] = SH_CLK_MSTP32_STS(&zg_clk, SMSTPCR8, 8, MSTPSR8, 0), /* VIN3 */ - [MSTP726] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 26, MSTPSR7, 0), /* LVDS0 */ - [MSTP725] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 25, MSTPSR7, 0), /* LVDS1 */ - [MSTP724] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 24, MSTPSR7, 0), /* DU0 */ - [MSTP723] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 23, MSTPSR7, 0), /* DU1 */ - [MSTP722] = SH_CLK_MSTP32_STS(&zx_clk, SMSTPCR7, 22, MSTPSR7, 0), /* DU2 */ - [MSTP721] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 21, MSTPSR7, 0), /* SCIF0 */ - [MSTP720] = SH_CLK_MSTP32_STS(&p_clk, SMSTPCR7, 20, MSTPSR7, 0), /* SCIF1 */ - [MSTP717] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR7, 17, MSTPSR7, 0), /* HSCIF0 */ - [MSTP716] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR7, 16, MSTPSR7, 0), /* HSCIF1 */ - [MSTP704] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR7, 4, MSTPSR7, 0), /* HSUSB */ - [MSTP703] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR7, 3, MSTPSR7, 0), /* EHCI */ - [MSTP522] = SH_CLK_MSTP32_STS(&extal_clk, SMSTPCR5, 22, MSTPSR5, 0), /* Thermal */ - [MSTP502] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR5, 2, MSTPSR5, 0), /* Audio-DMAC low */ - [MSTP501] = SH_CLK_MSTP32_STS(&zs_clk, SMSTPCR5, 1, MSTPSR5, 0), /* Audio-DMAC hi */ - [MSTP315] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_MMC0], SMSTPCR3, 15, MSTPSR3, 0), /* MMC0 */ - [MSTP314] = SH_CLK_MSTP32_STS(&div4_clks[DIV4_SD0], SMSTPCR3, 14, MSTPSR3, 0), /* SDHI0 */ - [MSTP313] = SH_CLK_MSTP32_STS(&div4_clks[DIV4_SD1], SMSTPCR3, 13, MSTPSR3, 0), /* SDHI1 */ - [MSTP312] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_SD2], SMSTPCR3, 12, MSTPSR3, 0), /* SDHI2 */ - [MSTP311] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_SD3], SMSTPCR3, 11, MSTPSR3, 0), /* SDHI3 */ - [MSTP305] = SH_CLK_MSTP32_STS(&div6_clks[DIV6_MMC1], SMSTPCR3, 5, MSTPSR3, 0), /* MMC1 */ - [MSTP304] = SH_CLK_MSTP32_STS(&cp_clk, SMSTPCR3, 4, MSTPSR3, 0), /* TPU0 */ - [MSTP216] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 16, MSTPSR2, 0), /* SCIFB2 */ - [MSTP207] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 7, MSTPSR2, 0), /* SCIFB1 */ - [MSTP206] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 6, MSTPSR2, 0), /* SCIFB0 */ - [MSTP204] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 4, MSTPSR2, 0), /* SCIFA0 */ - [MSTP203] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 3, MSTPSR2, 0), /* SCIFA1 */ - [MSTP202] = SH_CLK_MSTP32_STS(&mp_clk, SMSTPCR2, 2, MSTPSR2, 0), /* SCIFA2 */ - [MSTP124] = SH_CLK_MSTP32_STS(&rclk_clk, SMSTPCR1, 24, MSTPSR1, 0), /* CMT0 */ -}; - -static struct clk_lookup lookups[] = { - - /* main clocks */ - CLKDEV_CON_ID("extal", &extal_clk), - CLKDEV_CON_ID("extal_div2", &extal_div2_clk), - CLKDEV_CON_ID("main", &main_clk), - CLKDEV_CON_ID("pll1", &pll1_clk), - CLKDEV_CON_ID("pll1_div2", &pll1_div2_clk), - CLKDEV_CON_ID("pll3", &pll3_clk), - CLKDEV_CON_ID("zg", &zg_clk), - CLKDEV_CON_ID("zx", &zx_clk), - CLKDEV_CON_ID("zs", &zs_clk), - CLKDEV_CON_ID("hp", &hp_clk), - CLKDEV_CON_ID("i", &i_clk), - CLKDEV_CON_ID("b", &b_clk), - CLKDEV_CON_ID("lb", &lb_clk), - CLKDEV_CON_ID("p", &p_clk), - CLKDEV_CON_ID("cl", &cl_clk), - CLKDEV_CON_ID("m2", &m2_clk), - CLKDEV_CON_ID("imp", &imp_clk), - CLKDEV_CON_ID("rclk", &rclk_clk), - CLKDEV_CON_ID("oscclk", &oscclk_clk), - CLKDEV_CON_ID("zb3", &zb3_clk), - CLKDEV_CON_ID("zb3d2", &zb3d2_clk), - CLKDEV_CON_ID("ddr", &ddr_clk), - CLKDEV_CON_ID("mp", &mp_clk), - CLKDEV_CON_ID("qspi", &qspi_clk), - CLKDEV_CON_ID("cp", &cp_clk), - - /* DIV4 */ - CLKDEV_CON_ID("sdh", &div4_clks[DIV4_SDH]), - - /* DIV6 */ - CLKDEV_CON_ID("ssp", &div6_clks[DIV6_SSP]), - CLKDEV_CON_ID("ssprs", &div6_clks[DIV6_SSPRS]), - - /* MSTP */ - CLKDEV_DEV_ID("rcar_sound", &mstp_clks[MSTP1005]), - CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), - CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), - CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP206]), - CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP207]), - CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP216]), - CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP202]), - CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP721]), - CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP720]), - CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP717]), - CLKDEV_DEV_ID("sh-sci.9", &mstp_clks[MSTP716]), - CLKDEV_DEV_ID("i2c-rcar_gen2.0", &mstp_clks[MSTP931]), - CLKDEV_DEV_ID("i2c-rcar_gen2.1", &mstp_clks[MSTP930]), - CLKDEV_DEV_ID("i2c-rcar_gen2.2", &mstp_clks[MSTP929]), - CLKDEV_DEV_ID("i2c-rcar_gen2.3", &mstp_clks[MSTP928]), - CLKDEV_DEV_ID("r8a7790-ether", &mstp_clks[MSTP813]), - CLKDEV_DEV_ID("r8a7790-vin.0", &mstp_clks[MSTP811]), - CLKDEV_DEV_ID("r8a7790-vin.1", &mstp_clks[MSTP810]), - CLKDEV_DEV_ID("r8a7790-vin.2", &mstp_clks[MSTP809]), - CLKDEV_DEV_ID("r8a7790-vin.3", &mstp_clks[MSTP808]), - CLKDEV_DEV_ID("rcar_thermal", &mstp_clks[MSTP522]), - CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP502]), - CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP501]), - CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP315]), - CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), - CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), - CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP312]), - CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP311]), - CLKDEV_DEV_ID("sh_mmcif.1", &mstp_clks[MSTP305]), - CLKDEV_DEV_ID("qspi.0", &mstp_clks[MSTP917]), - CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP704]), - CLKDEV_DEV_ID("pci-rcar-gen2.0", &mstp_clks[MSTP703]), - CLKDEV_DEV_ID("pci-rcar-gen2.1", &mstp_clks[MSTP703]), - CLKDEV_DEV_ID("pci-rcar-gen2.2", &mstp_clks[MSTP703]), - CLKDEV_DEV_ID("sata-r8a7790.0", &mstp_clks[MSTP815]), - CLKDEV_DEV_ID("sata-r8a7790.1", &mstp_clks[MSTP814]), - - /* ICK */ - CLKDEV_ICK_ID("fck", "sh-cmt-48-gen2.0", &mstp_clks[MSTP124]), - CLKDEV_ICK_ID("usbhs", "usb_phy_rcar_gen2", &mstp_clks[MSTP704]), - CLKDEV_ICK_ID("lvds.0", "rcar-du-r8a7790", &mstp_clks[MSTP726]), - CLKDEV_ICK_ID("lvds.1", "rcar-du-r8a7790", &mstp_clks[MSTP725]), - CLKDEV_ICK_ID("du.0", "rcar-du-r8a7790", &mstp_clks[MSTP724]), - CLKDEV_ICK_ID("du.1", "rcar-du-r8a7790", &mstp_clks[MSTP723]), - CLKDEV_ICK_ID("du.2", "rcar-du-r8a7790", &mstp_clks[MSTP722]), - CLKDEV_ICK_ID("clk_a", "rcar_sound", &audio_clk_a), - CLKDEV_ICK_ID("clk_b", "rcar_sound", &audio_clk_b), - CLKDEV_ICK_ID("clk_c", "rcar_sound", &audio_clk_c), - CLKDEV_ICK_ID("clk_i", "rcar_sound", &m2_clk), - CLKDEV_ICK_ID("src.0", "rcar_sound", &mstp_clks[MSTP1031]), - CLKDEV_ICK_ID("src.1", "rcar_sound", &mstp_clks[MSTP1030]), - CLKDEV_ICK_ID("src.2", "rcar_sound", &mstp_clks[MSTP1029]), - CLKDEV_ICK_ID("src.3", "rcar_sound", &mstp_clks[MSTP1028]), - CLKDEV_ICK_ID("src.4", "rcar_sound", &mstp_clks[MSTP1027]), - CLKDEV_ICK_ID("src.5", "rcar_sound", &mstp_clks[MSTP1026]), - CLKDEV_ICK_ID("src.6", "rcar_sound", &mstp_clks[MSTP1025]), - CLKDEV_ICK_ID("src.7", "rcar_sound", &mstp_clks[MSTP1024]), - CLKDEV_ICK_ID("src.8", "rcar_sound", &mstp_clks[MSTP1023]), - CLKDEV_ICK_ID("src.9", "rcar_sound", &mstp_clks[MSTP1022]), - CLKDEV_ICK_ID("ssi.0", "rcar_sound", &mstp_clks[MSTP1015]), - CLKDEV_ICK_ID("ssi.1", "rcar_sound", &mstp_clks[MSTP1014]), - CLKDEV_ICK_ID("ssi.2", "rcar_sound", &mstp_clks[MSTP1013]), - CLKDEV_ICK_ID("ssi.3", "rcar_sound", &mstp_clks[MSTP1012]), - CLKDEV_ICK_ID("ssi.4", "rcar_sound", &mstp_clks[MSTP1011]), - CLKDEV_ICK_ID("ssi.5", "rcar_sound", &mstp_clks[MSTP1010]), - CLKDEV_ICK_ID("ssi.6", "rcar_sound", &mstp_clks[MSTP1009]), - CLKDEV_ICK_ID("ssi.7", "rcar_sound", &mstp_clks[MSTP1008]), - CLKDEV_ICK_ID("ssi.8", "rcar_sound", &mstp_clks[MSTP1007]), - CLKDEV_ICK_ID("ssi.9", "rcar_sound", &mstp_clks[MSTP1006]), - -}; - -#define R8A7790_CLOCK_ROOT(e, m, p0, p1, p30, p31) \ - extal_clk.rate = e * 1000 * 1000; \ - main_clk.parent = m; \ - SH_CLK_SET_RATIO(&pll1_clk_ratio, p1 / 2, 1); \ - if (mode & MD(19)) \ - SH_CLK_SET_RATIO(&pll3_clk_ratio, p31, 1); \ - else \ - SH_CLK_SET_RATIO(&pll3_clk_ratio, p30, 1) - - -void __init r8a7790_clock_init(void) -{ - u32 mode = rcar_gen2_read_mode_pins(); - int k, ret = 0; - - switch (mode & (MD(14) | MD(13))) { - case 0: - R8A7790_CLOCK_ROOT(15, &extal_clk, 172, 208, 106, 88); - break; - case MD(13): - R8A7790_CLOCK_ROOT(20, &extal_clk, 130, 156, 80, 66); - break; - case MD(14): - R8A7790_CLOCK_ROOT(26 / 2, &extal_div2_clk, 200, 240, 122, 102); - break; - case MD(13) | MD(14): - R8A7790_CLOCK_ROOT(30 / 2, &extal_div2_clk, 172, 208, 106, 88); - break; - } - - if (mode & (MD(18))) - SH_CLK_SET_RATIO(&lb_clk_ratio, 1, 36); - else - SH_CLK_SET_RATIO(&lb_clk_ratio, 1, 24); - - if ((mode & (MD(3) | MD(2) | MD(1))) == MD(2)) - SH_CLK_SET_RATIO(&qspi_clk_ratio, 1, 16); - else - SH_CLK_SET_RATIO(&qspi_clk_ratio, 1, 20); - - for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) - ret = clk_register(main_clks[k]); - - if (!ret) - ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); - - if (!ret) - ret = sh_clk_div6_register(div6_clks, DIV6_NR); - - if (!ret) - ret = sh_clk_mstp_register(mstp_clks, MSTP_NR); - - clkdev_add_table(lookups, ARRAY_SIZE(lookups)); - - if (!ret) - shmobile_clk_init(); - else - panic("failed to setup r8a7790 clocks\n"); -} diff --git a/arch/arm/mach-shmobile/r8a7790.h b/arch/arm/mach-shmobile/r8a7790.h index 388f0514d931..bf73a850aaed 100644 --- a/arch/arm/mach-shmobile/r8a7790.h +++ b/arch/arm/mach-shmobile/r8a7790.h @@ -1,34 +1,6 @@ #ifndef __ASM_R8A7790_H__ #define __ASM_R8A7790_H__ -/* DMA slave IDs */ -enum { - RCAR_DMA_SLAVE_INVALID, - AUDIO_DMAC_SLAVE_SSI0_TX, - AUDIO_DMAC_SLAVE_SSI0_RX, - AUDIO_DMAC_SLAVE_SSI1_TX, - AUDIO_DMAC_SLAVE_SSI1_RX, - AUDIO_DMAC_SLAVE_SSI2_TX, - AUDIO_DMAC_SLAVE_SSI2_RX, - AUDIO_DMAC_SLAVE_SSI3_TX, - AUDIO_DMAC_SLAVE_SSI3_RX, - AUDIO_DMAC_SLAVE_SSI4_TX, - AUDIO_DMAC_SLAVE_SSI4_RX, - AUDIO_DMAC_SLAVE_SSI5_TX, - AUDIO_DMAC_SLAVE_SSI5_RX, - AUDIO_DMAC_SLAVE_SSI6_TX, - AUDIO_DMAC_SLAVE_SSI6_RX, - AUDIO_DMAC_SLAVE_SSI7_TX, - AUDIO_DMAC_SLAVE_SSI7_RX, - AUDIO_DMAC_SLAVE_SSI8_TX, - AUDIO_DMAC_SLAVE_SSI8_RX, - AUDIO_DMAC_SLAVE_SSI9_TX, - AUDIO_DMAC_SLAVE_SSI9_RX, -}; - -void r8a7790_add_standard_devices(void); -void r8a7790_clock_init(void); -void r8a7790_pinmux_init(void); void r8a7790_pm_init(void); extern struct smp_operations r8a7790_smp_ops; diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c index ec7d97dca4de..3a18af4922b4 100644 --- a/arch/arm/mach-shmobile/setup-r8a7790.c +++ b/arch/arm/mach-shmobile/setup-r8a7790.c @@ -14,295 +14,14 @@ * GNU General Public License for more details. */ -#include -#include -#include -#include -#include -#include -#include -#include +#include #include #include "common.h" -#include "dma-register.h" -#include "irqs.h" #include "r8a7790.h" #include "rcar-gen2.h" -/* Audio-DMAC */ -#define AUDIO_DMAC_SLAVE(_id, _addr, t, r) \ -{ \ - .slave_id = AUDIO_DMAC_SLAVE_## _id ##_TX, \ - .addr = _addr + 0x8, \ - .chcr = CHCR_TX(XMIT_SZ_32BIT), \ - .mid_rid = t, \ -}, { \ - .slave_id = AUDIO_DMAC_SLAVE_## _id ##_RX, \ - .addr = _addr + 0xc, \ - .chcr = CHCR_RX(XMIT_SZ_32BIT), \ - .mid_rid = r, \ -} - -static const struct sh_dmae_slave_config r8a7790_audio_dmac_slaves[] = { - AUDIO_DMAC_SLAVE(SSI0, 0xec241000, 0x01, 0x02), - AUDIO_DMAC_SLAVE(SSI1, 0xec241040, 0x03, 0x04), - AUDIO_DMAC_SLAVE(SSI2, 0xec241080, 0x05, 0x06), - AUDIO_DMAC_SLAVE(SSI3, 0xec2410c0, 0x07, 0x08), - AUDIO_DMAC_SLAVE(SSI4, 0xec241100, 0x09, 0x0a), - AUDIO_DMAC_SLAVE(SSI5, 0xec241140, 0x0b, 0x0c), - AUDIO_DMAC_SLAVE(SSI6, 0xec241180, 0x0d, 0x0e), - AUDIO_DMAC_SLAVE(SSI7, 0xec2411c0, 0x0f, 0x10), - AUDIO_DMAC_SLAVE(SSI8, 0xec241200, 0x11, 0x12), - AUDIO_DMAC_SLAVE(SSI9, 0xec241240, 0x13, 0x14), -}; - -#define DMAE_CHANNEL(a, b) \ -{ \ - .offset = (a) - 0x20, \ - .dmars = (a) - 0x20 + 0x40, \ - .chclr_bit = (b), \ - .chclr_offset = 0x80 - 0x20, \ -} - -static const struct sh_dmae_channel r8a7790_audio_dmac_channels[] = { - DMAE_CHANNEL(0x8000, 0), - DMAE_CHANNEL(0x8080, 1), - DMAE_CHANNEL(0x8100, 2), - DMAE_CHANNEL(0x8180, 3), - DMAE_CHANNEL(0x8200, 4), - DMAE_CHANNEL(0x8280, 5), - DMAE_CHANNEL(0x8300, 6), - DMAE_CHANNEL(0x8380, 7), - DMAE_CHANNEL(0x8400, 8), - DMAE_CHANNEL(0x8480, 9), - DMAE_CHANNEL(0x8500, 10), - DMAE_CHANNEL(0x8580, 11), - DMAE_CHANNEL(0x8600, 12), -}; - -static struct sh_dmae_pdata r8a7790_audio_dmac_platform_data = { - .slave = r8a7790_audio_dmac_slaves, - .slave_num = ARRAY_SIZE(r8a7790_audio_dmac_slaves), - .channel = r8a7790_audio_dmac_channels, - .channel_num = ARRAY_SIZE(r8a7790_audio_dmac_channels), - .ts_low_shift = TS_LOW_SHIFT, - .ts_low_mask = TS_LOW_BIT << TS_LOW_SHIFT, - .ts_high_shift = TS_HI_SHIFT, - .ts_high_mask = TS_HI_BIT << TS_HI_SHIFT, - .ts_shift = dma_ts_shift, - .ts_shift_num = ARRAY_SIZE(dma_ts_shift), - .dmaor_init = DMAOR_DME, - .chclr_present = 1, - .chclr_bitwise = 1, -}; - -static struct resource r8a7790_audio_dmac_resources[] = { - /* Channel registers and DMAOR for low */ - DEFINE_RES_MEM(0xec700020, 0x8663 - 0x20), - DEFINE_RES_IRQ(gic_spi(346)), - DEFINE_RES_NAMED(gic_spi(320), 13, NULL, IORESOURCE_IRQ), - - /* Channel registers and DMAOR for hi */ - DEFINE_RES_MEM(0xec720020, 0x8663 - 0x20), /* hi */ - DEFINE_RES_IRQ(gic_spi(347)), - DEFINE_RES_NAMED(gic_spi(333), 13, NULL, IORESOURCE_IRQ), -}; - -#define r8a7790_register_audio_dmac(id) \ - platform_device_register_resndata( \ - NULL, "sh-dma-engine", id, \ - &r8a7790_audio_dmac_resources[id * 3], 3, \ - &r8a7790_audio_dmac_platform_data, \ - sizeof(r8a7790_audio_dmac_platform_data)) - -static const struct resource pfc_resources[] __initconst = { - DEFINE_RES_MEM(0xe6060000, 0x250), -}; - -#define r8a7790_register_pfc() \ - platform_device_register_simple("pfc-r8a7790", -1, pfc_resources, \ - ARRAY_SIZE(pfc_resources)) - -#define R8A7790_GPIO(idx) \ -static const struct resource r8a7790_gpio##idx##_resources[] __initconst = { \ - DEFINE_RES_MEM(0xe6050000 + 0x1000 * (idx), 0x50), \ - DEFINE_RES_IRQ(gic_spi(4 + (idx))), \ -}; \ - \ -static const struct gpio_rcar_config \ -r8a7790_gpio##idx##_platform_data __initconst = { \ - .gpio_base = 32 * (idx), \ - .irq_base = 0, \ - .number_of_pins = 32, \ - .pctl_name = "pfc-r8a7790", \ - .has_both_edge_trigger = 1, \ -}; \ - -R8A7790_GPIO(0); -R8A7790_GPIO(1); -R8A7790_GPIO(2); -R8A7790_GPIO(3); -R8A7790_GPIO(4); -R8A7790_GPIO(5); - -#define r8a7790_register_gpio(idx) \ - platform_device_register_resndata(NULL, "gpio_rcar", idx, \ - r8a7790_gpio##idx##_resources, \ - ARRAY_SIZE(r8a7790_gpio##idx##_resources), \ - &r8a7790_gpio##idx##_platform_data, \ - sizeof(r8a7790_gpio##idx##_platform_data)) - -static struct resource i2c_resources[] __initdata = { - /* I2C0 */ - DEFINE_RES_MEM(0xE6508000, 0x40), - DEFINE_RES_IRQ(gic_spi(287)), - /* I2C1 */ - DEFINE_RES_MEM(0xE6518000, 0x40), - DEFINE_RES_IRQ(gic_spi(288)), - /* I2C2 */ - DEFINE_RES_MEM(0xE6530000, 0x40), - DEFINE_RES_IRQ(gic_spi(286)), - /* I2C3 */ - DEFINE_RES_MEM(0xE6540000, 0x40), - DEFINE_RES_IRQ(gic_spi(290)), - -}; - -#define r8a7790_register_i2c(idx) \ - platform_device_register_simple( \ - "i2c-rcar_gen2", idx, \ - i2c_resources + (2 * idx), 2); \ - -void __init r8a7790_pinmux_init(void) -{ - r8a7790_register_pfc(); - r8a7790_register_gpio(0); - r8a7790_register_gpio(1); - r8a7790_register_gpio(2); - r8a7790_register_gpio(3); - r8a7790_register_gpio(4); - r8a7790_register_gpio(5); -} - -#define __R8A7790_SCIF(scif_type, _scscr, index, baseaddr, irq) \ -static struct plat_sci_port scif##index##_platform_data = { \ - .type = scif_type, \ - .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, \ - .scscr = _scscr, \ -}; \ - \ -static struct resource scif##index##_resources[] = { \ - DEFINE_RES_MEM(baseaddr, 0x100), \ - DEFINE_RES_IRQ(irq), \ -} - -#define R8A7790_SCIF(index, baseaddr, irq) \ - __R8A7790_SCIF(PORT_SCIF, SCSCR_RE | SCSCR_TE, \ - index, baseaddr, irq) - -#define R8A7790_SCIFA(index, baseaddr, irq) \ - __R8A7790_SCIF(PORT_SCIFA, SCSCR_RE | SCSCR_TE | SCSCR_CKE0, \ - index, baseaddr, irq) - -#define R8A7790_SCIFB(index, baseaddr, irq) \ - __R8A7790_SCIF(PORT_SCIFB, SCSCR_RE | SCSCR_TE, \ - index, baseaddr, irq) - -#define R8A7790_HSCIF(index, baseaddr, irq) \ - __R8A7790_SCIF(PORT_HSCIF, SCSCR_RE | SCSCR_TE, \ - index, baseaddr, irq) - -R8A7790_SCIFA(0, 0xe6c40000, gic_spi(144)); /* SCIFA0 */ -R8A7790_SCIFA(1, 0xe6c50000, gic_spi(145)); /* SCIFA1 */ -R8A7790_SCIFB(2, 0xe6c20000, gic_spi(148)); /* SCIFB0 */ -R8A7790_SCIFB(3, 0xe6c30000, gic_spi(149)); /* SCIFB1 */ -R8A7790_SCIFB(4, 0xe6ce0000, gic_spi(150)); /* SCIFB2 */ -R8A7790_SCIFA(5, 0xe6c60000, gic_spi(151)); /* SCIFA2 */ -R8A7790_SCIF(6, 0xe6e60000, gic_spi(152)); /* SCIF0 */ -R8A7790_SCIF(7, 0xe6e68000, gic_spi(153)); /* SCIF1 */ -R8A7790_HSCIF(8, 0xe62c0000, gic_spi(154)); /* HSCIF0 */ -R8A7790_HSCIF(9, 0xe62c8000, gic_spi(155)); /* HSCIF1 */ - -#define r8a7790_register_scif(index) \ - platform_device_register_resndata(NULL, "sh-sci", index, \ - scif##index##_resources, \ - ARRAY_SIZE(scif##index##_resources), \ - &scif##index##_platform_data, \ - sizeof(scif##index##_platform_data)) - -static const struct renesas_irqc_config irqc0_data __initconst = { - .irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */ -}; - -static const struct resource irqc0_resources[] __initconst = { - DEFINE_RES_MEM(0xe61c0000, 0x200), /* IRQC Event Detector Block_0 */ - DEFINE_RES_IRQ(gic_spi(0)), /* IRQ0 */ - DEFINE_RES_IRQ(gic_spi(1)), /* IRQ1 */ - DEFINE_RES_IRQ(gic_spi(2)), /* IRQ2 */ - DEFINE_RES_IRQ(gic_spi(3)), /* IRQ3 */ -}; - -#define r8a7790_register_irqc(idx) \ - platform_device_register_resndata(NULL, "renesas_irqc", \ - idx, irqc##idx##_resources, \ - ARRAY_SIZE(irqc##idx##_resources), \ - &irqc##idx##_data, \ - sizeof(struct renesas_irqc_config)) - -static const struct resource thermal_resources[] __initconst = { - DEFINE_RES_MEM(0xe61f0000, 0x14), - DEFINE_RES_MEM(0xe61f0100, 0x38), - DEFINE_RES_IRQ(gic_spi(69)), -}; - -#define r8a7790_register_thermal() \ - platform_device_register_simple("rcar_thermal", -1, \ - thermal_resources, \ - ARRAY_SIZE(thermal_resources)) - -static struct sh_timer_config cmt0_platform_data = { - .channels_mask = 0x60, -}; - -static struct resource cmt0_resources[] = { - DEFINE_RES_MEM(0xffca0000, 0x1004), - DEFINE_RES_IRQ(gic_spi(142)), -}; - -#define r8a7790_register_cmt(idx) \ - platform_device_register_resndata(NULL, "sh-cmt-48-gen2", \ - idx, cmt##idx##_resources, \ - ARRAY_SIZE(cmt##idx##_resources), \ - &cmt##idx##_platform_data, \ - sizeof(struct sh_timer_config)) - -void __init r8a7790_add_standard_devices(void) -{ - r8a7790_register_scif(0); - r8a7790_register_scif(1); - r8a7790_register_scif(2); - r8a7790_register_scif(3); - r8a7790_register_scif(4); - r8a7790_register_scif(5); - r8a7790_register_scif(6); - r8a7790_register_scif(7); - r8a7790_register_scif(8); - r8a7790_register_scif(9); - r8a7790_register_cmt(0); - r8a7790_register_irqc(0); - r8a7790_register_thermal(); - r8a7790_register_i2c(0); - r8a7790_register_i2c(1); - r8a7790_register_i2c(2); - r8a7790_register_i2c(3); - r8a7790_register_audio_dmac(0); - r8a7790_register_audio_dmac(1); -} - -#ifdef CONFIG_USE_OF - static const char * const r8a7790_boards_compat_dt[] __initconst = { "renesas,r8a7790", NULL, @@ -316,4 +35,3 @@ DT_MACHINE_START(R8A7790_DT, "Generic R8A7790 (Flattened Device Tree)") .reserve = rcar_gen2_reserve, .dt_compat = r8a7790_boards_compat_dt, MACHINE_END -#endif /* CONFIG_USE_OF */ -- cgit v1.2.3 From 78c11ec2e0c63262bae78c99872d4df81fb6d1e6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 18 Oct 2013 16:00:00 +0200 Subject: ARM: shmobile: lager: Rename SCIFA[01] serial ports to ttySC[01] There's no reason to name the only two available serial ports on the board ttySC6 and ttySC7 (apart from confusing userspace, which we should try to avoid). Signed-off-by: Laurent Pinchart Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790-lager.dts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts index 636d53bb87a2..ec843192d653 100644 --- a/arch/arm/boot/dts/r8a7790-lager.dts +++ b/arch/arm/boot/dts/r8a7790-lager.dts @@ -47,12 +47,12 @@ compatible = "renesas,lager", "renesas,r8a7790"; aliases { - serial6 = &scifa0; - serial7 = &scifa1; + serial0 = &scifa0; + serial1 = &scifa1; }; chosen { - bootargs = "console=ttySC6,115200 ignore_loglevel rw root=/dev/nfs ip=dhcp"; + bootargs = "console=ttySC0,115200 ignore_loglevel rw root=/dev/nfs ip=dhcp"; stdout-path = &scifa0; }; -- cgit v1.2.3 From 1f75cdac773bc9c93ad6126c01ae27bd343302b1 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 18 Oct 2013 16:00:00 +0200 Subject: ARM: shmobile: koelsch: Rename SCIF[01] serial ports to ttySC[01] There's no reason to name the only two available serial ports on the board ttySC6 and ttySC7 (apart from confusing userspace, which we should try to avoid). Signed-off-by: Laurent Pinchart Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7791-koelsch.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts index 990af167c551..bf58c79a6554 100644 --- a/arch/arm/boot/dts/r8a7791-koelsch.dts +++ b/arch/arm/boot/dts/r8a7791-koelsch.dts @@ -48,8 +48,8 @@ compatible = "renesas,koelsch", "renesas,r8a7791"; aliases { - serial6 = &scif0; - serial7 = &scif1; + serial0 = &scif0; + serial1 = &scif1; }; chosen { -- cgit v1.2.3 From 569dd56c9971c699472d3b270e988baf7f6de8c9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 2 Dec 2014 18:39:48 +0100 Subject: ARM: shmobile: lager dts: Drop console= bootargs parameter Since commit FIXME ("ARM: shmobile: lager: Remove legacy board support"), lager is restricted to booting from DT, so chosen/stdout-path is always used, and we can drop the "console=" parameter from chosen/bootargs. Signed-off-by: Geert Uytterhoeven Signed-off-by: Laurent Pinchart Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790-lager.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts index ec843192d653..4118030f366d 100644 --- a/arch/arm/boot/dts/r8a7790-lager.dts +++ b/arch/arm/boot/dts/r8a7790-lager.dts @@ -52,7 +52,7 @@ }; chosen { - bootargs = "console=ttySC0,115200 ignore_loglevel rw root=/dev/nfs ip=dhcp"; + bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp"; stdout-path = &scifa0; }; -- cgit v1.2.3 From 00df611376e5cd84ae836d04608766096e4702e6 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 10 Dec 2014 15:45:24 +0100 Subject: ARM: shmobile: sh73a0: Common clock framework DT description Declares all sh73a0 clocks supported by the legacy clock framework. Signed-off-by: Ulrich Hecht Tested-by: Geert Uytterhoeven Acked-by: Laurent Pinchart Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/sh73a0.dtsi | 329 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi index d8def5a529da..3f21b3257679 100644 --- a/arch/arm/boot/dts/sh73a0.dtsi +++ b/arch/arm/boot/dts/sh73a0.dtsi @@ -10,6 +10,7 @@ /include/ "skeleton.dtsi" +#include #include / { @@ -322,4 +323,332 @@ interrupts = <0 146 0x4>; status = "disabled"; }; + + clocks { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + /* External root clocks */ + extalr_clk: extalr_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "extalr"; + }; + extal1_clk: extal1_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <26000000>; + clock-output-names = "extal1"; + }; + extal2_clk: extal2_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-output-names = "extal2"; + }; + extcki_clk: extcki_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-output-names = "extcki"; + }; + fsiack_clk: fsiack_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + clock-output-names = "fsiack"; + }; + fsibck_clk: fsibck_clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + clock-output-names = "fsibck"; + }; + + /* Special CPG clocks */ + cpg_clocks: cpg_clocks@e6150000 { + compatible = "renesas,sh73a0-cpg-clocks"; + reg = <0xe6150000 0x10000>; + clocks = <&extal1_clk>, <&extal2_clk>; + #clock-cells = <1>; + clock-output-names = "main", "pll0", "pll1", "pll2", + "pll3", "dsi0phy", "dsi1phy", + "zg", "m3", "b", "m1", "m2", + "z", "zx", "hp"; + }; + + /* Variable factor clocks (DIV6) */ + vclk1_clk: vclk1_clk@e6150008 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150008 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "vclk1"; + }; + vclk2_clk: vclk2_clk@e615000c { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe615000c 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "vclk2"; + }; + vclk3_clk: vclk3_clk@e615001c { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe615001c 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "vclk3"; + }; + zb_clk: zb_clk@e6150010 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150010 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "zb"; + }; + flctl_clk: flctl_clk@e6150014 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150014 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "flctlck"; + }; + sdhi0_clk: sdhi0_clk@e6150074 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150074 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "sdhi0ck"; + }; + sdhi1_clk: sdhi1_clk@e6150078 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150078 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "sdhi1ck"; + }; + sdhi2_clk: sdhi2_clk@e615007c { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe615007c 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "sdhi2ck"; + }; + fsia_clk: fsia_clk@e6150018 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150018 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "fsia"; + }; + fsib_clk: fsib_clk@e6150090 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150090 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "fsib"; + }; + sub_clk: sub_clk@e6150080 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150080 4>; + clocks = <&extal2_clk>; + #clock-cells = <0>; + clock-output-names = "sub"; + }; + spua_clk: spua_clk@e6150084 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150084 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "spua"; + }; + spuv_clk: spuv_clk@e6150094 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150094 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "spuv"; + }; + msu_clk: msu_clk@e6150088 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150088 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "msu"; + }; + hsi_clk: hsi_clk@e615008c { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe615008c 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "hsi"; + }; + mfg1_clk: mfg1_clk@e6150098 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150098 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "mfg1"; + }; + mfg2_clk: mfg2_clk@e615009c { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe615009c 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "mfg2"; + }; + dsit_clk: dsit_clk@e6150060 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150060 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "dsit"; + }; + dsi0p_clk: dsi0p_clk@e6150064 { + compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock"; + reg = <0xe6150064 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "dsi0pck"; + }; + + /* Fixed factor clocks */ + main_div2_clk: main_div2_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks SH73A0_CLK_MAIN>; + #clock-cells = <0>; + clock-div = <2>; + clock-mult = <1>; + clock-output-names = "main_div2"; + }; + pll1_div2_clk: pll1_div2_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks SH73A0_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <2>; + clock-mult = <1>; + clock-output-names = "pll1_div2"; + }; + pll1_div7_clk: pll1_div7_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks SH73A0_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <7>; + clock-mult = <1>; + clock-output-names = "pll1_div7"; + }; + pll1_div13_clk: pll1_div13_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks SH73A0_CLK_PLL1>; + #clock-cells = <0>; + clock-div = <13>; + clock-mult = <1>; + clock-output-names = "pll1_div13"; + }; + twd_clk: twd_clk { + compatible = "fixed-factor-clock"; + clocks = <&cpg_clocks SH73A0_CLK_Z>; + #clock-cells = <0>; + clock-div = <4>; + clock-mult = <1>; + clock-output-names = "twd"; + }; + + /* Gate clocks */ + mstp0_clks: mstp0_clks@e6150130 { + compatible = "renesas,sh73a0-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0xe6150130 4>, <0xe6150030 4>; + clocks = <&cpg_clocks SH73A0_CLK_HP>; + #clock-cells = <1>; + clock-indices = < + SH73A0_CLK_IIC2 + >; + clock-output-names = + "iic2"; + }; + mstp1_clks: mstp1_clks@e6150134 { + compatible = "renesas,sh73a0-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0xe6150134 4>, <0xe6150038 4>; + clocks = <&cpg_clocks SH73A0_CLK_B>, + <&cpg_clocks SH73A0_CLK_B>, + <&cpg_clocks SH73A0_CLK_B>, + <&cpg_clocks SH73A0_CLK_B>, + <&sub_clk>, <&cpg_clocks SH73A0_CLK_B>, + <&cpg_clocks SH73A0_CLK_HP>, + <&cpg_clocks SH73A0_CLK_ZG>, + <&cpg_clocks SH73A0_CLK_B>; + #clock-cells = <1>; + clock-indices = < + SH73A0_CLK_CEU1 SH73A0_CLK_CSI2_RX1 + SH73A0_CLK_CEU0 SH73A0_CLK_CSI2_RX0 + SH73A0_CLK_TMU0 SH73A0_CLK_DSITX0 + SH73A0_CLK_IIC0 SH73A0_CLK_SGX + SH73A0_CLK_LCDC0 + >; + clock-output-names = + "ceu1", "csi2_rx1", "ceu0", "csi2_rx0", + "tmu0", "dsitx0", "iic0", "sgx", "lcdc0"; + }; + mstp2_clks: mstp2_clks@e6150138 { + compatible = "renesas,sh73a0-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0xe6150138 4>, <0xe6150040 4>; + clocks = <&sub_clk>, <&cpg_clocks SH73A0_CLK_HP>, + <&cpg_clocks SH73A0_CLK_HP>, <&sub_clk>, + <&sub_clk>, <&sub_clk>, <&sub_clk>, <&sub_clk>, + <&sub_clk>, <&sub_clk>; + #clock-cells = <1>; + clock-indices = < + SH73A0_CLK_SCIFA7 SH73A0_CLK_SY_DMAC + SH73A0_CLK_MP_DMAC SH73A0_CLK_SCIFA5 + SH73A0_CLK_SCIFB SH73A0_CLK_SCIFA0 + SH73A0_CLK_SCIFA1 SH73A0_CLK_SCIFA2 + SH73A0_CLK_SCIFA3 SH73A0_CLK_SCIFA4 + >; + clock-output-names = + "scifa7", "sy_dmac", "mp_dmac", "scifa5", + "scifb", "scifa0", "scifa1", "scifa2", + "scifa3", "scifa4"; + }; + mstp3_clks: mstp3_clks@e615013c { + compatible = "renesas,sh73a0-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0xe615013c 4>, <0xe6150048 4>; + clocks = <&sub_clk>, <&extalr_clk>, + <&cpg_clocks SH73A0_CLK_HP>, <&sub_clk>, + <&cpg_clocks SH73A0_CLK_HP>, + <&cpg_clocks SH73A0_CLK_HP>, <&flctl_clk>, + <&sdhi0_clk>, <&sdhi1_clk>, + <&cpg_clocks SH73A0_CLK_HP>, <&sdhi2_clk>, + <&main_div2_clk>, <&main_div2_clk>, + <&main_div2_clk>, <&main_div2_clk>, + <&main_div2_clk>; + #clock-cells = <1>; + clock-indices = < + SH73A0_CLK_SCIFA6 SH73A0_CLK_CMT1 + SH73A0_CLK_FSI SH73A0_CLK_IRDA + SH73A0_CLK_IIC1 SH73A0_CLK_USB SH73A0_CLK_FLCTL + SH73A0_CLK_SDHI0 SH73A0_CLK_SDHI1 + SH73A0_CLK_MMCIF0 SH73A0_CLK_SDHI2 + SH73A0_CLK_TPU0 SH73A0_CLK_TPU1 + SH73A0_CLK_TPU2 SH73A0_CLK_TPU3 + SH73A0_CLK_TPU4 + >; + clock-output-names = + "scifa6", "cmt1", "fsi", "irda", "iic1", + "usb", "flctl", "sdhi0", "sdhi1", "mmcif0", "sdhi2", + "tpu0", "tpu1", "tpu2", "tpu3", "tpu4"; + }; + mstp4_clks: mstp4_clks@e6150140 { + compatible = "renesas,sh73a0-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0xe6150140 4>, <0xe615004c 4>; + clocks = <&cpg_clocks SH73A0_CLK_HP>, + <&cpg_clocks SH73A0_CLK_HP>, <&extalr_clk>; + #clock-cells = <1>; + clock-indices = < + SH73A0_CLK_IIC3 SH73A0_CLK_IIC4 + SH73A0_CLK_KEYSC + >; + clock-output-names = + "iic3", "iic4", "keysc"; + }; + }; }; -- cgit v1.2.3 From 1a9a658113c33235ca12e622d91331dd91c61035 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 10 Dec 2014 15:45:25 +0100 Subject: ARM: shmobile: kzm9g-reference: Common clock framework DT description KZM9G-specific clock overrides. Signed-off-by: Ulrich Hecht Acked-by: Laurent Pinchart Tested-by: Geert Uytterhoeven Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/sh73a0-kzm9g-reference.dts | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts index 939be1299ca6..3d912ea8fef4 100644 --- a/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts +++ b/arch/arm/boot/dts/sh73a0-kzm9g-reference.dts @@ -182,6 +182,10 @@ status = "ok"; }; +&extal2_clk { + clock-frequency = <48000000>; +}; + &i2c0 { status = "okay"; as3711@40 { -- cgit v1.2.3 From f73e1e28b5ed9bbb2358606b5abf76d3f94fe8cf Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 10 Dec 2014 15:45:26 +0100 Subject: ARM: shmobile: sh73a0: add MSTP clock assignments to DT Assigns clocks to cmt1, i2c*, mmcif, sdhi*, and scif*. Signed-off-by: Ulrich Hecht Acked-by: Laurent Pinchart Tested-by: Geert Uytterhoeven Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/sh73a0.dtsi | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi index 3f21b3257679..cca22ec59a2e 100644 --- a/arch/arm/boot/dts/sh73a0.dtsi +++ b/arch/arm/boot/dts/sh73a0.dtsi @@ -56,6 +56,8 @@ renesas,channels-mask = <0x3f>; + clocks = <&mstp3_clks SH73A0_CLK_CMT1>; + clock-names = "fck"; status = "disabled"; }; @@ -145,6 +147,7 @@ 0 168 IRQ_TYPE_LEVEL_HIGH 0 169 IRQ_TYPE_LEVEL_HIGH 0 170 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp1_clks SH73A0_CLK_IIC0>; status = "disabled"; }; @@ -157,6 +160,7 @@ 0 52 IRQ_TYPE_LEVEL_HIGH 0 53 IRQ_TYPE_LEVEL_HIGH 0 54 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks SH73A0_CLK_IIC1>; status = "disabled"; }; @@ -169,6 +173,7 @@ 0 172 IRQ_TYPE_LEVEL_HIGH 0 173 IRQ_TYPE_LEVEL_HIGH 0 174 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp0_clks SH73A0_CLK_IIC2>; status = "disabled"; }; @@ -181,6 +186,7 @@ 0 184 IRQ_TYPE_LEVEL_HIGH 0 185 IRQ_TYPE_LEVEL_HIGH 0 186 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp4_clks SH73A0_CLK_IIC3>; status = "disabled"; }; @@ -193,6 +199,7 @@ 0 188 IRQ_TYPE_LEVEL_HIGH 0 189 IRQ_TYPE_LEVEL_HIGH 0 190 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp4_clks SH73A0_CLK_IIC4>; status = "disabled"; }; @@ -201,6 +208,7 @@ reg = <0xe6bd0000 0x100>; interrupts = <0 140 IRQ_TYPE_LEVEL_HIGH 0 141 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks SH73A0_CLK_MMCIF0>; reg-io-width = <4>; status = "disabled"; }; @@ -211,6 +219,7 @@ interrupts = <0 83 IRQ_TYPE_LEVEL_HIGH 0 84 IRQ_TYPE_LEVEL_HIGH 0 85 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks SH73A0_CLK_SDHI0>; cap-sd-highspeed; status = "disabled"; }; @@ -221,6 +230,7 @@ reg = <0xee120000 0x100>; interrupts = <0 88 IRQ_TYPE_LEVEL_HIGH 0 89 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks SH73A0_CLK_SDHI1>; toshiba,mmc-wrprotect-disable; cap-sd-highspeed; status = "disabled"; @@ -231,6 +241,7 @@ reg = <0xee140000 0x100>; interrupts = <0 104 IRQ_TYPE_LEVEL_HIGH 0 105 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks SH73A0_CLK_SDHI2>; toshiba,mmc-wrprotect-disable; cap-sd-highspeed; status = "disabled"; @@ -240,6 +251,8 @@ compatible = "renesas,scifa-sh73a0", "renesas,scifa"; reg = <0xe6c40000 0x100>; interrupts = <0 72 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp2_clks SH73A0_CLK_SCIFA0>; + clock-names = "sci_ick"; status = "disabled"; }; @@ -247,6 +260,8 @@ compatible = "renesas,scifa-sh73a0", "renesas,scifa"; reg = <0xe6c50000 0x100>; interrupts = <0 73 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp2_clks SH73A0_CLK_SCIFA1>; + clock-names = "sci_ick"; status = "disabled"; }; @@ -254,6 +269,8 @@ compatible = "renesas,scifa-sh73a0", "renesas,scifa"; reg = <0xe6c60000 0x100>; interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp2_clks SH73A0_CLK_SCIFA2>; + clock-names = "sci_ick"; status = "disabled"; }; @@ -261,6 +278,8 @@ compatible = "renesas,scifa-sh73a0", "renesas,scifa"; reg = <0xe6c70000 0x100>; interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp2_clks SH73A0_CLK_SCIFA3>; + clock-names = "sci_ick"; status = "disabled"; }; @@ -268,6 +287,8 @@ compatible = "renesas,scifa-sh73a0", "renesas,scifa"; reg = <0xe6c80000 0x100>; interrupts = <0 78 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp2_clks SH73A0_CLK_SCIFA4>; + clock-names = "sci_ick"; status = "disabled"; }; @@ -275,6 +296,8 @@ compatible = "renesas,scifa-sh73a0", "renesas,scifa"; reg = <0xe6cb0000 0x100>; interrupts = <0 79 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp2_clks SH73A0_CLK_SCIFA5>; + clock-names = "sci_ick"; status = "disabled"; }; @@ -282,6 +305,8 @@ compatible = "renesas,scifa-sh73a0", "renesas,scifa"; reg = <0xe6cc0000 0x100>; interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp3_clks SH73A0_CLK_SCIFA6>; + clock-names = "sci_ick"; status = "disabled"; }; @@ -289,6 +314,8 @@ compatible = "renesas,scifa-sh73a0", "renesas,scifa"; reg = <0xe6cd0000 0x100>; interrupts = <0 143 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp2_clks SH73A0_CLK_SCIFA7>; + clock-names = "sci_ick"; status = "disabled"; }; @@ -296,6 +323,8 @@ compatible = "renesas,scifb-sh73a0", "renesas,scifb"; reg = <0xe6c30000 0x100>; interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&mstp2_clks SH73A0_CLK_SCIFB>; + clock-names = "sci_ick"; status = "disabled"; }; -- cgit v1.2.3 From 09bd745b555c262d1e2c851777317f3adf3cf3d4 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 10 Dec 2014 15:45:27 +0100 Subject: ARM: shmobile: sh73a0: disable legacy clock initialization Disables sh73a0_clock_init() if CCF is enabled. Signed-off-by: Ulrich Hecht Acked-by: Laurent Pinchart Tested-by: Geert Uytterhoeven Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/setup-sh73a0.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c index 93ebe3430bfe..354cab111bf1 100644 --- a/arch/arm/mach-shmobile/setup-sh73a0.c +++ b/arch/arm/mach-shmobile/setup-sh73a0.c @@ -763,7 +763,9 @@ void __init __weak sh73a0_register_twd(void) { } void __init sh73a0_earlytimer_init(void) { shmobile_init_delay(); +#ifndef CONFIG_COMMON_CLK sh73a0_clock_init(); +#endif shmobile_earlytimer_init(); sh73a0_register_twd(); } @@ -782,8 +784,9 @@ void __init sh73a0_add_early_devices(void) void __init sh73a0_add_standard_devices_dt(void) { /* clocks are setup late during boot in the case of DT */ +#ifndef CONFIG_COMMON_CLK sh73a0_clock_init(); - +#endif of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } -- cgit v1.2.3 From 2f472ae6b1998af6d9a4ccc3f0d58781db21cafc Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 19 Nov 2014 16:26:59 +0100 Subject: ARM: shmobile: sh73a0 legacy/reference: Add missing INTCA0 clock for irqpin module This clock drives the irqpin controller modules. Before, it was assumed enabled by the bootloader or reset state. By making it available to the driver, we make sure it gets enabled when needed, and allow it to be managed by system or runtime PM. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/clock-sh73a0.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c index 6b4c1f313cc9..3855fb024fdb 100644 --- a/arch/arm/mach-shmobile/clock-sh73a0.c +++ b/arch/arm/mach-shmobile/clock-sh73a0.c @@ -553,6 +553,7 @@ enum { MSTP001, MSTP314, MSTP313, MSTP312, MSTP311, MSTP304, MSTP303, MSTP302, MSTP301, MSTP300, MSTP411, MSTP410, MSTP403, + MSTP508, MSTP_NR }; #define MSTP(_parent, _reg, _bit, _flags) \ @@ -597,6 +598,7 @@ static struct clk mstp_clks[MSTP_NR] = { [MSTP411] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 11, 0), /* IIC3 */ [MSTP410] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 10, 0), /* IIC4 */ [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */ + [MSTP508] = MSTP(&div4_clks[DIV4_HP], SMSTPCR5, 8, 0), /* INTCA0 */ }; /* The lookups structure below includes duplicate entries for some clocks @@ -677,6 +679,14 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* I2C4 */ CLKDEV_DEV_ID("e6828000.i2c", &mstp_clks[MSTP410]), /* I2C4 */ CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */ + CLKDEV_DEV_ID("renesas_intc_irqpin.0", &mstp_clks[MSTP508]), /* INTCA0 */ + CLKDEV_DEV_ID("e6900000.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */ + CLKDEV_DEV_ID("renesas_intc_irqpin.1", &mstp_clks[MSTP508]), /* INTCA0 */ + CLKDEV_DEV_ID("e6900004.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */ + CLKDEV_DEV_ID("renesas_intc_irqpin.2", &mstp_clks[MSTP508]), /* INTCA0 */ + CLKDEV_DEV_ID("e6900008.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */ + CLKDEV_DEV_ID("renesas_intc_irqpin.3", &mstp_clks[MSTP508]), /* INTCA0 */ + CLKDEV_DEV_ID("e690000c.irqpin", &mstp_clks[MSTP508]), /* INTCA0 */ /* ICK */ CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]), -- cgit v1.2.3 From 95abc9de7896bf65e67bf781d709ec453f1f5f84 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 3 Dec 2014 20:48:04 +0900 Subject: ARM: shmobile: Fix is_e2 warning Fix "is_e2" warning introduced by: 9ce3fa6 ARM: shmobile: rcar-gen2: Add CA7 arch_timer initialization for r8a7794 Only triggers on kernel configurations that have ARCH_ARM_TIMER=n. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/setup-rcar-gen2.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/setup-rcar-gen2.c b/arch/arm/mach-shmobile/setup-rcar-gen2.c index 3dd6edd9bd1d..c35b91d92190 100644 --- a/arch/arm/mach-shmobile/setup-rcar-gen2.c +++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c @@ -52,15 +52,13 @@ void __init rcar_gen2_timer_init(void) { #if defined(CONFIG_ARM_ARCH_TIMER) || defined(CONFIG_COMMON_CLK) u32 mode = rcar_gen2_read_mode_pins(); - bool is_e2 = (bool)of_find_compatible_node(NULL, NULL, - "renesas,r8a7794"); #endif #ifdef CONFIG_ARM_ARCH_TIMER void __iomem *base; int extal_mhz = 0; u32 freq; - if (is_e2) { + if (of_machine_is_compatible("renesas,r8a7794")) { freq = 260000000 / 8; /* ZS / 8 */ /* CNTVOFF has to be initialized either from non-secure * Hypervisor mode or secure Monitor mode with SCR.NS==1. -- cgit v1.2.3 From 1dc13eee3a5c60131657482aa88c997e5fa8b50c Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 16 Dec 2014 18:39:31 +0900 Subject: ARM: shmobile: r8a7779: No TWD setup in C for Multiplatform Skip the TWD setup in C for r8a7779 Multiplatform. We should use DTS for the TWD device anyway. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/smp-r8a7779.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c index 3f761f839043..9fc280e24ef4 100644 --- a/arch/arm/mach-shmobile/smp-r8a7779.c +++ b/arch/arm/mach-shmobile/smp-r8a7779.c @@ -56,7 +56,7 @@ static struct rcar_sysc_ch *r8a7779_ch_cpu[4] = { [3] = &r8a7779_ch_cpu3, }; -#ifdef CONFIG_HAVE_ARM_TWD +#if defined(CONFIG_HAVE_ARM_TWD) && !defined(CONFIG_ARCH_MULTIPLATFORM) static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, R8A7779_SCU_BASE + 0x600, 29); void __init r8a7779_register_twd(void) { -- cgit v1.2.3 From 39695882d3d642a73bca551e682426e4e3bcd158 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 17 Dec 2014 17:18:17 +0100 Subject: ARM: shmobile: r8a73a4: Multiplatform support Enable r8a73a4 Multiplatform support for the generic r8a73a4 machine vector. Signed-off-by: Ulrich Hecht Acked-by: Magnus Damm Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/Kconfig | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 1b4fafe524ff..d107b9386bda 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -51,6 +51,11 @@ config ARCH_R7S72100 bool "RZ/A1H (R7S72100)" select SYS_SUPPORTS_SH_MTU2 +config ARCH_R8A73A4 + bool "R-Mobile APE6 (R8A73A40)" + select ARCH_RMOBILE + select RENESAS_IRQC + config ARCH_R8A7740 bool "R-Mobile A1 (R8A77400)" select ARCH_RMOBILE -- cgit v1.2.3 From ce85ad47882fe375dcb3f7cce6c10ae800ac2d9c Mon Sep 17 00:00:00 2001 From: Ryo Kataoka Date: Tue, 9 Dec 2014 13:21:22 +0900 Subject: ARM: shmobile: r8a7791: Add IPMMU-SGX clock to device tree Signed-off-by: Ryo Kataoka [horms: resolved conflicts] Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7791.dtsi | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index 958a69b24ff4..78d637135e77 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -1154,15 +1154,17 @@ mstp8_clks: mstp8_clks@e6150990 { compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe6150990 0 4>, <0 0xe61509a0 0 4>; - clocks = <&zg_clk>, <&zg_clk>, <&zg_clk>, <&p_clk>, <&zs_clk>, - <&zs_clk>; + clocks = <&zg_clk>, <&zg_clk>, <&zg_clk>, <&zg_clk>, <&p_clk>, + <&zs_clk>, <&zs_clk>; #clock-cells = <1>; clock-indices = < + R8A7791_CLK_IPMMU_SGX R8A7791_CLK_VIN2 R8A7791_CLK_VIN1 R8A7791_CLK_VIN0 R8A7791_CLK_ETHER R8A7791_CLK_SATA1 R8A7791_CLK_SATA0 >; clock-output-names = - "vin2", "vin1", "vin0", "ether", "sata1", "sata0"; + "ipmmu_sgx", "vin2", "vin1", "vin0", "ether", "sata1", + "sata0"; }; mstp9_clks: mstp9_clks@e6150994 { compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks"; -- cgit v1.2.3 From be16cd385c08dce7efa406704b5aa420ef6d1992 Mon Sep 17 00:00:00 2001 From: Hiroyuki Yokoyama Date: Wed, 10 Dec 2014 10:21:12 +0900 Subject: ARM: shmobile: r8a7794: Add SYS-DMAC clocks to device tree Signed-off-by: Hiroyuki Yokoyama [horms: resolved conflicts] Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7794.dtsi | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index 13e4a8d73029..6d95638987e7 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -479,16 +479,19 @@ compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe6150138 0 4>, <0 0xe6150040 0 4>; clocks = <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>, <&mp_clk>, - <&mp_clk>, <&mp_clk>, <&mp_clk>; + <&mp_clk>, <&mp_clk>, <&mp_clk>, + <&zs_clk>, <&zs_clk>; #clock-cells = <1>; clock-indices = < R8A7794_CLK_SCIFA2 R8A7794_CLK_SCIFA1 R8A7794_CLK_SCIFA0 R8A7794_CLK_MSIOF2 R8A7794_CLK_SCIFB0 R8A7794_CLK_SCIFB1 R8A7794_CLK_MSIOF1 R8A7794_CLK_SCIFB2 + R8A7794_CLK_SYS_DMAC1 R8A7794_CLK_SYS_DMAC0 >; clock-output-names = "scifa2", "scifa1", "scifa0", "msiof2", "scifb0", - "scifb1", "msiof1", "scifb2"; + "scifb1", "msiof1", "scifb2", + "sys-dmac1", "sys-dmac0"; }; mstp3_clks: mstp3_clks@e615013c { compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; -- cgit v1.2.3 From cbf41168339adcb48de6a3537f88d4e85285db99 Mon Sep 17 00:00:00 2001 From: Hisashi Nakamura Date: Wed, 10 Dec 2014 11:30:27 +0900 Subject: ARM: shmobile: lager: Fix QSPI mode of SPI-Flash into mode3 In order to change into mode3, CPOL and CPHA bit of SPCMD register of QSPI is changed. Mode3 can avoid intermediate voltage. Signed-off-by: Hisashi Nakamura [horms: Updated changelog and re-ordered properties] Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7790-lager.dts | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts index 636d53bb87a2..bc257e8b1bf2 100644 --- a/arch/arm/boot/dts/r8a7790-lager.dts +++ b/arch/arm/boot/dts/r8a7790-lager.dts @@ -397,6 +397,8 @@ spi-max-frequency = <30000000>; spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; + spi-cpha; + spi-cpol; m25p,fast-read; partition@0 { -- cgit v1.2.3 From 3281480b70ceb9889b71f7b8a7bf54db3c05d40e Mon Sep 17 00:00:00 2001 From: Hisashi Nakamura Date: Thu, 11 Dec 2014 12:21:14 +0900 Subject: ARM: shmobile: r8a7794: Add QSPI clock to device tree Signed-off-by: Hisashi Nakamura [horms: omitted device node and alias; only add clock] [horms: use clock-indicies instead of renesas,clock-indicies] Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7794.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index 6d95638987e7..068ca0981ac9 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -535,6 +535,14 @@ clock-output-names = "vin1", "vin0", "ether"; }; + mstp9_clks: mstp9_clks@e6150994 { + compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; + reg = <0 0xe6150994 0 4>, <0 0xe61509a4 0 4>; + clocks = <&cpg_clocks R8A7794_CLK_QSPI>; + #clock-cells = <1>; + clock-indices = ; + clock-output-names = "qspi_mod"; + }; mstp11_clks: mstp11_clks@e615099c { compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe615099c 0 4>, <0 0xe61509ac 0 4>; -- cgit v1.2.3 From c6ce3cdfce6c0214f178fbad73d138dd1f1b04f6 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 15 Dec 2014 14:00:34 +0900 Subject: ARM: shmobile: r8a7779: Use R8A7779_CLK_P as SCIF parent clock Use R8A7779_CLK_P as parent clock for SCIF devices on r8a7779. With this change in place the SCIF CCF handling matches the legacy clock code. Also, this matches the data sheet. Signed-off-by: Magnus Damm Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7779.dtsi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi index e3846af833e1..ee3bb3e9cbf1 100644 --- a/arch/arm/boot/dts/r8a7779.dtsi +++ b/arch/arm/boot/dts/r8a7779.dtsi @@ -464,12 +464,12 @@ <&cpg_clocks R8A7779_CLK_P>, <&cpg_clocks R8A7779_CLK_S>, <&cpg_clocks R8A7779_CLK_S>, - <&cpg_clocks R8A7779_CLK_S1>, - <&cpg_clocks R8A7779_CLK_S1>, - <&cpg_clocks R8A7779_CLK_S1>, - <&cpg_clocks R8A7779_CLK_S1>, - <&cpg_clocks R8A7779_CLK_S1>, - <&cpg_clocks R8A7779_CLK_S1>, + <&cpg_clocks R8A7779_CLK_P>, + <&cpg_clocks R8A7779_CLK_P>, + <&cpg_clocks R8A7779_CLK_P>, + <&cpg_clocks R8A7779_CLK_P>, + <&cpg_clocks R8A7779_CLK_P>, + <&cpg_clocks R8A7779_CLK_P>, <&cpg_clocks R8A7779_CLK_P>, <&cpg_clocks R8A7779_CLK_P>, <&cpg_clocks R8A7779_CLK_P>, -- cgit v1.2.3 From 631324cf83a04cbfcc81a21801f321679493a072 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 15 Dec 2014 13:56:08 +0900 Subject: ARM: shmobile: r8a7779: Use MSTP for SCIF clocks Hook up MSTP clocks to SCIF devices on r8a7779 to allow clock gating to work as expected. Signed-off-by: Magnus Damm Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7779.dtsi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi index ee3bb3e9cbf1..d9e1abf9debe 100644 --- a/arch/arm/boot/dts/r8a7779.dtsi +++ b/arch/arm/boot/dts/r8a7779.dtsi @@ -200,7 +200,7 @@ compatible = "renesas,scif-r8a7779", "renesas,scif"; reg = <0xffe40000 0x100>; interrupts = <0 88 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg_clocks R8A7779_CLK_P>; + clocks = <&mstp0_clks R8A7779_CLK_SCIF0>; clock-names = "sci_ick"; status = "disabled"; }; @@ -209,7 +209,7 @@ compatible = "renesas,scif-r8a7779", "renesas,scif"; reg = <0xffe41000 0x100>; interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg_clocks R8A7779_CLK_P>; + clocks = <&mstp0_clks R8A7779_CLK_SCIF1>; clock-names = "sci_ick"; status = "disabled"; }; @@ -218,7 +218,7 @@ compatible = "renesas,scif-r8a7779", "renesas,scif"; reg = <0xffe42000 0x100>; interrupts = <0 90 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg_clocks R8A7779_CLK_P>; + clocks = <&mstp0_clks R8A7779_CLK_SCIF2>; clock-names = "sci_ick"; status = "disabled"; }; @@ -227,7 +227,7 @@ compatible = "renesas,scif-r8a7779", "renesas,scif"; reg = <0xffe43000 0x100>; interrupts = <0 91 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg_clocks R8A7779_CLK_P>; + clocks = <&mstp0_clks R8A7779_CLK_SCIF3>; clock-names = "sci_ick"; status = "disabled"; }; @@ -236,7 +236,7 @@ compatible = "renesas,scif-r8a7779", "renesas,scif"; reg = <0xffe44000 0x100>; interrupts = <0 92 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg_clocks R8A7779_CLK_P>; + clocks = <&mstp0_clks R8A7779_CLK_SCIF4>; clock-names = "sci_ick"; status = "disabled"; }; @@ -245,7 +245,7 @@ compatible = "renesas,scif-r8a7779", "renesas,scif"; reg = <0xffe45000 0x100>; interrupts = <0 93 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&cpg_clocks R8A7779_CLK_P>; + clocks = <&mstp0_clks R8A7779_CLK_SCIF5>; clock-names = "sci_ick"; status = "disabled"; }; -- cgit v1.2.3 From cea806542f6d7ec40eea1c5f9db2065996f56627 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 16 Dec 2014 18:39:41 +0900 Subject: ARM: shmobile: r8a7779: Add TWD device to DTS Now when r8a7779 CCF is in place we can hook up the ARM Cortex-A9 TWD timer via DTS. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7779.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi index d9e1abf9debe..5c2219b9f3eb 100644 --- a/arch/arm/boot/dts/r8a7779.dtsi +++ b/arch/arm/boot/dts/r8a7779.dtsi @@ -12,6 +12,7 @@ /include/ "skeleton.dtsi" #include +#include #include / { @@ -62,6 +63,14 @@ <0xf0000100 0x100>; }; + timer@f0000600 { + compatible = "arm,cortex-a9-twd-timer"; + reg = <0xf0000600 0x20>; + interrupts = ; + clocks = <&cpg_clocks R8A7779_CLK_ZS>; + }; + gpio0: gpio@ffc40000 { compatible = "renesas,gpio-r8a7779", "renesas,gpio-rcar"; reg = <0xffc40000 0x2c>; -- cgit v1.2.3 From c5d82c9996f68491375de47c208a41bcb150dfad Mon Sep 17 00:00:00 2001 From: Koji Matsuoka Date: Fri, 23 May 2014 18:37:04 +0900 Subject: ARM: shmobile: r8a7794: Add I2C clocks to device tree Signed-off-by: Koji Matsuoka [horms: omitted device nodes and aliases; only add clocks] Signed-off-by: Simon Horman Acked-by: Geert Uytterhoeven --- arch/arm/boot/dts/r8a7794.dtsi | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index 068ca0981ac9..728d719957b8 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -538,10 +538,16 @@ mstp9_clks: mstp9_clks@e6150994 { compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe6150994 0 4>, <0 0xe61509a4 0 4>; - clocks = <&cpg_clocks R8A7794_CLK_QSPI>; + clocks = <&cpg_clocks R8A7794_CLK_QSPI>, <&hp_clk>, <&hp_clk>, + <&hp_clk>, <&hp_clk>, <&hp_clk>, <&hp_clk>; #clock-cells = <1>; - clock-indices = ; - clock-output-names = "qspi_mod"; + clock-indices = < + R8A7794_CLK_QSPI_MOD R8A7794_CLK_I2C5 R8A7794_CLK_I2C4 + R8A7794_CLK_I2C3 R8A7794_CLK_I2C2 R8A7794_CLK_I2C1 + R8A7794_CLK_I2C0 + >; + clock-output-names = + "qspi_mod", "i2c5", "i2c4", "i2c3", "i2c2", "i2c1", "i2c0"; }; mstp11_clks: mstp11_clks@e615099c { compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; -- cgit v1.2.3 From 8e181633e6ca960491ac502ccd4a4aac482c3ff9 Mon Sep 17 00:00:00 2001 From: Shinobu Uehara Date: Fri, 23 May 2014 11:37:45 +0900 Subject: ARM: shmobile: r8a7794: Add SDHI clocks to device tree Signed-off-by: Shinobu Uehara [horms: omitted device nodes; only add clock] Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7794.dtsi | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index 728d719957b8..c37667633e54 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -293,6 +293,21 @@ clock-output-names = "main", "pll0", "pll1", "pll3", "lb", "qspi", "sdh", "sd0", "z"; }; + /* Variable factor clocks */ + sd1_clk: sd2_clk@e6150078 { + compatible = "renesas,r8a7794-div6-clock", "renesas,cpg-div6-clock"; + reg = <0 0xe6150078 0 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "sd1"; + }; + sd2_clk: sd3_clk@e615007c { + compatible = "renesas,r8a7794-div6-clock", "renesas,cpg-div6-clock"; + reg = <0 0xe615007c 0 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "sd2"; + }; /* Fixed factor clocks */ pll1_div2_clk: pll1_div2_clk { @@ -496,13 +511,16 @@ mstp3_clks: mstp3_clks@e615013c { compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>; - clocks = <&rclk_clk>, <&hp_clk>, <&hp_clk>; + clocks = <&sd2_clk>, <&sd1_clk>, <&cpg_clocks R8A7794_CLK_SD0>, + <&rclk_clk>, <&hp_clk>, <&hp_clk>; #clock-cells = <1>; clock-indices = < + R8A7794_CLK_SDHI2 R8A7794_CLK_SDHI1 R8A7794_CLK_SDHI0 R8A7794_CLK_CMT1 R8A7794_CLK_USBDMAC0 R8A7794_CLK_USBDMAC1 >; clock-output-names = + "sdhi2", "sdhi1", "sdhi0", "cmt1", "usbdmac0", "usbdmac1"; }; mstp7_clks: mstp7_clks@e615014c { -- cgit v1.2.3 From deac150c2d141c16c4814972c25c2a3aacae8d57 Mon Sep 17 00:00:00 2001 From: Shinobu Uehara Date: Tue, 27 May 2014 10:39:26 +0900 Subject: ARM: shmobile: r8a7794: Add MMCIF clock to device tree Signed-off-by: Shinobu Uehara [horms: omitted device node; only add clock] Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7794.dtsi | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi index c37667633e54..8f78da5ef10b 100644 --- a/arch/arm/boot/dts/r8a7794.dtsi +++ b/arch/arm/boot/dts/r8a7794.dtsi @@ -308,6 +308,13 @@ #clock-cells = <0>; clock-output-names = "sd2"; }; + mmc0_clk: mmc0_clk@e6150240 { + compatible = "renesas,r8a7794-div6-clock", "renesas,cpg-div6-clock"; + reg = <0 0xe6150240 0 4>; + clocks = <&pll1_div2_clk>; + #clock-cells = <0>; + clock-output-names = "mmc0"; + }; /* Fixed factor clocks */ pll1_div2_clk: pll1_div2_clk { @@ -512,16 +519,16 @@ compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe615013c 0 4>, <0 0xe6150048 0 4>; clocks = <&sd2_clk>, <&sd1_clk>, <&cpg_clocks R8A7794_CLK_SD0>, - <&rclk_clk>, <&hp_clk>, <&hp_clk>; + <&mmc0_clk>, <&rclk_clk>, <&hp_clk>, <&hp_clk>; #clock-cells = <1>; clock-indices = < R8A7794_CLK_SDHI2 R8A7794_CLK_SDHI1 R8A7794_CLK_SDHI0 - R8A7794_CLK_CMT1 R8A7794_CLK_USBDMAC0 - R8A7794_CLK_USBDMAC1 + R8A7794_CLK_MMCIF0 R8A7794_CLK_CMT1 + R8A7794_CLK_USBDMAC0 R8A7794_CLK_USBDMAC1 >; clock-output-names = "sdhi2", "sdhi1", "sdhi0", - "cmt1", "usbdmac0", "usbdmac1"; + "mmcif0", "cmt1", "usbdmac0", "usbdmac1"; }; mstp7_clks: mstp7_clks@e615014c { compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks"; -- cgit v1.2.3 From 6cdaa63f9e2b3ea0ac57a71a43f96cf626500d35 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 17 Dec 2014 17:18:13 +0100 Subject: ARM: shmobile: ape6evm: fix compatible string for Ethernet controller It's a 9220, not a 9118. Signed-off-by: Ulrich Hecht Acked-by: Laurent Pinchart Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a73a4-ape6evm.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/r8a73a4-ape6evm.dts index ce085fa444a1..baca8f8c4a5c 100644 --- a/arch/arm/boot/dts/r8a73a4-ape6evm.dts +++ b/arch/arm/boot/dts/r8a73a4-ape6evm.dts @@ -43,7 +43,7 @@ #size-cells = <1>; ethernet@8000000 { - compatible = "smsc,lan9118", "smsc,lan9115"; + compatible = "smsc,lan9220", "smsc,lan9115"; reg = <0x08000000 0x1000>; interrupt-parent = <&irqc1>; interrupts = <8 IRQ_TYPE_LEVEL_HIGH>; -- cgit v1.2.3 From 326baa8029706ba6fbba9dd40f2310f718bfab4b Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 17 Dec 2014 17:18:14 +0100 Subject: ARM: shmobile: ape6evm: synchronize dts with reference platform This moves everything to the legacy dts that is missing there in preparation for the switch to multiplatform. Signed-off-by: Ulrich Hecht Acked-by: Laurent Pinchart Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a73a4-ape6evm.dts | 92 ++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/r8a73a4-ape6evm.dts index baca8f8c4a5c..c98cd1442d7c 100644 --- a/arch/arm/boot/dts/r8a73a4-ape6evm.dts +++ b/arch/arm/boot/dts/r8a73a4-ape6evm.dts @@ -10,14 +10,19 @@ /dts-v1/; #include "r8a73a4.dtsi" -#include +#include / { model = "APE6EVM"; compatible = "renesas,ape6evm", "renesas,r8a73a4"; + aliases { + serial0 = &scifa0; + }; + chosen { bootargs = "console=ttySC0,115200 ignore_loglevel root=/dev/nfs ip=dhcp rw"; + stdout-path = &scifa0; }; memory@40000000 { @@ -30,7 +35,27 @@ reg = <2 0x00000000 0 0x40000000>; }; - ape6evm_fixed_3v3: fixedregulator@0 { + vcc_mmc0: regulator@0 { + compatible = "regulator-fixed"; + regulator-name = "MMC0 Vcc"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-always-on; + }; + + vcc_sdhi0: regulator@1 { + compatible = "regulator-fixed"; + + regulator-name = "SDHI0 Vcc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + gpio = <&pfc 76 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + /* Common 3.3V rail, used by several devices on APE6EVM */ + ape6evm_fixed_3v3: regulator@2 { compatible = "regulator-fixed"; regulator-name = "3V3"; regulator-min-microvolt = <3300000>; @@ -39,8 +64,10 @@ }; lbsc { + compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; + ranges = <0 0 0 0x20000000>; ethernet@8000000 { compatible = "smsc,lan9220", "smsc,lan9115"; @@ -79,3 +106,64 @@ >; voltage-tolerance = <1>; /* 1% */ }; + +&cmt1 { + status = "okay"; +}; + +&pfc { + scifa0_pins: serial0 { + renesas,groups = "scifa0_data"; + renesas,function = "scifa0"; + }; + + mmc0_pins: mmc { + renesas,groups = "mmc0_data8", "mmc0_ctrl"; + renesas,function = "mmc0"; + }; + + sdhi0_pins: sd0 { + renesas,groups = "sdhi0_data4", "sdhi0_ctrl", "sdhi0_cd"; + renesas,function = "sdhi0"; + }; + + sdhi1_pins: sd1 { + renesas,groups = "sdhi1_data4", "sdhi1_ctrl"; + renesas,function = "sdhi1"; + }; +}; + +&mmcif0 { + vmmc-supply = <&vcc_mmc0>; + bus-width = <8>; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&mmc0_pins>; + status = "okay"; +}; + +&scifa0 { + pinctrl-0 = <&scifa0_pins>; + pinctrl-names = "default"; + + status = "okay"; +}; + +&sdhi0 { + vmmc-supply = <&vcc_sdhi0>; + bus-width = <4>; + toshiba,mmc-wrprotect-disable; + pinctrl-names = "default"; + pinctrl-0 = <&sdhi0_pins>; + status = "okay"; +}; + +&sdhi1 { + vmmc-supply = <&ape6evm_fixed_3v3>; + bus-width = <4>; + broken-cd; + toshiba,mmc-wrprotect-disable; + pinctrl-names = "default"; + pinctrl-0 = <&sdhi1_pins>; + status = "okay"; +}; -- cgit v1.2.3 From b742257dd5ec574a35950ebcf4a3d77a0f01355f Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 17 Dec 2014 17:18:15 +0100 Subject: ARM: shmobile: ape6evm: Add LEDs to the device tree Signed-off-by: Ulrich Hecht Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a73a4-ape6evm.dts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/r8a73a4-ape6evm.dts index c98cd1442d7c..b939a372d408 100644 --- a/arch/arm/boot/dts/r8a73a4-ape6evm.dts +++ b/arch/arm/boot/dts/r8a73a4-ape6evm.dts @@ -82,6 +82,34 @@ vddvario-supply = <&ape6evm_fixed_3v3>; }; }; + + leds { + compatible = "gpio-leds"; + led1 { + gpios = <&pfc 28 GPIO_ACTIVE_LOW>; + label = "GNSS_EN"; + }; + led2 { + gpios = <&pfc 126 GPIO_ACTIVE_LOW>; + label = "NFC_NRST"; + }; + led3 { + gpios = <&pfc 132 GPIO_ACTIVE_LOW>; + label = "GNSS_NRST"; + }; + led4 { + gpios = <&pfc 232 GPIO_ACTIVE_LOW>; + label = "BT_WAKEUP"; + }; + led5 { + gpios = <&pfc 250 GPIO_ACTIVE_LOW>; + label = "STROBE"; + }; + led6 { + gpios = <&pfc 288 GPIO_ACTIVE_LOW>; + label = "BBRESETOUT"; + }; + }; }; &i2c5 { -- cgit v1.2.3 From 2670ee894f477c9dfe9da7cf774c167b2ba06594 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 17 Dec 2014 17:18:16 +0100 Subject: ARM: shmobile: ape6evm: Add keypad to the device tree Signed-off-by: Ulrich Hecht Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a73a4-ape6evm.dts | 41 +++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/r8a73a4-ape6evm.dts index b939a372d408..6b7bc1fb842e 100644 --- a/arch/arm/boot/dts/r8a73a4-ape6evm.dts +++ b/arch/arm/boot/dts/r8a73a4-ape6evm.dts @@ -11,6 +11,7 @@ /dts-v1/; #include "r8a73a4.dtsi" #include +#include / { model = "APE6EVM"; @@ -110,6 +111,46 @@ label = "BBRESETOUT"; }; }; + + keyboard { + compatible = "gpio-keys"; + + zero-key { + gpios = <&pfc 324 GPIO_ACTIVE_LOW>; + linux,code = ; + label = "S16"; + }; + + menu-key { + gpios = <&pfc 325 GPIO_ACTIVE_LOW>; + linux,code = ; + label = "S17"; + }; + + home-key { + gpios = <&pfc 326 GPIO_ACTIVE_LOW>; + linux,code = ; + label = "S18"; + }; + + back-key { + gpios = <&pfc 327 GPIO_ACTIVE_LOW>; + linux,code = ; + label = "S19"; + }; + + volup-key { + gpios = <&pfc 328 GPIO_ACTIVE_LOW>; + linux,code = ; + label = "S20"; + }; + + voldown-key { + gpios = <&pfc 329 GPIO_ACTIVE_LOW>; + linux,code = ; + label = "S21"; + }; + }; }; &i2c5 { -- cgit v1.2.3 From 088b1691f560afa4e5e7990fd8081546236b39cf Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 17 Dec 2014 17:18:18 +0100 Subject: ARM: shmobile: r8a73a4: Add r8a73a4-ape6evm.dtb to ARCH_SHMOBILE_MULTI Makes sure the dtb is built for multiplatform builds. Signed-off-by: Ulrich Hecht Acked-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 91bd5bd62857..fabc56983d24 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -416,6 +416,7 @@ dtb-$(CONFIG_ARCH_SHMOBILE_LEGACY) += \ sh73a0-kzm9g-reference.dtb dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += emev2-kzm9d.dtb \ r7s72100-genmai.dtb \ + r8a73a4-ape6evm.dtb \ r8a7740-armadillo800eva.dtb \ r8a7779-marzen.dtb \ r8a7790-lager.dtb \ -- cgit v1.2.3 From 09ee81da85b10e0ca876977d333c8761441ecc78 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 17 Dec 2014 01:17:25 +0200 Subject: ARM: shmobile: ape6evm: Fix LAN9220 VDDVARIO voltage The LAN9220 VDDVARIO supply is powered by a 1.8V source, not 3.3V. Fix it in the device tree. Signed-off-by: Laurent Pinchart Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a73a4-ape6evm.dts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/r8a73a4-ape6evm.dts index 6b7bc1fb842e..0d50bef01234 100644 --- a/arch/arm/boot/dts/r8a73a4-ape6evm.dts +++ b/arch/arm/boot/dts/r8a73a4-ape6evm.dts @@ -55,8 +55,16 @@ enable-active-high; }; - /* Common 3.3V rail, used by several devices on APE6EVM */ - ape6evm_fixed_3v3: regulator@2 { + /* Common 1.8V and 3.3V rails, used by several devices on APE6EVM */ + ape6evm_fixed_1v8: regulator@2 { + compatible = "regulator-fixed"; + regulator-name = "1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + ape6evm_fixed_3v3: regulator@3 { compatible = "regulator-fixed"; regulator-name = "3V3"; regulator-min-microvolt = <3300000>; @@ -80,7 +88,7 @@ smsc,irq-active-high; smsc,irq-push-pull; vdd33a-supply = <&ape6evm_fixed_3v3>; - vddvario-supply = <&ape6evm_fixed_3v3>; + vddvario-supply = <&ape6evm_fixed_1v8>; }; }; -- cgit v1.2.3 From 8b00601547ca28c5c55124dceba203b5f5e2c214 Mon Sep 17 00:00:00 2001 From: Richard Kunze Date: Sun, 14 Dec 2014 20:53:39 +0100 Subject: ARM: dts: use all remaining MTD space foor rootfs of Iomega ix2-200 The original MTD partition layout for the Iomega ix2-200 leaves most of the available space unused. This patch changes the layout to use all remaining MTD space after the partitions for u-boot/u-boot-env and the kernel uimage as a "rootfs" partition. Signed-off-by: Richard Kunze Signed-off-by: Andrew Lunn --- arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts b/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts index 05291f3990d0..2a5c5a33db0c 100644 --- a/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts +++ b/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts @@ -192,8 +192,8 @@ }; partition@400000 { - label = "uInitrd"; - reg = <0x540000 0x1000000>; + label = "rootfs"; + reg = <0x400000 0x1C00000>; }; }; -- cgit v1.2.3 From 1701308a6e2407e144cb5af729e5b51731a3957d Mon Sep 17 00:00:00 2001 From: Richard Kunze Date: Wed, 10 Dec 2014 19:40:41 +0100 Subject: ARM: dts: add gpio_poweroff support for Iomega ix2-200 Iomega ix2-200 can be powered off via GPIO 0 pin 17, this patch wires up the gpio-poweroff driver to do it. Signed-off-by: Richard Kunze Acked-by: Andrew Lunn Signed-off-by: Andrew Lunn --- arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts b/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts index 2a5c5a33db0c..8474bffec0ca 100644 --- a/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts +++ b/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts @@ -169,6 +169,10 @@ gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; }; }; + gpio-poweroff { + compatible = "gpio-poweroff"; + gpios = <&gpio0 17 GPIO_ACTIVE_LOW>; + }; }; &nand { -- cgit v1.2.3 From 9c569b390923f10d5551aa56c9e68f132459e0cc Mon Sep 17 00:00:00 2001 From: Evgeni Dobrev Date: Tue, 16 Dec 2014 19:22:18 +0100 Subject: ARM: dts: kirkwood: enable phy driver for SATA controller on 88f6192 This patch enables the phy drivers for the SATA controller on Marvell's 88f6192. Without them it is not possible to use SATA drives attached to this processor. Signed-off-by: Evgeni Dobrev Acked-by: Andrew Lunn Signed-off-by: Andrew Lunn --- arch/arm/boot/dts/kirkwood-6192.dtsi | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/kirkwood-6192.dtsi b/arch/arm/boot/dts/kirkwood-6192.dtsi index dd81508b919b..9e6e9e2691d5 100644 --- a/arch/arm/boot/dts/kirkwood-6192.dtsi +++ b/arch/arm/boot/dts/kirkwood-6192.dtsi @@ -66,6 +66,8 @@ interrupts = <21>; clocks = <&gate_clk 14>, <&gate_clk 15>; clock-names = "0", "1"; + phys = <&sata_phy0>, <&sata_phy1>; + phy-names = "port0", "port1"; status = "disabled"; }; -- cgit v1.2.3 From e42dcfbba1f0ab3050a7c550a4119e2945553042 Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 2 Dec 2014 18:06:52 +0100 Subject: ARM: mvebu: enable CPUFREQ_DT in mvebu_v7_defconfig This patch enables the cpufreq-dt driver in mvebu_v7_defconfig, as it is used on Armada XP platforms. Signed-off-by: Thomas Petazzoni Signed-off-by: Andrew Lunn --- arch/arm/configs/mvebu_v7_defconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/configs/mvebu_v7_defconfig b/arch/arm/configs/mvebu_v7_defconfig index 627accea72fb..05edf4622c8d 100644 --- a/arch/arm/configs/mvebu_v7_defconfig +++ b/arch/arm/configs/mvebu_v7_defconfig @@ -26,6 +26,7 @@ CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_ARM_APPENDED_DTB=y CONFIG_ARM_ATAG_DTB_COMPAT=y CONFIG_CPU_FREQ=y +CONFIG_CPUFREQ_DT=y CONFIG_CPU_IDLE=y CONFIG_ARM_MVEBU_V7_CPUIDLE=y CONFIG_VFP=y -- cgit v1.2.3 From f74ba117dab86b35e15f8b5a8d913145f3e72ca1 Mon Sep 17 00:00:00 2001 From: Addy Ke Date: Thu, 4 Dec 2014 10:49:35 +0800 Subject: ARM: dts: rockchip: set dw_mmc max-freq 150Mhz All of mmc controllers include SDMMC, SDIO0, SDIO1, and EMMC on RK3288 are limited to 150Mhz. It was mainly caused by two reasons: - RK3288's IO pad(except DDR IO pad) is generic, which can only support the max of 150Mhz. - Mmc controller was designed at 150Mhz, and the pressure test by IC team was based on this freequency point. Signed-off-by: Addy Ke Reviewed-by: Doug Anderson Tested-by: Doug Anderson Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288.dtsi | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index fd19f00784bd..3aad41d873d3 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -151,6 +151,7 @@ sdmmc: dwmmc@ff0c0000 { compatible = "rockchip,rk3288-dw-mshc"; + clock-freq-min-max = <400000 150000000>; clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>; clock-names = "biu", "ciu"; fifo-depth = <0x100>; @@ -161,6 +162,7 @@ sdio0: dwmmc@ff0d0000 { compatible = "rockchip,rk3288-dw-mshc"; + clock-freq-min-max = <400000 150000000>; clocks = <&cru HCLK_SDIO0>, <&cru SCLK_SDIO0>; clock-names = "biu", "ciu"; fifo-depth = <0x100>; @@ -171,6 +173,7 @@ sdio1: dwmmc@ff0e0000 { compatible = "rockchip,rk3288-dw-mshc"; + clock-freq-min-max = <400000 150000000>; clocks = <&cru HCLK_SDIO1>, <&cru SCLK_SDIO1>; clock-names = "biu", "ciu"; fifo-depth = <0x100>; @@ -181,6 +184,7 @@ emmc: dwmmc@ff0f0000 { compatible = "rockchip,rk3288-dw-mshc"; + clock-freq-min-max = <400000 150000000>; clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>; clock-names = "biu", "ciu"; fifo-depth = <0x100>; -- cgit v1.2.3 From 42cc71365ebf1ec35a667d76d32be8503c6d84e9 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 26 Nov 2014 15:16:53 +0800 Subject: ARM: dts: sun6i: Unify ahb1 clock nodes The clock driver has unified support for the ahb1 clock. Unify the clock nodes so it works. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun6i-a31.dtsi | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi index f47156b6572b..62d932e9b7d1 100644 --- a/arch/arm/boot/dts/sun6i-a31.dtsi +++ b/arch/arm/boot/dts/sun6i-a31.dtsi @@ -174,19 +174,11 @@ clock-output-names = "axi"; }; - ahb1_mux: ahb1_mux@01c20054 { - #clock-cells = <0>; - compatible = "allwinner,sun6i-a31-ahb1-mux-clk"; - reg = <0x01c20054 0x4>; - clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>; - clock-output-names = "ahb1_mux"; - }; - ahb1: ahb1@01c20054 { #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-ahb-clk"; + compatible = "allwinner,sun6i-a31-ahb1-clk"; reg = <0x01c20054 0x4>; - clocks = <&ahb1_mux>; + clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>; clock-output-names = "ahb1"; }; @@ -367,7 +359,7 @@ #dma-cells = <1>; /* DMA controller requires AHB1 clocked from PLL6 */ - assigned-clocks = <&ahb1_mux>; + assigned-clocks = <&ahb1>; assigned-clock-parents = <&pll6 0>; }; -- cgit v1.2.3 From de8e8e083def8f0ae5a331fb8ab2db35cdfbd676 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 26 Nov 2014 15:16:54 +0800 Subject: ARM: dts: sun8i: Unify ahb1 clock nodes The clock driver has unified support for the ahb1 clock. Unify the clock nodes so it works. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-a23.dtsi | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/sun8i-a23.dtsi b/arch/arm/boot/dts/sun8i-a23.dtsi index 0746cd1024d7..726b6139f730 100644 --- a/arch/arm/boot/dts/sun8i-a23.dtsi +++ b/arch/arm/boot/dts/sun8i-a23.dtsi @@ -140,19 +140,11 @@ clock-output-names = "axi"; }; - ahb1_mux: ahb1_mux_clk@01c20054 { - #clock-cells = <0>; - compatible = "allwinner,sun6i-a31-ahb1-mux-clk"; - reg = <0x01c20054 0x4>; - clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6>; - clock-output-names = "ahb1_mux"; - }; - ahb1: ahb1_clk@01c20054 { #clock-cells = <0>; - compatible = "allwinner,sun4i-a10-ahb-clk"; + compatible = "allwinner,sun6i-a31-ahb1-clk"; reg = <0x01c20054 0x4>; - clocks = <&ahb1_mux>; + clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6>; clock-output-names = "ahb1"; }; -- cgit v1.2.3 From ff8bbf78e45ee3a07d28642ee6fa1f3424f1bab8 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 24 Nov 2014 15:58:58 +0800 Subject: ARM: dts: sun8i: Add PLL6 and MBUS clock nodes Now that the clock driver supports PLL6 and MBUS on sun8i correctly, add the corresponding clock nodes to the dtsi. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/boot/dts/sun8i-a23.dtsi | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/sun8i-a23.dtsi b/arch/arm/boot/dts/sun8i-a23.dtsi index 726b6139f730..2fcccf0cbcee 100644 --- a/arch/arm/boot/dts/sun8i-a23.dtsi +++ b/arch/arm/boot/dts/sun8i-a23.dtsi @@ -110,11 +110,19 @@ }; /* dummy clock until actually implemented */ - pll6: pll6_clk { + pll5: pll5_clk { #clock-cells = <0>; compatible = "fixed-clock"; - clock-frequency = <600000000>; - clock-output-names = "pll6"; + clock-frequency = <0>; + clock-output-names = "pll5"; + }; + + pll6: clk@01c20028 { + #clock-cells = <1>; + compatible = "allwinner,sun6i-a31-pll6-clk"; + reg = <0x01c20028 0x4>; + clocks = <&osc24M>; + clock-output-names = "pll6", "pll6x2"; }; cpu: cpu_clk@01c20050 { @@ -144,7 +152,7 @@ #clock-cells = <0>; compatible = "allwinner,sun6i-a31-ahb1-clk"; reg = <0x01c20054 0x4>; - clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6>; + clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>; clock-output-names = "ahb1"; }; @@ -185,7 +193,7 @@ #clock-cells = <0>; compatible = "allwinner,sun4i-a10-apb1-clk"; reg = <0x01c20058 0x4>; - clocks = <&osc32k>, <&osc24M>, <&pll6>, <&pll6>; + clocks = <&osc32k>, <&osc24M>, <&pll6 0>, <&pll6 0>; clock-output-names = "apb2"; }; @@ -204,7 +212,7 @@ #clock-cells = <0>; compatible = "allwinner,sun4i-a10-mod0-clk"; reg = <0x01c20088 0x4>; - clocks = <&osc24M>, <&pll6>; + clocks = <&osc24M>, <&pll6 0>; clock-output-names = "mmc0"; }; @@ -212,7 +220,7 @@ #clock-cells = <0>; compatible = "allwinner,sun4i-a10-mod0-clk"; reg = <0x01c2008c 0x4>; - clocks = <&osc24M>, <&pll6>; + clocks = <&osc24M>, <&pll6 0>; clock-output-names = "mmc1"; }; @@ -220,9 +228,17 @@ #clock-cells = <0>; compatible = "allwinner,sun4i-a10-mod0-clk"; reg = <0x01c20090 0x4>; - clocks = <&osc24M>, <&pll6>; + clocks = <&osc24M>, <&pll6 0>; clock-output-names = "mmc2"; }; + + mbus_clk: clk@01c2015c { + #clock-cells = <0>; + compatible = "allwinner,sun8i-a23-mbus-clk"; + reg = <0x01c2015c 0x4>; + clocks = <&osc24M>, <&pll6 1>, <&pll5>; + clock-output-names = "mbus"; + }; }; soc@01c00000 { -- cgit v1.2.3 From b700e7f03df5d92f85fa5247fe1f557528d3363d Mon Sep 17 00:00:00 2001 From: Seth Jennings Date: Tue, 16 Dec 2014 11:58:19 -0600 Subject: livepatch: kernel: add support for live patching This commit introduces code for the live patching core. It implements an ftrace-based mechanism and kernel interface for doing live patching of kernel and kernel module functions. It represents the greatest common functionality set between kpatch and kgraft and can accept patches built using either method. This first version does not implement any consistency mechanism that ensures that old and new code do not run together. In practice, ~90% of CVEs are safe to apply in this way, since they simply add a conditional check. However, any function change that can not execute safely with the old version of the function can _not_ be safely applied in this version. [ jkosina@suse.cz: due to the number of contributions that got folded into this original patch from Seth Jennings, add SUSE's copyright as well, as discussed via e-mail ] Signed-off-by: Seth Jennings Signed-off-by: Josh Poimboeuf Reviewed-by: Miroslav Benes Reviewed-by: Petr Mladek Reviewed-by: Masami Hiramatsu Signed-off-by: Miroslav Benes Signed-off-by: Petr Mladek Signed-off-by: Jiri Kosina --- arch/x86/Kconfig | 3 ++ arch/x86/include/asm/livepatch.h | 37 +++++++++++++++++ arch/x86/kernel/Makefile | 1 + arch/x86/kernel/livepatch.c | 90 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+) create mode 100644 arch/x86/include/asm/livepatch.h create mode 100644 arch/x86/kernel/livepatch.c (limited to 'arch') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ba397bde7948..460b31b79938 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -17,6 +17,7 @@ config X86_64 depends on 64BIT select X86_DEV_DMA_OPS select ARCH_USE_CMPXCHG_LOCKREF + select ARCH_HAVE_LIVE_PATCHING ### Arch settings config X86 @@ -2008,6 +2009,8 @@ config CMDLINE_OVERRIDE This is used to work around broken boot loaders. This should be set to 'N' under normal conditions. +source "kernel/livepatch/Kconfig" + endmenu config ARCH_ENABLE_MEMORY_HOTPLUG diff --git a/arch/x86/include/asm/livepatch.h b/arch/x86/include/asm/livepatch.h new file mode 100644 index 000000000000..d529db1b1edf --- /dev/null +++ b/arch/x86/include/asm/livepatch.h @@ -0,0 +1,37 @@ +/* + * livepatch.h - x86-specific Kernel Live Patching Core + * + * Copyright (C) 2014 Seth Jennings + * Copyright (C) 2014 SUSE + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef _ASM_X86_LIVEPATCH_H +#define _ASM_X86_LIVEPATCH_H + +#include + +#ifdef CONFIG_LIVE_PATCHING +#ifndef CC_USING_FENTRY +#error Your compiler must support -mfentry for live patching to work +#endif +extern int klp_write_module_reloc(struct module *mod, unsigned long type, + unsigned long loc, unsigned long value); + +#else +#error Live patching support is disabled; check CONFIG_LIVE_PATCHING +#endif + +#endif /* _ASM_X86_LIVEPATCH_H */ diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 5d4502c8b983..316b34e74c15 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_X86_MPPARSE) += mpparse.o obj-y += apic/ obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups_32.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o +obj-$(CONFIG_LIVE_PATCHING) += livepatch.o obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o obj-$(CONFIG_X86_TSC) += trace_clock.o diff --git a/arch/x86/kernel/livepatch.c b/arch/x86/kernel/livepatch.c new file mode 100644 index 000000000000..ff3c3101d003 --- /dev/null +++ b/arch/x86/kernel/livepatch.c @@ -0,0 +1,90 @@ +/* + * livepatch.c - x86-specific Kernel Live Patching Core + * + * Copyright (C) 2014 Seth Jennings + * Copyright (C) 2014 SUSE + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include +#include +#include + +/** + * klp_write_module_reloc() - write a relocation in a module + * @mod: module in which the section to be modified is found + * @type: ELF relocation type (see asm/elf.h) + * @loc: address that the relocation should be written to + * @value: relocation value (sym address + addend) + * + * This function writes a relocation to the specified location for + * a particular module. + */ +int klp_write_module_reloc(struct module *mod, unsigned long type, + unsigned long loc, unsigned long value) +{ + int ret, numpages, size = 4; + bool readonly; + unsigned long val; + unsigned long core = (unsigned long)mod->module_core; + unsigned long core_ro_size = mod->core_ro_size; + unsigned long core_size = mod->core_size; + + switch (type) { + case R_X86_64_NONE: + return 0; + case R_X86_64_64: + val = value; + size = 8; + break; + case R_X86_64_32: + val = (u32)value; + break; + case R_X86_64_32S: + val = (s32)value; + break; + case R_X86_64_PC32: + val = (u32)(value - loc); + break; + default: + /* unsupported relocation type */ + return -EINVAL; + } + + if (loc < core || loc >= core + core_size) + /* loc does not point to any symbol inside the module */ + return -EINVAL; + + if (loc < core + core_ro_size) + readonly = true; + else + readonly = false; + + /* determine if the relocation spans a page boundary */ + numpages = ((loc & PAGE_MASK) == ((loc + size) & PAGE_MASK)) ? 1 : 2; + + if (readonly) + set_memory_rw(loc & PAGE_MASK, numpages); + + ret = probe_kernel_write((void *)loc, &val, size); + + if (readonly) + set_memory_ro(loc & PAGE_MASK, numpages); + + return ret; +} -- cgit v1.2.3 From b5bfc51707f1b56b0b733980bb4fcc0562bf02d8 Mon Sep 17 00:00:00 2001 From: Li Bin Date: Fri, 19 Dec 2014 14:11:17 +0800 Subject: livepatch: move x86 specific ftrace handler code to arch/x86 The execution flow redirection related implemention in the livepatch ftrace handler is depended on the specific architecture. This patch introduces klp_arch_set_pc(like kgdb_arch_set_pc) interface to change the pt_regs. Signed-off-by: Li Bin Acked-by: Josh Poimboeuf Signed-off-by: Jiri Kosina --- arch/x86/include/asm/livepatch.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/x86/include/asm/livepatch.h b/arch/x86/include/asm/livepatch.h index d529db1b1edf..b5608d7757fd 100644 --- a/arch/x86/include/asm/livepatch.h +++ b/arch/x86/include/asm/livepatch.h @@ -22,6 +22,7 @@ #define _ASM_X86_LIVEPATCH_H #include +#include #ifdef CONFIG_LIVE_PATCHING #ifndef CC_USING_FENTRY @@ -30,6 +31,10 @@ extern int klp_write_module_reloc(struct module *mod, unsigned long type, unsigned long loc, unsigned long value); +static inline void klp_arch_set_pc(struct pt_regs *regs, unsigned long ip) +{ + regs->ip = ip; +} #else #error Live patching support is disabled; check CONFIG_LIVE_PATCHING #endif -- cgit v1.2.3 From b9024cbc937df97987b139c6cf01e59369c5756d Mon Sep 17 00:00:00 2001 From: Naveen Krishna Ch Date: Sat, 22 Nov 2014 22:41:23 +0900 Subject: arm64: dts: Add initial device tree support for exynos7 Add initial device tree nodes for exynos7 SoC and board dts file to support espresso board based on exynos7 SoC. Signed-off-by: Naveen Krishna Ch Signed-off-by: Abhilash Kesavan Reviewed-by: Thomas Abraham Tested-by: Thomas Abraham Cc: Rob Herring Cc: Catalin Marinas Signed-off-by: Kukjin Kim --- arch/arm64/boot/dts/Makefile | 1 + arch/arm64/boot/dts/exynos/Makefile | 5 + arch/arm64/boot/dts/exynos/exynos7-espresso.dts | 39 +++++ arch/arm64/boot/dts/exynos/exynos7.dtsi | 183 ++++++++++++++++++++++++ 4 files changed, 228 insertions(+) create mode 100644 arch/arm64/boot/dts/exynos/Makefile create mode 100644 arch/arm64/boot/dts/exynos/exynos7-espresso.dts create mode 100644 arch/arm64/boot/dts/exynos/exynos7.dtsi (limited to 'arch') diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile index 3b8d427c3985..b4112518552f 100644 --- a/arch/arm64/boot/dts/Makefile +++ b/arch/arm64/boot/dts/Makefile @@ -2,6 +2,7 @@ dts-dirs += amd dts-dirs += apm dts-dirs += arm dts-dirs += cavium +dts-dirs += exynos always := $(dtb-y) subdir-y := $(dts-dirs) diff --git a/arch/arm64/boot/dts/exynos/Makefile b/arch/arm64/boot/dts/exynos/Makefile new file mode 100644 index 000000000000..20310e5b6d6f --- /dev/null +++ b/arch/arm64/boot/dts/exynos/Makefile @@ -0,0 +1,5 @@ +dtb-$(CONFIG_ARCH_EXYNOS7) += exynos7-espresso.dtb + +always := $(dtb-y) +subdir-y := $(dts-dirs) +clean-files := *.dtb diff --git a/arch/arm64/boot/dts/exynos/exynos7-espresso.dts b/arch/arm64/boot/dts/exynos/exynos7-espresso.dts new file mode 100644 index 000000000000..e2c828322687 --- /dev/null +++ b/arch/arm64/boot/dts/exynos/exynos7-espresso.dts @@ -0,0 +1,39 @@ +/* + * SAMSUNG Exynos7 Espresso board device tree source + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * http://www.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. +*/ + +/dts-v1/; +#include "exynos7.dtsi" + +/ { + model = "Samsung Exynos7 Espresso board based on EXYNOS7"; + compatible = "samsung,exynos7-espresso", "samsung,exynos7"; + + aliases { + serial0 = &serial_2; + }; + + chosen { + linux,stdout-path = &serial_2; + }; + + memory@40000000 { + device_type = "memory"; + reg = <0x0 0x40000000 0x0 0xC0000000>; + }; +}; + +&fin_pll { + clock-frequency = <24000000>; +}; + +&serial_2 { + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/exynos/exynos7.dtsi b/arch/arm64/boot/dts/exynos/exynos7.dtsi new file mode 100644 index 000000000000..6d6a4c2e4dfb --- /dev/null +++ b/arch/arm64/boot/dts/exynos/exynos7.dtsi @@ -0,0 +1,183 @@ +/* + * SAMSUNG EXYNOS7 SoC device tree source + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * http://www.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. + */ + +#include + +/ { + compatible = "samsung,exynos7"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x0>; + enable-method = "psci"; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x1>; + enable-method = "psci"; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x2>; + enable-method = "psci"; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x3>; + enable-method = "psci"; + }; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + soc: soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0 0x18000000>; + + chipid@10000000 { + compatible = "samsung,exynos4210-chipid"; + reg = <0x10000000 0x100>; + }; + + fin_pll: xxti { + compatible = "fixed-clock"; + clock-output-names = "fin_pll"; + #clock-cells = <0>; + }; + + gic: interrupt-controller@11001000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x11001000 0x1000>, + <0x11002000 0x1000>, + <0x11004000 0x2000>, + <0x11006000 0x2000>; + }; + + clock_topc: clock-controller@10570000 { + compatible = "samsung,exynos7-clock-topc"; + reg = <0x10570000 0x10000>; + #clock-cells = <1>; + }; + + clock_top0: clock-controller@105d0000 { + compatible = "samsung,exynos7-clock-top0"; + reg = <0x105d0000 0xb000>; + #clock-cells = <1>; + clocks = <&fin_pll>, <&clock_topc DOUT_SCLK_BUS0_PLL>, + <&clock_topc DOUT_SCLK_BUS1_PLL>, + <&clock_topc DOUT_SCLK_CC_PLL>, + <&clock_topc DOUT_SCLK_MFC_PLL>; + clock-names = "fin_pll", "dout_sclk_bus0_pll", + "dout_sclk_bus1_pll", "dout_sclk_cc_pll", + "dout_sclk_mfc_pll"; + }; + + clock_peric0: clock-controller@13610000 { + compatible = "samsung,exynos7-clock-peric0"; + reg = <0x13610000 0xd00>; + #clock-cells = <1>; + clocks = <&fin_pll>, <&clock_top0 DOUT_ACLK_PERIC0>, + <&clock_top0 CLK_SCLK_UART0>; + clock-names = "fin_pll", "dout_aclk_peric0_66", + "sclk_uart0"; + }; + + clock_peric1: clock-controller@14c80000 { + compatible = "samsung,exynos7-clock-peric1"; + reg = <0x14c80000 0xd00>; + #clock-cells = <1>; + clocks = <&fin_pll>, <&clock_top0 DOUT_ACLK_PERIC1>, + <&clock_top0 CLK_SCLK_UART1>, + <&clock_top0 CLK_SCLK_UART2>, + <&clock_top0 CLK_SCLK_UART3>; + clock-names = "fin_pll", "dout_aclk_peric1_66", + "sclk_uart1", "sclk_uart2", "sclk_uart3"; + }; + + clock_peris: clock-controller@10040000 { + compatible = "samsung,exynos7-clock-peris"; + reg = <0x10040000 0xd00>; + #clock-cells = <1>; + clocks = <&fin_pll>, <&clock_topc DOUT_ACLK_PERIS>; + clock-names = "fin_pll", "dout_aclk_peris_66"; + }; + + serial_0: serial@13630000 { + compatible = "samsung,exynos4210-uart"; + reg = <0x13630000 0x100>; + interrupts = <0 440 0>; + clocks = <&clock_peric0 PCLK_UART0>, + <&clock_peric0 SCLK_UART0>; + clock-names = "uart", "clk_uart_baud0"; + status = "disabled"; + }; + + serial_1: serial@14c20000 { + compatible = "samsung,exynos4210-uart"; + reg = <0x14c20000 0x100>; + interrupts = <0 456 0>; + clocks = <&clock_peric1 PCLK_UART1>, + <&clock_peric1 SCLK_UART1>; + clock-names = "uart", "clk_uart_baud0"; + status = "disabled"; + }; + + serial_2: serial@14c30000 { + compatible = "samsung,exynos4210-uart"; + reg = <0x14c30000 0x100>; + interrupts = <0 457 0>; + clocks = <&clock_peric1 PCLK_UART2>, + <&clock_peric1 SCLK_UART2>; + clock-names = "uart", "clk_uart_baud0"; + status = "disabled"; + }; + + serial_3: serial@14c40000 { + compatible = "samsung,exynos4210-uart"; + reg = <0x14c40000 0x100>; + interrupts = <0 458 0>; + clocks = <&clock_peric1 PCLK_UART3>, + <&clock_peric1 SCLK_UART3>; + clock-names = "uart", "clk_uart_baud0"; + status = "disabled"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <1 13 0xff01>, + <1 14 0xff01>, + <1 11 0xff01>, + <1 10 0xff01>; + }; + }; +}; -- cgit v1.2.3 From f17a618b1e97b7f9b6e286e8a5c54d08a55564d9 Mon Sep 17 00:00:00 2001 From: Naveen Krishna Ch Date: Sat, 22 Nov 2014 22:41:33 +0900 Subject: arm64: dts: Add initial pinctrl support to exynos7 Add initial pin configuration nodes for exynos7 SoC. Signed-off-by: Naveen Krishna Ch Signed-off-by: Abhilash Kesavan Reviewed-by: Thomas Abraham Tested-by: Thomas Abraham Acked-by: Tomasz Figa Cc: Rob Herring Cc: Catalin Marinas Cc: Linus Walleij Signed-off-by: Kukjin Kim --- arch/arm64/boot/dts/exynos/exynos7-pinctrl.dtsi | 588 ++++++++++++++++++++++++ arch/arm64/boot/dts/exynos/exynos7.dtsi | 66 +++ 2 files changed, 654 insertions(+) create mode 100644 arch/arm64/boot/dts/exynos/exynos7-pinctrl.dtsi (limited to 'arch') diff --git a/arch/arm64/boot/dts/exynos/exynos7-pinctrl.dtsi b/arch/arm64/boot/dts/exynos/exynos7-pinctrl.dtsi new file mode 100644 index 000000000000..2eef4a279131 --- /dev/null +++ b/arch/arm64/boot/dts/exynos/exynos7-pinctrl.dtsi @@ -0,0 +1,588 @@ +/* + * Samsung's Exynos7 SoC pin-mux and pin-config device tree source + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * Samsung's Exynos7 SoC pin-mux and pin-config options are listed as + * device tree nodes in this file. + * + * 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. +*/ + +&pinctrl_alive { + gpa0: gpa0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + interrupt-parent = <&gic>; + #interrupt-cells = <2>; + interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>, + <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>; + }; + + gpa1: gpa1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + interrupt-parent = <&gic>; + #interrupt-cells = <2>; + interrupts = <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>, + <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>; + }; + + gpa2: gpa2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpa3: gpa3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; +}; + +&pinctrl_bus0 { + gpb0: gpb0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpc0: gpc0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpc1: gpc1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpc2: gpc2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpc3: gpc3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd0: gpd0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd1: gpd1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd2: gpd2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd4: gpd4 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd5: gpd5 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd6: gpd6 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd7: gpd7 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpd8: gpd8 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpg0: gpg0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpg3: gpg3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + hs_i2c10_bus: hs-i2c10-bus { + samsung,pins = "gpb0-1", "gpb0-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + hs_i2c11_bus: hs-i2c11-bus { + samsung,pins = "gpb0-3", "gpb0-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + hs_i2c2_bus: hs-i2c2-bus { + samsung,pins = "gpd0-3", "gpd0-2"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + uart0_data: uart0-data { + samsung,pins = "gpd0-0", "gpd0-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + uart0_fctl: uart0-fctl { + samsung,pins = "gpd0-2", "gpd0-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + uart2_data: uart2-data { + samsung,pins = "gpd1-4", "gpd1-5"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + hs_i2c3_bus: hs-i2c3-bus { + samsung,pins = "gpd1-3", "gpd1-2"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + uart1_data: uart1-data { + samsung,pins = "gpd1-0", "gpd1-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + uart1_fctl: uart1-fctl { + samsung,pins = "gpd1-2", "gpd1-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + hs_i2c0_bus: hs-i2c0-bus { + samsung,pins = "gpd2-1", "gpd2-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + hs_i2c1_bus: hs-i2c1-bus { + samsung,pins = "gpd2-3", "gpd2-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + hs_i2c9_bus: hs-i2c9-bus { + samsung,pins = "gpd2-7", "gpd2-6"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + pwm0_out: pwm0-out { + samsung,pins = "gpd2-4"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + pwm1_out: pwm1-out { + samsung,pins = "gpd2-5"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + pwm2_out: pwm2-out { + samsung,pins = "gpd2-6"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + pwm3_out: pwm3-out { + samsung,pins = "gpd2-7"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + hs_i2c8_bus: hs-i2c8-bus { + samsung,pins = "gpd5-3", "gpd5-2"; + samsung,pin-function = <3>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + uart3_data: uart3-data { + samsung,pins = "gpd5-0", "gpd5-1"; + samsung,pin-function = <3>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + spi2_bus: spi2-bus { + samsung,pins = "gpd5-0", "gpd5-1", "gpd5-2", "gpd5-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + spi1_bus: spi1-bus { + samsung,pins = "gpd6-2", "gpd6-3", "gpd6-4", "gpd6-5"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + spi0_bus: spi0-bus { + samsung,pins = "gpd8-0", "gpd8-1", "gpd6-0", "gpd6-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + hs_i2c4_bus: hs-i2c4-bus { + samsung,pins = "gpg3-1", "gpg3-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; + + hs_i2c5_bus: hs-i2c5-bus { + samsung,pins = "gpg3-3", "gpg3-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; +}; + +&pinctrl_nfc { + gpj0: gpj0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + hs_i2c6_bus: hs-i2c6-bus { + samsung,pins = "gpj0-1", "gpj0-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; +}; + +&pinctrl_touch { + gpj1: gpj1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + hs_i2c7_bus: hs-i2c7-bus { + samsung,pins = "gpj1-1", "gpj1-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; +}; + +&pinctrl_ff { + gpg4: gpg4 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + spi3_bus: spi3-bus { + samsung,pins = "gpg4-0", "gpg4-1", "gpg4-2", "gpg4-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; +}; + +&pinctrl_ese { + gpv7: gpv7 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + spi4_bus: spi4-bus { + samsung,pins = "gpv7-0", "gpv7-1", "gpv7-2", "gpv7-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <0>; + }; +}; + +&pinctrl_fsys0 { + gpr4: gpr4 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + sd2_clk: sd2-clk { + samsung,pins = "gpr4-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd2_cmd: sd2-cmd { + samsung,pins = "gpr4-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd2_cd: sd2-cd { + samsung,pins = "gpr4-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd2_bus1: sd2-bus-width1 { + samsung,pins = "gpr4-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd2_bus4: sd2-bus-width4 { + samsung,pins = "gpr4-4", "gpr4-5", "gpr4-6"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; +}; + +&pinctrl_fsys1 { + gpr0: gpr0 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpr1: gpr1 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpr2: gpr2 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpr3: gpr3 { + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + sd0_clk: sd0-clk { + samsung,pins = "gpr0-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd0_cmd: sd0-cmd { + samsung,pins = "gpr0-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd0_ds: sd0-ds { + samsung,pins = "gpr0-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <1>; + samsung,pin-drv = <3>; + }; + + sd0_qrdy: sd0-qrdy { + samsung,pins = "gpr0-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <1>; + samsung,pin-drv = <3>; + }; + + sd0_bus1: sd0-bus-width1 { + samsung,pins = "gpr1-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd0_bus4: sd0-bus-width4 { + samsung,pins = "gpr1-1", "gpr1-2", "gpr1-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd0_bus8: sd0-bus-width8 { + samsung,pins = "gpr1-4", "gpr1-5", "gpr1-6", "gpr1-7"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <3>; + }; + + sd1_clk: sd1-clk { + samsung,pins = "gpr2-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <2>; + }; + + sd1_cmd: sd1-cmd { + samsung,pins = "gpr2-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <2>; + }; + + sd1_ds: sd1-ds { + samsung,pins = "gpr2-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <1>; + samsung,pin-drv = <6>; + }; + + sd1_qrdy: sd1-qrdy { + samsung,pins = "gpr2-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <1>; + samsung,pin-drv = <6>; + }; + + sd1_int: sd1-int { + samsung,pins = "gpr2-4"; + samsung,pin-function = <2>; + samsung,pin-pud = <1>; + samsung,pin-drv = <6>; + }; + + sd1_bus1: sd1-bus-width1 { + samsung,pins = "gpr3-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <2>; + }; + + sd1_bus4: sd1-bus-width4 { + samsung,pins = "gpr3-1", "gpr3-2", "gpr3-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <2>; + }; + + sd1_bus8: sd1-bus-width8 { + samsung,pins = "gpr3-4", "gpr3-5", "gpr3-6", "gpr3-7"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <2>; + }; +}; diff --git a/arch/arm64/boot/dts/exynos/exynos7.dtsi b/arch/arm64/boot/dts/exynos/exynos7.dtsi index 6d6a4c2e4dfb..22fb71c15c5f 100644 --- a/arch/arm64/boot/dts/exynos/exynos7.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos7.dtsi @@ -17,6 +17,17 @@ #address-cells = <2>; #size-cells = <2>; + aliases { + pinctrl0 = &pinctrl_alive; + pinctrl1 = &pinctrl_bus0; + pinctrl2 = &pinctrl_nfc; + pinctrl3 = &pinctrl_touch; + pinctrl4 = &pinctrl_ff; + pinctrl5 = &pinctrl_ese; + pinctrl6 = &pinctrl_fsys0; + pinctrl7 = &pinctrl_fsys1; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -172,6 +183,59 @@ status = "disabled"; }; + pinctrl_alive: pinctrl@10580000 { + compatible = "samsung,exynos7-pinctrl"; + reg = <0x10580000 0x1000>; + + wakeup-interrupt-controller { + compatible = "samsung,exynos7-wakeup-eint"; + interrupt-parent = <&gic>; + interrupts = <0 16 0>; + }; + }; + + pinctrl_bus0: pinctrl@13470000 { + compatible = "samsung,exynos7-pinctrl"; + reg = <0x13470000 0x1000>; + interrupts = <0 383 0>; + }; + + pinctrl_nfc: pinctrl@14cd0000 { + compatible = "samsung,exynos7-pinctrl"; + reg = <0x14cd0000 0x1000>; + interrupts = <0 473 0>; + }; + + pinctrl_touch: pinctrl@14ce0000 { + compatible = "samsung,exynos7-pinctrl"; + reg = <0x14ce0000 0x1000>; + interrupts = <0 474 0>; + }; + + pinctrl_ff: pinctrl@14c90000 { + compatible = "samsung,exynos7-pinctrl"; + reg = <0x14c90000 0x1000>; + interrupts = <0 475 0>; + }; + + pinctrl_ese: pinctrl@14ca0000 { + compatible = "samsung,exynos7-pinctrl"; + reg = <0x14ca0000 0x1000>; + interrupts = <0 476 0>; + }; + + pinctrl_fsys0: pinctrl@10e60000 { + compatible = "samsung,exynos7-pinctrl"; + reg = <0x10e60000 0x1000>; + interrupts = <0 221 0>; + }; + + pinctrl_fsys1: pinctrl@15690000 { + compatible = "samsung,exynos7-pinctrl"; + reg = <0x15690000 0x1000>; + interrupts = <0 203 0>; + }; + timer { compatible = "arm,armv8-timer"; interrupts = <1 13 0xff01>, @@ -181,3 +245,5 @@ }; }; }; + +#include "exynos7-pinctrl.dtsi" -- cgit v1.2.3 From 0a7d1d805d741a6ed36e13c1441ba1e24945e898 Mon Sep 17 00:00:00 2001 From: Abhilash Kesavan Date: Sat, 22 Nov 2014 22:41:40 +0900 Subject: arm64: dts: Add PMU DT node for exynos7 SoC Adds PMU DT node for exynos7 SoC. Signed-off-by: Abhilash Kesavan Signed-off-by: Kukjin Kim --- arch/arm64/boot/dts/exynos/exynos7.dtsi | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/arm64/boot/dts/exynos/exynos7.dtsi b/arch/arm64/boot/dts/exynos/exynos7.dtsi index 22fb71c15c5f..8aab9f9c0cd8 100644 --- a/arch/arm64/boot/dts/exynos/exynos7.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos7.dtsi @@ -243,6 +243,11 @@ <1 11 0xff01>, <1 10 0xff01>; }; + + pmu_system_controller: system-controller@105c0000 { + compatible = "samsung,exynos7-pmu", "syscon"; + reg = <0x105c0000 0x5000>; + }; }; }; -- cgit v1.2.3 From 6de6f73ce644d2274b5ff53387769ce86bd7413f Mon Sep 17 00:00:00 2001 From: Abhilash Kesavan Date: Sat, 22 Nov 2014 22:41:45 +0900 Subject: arm64: dts: Add nodes for mmc, i2c, rtc, watchdog, adc on exynos7 Add nodes for 3 mmc channels, 12 i2c channels, rtc, watchdog and adc on exynos7 SoC. Signed-off-by: Naveen Krishna Ch Signed-off-by: Abhilash Kesavan Signed-off-by: Kukjin Kim --- arch/arm64/boot/dts/exynos/exynos7-espresso.dts | 45 ++++ arch/arm64/boot/dts/exynos/exynos7.dtsi | 276 ++++++++++++++++++++++++ 2 files changed, 321 insertions(+) (limited to 'arch') diff --git a/arch/arm64/boot/dts/exynos/exynos7-espresso.dts b/arch/arm64/boot/dts/exynos/exynos7-espresso.dts index e2c828322687..5424cc450f72 100644 --- a/arch/arm64/boot/dts/exynos/exynos7-espresso.dts +++ b/arch/arm64/boot/dts/exynos/exynos7-espresso.dts @@ -18,6 +18,8 @@ aliases { serial0 = &serial_2; + mshc0 = &mmc_0; + mshc2 = &mmc_2; }; chosen { @@ -37,3 +39,46 @@ &serial_2 { status = "okay"; }; + +&rtc { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&adc { + status = "okay"; +}; + +&mmc_0 { + status = "okay"; + num-slots = <1>; + broken-cd; + cap-mmc-highspeed; + non-removable; + card-detect-delay = <200>; + clock-frequency = <800000000>; + samsung,dw-mshc-ciu-div = <3>; + samsung,dw-mshc-sdr-timing = <0 4>; + samsung,dw-mshc-ddr-timing = <0 2>; + pinctrl-names = "default"; + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_qrdy &sd0_bus1 &sd0_bus4 &sd0_bus8>; + bus-width = <8>; +}; + +&mmc_2 { + status = "okay"; + num-slots = <1>; + cap-sd-highspeed; + card-detect-delay = <200>; + clock-frequency = <400000000>; + samsung,dw-mshc-ciu-div = <3>; + samsung,dw-mshc-sdr-timing = <2 3>; + samsung,dw-mshc-ddr-timing = <1 2>; + pinctrl-names = "default"; + pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus1 &sd2_bus4>; + bus-width = <4>; + disable-wp; +}; diff --git a/arch/arm64/boot/dts/exynos/exynos7.dtsi b/arch/arm64/boot/dts/exynos/exynos7.dtsi index 8aab9f9c0cd8..d7a37c3a6b52 100644 --- a/arch/arm64/boot/dts/exynos/exynos7.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos7.dtsi @@ -113,6 +113,27 @@ "dout_sclk_mfc_pll"; }; + clock_top1: clock-controller@105e0000 { + compatible = "samsung,exynos7-clock-top1"; + reg = <0x105e0000 0xb000>; + #clock-cells = <1>; + clocks = <&fin_pll>, <&clock_topc DOUT_SCLK_BUS0_PLL>, + <&clock_topc DOUT_SCLK_BUS1_PLL>, + <&clock_topc DOUT_SCLK_CC_PLL>, + <&clock_topc DOUT_SCLK_MFC_PLL>; + clock-names = "fin_pll", "dout_sclk_bus0_pll", + "dout_sclk_bus1_pll", "dout_sclk_cc_pll", + "dout_sclk_mfc_pll"; + }; + + clock_ccore: clock-controller@105b0000 { + compatible = "samsung,exynos7-clock-ccore"; + reg = <0x105b0000 0xd00>; + #clock-cells = <1>; + clocks = <&fin_pll>, <&clock_topc DOUT_ACLK_CCORE_133>; + clock-names = "fin_pll", "dout_aclk_ccore_133"; + }; + clock_peric0: clock-controller@13610000 { compatible = "samsung,exynos7-clock-peric0"; reg = <0x13610000 0xd00>; @@ -143,6 +164,27 @@ clock-names = "fin_pll", "dout_aclk_peris_66"; }; + clock_fsys0: clock-controller@10e90000 { + compatible = "samsung,exynos7-clock-fsys0"; + reg = <0x10e90000 0xd00>; + #clock-cells = <1>; + clocks = <&fin_pll>, <&clock_top1 DOUT_ACLK_FSYS0_200>, + <&clock_top1 DOUT_SCLK_MMC2>; + clock-names = "fin_pll", "dout_aclk_fsys0_200", + "dout_sclk_mmc2"; + }; + + clock_fsys1: clock-controller@156e0000 { + compatible = "samsung,exynos7-clock-fsys1"; + reg = <0x156e0000 0xd00>; + #clock-cells = <1>; + clocks = <&fin_pll>, <&clock_top1 DOUT_ACLK_FSYS1_200>, + <&clock_top1 DOUT_SCLK_MMC0>, + <&clock_top1 DOUT_SCLK_MMC1>; + clock-names = "fin_pll", "dout_aclk_fsys1_200", + "dout_sclk_mmc0", "dout_sclk_mmc1"; + }; + serial_0: serial@13630000 { compatible = "samsung,exynos4210-uart"; reg = <0x13630000 0x100>; @@ -236,6 +278,162 @@ interrupts = <0 203 0>; }; + hsi2c_0: hsi2c@13640000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x13640000 0x1000>; + interrupts = <0 441 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c0_bus>; + clocks = <&clock_peric0 PCLK_HSI2C0>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_1: hsi2c@13650000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x13650000 0x1000>; + interrupts = <0 442 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c1_bus>; + clocks = <&clock_peric0 PCLK_HSI2C1>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_2: hsi2c@14e60000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x14e60000 0x1000>; + interrupts = <0 459 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c2_bus>; + clocks = <&clock_peric1 PCLK_HSI2C2>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_3: hsi2c@14e70000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x14e70000 0x1000>; + interrupts = <0 460 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c3_bus>; + clocks = <&clock_peric1 PCLK_HSI2C3>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_4: hsi2c@13660000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x13660000 0x1000>; + interrupts = <0 443 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c4_bus>; + clocks = <&clock_peric0 PCLK_HSI2C4>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_5: hsi2c@13670000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x13670000 0x1000>; + interrupts = <0 444 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c5_bus>; + clocks = <&clock_peric0 PCLK_HSI2C5>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_6: hsi2c@14e00000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x14e00000 0x1000>; + interrupts = <0 461 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c6_bus>; + clocks = <&clock_peric1 PCLK_HSI2C6>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_7: hsi2c@13e10000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x13e10000 0x1000>; + interrupts = <0 462 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c7_bus>; + clocks = <&clock_peric1 PCLK_HSI2C7>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_8: hsi2c@14e20000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x14e20000 0x1000>; + interrupts = <0 463 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c8_bus>; + clocks = <&clock_peric1 PCLK_HSI2C8>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_9: hsi2c@13680000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x13680000 0x1000>; + interrupts = <0 445 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c9_bus>; + clocks = <&clock_peric0 PCLK_HSI2C9>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_10: hsi2c@13690000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x13690000 0x1000>; + interrupts = <0 446 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c10_bus>; + clocks = <&clock_peric0 PCLK_HSI2C10>; + clock-names = "hsi2c"; + status = "disabled"; + }; + + hsi2c_11: hsi2c@136a0000 { + compatible = "samsung,exynos7-hsi2c"; + reg = <0x136a0000 0x1000>; + interrupts = <0 447 0>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&hs_i2c11_bus>; + clocks = <&clock_peric0 PCLK_HSI2C11>; + clock-names = "hsi2c"; + status = "disabled"; + }; + timer { compatible = "arm,armv8-timer"; interrupts = <1 13 0xff01>, @@ -248,6 +446,84 @@ compatible = "samsung,exynos7-pmu", "syscon"; reg = <0x105c0000 0x5000>; }; + + rtc: rtc@10590000 { + compatible = "samsung,s3c6410-rtc"; + reg = <0x10590000 0x100>; + interrupts = <0 355 0>, <0 356 0>; + clocks = <&clock_ccore PCLK_RTC>; + clock-names = "rtc"; + status = "disabled"; + }; + + watchdog: watchdog@101d0000 { + compatible = "samsung,exynos7-wdt"; + reg = <0x101d0000 0x100>; + interrupts = <0 110 0>; + clocks = <&clock_peris PCLK_WDT>; + clock-names = "watchdog"; + samsung,syscon-phandle = <&pmu_system_controller>; + status = "disabled"; + }; + + mmc_0: mmc@15740000 { + compatible = "samsung,exynos7-dw-mshc-smu"; + interrupts = <0 201 0>; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x15740000 0x2000>; + clocks = <&clock_fsys1 ACLK_MMC0>, + <&clock_top1 CLK_SCLK_MMC0>; + clock-names = "biu", "ciu"; + fifo-depth = <0x40>; + status = "disabled"; + }; + + mmc_1: mmc@15750000 { + compatible = "samsung,exynos7-dw-mshc"; + interrupts = <0 202 0>; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x15750000 0x2000>; + clocks = <&clock_fsys1 ACLK_MMC1>, + <&clock_top1 CLK_SCLK_MMC1>; + clock-names = "biu", "ciu"; + fifo-depth = <0x40>; + status = "disabled"; + }; + + mmc_2: mmc@15560000 { + compatible = "samsung,exynos7-dw-mshc-smu"; + interrupts = <0 216 0>; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x15560000 0x2000>; + clocks = <&clock_fsys0 ACLK_MMC2>, + <&clock_top1 CLK_SCLK_MMC2>; + clock-names = "biu", "ciu"; + fifo-depth = <0x40>; + status = "disabled"; + }; + + adc: adc@13620000 { + compatible = "samsung,exynos7-adc"; + reg = <0x13620000 0x100>; + interrupts = <0 448 0>; + clocks = <&clock_peric0 PCLK_ADCIF>; + clock-names = "adc"; + #io-channel-cells = <1>; + io-channel-ranges; + status = "disabled"; + }; + + pwm: pwm@136c0000 { + compatible = "samsung,exynos4210-pwm"; + reg = <0x136c0000 0x100>; + samsung,pwm-outputs = <0>, <1>, <2>, <3>; + #pwm-cells = <3>; + clocks = <&clock_peric0 PCLK_PWM>; + clock-names = "timers"; + }; }; }; -- cgit v1.2.3 From 6f56eef1f9aba3747c811780a4768618167d5c97 Mon Sep 17 00:00:00 2001 From: Alim Akhtar Date: Sat, 22 Nov 2014 22:41:52 +0900 Subject: arm64: Enable ARMv8 based exynos7 SoC support This patch adds the necessary Kconfig entries to enable support for the ARMv8 based exynos7 SoC. It also enables RTC, WDT and Pinctrl for exynos7 SoC. Signed-off-by: Alim Akhtar Signed-off-by: Naveen Krishna Ch Signed-off-by: Abhilash Kesavan Reviewed-by: Thomas Abraham Tested-by: Thomas Abraham Cc: Rob Herring Cc: Catalin Marinas Signed-off-by: Kukjin Kim --- arch/arm64/Kconfig | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'arch') diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index b1f9a20a3677..15e8e7469ffd 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -148,6 +148,23 @@ source "kernel/Kconfig.freezer" menu "Platform selection" +config ARCH_EXYNOS + bool + help + This enables support for Samsung Exynos SoC family + +config ARCH_EXYNOS7 + bool "ARMv8 based Samsung Exynos7" + select ARCH_EXYNOS + select COMMON_CLK_SAMSUNG + select HAVE_S3C2410_WATCHDOG if WATCHDOG + select HAVE_S3C_RTC if RTC_CLASS + select PINCTRL + select PINCTRL_EXYNOS + + help + This enables support for Samsung Exynos7 SoC family + config ARCH_SEATTLE bool "AMD Seattle SoC Family" help -- cgit v1.2.3 From 1a14f53271aee500da0ed450ff62ce848213c60a Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 26 Nov 2014 15:43:35 +0900 Subject: ARM: SAMSUNG: print CPU id on probe It's useful to get the CPU ID/rev printed during boot sometimes, so add a line with that information. Given that the fields have moved within the register over time, don't try to be clever and parse it -- just print the raw values for now. Signed-off-by: Olof Johansson Signed-off-by: Kukjin Kim --- arch/arm/plat-samsung/cpu.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/arm/plat-samsung/cpu.c b/arch/arm/plat-samsung/cpu.c index 360618ee39e5..71333bb61013 100644 --- a/arch/arm/plat-samsung/cpu.c +++ b/arch/arm/plat-samsung/cpu.c @@ -40,10 +40,14 @@ void __init s3c64xx_init_cpu(void) } samsung_cpu_rev = 0; + + pr_info("Samsung CPU ID: 0x%08lx\n", samsung_cpu_id); } void __init s5p_init_cpu(void __iomem *cpuid_addr) { samsung_cpu_id = __raw_readl(cpuid_addr); samsung_cpu_rev = samsung_cpu_id & 0xFF; + + pr_info("Samsung CPU ID: 0x%08lx\n", samsung_cpu_id); } -- cgit v1.2.3 From 842ebf60bbad6d6e5ebaa063409fefdd2a7eb992 Mon Sep 17 00:00:00 2001 From: Andreas Faerber Date: Sat, 22 Nov 2014 23:31:30 +0900 Subject: ARM: exynos_defconfig: Enable LM90 driver multi_v7_defconfig has it as Y already, so build it in here, too, for consistency, and therefore build in HWMON as well. Signed-off-by: Andreas Faerber Reviewed-by: Javier Martinez Canillas Signed-off-by: Kukjin Kim --- arch/arm/configs/exynos_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig index 5ef14de00a29..311157124619 100644 --- a/arch/arm/configs/exynos_defconfig +++ b/arch/arm/configs/exynos_defconfig @@ -84,7 +84,8 @@ CONFIG_DEBUG_GPIO=y CONFIG_POWER_SUPPLY=y CONFIG_BATTERY_SBS=y CONFIG_CHARGER_TPS65090=y -# CONFIG_HWMON is not set +CONFIG_HWMON=y +CONFIG_SENSORS_LM90=y CONFIG_THERMAL=y CONFIG_EXYNOS_THERMAL=y CONFIG_EXYNOS_THERMAL_CORE=y -- cgit v1.2.3 From 8e7a4cef71790d9406a7bd85aea6cfb12bc07d3c Mon Sep 17 00:00:00 2001 From: Yalin Wang Date: Mon, 3 Nov 2014 03:02:23 +0100 Subject: ARM: 8189/1: arm64:add bitrev.h file to support rbit instruction This patch add bitrev.h file to support rbit instruction, so that we can do bitrev operation by hardware. Signed-off-by: Yalin Wang Acked-by: Will Deacon Signed-off-by: Russell King --- arch/arm64/Kconfig | 1 + arch/arm64/include/asm/bitrev.h | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 arch/arm64/include/asm/bitrev.h (limited to 'arch') diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index b1f9a20a3677..0ed36d1f536d 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -39,6 +39,7 @@ config ARM64 select HARDIRQS_SW_RESEND select HAVE_ALIGNED_STRUCT_PAGE if SLUB select HAVE_ARCH_AUDITSYSCALL + select HAVE_ARCH_BITREVERSE select HAVE_ARCH_JUMP_LABEL select HAVE_ARCH_KGDB select HAVE_ARCH_SECCOMP_FILTER diff --git a/arch/arm64/include/asm/bitrev.h b/arch/arm64/include/asm/bitrev.h new file mode 100644 index 000000000000..a5a0c3660137 --- /dev/null +++ b/arch/arm64/include/asm/bitrev.h @@ -0,0 +1,19 @@ +#ifndef __ASM_BITREV_H +#define __ASM_BITREV_H +static __always_inline __attribute_const__ u32 __arch_bitrev32(u32 x) +{ + __asm__ ("rbit %w0, %w1" : "=r" (x) : "r" (x)); + return x; +} + +static __always_inline __attribute_const__ u16 __arch_bitrev16(u16 x) +{ + return __arch_bitrev32((u32)x) >> 16; +} + +static __always_inline __attribute_const__ u8 __arch_bitrev8(u8 x) +{ + return __arch_bitrev32((u32)x) >> 24; +} + +#endif -- cgit v1.2.3 From 6c80f87ed4483bff0ecbf4455a1b09e7f950e9ab Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Sun, 21 Dec 2014 08:18:25 -0800 Subject: x86, mce: Improve timeout error messages There are four different possible types of timeouts. Distinguish them in the logs to help debug them. Signed-off-by: Andy Lutomirski Link: http://lkml.kernel.org/r/0fa6d2653a54a01c48b43a3583caf950ea99606e.1419178397.git.luto@amacapital.net Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/mcheck/mce.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index d2c611699cd9..323e02c658af 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -311,7 +311,7 @@ static void wait_for_panic(void) panic("Panicing machine check CPU died"); } -static void mce_panic(char *msg, struct mce *final, char *exp) +static void mce_panic(const char *msg, struct mce *final, char *exp) { int i, apei_err = 0; @@ -735,7 +735,7 @@ static atomic_t mce_callin; /* * Check if a timeout waiting for other CPUs happened. */ -static int mce_timed_out(u64 *t) +static int mce_timed_out(u64 *t, const char *msg) { /* * The others already did panic for some reason. @@ -750,8 +750,7 @@ static int mce_timed_out(u64 *t) goto out; if ((s64)*t < SPINUNIT) { if (mca_cfg.tolerant <= 1) - mce_panic("Timeout synchronizing machine check over CPUs", - NULL, NULL); + mce_panic(msg, NULL, NULL); cpu_missing = 1; return 1; } @@ -867,7 +866,8 @@ static int mce_start(int *no_way_out) * Wait for everyone. */ while (atomic_read(&mce_callin) != cpus) { - if (mce_timed_out(&timeout)) { + if (mce_timed_out(&timeout, + "Timeout: Not all CPUs entered broadcast exception handler")) { atomic_set(&global_nwo, 0); return -1; } @@ -892,7 +892,8 @@ static int mce_start(int *no_way_out) * only seen by one CPU before cleared, avoiding duplicates. */ while (atomic_read(&mce_executing) < order) { - if (mce_timed_out(&timeout)) { + if (mce_timed_out(&timeout, + "Timeout: Subject CPUs unable to finish machine check processing")) { atomic_set(&global_nwo, 0); return -1; } @@ -936,7 +937,8 @@ static int mce_end(int order) * loops. */ while (atomic_read(&mce_executing) <= cpus) { - if (mce_timed_out(&timeout)) + if (mce_timed_out(&timeout, + "Timeout: Monarch CPU unable to finish machine check processing")) goto reset; ndelay(SPINUNIT); } @@ -949,7 +951,8 @@ static int mce_end(int order) * Subject: Wait for Monarch to finish. */ while (atomic_read(&mce_executing) != 0) { - if (mce_timed_out(&timeout)) + if (mce_timed_out(&timeout, + "Timeout: Monarch CPU did not finish machine check processing")) goto reset; ndelay(SPINUNIT); } -- cgit v1.2.3 From 83737691e586cd2767fa4fc87cd41251d1a49e9e Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 22 Dec 2014 21:04:31 +0100 Subject: x86, mce: Fix sparse errors Make stuff used in mce.c only, static. Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/mcheck/mce.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 323e02c658af..4c5cd7575d31 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -115,7 +115,7 @@ static void (*quirk_no_way_out)(int bank, struct mce *m, struct pt_regs *regs); * CPU/chipset specific EDAC code can register a notifier call here to print * MCE errors in a human-readable form. */ -ATOMIC_NOTIFIER_HEAD(x86_mce_decoder_chain); +static ATOMIC_NOTIFIER_HEAD(x86_mce_decoder_chain); /* Do initial initialization of a struct mce */ void mce_setup(struct mce *m) @@ -529,7 +529,7 @@ static void mce_schedule_work(void) schedule_work(this_cpu_ptr(&mce_work)); } -DEFINE_PER_CPU(struct irq_work, mce_irq_work); +static DEFINE_PER_CPU(struct irq_work, mce_irq_work); static void mce_irq_work_cb(struct irq_work *entry) { @@ -1012,7 +1012,7 @@ static void mce_clear_state(unsigned long *toclear) */ #define MCE_INFO_MAX 16 -struct mce_info { +static struct mce_info { atomic_t inuse; struct task_struct *t; __u64 paddr; -- cgit v1.2.3 From f6b5dd4088d082b53eb135e1d6b4b213bf5ce127 Mon Sep 17 00:00:00 2001 From: Andrey Gusakov Date: Thu, 18 Dec 2014 23:41:52 +0300 Subject: ARM: shmobile: r8a7790: add MLB+ clock Add MLB+ clock to R8A7790 device tree. Signed-off-by: Andrey Gusakov [Sergei: rebased, renamed, added changelog] Signed-off-by: Sergei Shtylyov Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790.dtsi | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index ffeff98fa16e..af30c2470f85 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -1149,16 +1149,17 @@ mstp8_clks: mstp8_clks@e6150990 { compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe6150990 0 4>, <0 0xe61509a0 0 4>; - clocks = <&zg_clk>, <&zg_clk>, <&zg_clk>, <&zg_clk>, <&p_clk>, - <&zs_clk>, <&zs_clk>; + clocks = <&hp_clk>, <&zg_clk>, <&zg_clk>, <&zg_clk>, + <&zg_clk>, <&p_clk>, <&zs_clk>, <&zs_clk>; #clock-cells = <1>; clock-indices = < - R8A7790_CLK_VIN3 R8A7790_CLK_VIN2 R8A7790_CLK_VIN1 - R8A7790_CLK_VIN0 R8A7790_CLK_ETHER R8A7790_CLK_SATA1 - R8A7790_CLK_SATA0 + R8A7790_CLK_MLB R8A7790_CLK_VIN3 R8A7790_CLK_VIN2 + R8A7790_CLK_VIN1 R8A7790_CLK_VIN0 R8A7790_CLK_ETHER + R8A7790_CLK_SATA1 R8A7790_CLK_SATA0 >; clock-output-names = - "vin3", "vin2", "vin1", "vin0", "ether", "sata1", "sata0"; + "mlb", "vin3", "vin2", "vin1", "vin0", "ether", + "sata1", "sata0"; }; mstp9_clks: mstp9_clks@e6150994 { compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks"; -- cgit v1.2.3 From 7408d3061d2f04181820902fae6e92e4a73d5cc0 Mon Sep 17 00:00:00 2001 From: Andrey Gusakov Date: Thu, 18 Dec 2014 23:43:03 +0300 Subject: ARM: shmobile: r8a7791: add MLB+ clock Add MLB+ clock to R8A7791 device tree. Signed-off-by: Andrey Gusakov [Sergei: rebased, renamed, added changelog] Signed-off-by: Sergei Shtylyov Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7791.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index 78d637135e77..28102265cc71 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -1154,17 +1154,17 @@ mstp8_clks: mstp8_clks@e6150990 { compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe6150990 0 4>, <0 0xe61509a0 0 4>; - clocks = <&zg_clk>, <&zg_clk>, <&zg_clk>, <&zg_clk>, <&p_clk>, - <&zs_clk>, <&zs_clk>; + clocks = <&hp_clk>, <&zg_clk>, <&zg_clk>, <&zg_clk>, + <&zg_clk>, <&p_clk>, <&zs_clk>, <&zs_clk>; #clock-cells = <1>; clock-indices = < - R8A7791_CLK_IPMMU_SGX + R8A7791_CLK_IPMMU_SGX R8A7791_CLK_MLB R8A7791_CLK_VIN2 R8A7791_CLK_VIN1 R8A7791_CLK_VIN0 R8A7791_CLK_ETHER R8A7791_CLK_SATA1 R8A7791_CLK_SATA0 >; clock-output-names = - "ipmmu_sgx", "vin2", "vin1", "vin0", "ether", "sata1", - "sata0"; + "ipmmu_sgx", "mlb", "vin2", "vin1", "vin0", "ether", + "sata1", "sata0"; }; mstp9_clks: mstp9_clks@e6150994 { compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks"; -- cgit v1.2.3 From 6ca7a8a15035add0a4f9b2fd658118d41dbeb20c Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sun, 21 Dec 2014 15:02:23 +0100 Subject: x86/fpu: Use a symbolic name for asm operand Fix up the else-case in fpu_fxsave() which seems like it has been overlooked. Correct comment style in restore_fpu_checking() while at it. Signed-off-by: Borislav Petkov Cc: Linus Torvalds Link: http://lkml.kernel.org/r/1419170543-11393-1-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/include/asm/fpu-internal.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h index e97622f57722..0dbc08282291 100644 --- a/arch/x86/include/asm/fpu-internal.h +++ b/arch/x86/include/asm/fpu-internal.h @@ -207,7 +207,7 @@ static inline void fpu_fxsave(struct fpu *fpu) if (config_enabled(CONFIG_X86_32)) asm volatile( "fxsave %[fx]" : [fx] "=m" (fpu->state->fxsave)); else if (config_enabled(CONFIG_AS_FXSAVEQ)) - asm volatile("fxsaveq %0" : "=m" (fpu->state->fxsave)); + asm volatile("fxsaveq %[fx]" : [fx] "=m" (fpu->state->fxsave)); else { /* Using "rex64; fxsave %0" is broken because, if the memory * operand uses any extended registers for addressing, a second @@ -290,9 +290,11 @@ static inline int fpu_restore_checking(struct fpu *fpu) static inline int restore_fpu_checking(struct task_struct *tsk) { - /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception - is pending. Clear the x87 state here by setting it to fixed - values. "m" is a random variable that should be in L1 */ + /* + * AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception is + * pending. Clear the x87 state here by setting it to fixed values. + * "m" is a random variable that should be in L1. + */ if (unlikely(static_cpu_has_bug_safe(X86_BUG_FXSAVE_LEAK))) { asm volatile( "fnclex\n\t" -- cgit v1.2.3 From 2b261f9f7bd9333e62140ca7e02a2f4ffec5e44f Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 21 Dec 2014 13:58:18 +0100 Subject: x86/platform: Remove unused function from apb_timer.c Remove the function is_apbt_capable() that is not used anywhere. This was partially found by using a static code analysis program called 'cppcheck'. Signed-off-by: Rickard Strandqvist Reviewed-by: Jiang Liu Cc: Christoph Lameter Cc: Tejun Heo Link: http://lkml.kernel.org/r/1419166698-2470-1-git-send-email-rickard_strandqvist@spectrumdigital.se Signed-off-by: Ingo Molnar --- arch/x86/kernel/apb_timer.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c index b708738d016e..6a7c23ff21d3 100644 --- a/arch/x86/kernel/apb_timer.c +++ b/arch/x86/kernel/apb_timer.c @@ -135,14 +135,6 @@ static inline void apbt_clear_mapping(void) apbt_virt_address = NULL; } -/* - * APBT timer interrupt enable / disable - */ -static inline int is_apbt_capable(void) -{ - return apbt_virt_address ? 1 : 0; -} - static int __init apbt_clockevent_register(void) { struct sfi_timer_table_entry *mtmr; -- cgit v1.2.3 From f421258d5bf883b68b1cdaa299a8a1da3eb92e0f Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 21 Dec 2014 22:53:58 +0200 Subject: MIPS: OCTEON: add crypto helper functions Add crypto helper functions which are needed for kernel level usage. The code for these has been extracted from the EdgeRouter Pro GPL tarball. While at it, also delete duplicate definitions of the functions. Signed-off-by: Aaro Koskinen Signed-off-by: Herbert Xu --- arch/mips/cavium-octeon/Makefile | 1 + arch/mips/cavium-octeon/crypto/Makefile | 5 ++ arch/mips/cavium-octeon/crypto/octeon-crypto.c | 66 ++++++++++++++++++++++++++ arch/mips/cavium-octeon/crypto/octeon-crypto.h | 17 +++++++ arch/mips/include/asm/octeon/octeon.h | 5 -- 5 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 arch/mips/cavium-octeon/crypto/Makefile create mode 100644 arch/mips/cavium-octeon/crypto/octeon-crypto.c create mode 100644 arch/mips/cavium-octeon/crypto/octeon-crypto.h (limited to 'arch') diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile index 42f5f1a4b40a..69a8a8dabc2b 100644 --- a/arch/mips/cavium-octeon/Makefile +++ b/arch/mips/cavium-octeon/Makefile @@ -16,6 +16,7 @@ obj-y := cpu.o setup.o octeon-platform.o octeon-irq.o csrc-octeon.o obj-y += dma-octeon.o obj-y += octeon-memcpy.o obj-y += executive/ +obj-y += crypto/ obj-$(CONFIG_MTD) += flash_setup.o obj-$(CONFIG_SMP) += smp.o diff --git a/arch/mips/cavium-octeon/crypto/Makefile b/arch/mips/cavium-octeon/crypto/Makefile new file mode 100644 index 000000000000..739b80366c25 --- /dev/null +++ b/arch/mips/cavium-octeon/crypto/Makefile @@ -0,0 +1,5 @@ +# +# OCTEON-specific crypto modules. +# + +obj-y += octeon-crypto.o diff --git a/arch/mips/cavium-octeon/crypto/octeon-crypto.c b/arch/mips/cavium-octeon/crypto/octeon-crypto.c new file mode 100644 index 000000000000..7c82ff463b65 --- /dev/null +++ b/arch/mips/cavium-octeon/crypto/octeon-crypto.c @@ -0,0 +1,66 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2004-2012 Cavium Networks + */ + +#include +#include +#include + +#include "octeon-crypto.h" + +/** + * Enable access to Octeon's COP2 crypto hardware for kernel use. Wrap any + * crypto operations in calls to octeon_crypto_enable/disable in order to make + * sure the state of COP2 isn't corrupted if userspace is also performing + * hardware crypto operations. Allocate the state parameter on the stack. + * Preemption must be disabled to prevent context switches. + * + * @state: Pointer to state structure to store current COP2 state in. + * + * Returns: Flags to be passed to octeon_crypto_disable() + */ +unsigned long octeon_crypto_enable(struct octeon_cop2_state *state) +{ + int status; + unsigned long flags; + + local_irq_save(flags); + status = read_c0_status(); + write_c0_status(status | ST0_CU2); + if (KSTK_STATUS(current) & ST0_CU2) { + octeon_cop2_save(&(current->thread.cp2)); + KSTK_STATUS(current) &= ~ST0_CU2; + status &= ~ST0_CU2; + } else if (status & ST0_CU2) { + octeon_cop2_save(state); + } + local_irq_restore(flags); + return status & ST0_CU2; +} +EXPORT_SYMBOL_GPL(octeon_crypto_enable); + +/** + * Disable access to Octeon's COP2 crypto hardware in the kernel. This must be + * called after an octeon_crypto_enable() before any context switch or return to + * userspace. + * + * @state: Pointer to COP2 state to restore + * @flags: Return value from octeon_crypto_enable() + */ +void octeon_crypto_disable(struct octeon_cop2_state *state, + unsigned long crypto_flags) +{ + unsigned long flags; + + local_irq_save(flags); + if (crypto_flags & ST0_CU2) + octeon_cop2_restore(state); + else + write_c0_status(read_c0_status() & ~ST0_CU2); + local_irq_restore(flags); +} +EXPORT_SYMBOL_GPL(octeon_crypto_disable); diff --git a/arch/mips/cavium-octeon/crypto/octeon-crypto.h b/arch/mips/cavium-octeon/crypto/octeon-crypto.h new file mode 100644 index 000000000000..5ca86d4ead52 --- /dev/null +++ b/arch/mips/cavium-octeon/crypto/octeon-crypto.h @@ -0,0 +1,17 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2012-2013 Cavium Inc., All Rights Reserved. + */ +#ifndef __LINUX_OCTEON_CRYPTO_H +#define __LINUX_OCTEON_CRYPTO_H + +#include + +extern unsigned long octeon_crypto_enable(struct octeon_cop2_state *state); +extern void octeon_crypto_disable(struct octeon_cop2_state *state, + unsigned long flags); + +#endif /* __LINUX_OCTEON_CRYPTO_H */ diff --git a/arch/mips/include/asm/octeon/octeon.h b/arch/mips/include/asm/octeon/octeon.h index d781f9e66884..6dfefd2d5cdf 100644 --- a/arch/mips/include/asm/octeon/octeon.h +++ b/arch/mips/include/asm/octeon/octeon.h @@ -44,11 +44,6 @@ extern int octeon_get_boot_num_arguments(void); extern const char *octeon_get_boot_argument(int arg); extern void octeon_hal_setup_reserved32(void); extern void octeon_user_io_init(void); -struct octeon_cop2_state; -extern unsigned long octeon_crypto_enable(struct octeon_cop2_state *state); -extern void octeon_crypto_disable(struct octeon_cop2_state *state, - unsigned long flags); -extern asmlinkage void octeon_cop2_restore(struct octeon_cop2_state *task); extern void octeon_init_cvmcount(void); extern void octeon_setup_delays(void); -- cgit v1.2.3 From 1e585ef51c3fdcf296d2ce5cb8c9e74b1a36cfb4 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 21 Dec 2014 22:53:59 +0200 Subject: crypto: octeon - add instruction definitions for MD5 Add instruction definitions for MD5. Based on information extracted from EdgeRouter Pro GPL source tarball. Signed-off-by: Aaro Koskinen Signed-off-by: Herbert Xu --- arch/mips/cavium-octeon/crypto/octeon-crypto.h | 56 ++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/crypto/octeon-crypto.h b/arch/mips/cavium-octeon/crypto/octeon-crypto.h index 5ca86d4ead52..3f65bc6ccb83 100644 --- a/arch/mips/cavium-octeon/crypto/octeon-crypto.h +++ b/arch/mips/cavium-octeon/crypto/octeon-crypto.h @@ -4,14 +4,70 @@ * for more details. * * Copyright (C) 2012-2013 Cavium Inc., All Rights Reserved. + * + * MD5 instruction definitions added by Aaro Koskinen . + * */ #ifndef __LINUX_OCTEON_CRYPTO_H #define __LINUX_OCTEON_CRYPTO_H #include +#include extern unsigned long octeon_crypto_enable(struct octeon_cop2_state *state); extern void octeon_crypto_disable(struct octeon_cop2_state *state, unsigned long flags); +/* + * Macros needed to implement MD5: + */ + +/* + * The index can be 0-1. + */ +#define write_octeon_64bit_hash_dword(value, index) \ +do { \ + __asm__ __volatile__ ( \ + "dmtc2 %[rt],0x0048+" STR(index) \ + : \ + : [rt] "d" (value)); \ +} while (0) + +/* + * The index can be 0-1. + */ +#define read_octeon_64bit_hash_dword(index) \ +({ \ + u64 __value; \ + \ + __asm__ __volatile__ ( \ + "dmfc2 %[rt],0x0048+" STR(index) \ + : [rt] "=d" (__value) \ + : ); \ + \ + __value; \ +}) + +/* + * The index can be 0-6. + */ +#define write_octeon_64bit_block_dword(value, index) \ +do { \ + __asm__ __volatile__ ( \ + "dmtc2 %[rt],0x0040+" STR(index) \ + : \ + : [rt] "d" (value)); \ +} while (0) + +/* + * The value is the final block dword (64-bit). + */ +#define octeon_md5_start(value) \ +do { \ + __asm__ __volatile__ ( \ + "dmtc2 %[rt],0x4047" \ + : \ + : [rt] "d" (value)); \ +} while (0) + #endif /* __LINUX_OCTEON_CRYPTO_H */ -- cgit v1.2.3 From 011f3c6cbb97859860e451f2a75767cd4c1ffc03 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 21 Dec 2014 22:54:00 +0200 Subject: MIPS: OCTEON: reintroduce crypto features check Reintroduce run-time check for crypto features. The old one was deleted because it was unreliable, now decide the crypto availability on early boot when the model string is constructed. Signed-off-by: Aaro Koskinen Signed-off-by: Herbert Xu --- arch/mips/cavium-octeon/executive/octeon-model.c | 6 ++++++ arch/mips/include/asm/octeon/octeon-feature.h | 17 +++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/executive/octeon-model.c b/arch/mips/cavium-octeon/executive/octeon-model.c index e15b049b3bd7..b2104bd9ab3b 100644 --- a/arch/mips/cavium-octeon/executive/octeon-model.c +++ b/arch/mips/cavium-octeon/executive/octeon-model.c @@ -27,6 +27,9 @@ #include +enum octeon_feature_bits __octeon_feature_bits __read_mostly; +EXPORT_SYMBOL_GPL(__octeon_feature_bits); + /** * Read a byte of fuse data * @byte_addr: address to read @@ -103,6 +106,9 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id, else suffix = "NSP"; + if (!fus_dat2.s.nocrypto) + __octeon_feature_bits |= OCTEON_HAS_CRYPTO; + /* * Assume pass number is encoded using <5:3><2:0>. Exceptions * will be fixed later. diff --git a/arch/mips/include/asm/octeon/octeon-feature.h b/arch/mips/include/asm/octeon/octeon-feature.h index c4fe81f47f53..8ebd3f579b84 100644 --- a/arch/mips/include/asm/octeon/octeon-feature.h +++ b/arch/mips/include/asm/octeon/octeon-feature.h @@ -46,8 +46,6 @@ enum octeon_feature { OCTEON_FEATURE_SAAD, /* Does this Octeon support the ZIP offload engine? */ OCTEON_FEATURE_ZIP, - /* Does this Octeon support crypto acceleration using COP2? */ - OCTEON_FEATURE_CRYPTO, OCTEON_FEATURE_DORM_CRYPTO, /* Does this Octeon support PCI express? */ OCTEON_FEATURE_PCIE, @@ -86,6 +84,21 @@ enum octeon_feature { OCTEON_MAX_FEATURE }; +enum octeon_feature_bits { + OCTEON_HAS_CRYPTO = 0x0001, /* Crypto acceleration using COP2 */ +}; +extern enum octeon_feature_bits __octeon_feature_bits; + +/** + * octeon_has_crypto() - Check if this OCTEON has crypto acceleration support. + * + * Returns: Non-zero if the feature exists. Zero if the feature does not exist. + */ +static inline int octeon_has_crypto(void) +{ + return __octeon_feature_bits & OCTEON_HAS_CRYPTO; +} + /** * Determine if the current Octeon supports a specific feature. These * checks have been optimized to be fairly quick, but they should still -- cgit v1.2.3 From 1953c22f53747035b28c36dbb337ac3c10902644 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 21 Dec 2014 22:54:01 +0200 Subject: crypto: octeon - add MD5 module Add OCTEON MD5 module. Signed-off-by: Aaro Koskinen Signed-off-by: Herbert Xu --- arch/mips/cavium-octeon/crypto/Makefile | 2 + arch/mips/cavium-octeon/crypto/octeon-crypto.h | 2 + arch/mips/cavium-octeon/crypto/octeon-md5.c | 216 +++++++++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 arch/mips/cavium-octeon/crypto/octeon-md5.c (limited to 'arch') diff --git a/arch/mips/cavium-octeon/crypto/Makefile b/arch/mips/cavium-octeon/crypto/Makefile index 739b80366c25..a74f76d85a2f 100644 --- a/arch/mips/cavium-octeon/crypto/Makefile +++ b/arch/mips/cavium-octeon/crypto/Makefile @@ -3,3 +3,5 @@ # obj-y += octeon-crypto.o + +obj-$(CONFIG_CRYPTO_MD5_OCTEON) += octeon-md5.o diff --git a/arch/mips/cavium-octeon/crypto/octeon-crypto.h b/arch/mips/cavium-octeon/crypto/octeon-crypto.h index 3f65bc6ccb83..e2a4aece9c24 100644 --- a/arch/mips/cavium-octeon/crypto/octeon-crypto.h +++ b/arch/mips/cavium-octeon/crypto/octeon-crypto.h @@ -14,6 +14,8 @@ #include #include +#define OCTEON_CR_OPCODE_PRIORITY 300 + extern unsigned long octeon_crypto_enable(struct octeon_cop2_state *state); extern void octeon_crypto_disable(struct octeon_cop2_state *state, unsigned long flags); diff --git a/arch/mips/cavium-octeon/crypto/octeon-md5.c b/arch/mips/cavium-octeon/crypto/octeon-md5.c new file mode 100644 index 000000000000..b909881ba6c1 --- /dev/null +++ b/arch/mips/cavium-octeon/crypto/octeon-md5.c @@ -0,0 +1,216 @@ +/* + * Cryptographic API. + * + * MD5 Message Digest Algorithm (RFC1321). + * + * Adapted for OCTEON by Aaro Koskinen . + * + * Based on crypto/md5.c, which is: + * + * Derived from cryptoapi implementation, originally based on the + * public domain implementation written by Colin Plumb in 1993. + * + * Copyright (c) Cryptoapi developers. + * Copyright (c) 2002 James Morris + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "octeon-crypto.h" + +/* + * We pass everything as 64-bit. OCTEON can handle misaligned data. + */ + +static void octeon_md5_store_hash(struct md5_state *ctx) +{ + u64 *hash = (u64 *)ctx->hash; + + write_octeon_64bit_hash_dword(hash[0], 0); + write_octeon_64bit_hash_dword(hash[1], 1); +} + +static void octeon_md5_read_hash(struct md5_state *ctx) +{ + u64 *hash = (u64 *)ctx->hash; + + hash[0] = read_octeon_64bit_hash_dword(0); + hash[1] = read_octeon_64bit_hash_dword(1); +} + +static void octeon_md5_transform(const void *_block) +{ + const u64 *block = _block; + + write_octeon_64bit_block_dword(block[0], 0); + write_octeon_64bit_block_dword(block[1], 1); + write_octeon_64bit_block_dword(block[2], 2); + write_octeon_64bit_block_dword(block[3], 3); + write_octeon_64bit_block_dword(block[4], 4); + write_octeon_64bit_block_dword(block[5], 5); + write_octeon_64bit_block_dword(block[6], 6); + octeon_md5_start(block[7]); +} + +static int octeon_md5_init(struct shash_desc *desc) +{ + struct md5_state *mctx = shash_desc_ctx(desc); + + mctx->hash[0] = cpu_to_le32(0x67452301); + mctx->hash[1] = cpu_to_le32(0xefcdab89); + mctx->hash[2] = cpu_to_le32(0x98badcfe); + mctx->hash[3] = cpu_to_le32(0x10325476); + mctx->byte_count = 0; + + return 0; +} + +static int octeon_md5_update(struct shash_desc *desc, const u8 *data, + unsigned int len) +{ + struct md5_state *mctx = shash_desc_ctx(desc); + const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); + struct octeon_cop2_state state; + unsigned long flags; + + mctx->byte_count += len; + + if (avail > len) { + memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), + data, len); + return 0; + } + + memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), data, + avail); + + local_bh_disable(); + preempt_disable(); + flags = octeon_crypto_enable(&state); + octeon_md5_store_hash(mctx); + + octeon_md5_transform(mctx->block); + data += avail; + len -= avail; + + while (len >= sizeof(mctx->block)) { + octeon_md5_transform(data); + data += sizeof(mctx->block); + len -= sizeof(mctx->block); + } + + octeon_md5_read_hash(mctx); + octeon_crypto_disable(&state, flags); + preempt_enable(); + local_bh_enable(); + + memcpy(mctx->block, data, len); + + return 0; +} + +static int octeon_md5_final(struct shash_desc *desc, u8 *out) +{ + struct md5_state *mctx = shash_desc_ctx(desc); + const unsigned int offset = mctx->byte_count & 0x3f; + char *p = (char *)mctx->block + offset; + int padding = 56 - (offset + 1); + struct octeon_cop2_state state; + unsigned long flags; + + *p++ = 0x80; + + local_bh_disable(); + preempt_disable(); + flags = octeon_crypto_enable(&state); + octeon_md5_store_hash(mctx); + + if (padding < 0) { + memset(p, 0x00, padding + sizeof(u64)); + octeon_md5_transform(mctx->block); + p = (char *)mctx->block; + padding = 56; + } + + memset(p, 0, padding); + mctx->block[14] = cpu_to_le32(mctx->byte_count << 3); + mctx->block[15] = cpu_to_le32(mctx->byte_count >> 29); + octeon_md5_transform(mctx->block); + + octeon_md5_read_hash(mctx); + octeon_crypto_disable(&state, flags); + preempt_enable(); + local_bh_enable(); + + memcpy(out, mctx->hash, sizeof(mctx->hash)); + memset(mctx, 0, sizeof(*mctx)); + + return 0; +} + +static int octeon_md5_export(struct shash_desc *desc, void *out) +{ + struct md5_state *ctx = shash_desc_ctx(desc); + + memcpy(out, ctx, sizeof(*ctx)); + return 0; +} + +static int octeon_md5_import(struct shash_desc *desc, const void *in) +{ + struct md5_state *ctx = shash_desc_ctx(desc); + + memcpy(ctx, in, sizeof(*ctx)); + return 0; +} + +static struct shash_alg alg = { + .digestsize = MD5_DIGEST_SIZE, + .init = octeon_md5_init, + .update = octeon_md5_update, + .final = octeon_md5_final, + .export = octeon_md5_export, + .import = octeon_md5_import, + .descsize = sizeof(struct md5_state), + .statesize = sizeof(struct md5_state), + .base = { + .cra_name = "md5", + .cra_driver_name= "octeon-md5", + .cra_priority = OCTEON_CR_OPCODE_PRIORITY, + .cra_flags = CRYPTO_ALG_TYPE_SHASH, + .cra_blocksize = MD5_HMAC_BLOCK_SIZE, + .cra_module = THIS_MODULE, + } +}; + +static int __init md5_mod_init(void) +{ + if (!octeon_has_crypto()) + return -ENOTSUPP; + return crypto_register_shash(&alg); +} + +static void __exit md5_mod_fini(void) +{ + crypto_unregister_shash(&alg); +} + +module_init(md5_mod_init); +module_exit(md5_mod_fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("MD5 Message Digest Algorithm (OCTEON)"); +MODULE_AUTHOR("Aaro Koskinen "); -- cgit v1.2.3 From 95d8c4c8499f8a868af719ecfb005f55c959c73a Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Fri, 28 Nov 2014 21:32:48 +0100 Subject: arm: pxa: fix pxa27x device-tree support kconfig Remove the useless CPU_PXA27x non existing kconfig option. The true options is PXA27x, which is already selected. Reported-by: Paul Bolle Signed-off-by: Robert Jarzmik --- arch/arm/mach-pxa/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 83efe914bf7d..5f71c06a4b5b 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -6,7 +6,6 @@ comment "Intel/Marvell Dev Platforms (sorted by hardware release time)" config MACH_PXA27X_DT bool "Support PXA27x platforms from device tree" - select CPU_PXA27x select POWER_SUPPLY select PXA27x select USE_OF -- cgit v1.2.3 From 3ad32229bed9953dd2085ef992adb161ed0c9194 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Mon, 24 Nov 2014 23:18:22 +0100 Subject: ARM: pxa: arbitrarily set first interrupt number As IRQ0, the legacy timer interrupt should not be used as an interrupt number, shift the interrupts by a fixed number. As we had in a special case a shift of 16 when ISA bus was used on a PXA, use that value as the first interrupt number, regardless of ISA or not. Signed-off-by: Robert Jarzmik --- arch/arm/mach-pxa/Kconfig | 5 ----- arch/arm/mach-pxa/include/mach/irqs.h | 9 ++------- 2 files changed, 2 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 5f71c06a4b5b..8896e71586f5 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -83,14 +83,12 @@ config ARCH_VIPER select I2C_GPIO if I2C=y select ISA select PXA25x - select PXA_HAVE_ISA_IRQS config MACH_ARCOM_ZEUS bool "Arcom/Eurotech ZEUS SBC" select ARCOM_PCMCIA select ISA select PXA27x - select PXA_HAVE_ISA_IRQS config MACH_BALLOON3 bool "Balloon 3 board" @@ -690,9 +688,6 @@ config SHARPSL_PM_MAX1111 select SPI select SPI_MASTER -config PXA_HAVE_ISA_IRQS - bool - config PXA310_ULPI bool diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h index 48c2fd851686..83e04d4e72a8 100644 --- a/arch/arm/mach-pxa/include/mach/irqs.h +++ b/arch/arm/mach-pxa/include/mach/irqs.h @@ -12,14 +12,9 @@ #ifndef __ASM_MACH_IRQS_H #define __ASM_MACH_IRQS_H -#ifdef CONFIG_PXA_HAVE_ISA_IRQS -#define PXA_ISA_IRQ(x) (x) -#define PXA_ISA_IRQ_NUM (16) -#else -#define PXA_ISA_IRQ_NUM (0) -#endif +#include -#define PXA_IRQ(x) (PXA_ISA_IRQ_NUM + (x)) +#define PXA_IRQ(x) (NR_IRQS_LEGACY + (x)) #define IRQ_SSP3 PXA_IRQ(0) /* SSP3 service request */ #define IRQ_MSL PXA_IRQ(1) /* MSL Interface interrupt */ -- cgit v1.2.3 From 271e80176aae4e5b481f4bb92df9768c6075bbca Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Thu, 4 Dec 2014 14:10:00 +0300 Subject: ARM: pxa: add regulator_has_full_constraints to corgi board file Add regulator_has_full_constraints() call to corgi board file to let regulator core know that we do not have any additional regulators left. This lets it substitute unprovided regulators with dummy ones. This fixes the following warnings that can be seen on corgi if regulators are enabled: ads7846 spi1.0: unable to get regulator: -517 spi spi1.0: Driver ads7846 requests probe deferral wm8731 0-001b: Failed to get supply 'AVDD': -517 wm8731 0-001b: Failed to request supplies: -517 wm8731 0-001b: ASoC: failed to probe component -517 corgi-audio corgi-audio: ASoC: failed to instantiate card -517 Cc: stable@vger.kernel.org Signed-off-by: Dmitry Eremin-Solenikov Acked-by: Mark Brown Signed-off-by: Robert Jarzmik --- arch/arm/mach-pxa/corgi.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 06022b235730..89f790dda93e 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -752,6 +753,8 @@ static void __init corgi_init(void) sharpsl_nand_partitions[1].size = 53 * 1024 * 1024; platform_add_devices(devices, ARRAY_SIZE(devices)); + + regulator_has_full_constraints(); } static void __init fixup_corgi(struct tag *tags, char **cmdline) -- cgit v1.2.3 From 9bc78f32c2e430aebf6def965b316aa95e37a20c Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Thu, 4 Dec 2014 14:10:01 +0300 Subject: ARM: pxa: add regulator_has_full_constraints to poodle board file Add regulator_has_full_constraints() call to poodle board file to let regulator core know that we do not have any additional regulators left. This lets it substitute unprovided regulators with dummy ones. This fixes the following warnings that can be seen on poodle if regulators are enabled: ads7846 spi1.0: unable to get regulator: -517 spi spi1.0: Driver ads7846 requests probe deferral wm8731 0-001b: Failed to get supply 'AVDD': -517 wm8731 0-001b: Failed to request supplies: -517 wm8731 0-001b: ASoC: failed to probe component -517 Cc: stable@vger.kernel.org Signed-off-by: Dmitry Eremin-Solenikov Acked-by: Mark Brown Signed-off-by: Robert Jarzmik --- arch/arm/mach-pxa/poodle.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 29019beae591..195b1121c8f1 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -455,6 +456,7 @@ static void __init poodle_init(void) pxa_set_i2c_info(NULL); i2c_register_board_info(0, ARRAY_AND_SIZE(poodle_i2c_devices)); poodle_init_spi(); + regulator_has_full_constraints(); } static void __init fixup_poodle(struct tag *tags, char **cmdline) -- cgit v1.2.3 From baad2dc49c5d970ea881d92981a1b76c94a7b7a1 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Thu, 4 Dec 2014 14:10:02 +0300 Subject: ARM: pxa: add regulator_has_full_constraints to spitz board file Add regulator_has_full_constraints() call to spitz board file to let regulator core know that we do not have any additional regulators left. This lets it substitute unprovided regulators with dummy ones. This fixes the following warnings that can be seen on spitz if regulators are enabled: ads7846 spi2.0: unable to get regulator: -517 spi spi2.0: Driver ads7846 requests probe deferral Cc: stable@vger.kernel.org Signed-off-by: Dmitry Eremin-Solenikov Acked-by: Mark Brown Signed-off-by: Robert Jarzmik --- arch/arm/mach-pxa/spitz.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 962a7f31f596..f4e2e2719580 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -979,6 +979,8 @@ static void __init spitz_init(void) spitz_nand_init(); spitz_i2c_init(); spitz_audio_init(); + + regulator_has_full_constraints(); } static void __init spitz_fixup(struct tag *tags, char **cmdline) -- cgit v1.2.3 From a52d209336f8fc7483a8c7f4a8a7d2a8e1692a6c Mon Sep 17 00:00:00 2001 From: Martin Vajnar Date: Wed, 24 Dec 2014 00:27:57 +0100 Subject: hx4700: regulator: declare full constraints Since the removal of CONFIG_REGULATOR_DUMMY option, the touchscreen stopped working. This patch enables the "replacement" for REGULATOR_DUMMY and allows the touchscreen to work even though there is no regulator for "vcc". Cc: stable@vger.kernel.org Signed-off-by: Martin Vajnar Signed-off-by: Robert Jarzmik --- arch/arm/mach-pxa/hx4700.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c index c66ad4edc5e3..5fb41ad6e3bc 100644 --- a/arch/arm/mach-pxa/hx4700.c +++ b/arch/arm/mach-pxa/hx4700.c @@ -893,6 +893,8 @@ static void __init hx4700_init(void) mdelay(10); gpio_set_value(GPIO71_HX4700_ASIC3_nRESET, 1); mdelay(10); + + regulator_has_full_constraints(); } MACHINE_START(H4700, "HP iPAQ HX4700") -- cgit v1.2.3 From 7c674700098c87b305b99652e3c694c4ef195866 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Sat, 27 Dec 2014 18:19:12 -0700 Subject: PCI: Move domain assignment from arm64 to generic code The current logic in arm64 pci_bus_assign_domain_nr() is flawed in that depending on the host controller configuration for a platform and the initialization sequence, core code may end up allocating PCI domain numbers from both DT and the generic domain counter, which would result in PCI domain allocation aliases/errors. Fix the logic behind the PCI domain number assignment and move the resulting code to the PCI core so the same domain allocation logic is used on all platforms that select CONFIG_PCI_DOMAINS_GENERIC. [bhelgaas: tidy changelog] Signed-off-by: Lorenzo Pieralisi Signed-off-by: Bjorn Helgaas Acked-by: Liviu Dudau Acked-by: Arnd Bergmann CC: Rob Herring CC: Catalin Marinas --- arch/arm64/kernel/pci.c | 22 ---------------------- 1 file changed, 22 deletions(-) (limited to 'arch') diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c index ce5836c14ec1..6f93c24ca801 100644 --- a/arch/arm64/kernel/pci.c +++ b/arch/arm64/kernel/pci.c @@ -46,25 +46,3 @@ int pcibios_add_device(struct pci_dev *dev) return 0; } - - -#ifdef CONFIG_PCI_DOMAINS_GENERIC -static bool dt_domain_found = false; - -void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent) -{ - int domain = of_get_pci_domain_nr(parent->of_node); - - if (domain >= 0) { - dt_domain_found = true; - } else if (dt_domain_found == true) { - dev_err(parent, "Node %s is missing \"linux,pci-domain\" property in DT\n", - parent->of_node->full_name); - return; - } else { - domain = pci_get_new_domain_nr(); - } - - bus->domain_nr = domain; -} -#endif -- cgit v1.2.3 From c88d54ba0c3d89b925bfb8e98b13a3f55b55cde4 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Fri, 21 Nov 2014 11:29:25 +0000 Subject: CNS3xxx: Remove artificial dependency on pci_sys_data domain. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On cns3xxx platforms the PCI controller probing code relies on an artificial dependency on the domain number to look-up the internal data structures. This patch reworks the host controller control data structure and adds a domain equivalent field named port in it so that the dependency on pci_sys_data domain field can be eventually removed. Acked-by: Krzysztof Hałasa Signed-off-by: Arnd Bergmann [lp: added commit log, removed pci_sys_data domain references] Signed-off-by: Lorenzo Pieralisi Signed-off-by: Bjorn Helgaas --- arch/arm/mach-cns3xxx/pcie.c | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-cns3xxx/pcie.c b/arch/arm/mach-cns3xxx/pcie.c index 45d6bd09e6ef..f6bf9f623d70 100644 --- a/arch/arm/mach-cns3xxx/pcie.c +++ b/arch/arm/mach-cns3xxx/pcie.c @@ -30,18 +30,15 @@ struct cns3xxx_pcie { unsigned int irqs[2]; struct resource res_io; struct resource res_mem; - struct hw_pci hw_pci; - + int port; bool linked; }; -static struct cns3xxx_pcie cns3xxx_pcie[]; /* forward decl. */ - static struct cns3xxx_pcie *sysdata_to_cnspci(void *sysdata) { struct pci_sys_data *root = sysdata; - return &cns3xxx_pcie[root->domain]; + return root->private_data; } static struct cns3xxx_pcie *pdev_to_cnspci(const struct pci_dev *dev) @@ -192,13 +189,7 @@ static struct cns3xxx_pcie cns3xxx_pcie[] = { .flags = IORESOURCE_MEM, }, .irqs = { IRQ_CNS3XXX_PCIE0_RC, IRQ_CNS3XXX_PCIE0_DEVICE, }, - .hw_pci = { - .domain = 0, - .nr_controllers = 1, - .ops = &cns3xxx_pcie_ops, - .setup = cns3xxx_pci_setup, - .map_irq = cns3xxx_pcie_map_irq, - }, + .port = 0, }, [1] = { .host_regs = (void __iomem *)CNS3XXX_PCIE1_HOST_BASE_VIRT, @@ -217,19 +208,13 @@ static struct cns3xxx_pcie cns3xxx_pcie[] = { .flags = IORESOURCE_MEM, }, .irqs = { IRQ_CNS3XXX_PCIE1_RC, IRQ_CNS3XXX_PCIE1_DEVICE, }, - .hw_pci = { - .domain = 1, - .nr_controllers = 1, - .ops = &cns3xxx_pcie_ops, - .setup = cns3xxx_pci_setup, - .map_irq = cns3xxx_pcie_map_irq, - }, + .port = 1, }, }; static void __init cns3xxx_pcie_check_link(struct cns3xxx_pcie *cnspci) { - int port = cnspci->hw_pci.domain; + int port = cnspci->port; u32 reg; unsigned long time; @@ -260,9 +245,9 @@ static void __init cns3xxx_pcie_check_link(struct cns3xxx_pcie *cnspci) static void __init cns3xxx_pcie_hw_init(struct cns3xxx_pcie *cnspci) { - int port = cnspci->hw_pci.domain; + int port = cnspci->port; struct pci_sys_data sd = { - .domain = port, + .private_data = cnspci, }; struct pci_bus bus = { .number = 0, @@ -323,6 +308,14 @@ static int cns3xxx_pcie_abort_handler(unsigned long addr, unsigned int fsr, void __init cns3xxx_pcie_init_late(void) { int i; + void *private_data; + struct hw_pci hw_pci = { + .nr_controllers = 1, + .ops = &cns3xxx_pcie_ops, + .setup = cns3xxx_pci_setup, + .map_irq = cns3xxx_pcie_map_irq, + .private_data = &private_data, + }; pcibios_min_io = 0; pcibios_min_mem = 0; @@ -335,7 +328,8 @@ void __init cns3xxx_pcie_init_late(void) cns3xxx_pwr_soft_rst(0x1 << PM_SOFT_RST_REG_OFFST_PCIE(i)); cns3xxx_pcie_check_link(&cns3xxx_pcie[i]); cns3xxx_pcie_hw_init(&cns3xxx_pcie[i]); - pci_common_init(&cns3xxx_pcie[i].hw_pci); + private_data = &cns3xxx_pcie[i]; + pci_common_init(&hw_pci); } pci_assign_unassigned_resources(); -- cgit v1.2.3 From 8c7d14746abce601b768533c3ccb3f3e64f98551 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Fri, 21 Nov 2014 11:29:26 +0000 Subject: ARM/PCI: Move to generic PCI domains Most if not all ARM PCI host controller device drivers either ignore the domain field in the pci_sys_data structure or just increment it every time a host controller is probed, using it as a domain counter. Therefore, instead of relying on pci_sys_data to stash the domain number in a standard location, ARM pcibios code can be moved to the newly introduced generic PCI domains code, implemented in commits: 41e5c0f81d3e ("of/pci: Add pci_get_new_domain_nr() and of_get_pci_domain_nr()") 670ba0c8883b ("PCI: Add generic domain handling") ARM code is made to select PCI_DOMAINS_GENERIC by default, which builds core PCI code that assigns the domain number through the generic function: void pci_bus_assign_domain_nr(...) that relies on a DT property to define the domain number or falls back to a counter according to a predefined logic; its usage replaces the current domain assignment code in PCI host controllers present in the kernel. Tested-by: Lucas Stach Signed-off-by: Lorenzo Pieralisi Signed-off-by: Bjorn Helgaas Reviewed-by: Yijing Wang Reviewed-By: Jason Gunthorpe # mvebu Acked-by: Russell King Acked-by: Lucas Stach Acked-by: Jingoo Han Acked-by: Phil Edworthy Acked-by: Arnd Bergmann CC: Mohit Kumar --- arch/arm/Kconfig | 3 +++ arch/arm/include/asm/mach/pci.h | 6 ------ arch/arm/include/asm/pci.h | 7 ------- arch/arm/kernel/bios32.c | 3 --- 4 files changed, 3 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 97d07ed60a0b..dcb2e0c55be4 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1279,6 +1279,9 @@ config PCI_DOMAINS bool depends on PCI +config PCI_DOMAINS_GENERIC + def_bool PCI_DOMAINS + config PCI_NANOENGINE bool "BSE nanoEngine PCI support" depends on SA1100_NANOENGINE diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h index 8292b5f81e23..28b9bb35949e 100644 --- a/arch/arm/include/asm/mach/pci.h +++ b/arch/arm/include/asm/mach/pci.h @@ -19,9 +19,6 @@ struct pci_bus; struct device; struct hw_pci { -#ifdef CONFIG_PCI_DOMAINS - int domain; -#endif #ifdef CONFIG_PCI_MSI struct msi_controller *msi_ctrl; #endif @@ -45,9 +42,6 @@ struct hw_pci { * Per-controller structure */ struct pci_sys_data { -#ifdef CONFIG_PCI_DOMAINS - int domain; -#endif #ifdef CONFIG_PCI_MSI struct msi_controller *msi_ctrl; #endif diff --git a/arch/arm/include/asm/pci.h b/arch/arm/include/asm/pci.h index 7e95d8535e24..585dc33a7a24 100644 --- a/arch/arm/include/asm/pci.h +++ b/arch/arm/include/asm/pci.h @@ -18,13 +18,6 @@ static inline int pcibios_assign_all_busses(void) } #ifdef CONFIG_PCI_DOMAINS -static inline int pci_domain_nr(struct pci_bus *bus) -{ - struct pci_sys_data *root = bus->sysdata; - - return root->domain; -} - static inline int pci_proc_domain(struct pci_bus *bus) { return pci_domain_nr(bus); diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index a4effd6d8f2f..ddd75c58b1e8 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -463,9 +463,6 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw, if (!sys) panic("PCI: unable to allocate sys data!"); -#ifdef CONFIG_PCI_DOMAINS - sys->domain = hw->domain; -#endif #ifdef CONFIG_PCI_MSI sys->msi_ctrl = hw->msi_ctrl; #endif -- cgit v1.2.3 From e3a8446a6a1bff8c2345cacd4f3b8bdea0ba36d8 Mon Sep 17 00:00:00 2001 From: Cody P Schafer Date: Mon, 12 May 2014 20:09:55 -0700 Subject: powerpc/pseries: relocate "config DTL" so kconfig nests properly Moving config DTL up so it is below config PPC_SPLPAR means that menuconfig will show config DTL nicely indented right below config PPC_SPLPAR when PPC_SPLPAR is enabled. To contrast that, right now if I enable PPC_SPLPAR in menuconfig, all I can immediately tell is that "something showed up further down the list where I wasn't looking", and I end up having to toggle the option a few times to figure out what showed up, or look at the KConfig to find out that config DTL depends on config PPC_SPLPAR. Signed-off-by: Cody P Schafer Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/pseries/Kconfig | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index 756b482f819a..a758a9c3bbba 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig @@ -34,6 +34,16 @@ config PPC_SPLPAR processors, that is, which share physical processors between two or more partitions. +config DTL + bool "Dispatch Trace Log" + depends on PPC_SPLPAR && DEBUG_FS + help + SPLPAR machines can log hypervisor preempt & dispatch events to a + kernel buffer. Saying Y here will enable logging these events, + which are accessible through a debugfs file. + + Say N if you are unsure. + config PSERIES_MSI bool depends on PCI_MSI && PPC_PSERIES && EEH @@ -123,13 +133,3 @@ config HV_PERF_CTRS systems. 24x7 is available on Power 8 systems. If unsure, select Y. - -config DTL - bool "Dispatch Trace Log" - depends on PPC_SPLPAR && DEBUG_FS - help - SPLPAR machines can log hypervisor preempt & dispatch events to a - kernel buffer. Saying Y here will enable logging these events, - which are accessible through a debugfs file. - - Say N if you are unsure. -- cgit v1.2.3 From 05b981f493e07856371ecd4a9294f187f5b50cf6 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Tue, 15 Jul 2014 13:43:47 +0200 Subject: powerpc/xmon: use isspace/isxdigit/isalnum from linux/ctype.h isxdigit() macro definition is the same. isalnum() from linux/ctype.h will accept additional latin non-ASCII characters. This is harmless since this macro is used in scanhex() which parses user input. isspace() from linux/ctype.h will accept vertical tab and form feed but not NULL. The use of this macro is modified to accept NULL as well. Additional characters are harmless since this macro is also only used in scanhex(). Signed-off-by: Vincent Bernat Signed-off-by: Michael Ellerman --- arch/powerpc/xmon/xmon.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 5b150f0c5df9..e66ace703a69 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -183,14 +184,6 @@ extern void xmon_leave(void); #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3]) #endif -#define isxdigit(c) (('0' <= (c) && (c) <= '9') \ - || ('a' <= (c) && (c) <= 'f') \ - || ('A' <= (c) && (c) <= 'F')) -#define isalnum(c) (('0' <= (c) && (c) <= '9') \ - || ('a' <= (c) && (c) <= 'z') \ - || ('A' <= (c) && (c) <= 'Z')) -#define isspace(c) (c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0) - static char *help_string = "\ Commands:\n\ b show breakpoints\n\ @@ -2164,9 +2157,6 @@ static void dump_pacas(void) } #endif -#define isxdigit(c) (('0' <= (c) && (c) <= '9') \ - || ('a' <= (c) && (c) <= 'f') \ - || ('A' <= (c) && (c) <= 'F')) static void dump(void) { @@ -2569,7 +2559,7 @@ scanhex(unsigned long *vp) int i; for (i=0; i<63; i++) { c = inchar(); - if (isspace(c)) { + if (isspace(c) || c == '\0') { termch = c; break; } -- cgit v1.2.3 From e144d4edbce67ea269d181f81b9c5ef631743430 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 20 Jul 2014 15:20:59 +0800 Subject: powerpc/4xx: Fix return value check in hsta_msi_probe() In case of error, the function ioremap() returns NULL not ERR_PTR(). The IS_ERR() test in the return value check should be replaced with NULL test. Signed-off-by: Wei Yongjun Signed-off-by: Michael Ellerman --- arch/powerpc/sysdev/ppc4xx_hsta_msi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/powerpc/sysdev/ppc4xx_hsta_msi.c b/arch/powerpc/sysdev/ppc4xx_hsta_msi.c index ed9970ff8d94..f366d2d4c079 100644 --- a/arch/powerpc/sysdev/ppc4xx_hsta_msi.c +++ b/arch/powerpc/sysdev/ppc4xx_hsta_msi.c @@ -145,7 +145,7 @@ static int hsta_msi_probe(struct platform_device *pdev) ppc4xx_hsta_msi.address = mem->start; ppc4xx_hsta_msi.data = ioremap(mem->start, resource_size(mem)); ppc4xx_hsta_msi.irq_count = irq_count; - if (IS_ERR(ppc4xx_hsta_msi.data)) { + if (!ppc4xx_hsta_msi.data) { dev_err(dev, "Unable to map memory\n"); return -ENOMEM; } -- cgit v1.2.3 From 01b14505c35cdc47f5abc1f6799cee23f2f10149 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Tue, 23 Dec 2014 11:32:07 +1100 Subject: powerpc/44x/Akebono: Remove select of IBM_EMAC_RGMII_WOL Commit 2a2c74b2efcb ("IBM Akebono: Add the Akebono platform") added a select of IBM_EMAC_RGMII_WOL. But that Kconfig symbol isn't (yet) part of the tree. So this select has been a nop since that commit was included in v3.16-rc1. Signed-off-by: Paul Bolle Acked-by: Alistair Popple Signed-off-by: Michael Ellerman --- arch/powerpc/platforms/44x/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig index d2ac1c116454..5538e57c36c1 100644 --- a/arch/powerpc/platforms/44x/Kconfig +++ b/arch/powerpc/platforms/44x/Kconfig @@ -214,7 +214,6 @@ config AKEBONO select ETHERNET select NET_VENDOR_IBM select IBM_EMAC_EMAC4 - select IBM_EMAC_RGMII_WOL select USB if USB_SUPPORT select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD -- cgit v1.2.3 From 803d57de2b27000ed4400d16561c75821efe8333 Mon Sep 17 00:00:00 2001 From: Andreas Ruprecht Date: Wed, 17 Dec 2014 12:05:13 +0100 Subject: powerpc/lib: Do not include string.o in obj-y twice In the Makefile, string.o (which is generated from string.S) is included into the list of objects being built unconditionally (obj-y) in line 12. Additionally, if CONFIG_PPC64 is set, it is included again in line 17. This patch removes the latter unnecessary inclusion. Signed-off-by: Andreas Ruprecht Signed-off-by: Michael Ellerman --- arch/powerpc/lib/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index 597562f69b2d..1b01159b81f3 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile @@ -14,8 +14,7 @@ obj-y := string.o alloc.o \ obj-$(CONFIG_PPC32) += div64.o copy_32.o obj-$(CONFIG_PPC64) += copypage_64.o copyuser_64.o \ - usercopy_64.o mem_64.o string.o \ - hweight_64.o \ + usercopy_64.o mem_64.o hweight_64.o \ copyuser_power7.o string_64.o copypage_power7.o ifeq ($(CONFIG_GENERIC_CSUM),) obj-y += checksum_$(CONFIG_WORD_SIZE).o -- cgit v1.2.3 From 9a4fc4eaf111ca960c9f524b850598e9dbc9697f Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 10 Jul 2014 19:34:31 +1000 Subject: powerpc/kvm: Create proper names for the kvm_host_state PMU fields We have two arrays in kvm_host_state that contain register values for the PMU. Currently we only create an asm-offsets symbol for the base of the arrays, and do the array offset in the assembly code. Creating an asm-offsets symbol for each field individually makes the code much nicer to read, particularly for the MMCRx/SIxR/SDAR fields, and might have helped us notice the recent double restore bug we had in this code. Signed-off-by: Michael Ellerman Acked-by: Alexander Graf --- arch/powerpc/kernel/asm-offsets.c | 15 +++++++++++++-- arch/powerpc/kvm/book3s_hv_interrupts.S | 26 +++++++++++++------------- arch/powerpc/kvm/book3s_hv_rmhandlers.S | 28 ++++++++++++++-------------- 3 files changed, 40 insertions(+), 29 deletions(-) (limited to 'arch') diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index e624f9646350..4717859fdd04 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -644,8 +644,19 @@ int main(void) HSTATE_FIELD(HSTATE_SAVED_XIRR, saved_xirr); HSTATE_FIELD(HSTATE_HOST_IPI, host_ipi); HSTATE_FIELD(HSTATE_PTID, ptid); - HSTATE_FIELD(HSTATE_MMCR, host_mmcr); - HSTATE_FIELD(HSTATE_PMC, host_pmc); + HSTATE_FIELD(HSTATE_MMCR0, host_mmcr[0]); + HSTATE_FIELD(HSTATE_MMCR1, host_mmcr[1]); + HSTATE_FIELD(HSTATE_MMCRA, host_mmcr[2]); + HSTATE_FIELD(HSTATE_SIAR, host_mmcr[3]); + HSTATE_FIELD(HSTATE_SDAR, host_mmcr[4]); + HSTATE_FIELD(HSTATE_MMCR2, host_mmcr[5]); + HSTATE_FIELD(HSTATE_SIER, host_mmcr[6]); + HSTATE_FIELD(HSTATE_PMC1, host_pmc[0]); + HSTATE_FIELD(HSTATE_PMC2, host_pmc[1]); + HSTATE_FIELD(HSTATE_PMC3, host_pmc[2]); + HSTATE_FIELD(HSTATE_PMC4, host_pmc[3]); + HSTATE_FIELD(HSTATE_PMC5, host_pmc[4]); + HSTATE_FIELD(HSTATE_PMC6, host_pmc[5]); HSTATE_FIELD(HSTATE_PURR, host_purr); HSTATE_FIELD(HSTATE_SPURR, host_spurr); HSTATE_FIELD(HSTATE_DSCR, host_dscr); diff --git a/arch/powerpc/kvm/book3s_hv_interrupts.S b/arch/powerpc/kvm/book3s_hv_interrupts.S index 36540a99d178..0fdc4a28970b 100644 --- a/arch/powerpc/kvm/book3s_hv_interrupts.S +++ b/arch/powerpc/kvm/book3s_hv_interrupts.S @@ -93,15 +93,15 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) mfspr r5, SPRN_MMCR1 mfspr r9, SPRN_SIAR mfspr r10, SPRN_SDAR - std r7, HSTATE_MMCR(r13) - std r5, HSTATE_MMCR + 8(r13) - std r6, HSTATE_MMCR + 16(r13) - std r9, HSTATE_MMCR + 24(r13) - std r10, HSTATE_MMCR + 32(r13) + std r7, HSTATE_MMCR0(r13) + std r5, HSTATE_MMCR1(r13) + std r6, HSTATE_MMCRA(r13) + std r9, HSTATE_SIAR(r13) + std r10, HSTATE_SDAR(r13) BEGIN_FTR_SECTION mfspr r9, SPRN_SIER - std r8, HSTATE_MMCR + 40(r13) - std r9, HSTATE_MMCR + 48(r13) + std r8, HSTATE_MMCR2(r13) + std r9, HSTATE_SIER(r13) END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) mfspr r3, SPRN_PMC1 mfspr r5, SPRN_PMC2 @@ -109,12 +109,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) mfspr r7, SPRN_PMC4 mfspr r8, SPRN_PMC5 mfspr r9, SPRN_PMC6 - stw r3, HSTATE_PMC(r13) - stw r5, HSTATE_PMC + 4(r13) - stw r6, HSTATE_PMC + 8(r13) - stw r7, HSTATE_PMC + 12(r13) - stw r8, HSTATE_PMC + 16(r13) - stw r9, HSTATE_PMC + 20(r13) + stw r3, HSTATE_PMC1(r13) + stw r5, HSTATE_PMC2(r13) + stw r6, HSTATE_PMC3(r13) + stw r7, HSTATE_PMC4(r13) + stw r8, HSTATE_PMC5(r13) + stw r9, HSTATE_PMC6(r13) 31: /* diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index 10554df13852..bb94e6f20c81 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S @@ -83,35 +83,35 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) cmpwi r4, 0 beq 23f /* skip if not */ BEGIN_FTR_SECTION - ld r3, HSTATE_MMCR(r13) + ld r3, HSTATE_MMCR0(r13) andi. r4, r3, MMCR0_PMAO_SYNC | MMCR0_PMAO cmpwi r4, MMCR0_PMAO beql kvmppc_fix_pmao END_FTR_SECTION_IFSET(CPU_FTR_PMAO_BUG) - lwz r3, HSTATE_PMC(r13) - lwz r4, HSTATE_PMC + 4(r13) - lwz r5, HSTATE_PMC + 8(r13) - lwz r6, HSTATE_PMC + 12(r13) - lwz r8, HSTATE_PMC + 16(r13) - lwz r9, HSTATE_PMC + 20(r13) + lwz r3, HSTATE_PMC1(r13) + lwz r4, HSTATE_PMC2(r13) + lwz r5, HSTATE_PMC3(r13) + lwz r6, HSTATE_PMC4(r13) + lwz r8, HSTATE_PMC5(r13) + lwz r9, HSTATE_PMC6(r13) mtspr SPRN_PMC1, r3 mtspr SPRN_PMC2, r4 mtspr SPRN_PMC3, r5 mtspr SPRN_PMC4, r6 mtspr SPRN_PMC5, r8 mtspr SPRN_PMC6, r9 - ld r3, HSTATE_MMCR(r13) - ld r4, HSTATE_MMCR + 8(r13) - ld r5, HSTATE_MMCR + 16(r13) - ld r6, HSTATE_MMCR + 24(r13) - ld r7, HSTATE_MMCR + 32(r13) + ld r3, HSTATE_MMCR0(r13) + ld r4, HSTATE_MMCR1(r13) + ld r5, HSTATE_MMCRA(r13) + ld r6, HSTATE_SIAR(r13) + ld r7, HSTATE_SDAR(r13) mtspr SPRN_MMCR1, r4 mtspr SPRN_MMCRA, r5 mtspr SPRN_SIAR, r6 mtspr SPRN_SDAR, r7 BEGIN_FTR_SECTION - ld r8, HSTATE_MMCR + 40(r13) - ld r9, HSTATE_MMCR + 48(r13) + ld r8, HSTATE_MMCR2(r13) + ld r9, HSTATE_SIER(r13) mtspr SPRN_MMCR2, r8 mtspr SPRN_SIER, r9 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) -- cgit v1.2.3 From dd450777990baae668c1143064f2f234dbab1b9b Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Wed, 24 Dec 2014 01:14:14 +0300 Subject: arm: sa1100: move irda header to linux/platform_data In the end asm/mach/irda.h header is not used by anybody except sa1100. Move the header to the platform data includes dir and rename it to irda-sa11x0.h. Signed-off-by: Dmitry Eremin-Solenikov Signed-off-by: David S. Miller --- arch/arm/include/asm/mach/irda.h | 20 -------------------- arch/arm/mach-sa1100/assabet.c | 2 +- arch/arm/mach-sa1100/collie.c | 2 +- arch/arm/mach-sa1100/h3100.c | 2 +- arch/arm/mach-sa1100/h3600.c | 2 +- 5 files changed, 4 insertions(+), 24 deletions(-) delete mode 100644 arch/arm/include/asm/mach/irda.h (limited to 'arch') diff --git a/arch/arm/include/asm/mach/irda.h b/arch/arm/include/asm/mach/irda.h deleted file mode 100644 index 38f77b5e56cf..000000000000 --- a/arch/arm/include/asm/mach/irda.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * arch/arm/include/asm/mach/irda.h - * - * Copyright (C) 2004 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. - */ -#ifndef __ASM_ARM_MACH_IRDA_H -#define __ASM_ARM_MACH_IRDA_H - -struct irda_platform_data { - int (*startup)(struct device *); - void (*shutdown)(struct device *); - int (*set_power)(struct device *, unsigned int state); - void (*set_speed)(struct device *, unsigned int speed); -}; - -#endif diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index 7dd894ece9ae..d28ecb9ef172 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -37,7 +37,7 @@ #include #include -#include +#include #include #include #include diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index b90c7d828391..7fcbe3d119c7 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/arm/mach-sa1100/h3100.c b/arch/arm/mach-sa1100/h3100.c index 3c43219bc881..c6b412054a3c 100644 --- a/arch/arm/mach-sa1100/h3100.c +++ b/arch/arm/mach-sa1100/h3100.c @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c index 5be54c214c7c..118338efd790 100644 --- a/arch/arm/mach-sa1100/h3600.c +++ b/arch/arm/mach-sa1100/h3600.c @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include -- cgit v1.2.3 From 9c1ec8e18c210092418d27278a742a2a98eafffe Mon Sep 17 00:00:00 2001 From: Chris Zhong Date: Mon, 1 Dec 2014 16:52:17 +0800 Subject: ARM: rockchip: add suspend and resume for RK3288 It's a basic version of suspend and resume for rockchip, it only support RK3288 now. Signed-off-by: Tony Xie Signed-off-by: Chris Zhong Tested-by: Doug Anderson Reviewed-by: Doug Anderson Signed-off-by: Heiko Stuebner --- arch/arm/mach-rockchip/Makefile | 1 + arch/arm/mach-rockchip/pm.c | 260 ++++++++++++++++++++++++++++++++++++++ arch/arm/mach-rockchip/pm.h | 99 +++++++++++++++ arch/arm/mach-rockchip/rockchip.c | 2 + arch/arm/mach-rockchip/sleep.S | 73 +++++++++++ 5 files changed, 435 insertions(+) create mode 100644 arch/arm/mach-rockchip/pm.c create mode 100644 arch/arm/mach-rockchip/pm.h create mode 100644 arch/arm/mach-rockchip/sleep.S (limited to 'arch') diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile index b29d8ead4cf2..5c3a9b2de920 100644 --- a/arch/arm/mach-rockchip/Makefile +++ b/arch/arm/mach-rockchip/Makefile @@ -1,4 +1,5 @@ CFLAGS_platsmp.o := -march=armv7-a obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip.o +obj-$(CONFIG_PM_SLEEP) += pm.o sleep.o obj-$(CONFIG_SMP) += headsmp.o platsmp.o diff --git a/arch/arm/mach-rockchip/pm.c b/arch/arm/mach-rockchip/pm.c new file mode 100644 index 000000000000..50cb781aaa36 --- /dev/null +++ b/arch/arm/mach-rockchip/pm.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * Author: Tony Xie + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "pm.h" + +/* These enum are option of low power mode */ +enum { + ROCKCHIP_ARM_OFF_LOGIC_NORMAL = 0, + ROCKCHIP_ARM_OFF_LOGIC_DEEP = 1, +}; + +struct rockchip_pm_data { + const struct platform_suspend_ops *ops; + int (*init)(struct device_node *np); +}; + +static void __iomem *rk3288_bootram_base; +static phys_addr_t rk3288_bootram_phy; + +static struct regmap *pmu_regmap; +static struct regmap *sgrf_regmap; + +static u32 rk3288_pmu_pwr_mode_con; +static u32 rk3288_sgrf_soc_con0; + +static inline u32 rk3288_l2_config(void) +{ + u32 l2ctlr; + + asm("mrc p15, 1, %0, c9, c0, 2" : "=r" (l2ctlr)); + return l2ctlr; +} + +static void rk3288_config_bootdata(void) +{ + rkpm_bootdata_cpusp = rk3288_bootram_phy + (SZ_4K - 8); + rkpm_bootdata_cpu_code = virt_to_phys(cpu_resume); + + rkpm_bootdata_l2ctlr_f = 1; + rkpm_bootdata_l2ctlr = rk3288_l2_config(); +} + +static void rk3288_slp_mode_set(int level) +{ + u32 mode_set, mode_set1; + + regmap_read(sgrf_regmap, RK3288_SGRF_SOC_CON0, &rk3288_sgrf_soc_con0); + + regmap_read(pmu_regmap, RK3288_PMU_PWRMODE_CON, + &rk3288_pmu_pwr_mode_con); + + /* set bit 8 so that system will resume to FAST_BOOT_ADDR */ + regmap_write(sgrf_regmap, RK3288_SGRF_SOC_CON0, + SGRF_FAST_BOOT_EN | SGRF_FAST_BOOT_EN_WRITE); + + /* booting address of resuming system is from this register value */ + regmap_write(sgrf_regmap, RK3288_SGRF_FAST_BOOT_ADDR, + rk3288_bootram_phy); + + regmap_write(pmu_regmap, RK3288_PMU_WAKEUP_CFG1, + PMU_ARMINT_WAKEUP_EN); + + mode_set = BIT(PMU_GLOBAL_INT_DISABLE) | BIT(PMU_L2FLUSH_EN) | + BIT(PMU_SREF0_ENTER_EN) | BIT(PMU_SREF1_ENTER_EN) | + BIT(PMU_DDR0_GATING_EN) | BIT(PMU_DDR1_GATING_EN) | + BIT(PMU_PWR_MODE_EN) | BIT(PMU_CHIP_PD_EN) | + BIT(PMU_SCU_EN); + + mode_set1 = BIT(PMU_CLR_CORE) | BIT(PMU_CLR_CPUP); + + if (level == ROCKCHIP_ARM_OFF_LOGIC_DEEP) { + /* arm off, logic deep sleep */ + mode_set |= BIT(PMU_BUS_PD_EN) | + BIT(PMU_DDR1IO_RET_EN) | BIT(PMU_DDR0IO_RET_EN) | + BIT(PMU_OSC_24M_DIS) | BIT(PMU_PMU_USE_LF) | + BIT(PMU_ALIVE_USE_LF) | BIT(PMU_PLL_PD_EN); + + mode_set1 |= BIT(PMU_CLR_ALIVE) | BIT(PMU_CLR_BUS) | + BIT(PMU_CLR_PERI) | BIT(PMU_CLR_DMA); + } else { + /* + * arm off, logic normal + * if pmu_clk_core_src_gate_en is not set, + * wakeup will be error + */ + mode_set |= BIT(PMU_CLK_CORE_SRC_GATE_EN); + } + + regmap_write(pmu_regmap, RK3288_PMU_PWRMODE_CON, mode_set); + regmap_write(pmu_regmap, RK3288_PMU_PWRMODE_CON1, mode_set1); +} + +static void rk3288_slp_mode_set_resume(void) +{ + regmap_write(pmu_regmap, RK3288_PMU_PWRMODE_CON, + rk3288_pmu_pwr_mode_con); + + regmap_write(sgrf_regmap, RK3288_SGRF_SOC_CON0, + rk3288_sgrf_soc_con0 | SGRF_FAST_BOOT_EN_WRITE); +} + +static int rockchip_lpmode_enter(unsigned long arg) +{ + flush_cache_all(); + + cpu_do_idle(); + + pr_err("%s: Failed to suspend\n", __func__); + + return 1; +} + +static int rk3288_suspend_enter(suspend_state_t state) +{ + local_fiq_disable(); + + rk3288_slp_mode_set(ROCKCHIP_ARM_OFF_LOGIC_NORMAL); + + cpu_suspend(0, rockchip_lpmode_enter); + + rk3288_slp_mode_set_resume(); + + local_fiq_enable(); + + return 0; +} + +static int rk3288_suspend_prepare(void) +{ + return regulator_suspend_prepare(PM_SUSPEND_MEM); +} + +static void rk3288_suspend_finish(void) +{ + if (regulator_suspend_finish()) + pr_err("%s: Suspend finish failed\n", __func__); +} + +static int rk3288_suspend_init(struct device_node *np) +{ + struct device_node *sram_np; + struct resource res; + int ret; + + pmu_regmap = syscon_node_to_regmap(np); + if (IS_ERR(pmu_regmap)) { + pr_err("%s: could not find pmu regmap\n", __func__); + return PTR_ERR(pmu_regmap); + } + + sgrf_regmap = syscon_regmap_lookup_by_compatible( + "rockchip,rk3288-sgrf"); + if (IS_ERR(sgrf_regmap)) { + pr_err("%s: could not find sgrf regmap\n", __func__); + return PTR_ERR(pmu_regmap); + } + + sram_np = of_find_compatible_node(NULL, NULL, + "rockchip,rk3288-pmu-sram"); + if (!sram_np) { + pr_err("%s: could not find bootram dt node\n", __func__); + return -ENODEV; + } + + rk3288_bootram_base = of_iomap(sram_np, 0); + if (!rk3288_bootram_base) { + pr_err("%s: could not map bootram base\n", __func__); + return -ENOMEM; + } + + ret = of_address_to_resource(sram_np, 0, &res); + if (ret) { + pr_err("%s: could not get bootram phy addr\n", __func__); + return ret; + } + rk3288_bootram_phy = res.start; + + of_node_put(sram_np); + + rk3288_config_bootdata(); + + /* copy resume code and data to bootsram */ + memcpy(rk3288_bootram_base, rockchip_slp_cpu_resume, + rk3288_bootram_sz); + + return 0; +} + +static const struct platform_suspend_ops rk3288_suspend_ops = { + .enter = rk3288_suspend_enter, + .valid = suspend_valid_only_mem, + .prepare = rk3288_suspend_prepare, + .finish = rk3288_suspend_finish, +}; + +static const struct rockchip_pm_data rk3288_pm_data __initconst = { + .ops = &rk3288_suspend_ops, + .init = rk3288_suspend_init, +}; + +static const struct of_device_id rockchip_pmu_of_device_ids[] __initconst = { + { + .compatible = "rockchip,rk3288-pmu", + .data = &rk3288_pm_data, + }, + { /* sentinel */ }, +}; + +void __init rockchip_suspend_init(void) +{ + const struct rockchip_pm_data *pm_data; + const struct of_device_id *match; + struct device_node *np; + int ret; + + np = of_find_matching_node_and_match(NULL, rockchip_pmu_of_device_ids, + &match); + if (!match) { + pr_err("Failed to find PMU node\n"); + return; + } + pm_data = (struct rockchip_pm_data *) match->data; + + if (pm_data->init) { + ret = pm_data->init(np); + + if (ret) { + pr_err("%s: matches init error %d\n", __func__, ret); + return; + } + } + + suspend_set_ops(pm_data->ops); +} diff --git a/arch/arm/mach-rockchip/pm.h b/arch/arm/mach-rockchip/pm.h new file mode 100644 index 000000000000..7d752ff39f91 --- /dev/null +++ b/arch/arm/mach-rockchip/pm.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * Author: Tony Xie + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef __MACH_ROCKCHIP_PM_H +#define __MACH_ROCKCHIP_PM_H + +extern unsigned long rkpm_bootdata_cpusp; +extern unsigned long rkpm_bootdata_cpu_code; +extern unsigned long rkpm_bootdata_l2ctlr_f; +extern unsigned long rkpm_bootdata_l2ctlr; +extern unsigned long rkpm_bootdata_ddr_code; +extern unsigned long rkpm_bootdata_ddr_data; +extern unsigned long rk3288_bootram_sz; + +void rockchip_slp_cpu_resume(void); +void __init rockchip_suspend_init(void); + +/****** following is rk3288 defined **********/ +#define RK3288_PMU_WAKEUP_CFG0 0x00 +#define RK3288_PMU_WAKEUP_CFG1 0x04 +#define RK3288_PMU_PWRMODE_CON 0x18 +#define RK3288_PMU_OSC_CNT 0x20 +#define RK3288_PMU_PLL_CNT 0x24 +#define RK3288_PMU_STABL_CNT 0x28 +#define RK3288_PMU_DDR0IO_PWRON_CNT 0x2c +#define RK3288_PMU_DDR1IO_PWRON_CNT 0x30 +#define RK3288_PMU_CORE_PWRDWN_CNT 0x34 +#define RK3288_PMU_CORE_PWRUP_CNT 0x38 +#define RK3288_PMU_GPU_PWRDWN_CNT 0x3c +#define RK3288_PMU_GPU_PWRUP_CNT 0x40 +#define RK3288_PMU_WAKEUP_RST_CLR_CNT 0x44 +#define RK3288_PMU_PWRMODE_CON1 0x90 + +#define RK3288_SGRF_SOC_CON0 (0x0000) +#define RK3288_SGRF_FAST_BOOT_ADDR (0x0120) +#define SGRF_FAST_BOOT_EN BIT(8) +#define SGRF_FAST_BOOT_EN_WRITE BIT(24) + +#define RK3288_CRU_MODE_CON 0x50 +#define RK3288_CRU_SEL0_CON 0x60 +#define RK3288_CRU_SEL1_CON 0x64 +#define RK3288_CRU_SEL10_CON 0x88 +#define RK3288_CRU_SEL33_CON 0xe4 +#define RK3288_CRU_SEL37_CON 0xf4 + +/* PMU_WAKEUP_CFG1 bits */ +#define PMU_ARMINT_WAKEUP_EN BIT(0) + +enum rk3288_pwr_mode_con { + PMU_PWR_MODE_EN = 0, + PMU_CLK_CORE_SRC_GATE_EN, + PMU_GLOBAL_INT_DISABLE, + PMU_L2FLUSH_EN, + PMU_BUS_PD_EN, + PMU_A12_0_PD_EN, + PMU_SCU_EN, + PMU_PLL_PD_EN, + PMU_CHIP_PD_EN, /* POWER OFF PIN ENABLE */ + PMU_PWROFF_COMB, + PMU_ALIVE_USE_LF, + PMU_PMU_USE_LF, + PMU_OSC_24M_DIS, + PMU_INPUT_CLAMP_EN, + PMU_WAKEUP_RESET_EN, + PMU_SREF0_ENTER_EN, + PMU_SREF1_ENTER_EN, + PMU_DDR0IO_RET_EN, + PMU_DDR1IO_RET_EN, + PMU_DDR0_GATING_EN, + PMU_DDR1_GATING_EN, + PMU_DDR0IO_RET_DE_REQ, + PMU_DDR1IO_RET_DE_REQ +}; + +enum rk3288_pwr_mode_con1 { + PMU_CLR_BUS = 0, + PMU_CLR_CORE, + PMU_CLR_CPUP, + PMU_CLR_ALIVE, + PMU_CLR_DMA, + PMU_CLR_PERI, + PMU_CLR_GPU, + PMU_CLR_VIDEO, + PMU_CLR_HEVC, + PMU_CLR_VIO, +}; + +#endif /* __MACH_ROCKCHIP_PM_H */ diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c index d226b71d21d5..2b68a1a70912 100644 --- a/arch/arm/mach-rockchip/rockchip.c +++ b/arch/arm/mach-rockchip/rockchip.c @@ -23,9 +23,11 @@ #include #include #include "core.h" +#include "pm.h" static void __init rockchip_dt_init(void) { + rockchip_suspend_init(); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); platform_device_register_simple("cpufreq-dt", 0, NULL, 0); } diff --git a/arch/arm/mach-rockchip/sleep.S b/arch/arm/mach-rockchip/sleep.S new file mode 100644 index 000000000000..2eec9a341f05 --- /dev/null +++ b/arch/arm/mach-rockchip/sleep.S @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * Author: Tony Xie + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 +#include +#include + +.data +/* + * this code will be copied from + * ddr to sram for system resumeing. + * so it is ".data section". + */ +.align + +ENTRY(rockchip_slp_cpu_resume) + setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1 @ set svc, irqs off + mrc p15, 0, r1, c0, c0, 5 + and r1, r1, #0xf + cmp r1, #0 + /* olny cpu0 can continue to run, the others is halt here */ + beq cpu0run +secondary_loop: + wfe + b secondary_loop +cpu0run: + ldr r3, rkpm_bootdata_l2ctlr_f + cmp r3, #0 + beq sp_set + ldr r3, rkpm_bootdata_l2ctlr + mcr p15, 1, r3, c9, c0, 2 +sp_set: + ldr sp, rkpm_bootdata_cpusp + ldr r1, rkpm_bootdata_cpu_code + bx r1 +ENDPROC(rockchip_slp_cpu_resume) + +/* Parameters filled in by the kernel */ + +/* Flag for whether to restore L2CTLR on resume */ + .global rkpm_bootdata_l2ctlr_f +rkpm_bootdata_l2ctlr_f: + .long 0 + +/* Saved L2CTLR to restore on resume */ + .global rkpm_bootdata_l2ctlr +rkpm_bootdata_l2ctlr: + .long 0 + +/* CPU resume SP addr */ + .globl rkpm_bootdata_cpusp +rkpm_bootdata_cpusp: + .long 0 + +/* CPU resume function (physical address) */ + .globl rkpm_bootdata_cpu_code +rkpm_bootdata_cpu_code: + .long 0 + +ENTRY(rk3288_bootram_sz) + .word . - rockchip_slp_cpu_resume -- cgit v1.2.3 From eecfe981cecd82791a72668a416727cb50935bdb Mon Sep 17 00:00:00 2001 From: Chris Zhong Date: Mon, 1 Dec 2014 16:52:19 +0800 Subject: ARM: dts: rockchip: add RK3288 suspend support add pmu sram node for suspend, add global_pwroff pinctrl. The pmu sram is used to store the resume code. global_pwroff is held low level at work, it would be pull to high when entering suspend. reference this in the board DTS file since some boards need it. Signed-off-by: Tony Xie Signed-off-by: Chris Zhong Reviewed-by: Doug Anderson Tested-by: Doug Anderson Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288.dtsi | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index 3aad41d873d3..2a878a35facc 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -506,6 +506,11 @@ }; }; + sram@ff720000 { + compatible = "rockchip,rk3288-pmu-sram", "mmio-sram"; + reg = <0xff720000 0x1000>; + }; + pmu: power-management@ff730000 { compatible = "rockchip,rk3288-pmu", "syscon"; reg = <0xff730000 0x100>; @@ -729,6 +734,24 @@ bias-disable; }; + sleep { + global_pwroff: global-pwroff { + rockchip,pins = <0 0 RK_FUNC_1 &pcfg_pull_none>; + }; + + ddrio_pwroff: ddrio-pwroff { + rockchip,pins = <0 1 RK_FUNC_1 &pcfg_pull_none>; + }; + + ddr0_retention: ddr0-retention { + rockchip,pins = <0 2 RK_FUNC_1 &pcfg_pull_up>; + }; + + ddr1_retention: ddr1-retention { + rockchip,pins = <0 3 RK_FUNC_1 &pcfg_pull_up>; + }; + }; + i2c0 { i2c0_xfer: i2c0-xfer { rockchip,pins = <0 15 RK_FUNC_1 &pcfg_pull_none>, -- cgit v1.2.3 From 5963e106df7b601a8f23cbbaac1420e4c740ada6 Mon Sep 17 00:00:00 2001 From: Chris Zhong Date: Mon, 1 Dec 2014 16:52:20 +0800 Subject: ARM: dts: rockchip: add suspend settings for rk3288-evb-rk808 Add suspend-voltages and necessary pin-states for suspend on rk3288-evb-rk808 boards. global_pwroff would be pulled high when RK3288 entering suspend, this pin is a sleep signal for RK808, so RK808 could goto sleep mode, and some regulators would be disable. Signed-off-by: Chris Zhong Reviewed-by: Doug Anderson Tested-by: Doug Anderson Signed-off-by: Heiko Stuebner --- arch/arm/boot/dts/rk3288-evb-rk808.dts | 53 +++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/rk3288-evb-rk808.dts b/arch/arm/boot/dts/rk3288-evb-rk808.dts index d8c775e6d5fe..d453ddd4b476 100644 --- a/arch/arm/boot/dts/rk3288-evb-rk808.dts +++ b/arch/arm/boot/dts/rk3288-evb-rk808.dts @@ -31,7 +31,7 @@ interrupt-parent = <&gpio0>; interrupts = <4 IRQ_TYPE_LEVEL_LOW>; pinctrl-names = "default"; - pinctrl-0 = <&pmic_int>; + pinctrl-0 = <&pmic_int &global_pwroff>; rockchip,system-power-controller; wakeup-source; #clock-cells = <1>; @@ -50,6 +50,9 @@ regulator-min-microvolt = <750000>; regulator-max-microvolt = <1350000>; regulator-name = "vdd_arm"; + regulator-state-mem { + regulator-off-in-suspend; + }; }; vdd_gpu: DCDC_REG2 { @@ -58,12 +61,19 @@ regulator-min-microvolt = <850000>; regulator-max-microvolt = <1250000>; regulator-name = "vdd_gpu"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; }; vcc_ddr: DCDC_REG3 { regulator-always-on; regulator-boot-on; regulator-name = "vcc_ddr"; + regulator-state-mem { + regulator-on-in-suspend; + }; }; vcc_io: DCDC_REG4 { @@ -72,6 +82,10 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-name = "vcc_io"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; }; vccio_pmu: LDO_REG1 { @@ -80,6 +94,10 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-name = "vccio_pmu"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; }; vcc_tp: LDO_REG2 { @@ -88,6 +106,9 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-name = "vcc_tp"; + regulator-state-mem { + regulator-off-in-suspend; + }; }; vdd_10: LDO_REG3 { @@ -96,6 +117,10 @@ regulator-min-microvolt = <1000000>; regulator-max-microvolt = <1000000>; regulator-name = "vdd_10"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; }; vcc18_lcd: LDO_REG4 { @@ -104,6 +129,10 @@ regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-name = "vcc18_lcd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; }; vccio_sd: LDO_REG5 { @@ -112,6 +141,10 @@ regulator-min-microvolt = <1800000>; regulator-max-microvolt = <3300000>; regulator-name = "vccio_sd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; }; vdd10_lcd: LDO_REG6 { @@ -120,6 +153,10 @@ regulator-min-microvolt = <1000000>; regulator-max-microvolt = <1000000>; regulator-name = "vdd10_lcd"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1000000>; + }; }; vcc_18: LDO_REG7 { @@ -128,6 +165,10 @@ regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-name = "vcc_18"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <1800000>; + }; }; vcca_codec: LDO_REG8 { @@ -136,18 +177,28 @@ regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-name = "vcca_codec"; + regulator-state-mem { + regulator-on-in-suspend; + regulator-suspend-microvolt = <3300000>; + }; }; vcc_wl: SWITCH_REG1 { regulator-always-on; regulator-boot-on; regulator-name = "vcc_wl"; + regulator-state-mem { + regulator-on-in-suspend; + }; }; vcc_lcd: SWITCH_REG2 { regulator-always-on; regulator-boot-on; regulator-name = "vcc_lcd"; + regulator-state-mem { + regulator-on-in-suspend; + }; }; }; }; -- cgit v1.2.3 From 456062b3ec6f5b96ffe7dd31c84e8666747f8720 Mon Sep 17 00:00:00 2001 From: Nimrod Andy Date: Wed, 24 Dec 2014 17:30:40 +0800 Subject: ARM: imx: add FEC sleep mode callback function i.MX6q/dl, i.MX6SX SOCs enet support sleep mode that magic packet can wake up system in suspend status. For different SOCs, there have some SOC specifical GPR register to set sleep on/off mode. So add these to callback function for driver. Signed-off-by: Fugang Duan Signed-off-by: David S. Miller --- arch/arm/mach-imx/mach-imx6q.c | 41 ++++++++++++++++++++++++++++++++- arch/arm/mach-imx/mach-imx6sx.c | 50 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index 5057d61298b7..2f7616889c3f 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include #include @@ -39,6 +41,35 @@ #include "cpuidle.h" #include "hardware.h" +static struct fec_platform_data fec_pdata; + +static void imx6q_fec_sleep_enable(int enabled) +{ + struct regmap *gpr; + + gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); + if (!IS_ERR(gpr)) { + if (enabled) + regmap_update_bits(gpr, IOMUXC_GPR13, + IMX6Q_GPR13_ENET_STOP_REQ, + IMX6Q_GPR13_ENET_STOP_REQ); + + else + regmap_update_bits(gpr, IOMUXC_GPR13, + IMX6Q_GPR13_ENET_STOP_REQ, 0); + } else + pr_err("failed to find fsl,imx6q-iomux-gpr regmap\n"); +} + +static void __init imx6q_enet_plt_init(void) +{ + struct device_node *np; + + np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@02188000"); + if (np && of_get_property(np, "fsl,magic-packet", NULL)) + fec_pdata.sleep_mode_enable = imx6q_fec_sleep_enable; +} + /* For imx6q sabrelite board: set KSZ9021RN RGMII pad skew */ static int ksz9021rn_phy_fixup(struct phy_device *phydev) { @@ -261,6 +292,12 @@ static void __init imx6q_axi_init(void) } } +/* Add auxdata to pass platform data */ +static const struct of_dev_auxdata imx6q_auxdata_lookup[] __initconst = { + OF_DEV_AUXDATA("fsl,imx6q-fec", 0x02188000, NULL, &fec_pdata), + { /* sentinel */ } +}; + static void __init imx6q_init_machine(void) { struct device *parent; @@ -274,11 +311,13 @@ static void __init imx6q_init_machine(void) imx6q_enet_phy_init(); - of_platform_populate(NULL, of_default_bus_match_table, NULL, parent); + of_platform_populate(NULL, of_default_bus_match_table, + imx6q_auxdata_lookup, parent); imx_anatop_init(); cpu_is_imx6q() ? imx6q_pm_init() : imx6dl_pm_init(); imx6q_1588_init(); + imx6q_enet_plt_init(); imx6q_axi_init(); } diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c index 7a96c6577234..747b012665f5 100644 --- a/arch/arm/mach-imx/mach-imx6sx.c +++ b/arch/arm/mach-imx/mach-imx6sx.c @@ -12,12 +12,62 @@ #include #include #include +#include +#include #include #include #include "common.h" #include "cpuidle.h" +static struct fec_platform_data fec_pdata[2]; + +static void imx6sx_fec1_sleep_enable(int enabled) +{ + struct regmap *gpr; + + gpr = syscon_regmap_lookup_by_compatible("fsl,imx6sx-iomuxc-gpr"); + if (!IS_ERR(gpr)) { + if (enabled) + regmap_update_bits(gpr, IOMUXC_GPR4, + IMX6SX_GPR4_FEC_ENET1_STOP_REQ, + IMX6SX_GPR4_FEC_ENET1_STOP_REQ); + else + regmap_update_bits(gpr, IOMUXC_GPR4, + IMX6SX_GPR4_FEC_ENET1_STOP_REQ, 0); + } else + pr_err("failed to find fsl,imx6sx-iomux-gpr regmap\n"); +} + +static void imx6sx_fec2_sleep_enable(int enabled) +{ + struct regmap *gpr; + + gpr = syscon_regmap_lookup_by_compatible("fsl,imx6sx-iomuxc-gpr"); + if (!IS_ERR(gpr)) { + if (enabled) + regmap_update_bits(gpr, IOMUXC_GPR4, + IMX6SX_GPR4_FEC_ENET2_STOP_REQ, + IMX6SX_GPR4_FEC_ENET2_STOP_REQ); + else + regmap_update_bits(gpr, IOMUXC_GPR4, + IMX6SX_GPR4_FEC_ENET2_STOP_REQ, 0); + } else + pr_err("failed to find fsl,imx6sx-iomux-gpr regmap\n"); +} + +static void __init imx6sx_enet_plt_init(void) +{ + struct device_node *np; + + np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@02188000"); + if (np && of_get_property(np, "fsl,magic-packet", NULL)) + fec_pdata[0].sleep_mode_enable = imx6sx_fec1_sleep_enable; + np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@021b4000"); + if (np && of_get_property(np, "fsl,magic-packet", NULL)) + fec_pdata[1].sleep_mode_enable = imx6sx_fec2_sleep_enable; +} + static int ar8031_phy_fixup(struct phy_device *dev) { u16 val; -- cgit v1.2.3 From 07b4d2dda0c00f56248ac35e2200474609c294b7 Mon Sep 17 00:00:00 2001 From: Nimrod Andy Date: Wed, 24 Dec 2014 17:30:41 +0800 Subject: ARM: dts: imx6qdl: enable FEC magic-packet feature Add FEC magic-packet feature support. Signed-off-by: Fugang Duan Signed-off-by: David S. Miller --- arch/arm/boot/dts/imx6qdl-sabreauto.dtsi | 1 + arch/arm/boot/dts/imx6qdl-sabresd.dtsi | 1 + 2 files changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi index 009abd69385d..327d362fe275 100644 --- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi +++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi @@ -67,6 +67,7 @@ phy-mode = "rgmii"; interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>, <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; + fsl,magic-packet; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi index f1cd2147421d..6bfd0bc6e658 100644 --- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi +++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi @@ -160,6 +160,7 @@ pinctrl-0 = <&pinctrl_enet>; phy-mode = "rgmii"; phy-reset-gpios = <&gpio1 25 0>; + fsl,magic-packet; status = "okay"; }; -- cgit v1.2.3 From 3d3fb74afc9b511013966ec0b1f8fd60d55b886b Mon Sep 17 00:00:00 2001 From: Roger Chen Date: Mon, 29 Dec 2014 17:44:16 +0800 Subject: ARM: dts: rockchip: add gmac info for rk3288 add gmac info in rk3288.dtsi for GMAC driver changes since v2: 1. add drive-strength in the pinctrl settings Signed-off-by: Roger Chen Signed-off-by: David S. Miller --- arch/arm/boot/dts/rk3288.dtsi | 54 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi index fd19f00784bd..910dcad2088a 100644 --- a/arch/arm/boot/dts/rk3288.dtsi +++ b/arch/arm/boot/dts/rk3288.dtsi @@ -380,6 +380,22 @@ status = "disabled"; }; + gmac: ethernet@ff290000 { + compatible = "rockchip,rk3288-gmac"; + reg = <0xff290000 0x10000>; + interrupts = ; + interrupt-names = "macirq"; + rockchip,grf = <&grf>; + clocks = <&cru SCLK_MAC>, + <&cru SCLK_MAC_RX>, <&cru SCLK_MAC_TX>, + <&cru SCLK_MACREF>, <&cru SCLK_MACREF_OUT>, + <&cru ACLK_GMAC>, <&cru PCLK_GMAC>; + clock-names = "stmmaceth", + "mac_clk_rx", "mac_clk_tx", + "clk_mac_ref", "clk_mac_refout", + "aclk_mac", "pclk_mac"; + }; + usb_host0_ehci: usb@ff500000 { compatible = "generic-ehci"; reg = <0xff500000 0x100>; @@ -725,6 +741,11 @@ bias-disable; }; + pcfg_pull_none_12ma: pcfg-pull-none-12ma { + bias-disable; + drive-strength = <12>; + }; + i2c0 { i2c0_xfer: i2c0-xfer { rockchip,pins = <0 15 RK_FUNC_1 &pcfg_pull_none>, @@ -1068,5 +1089,38 @@ rockchip,pins = <7 23 3 &pcfg_pull_none>; }; }; + + gmac { + rgmii_pins: rgmii-pins { + rockchip,pins = <3 30 3 &pcfg_pull_none>, + <3 31 3 &pcfg_pull_none>, + <3 26 3 &pcfg_pull_none>, + <3 27 3 &pcfg_pull_none>, + <3 28 3 &pcfg_pull_none_12ma>, + <3 29 3 &pcfg_pull_none_12ma>, + <3 24 3 &pcfg_pull_none_12ma>, + <3 25 3 &pcfg_pull_none_12ma>, + <4 0 3 &pcfg_pull_none>, + <4 5 3 &pcfg_pull_none>, + <4 6 3 &pcfg_pull_none>, + <4 9 3 &pcfg_pull_none_12ma>, + <4 4 3 &pcfg_pull_none_12ma>, + <4 1 3 &pcfg_pull_none>, + <4 3 3 &pcfg_pull_none>; + }; + + rmii_pins: rmii-pins { + rockchip,pins = <3 30 3 &pcfg_pull_none>, + <3 31 3 &pcfg_pull_none>, + <3 28 3 &pcfg_pull_none>, + <3 29 3 &pcfg_pull_none>, + <4 0 3 &pcfg_pull_none>, + <4 5 3 &pcfg_pull_none>, + <4 4 3 &pcfg_pull_none>, + <4 1 3 &pcfg_pull_none>, + <4 2 3 &pcfg_pull_none>, + <4 3 3 &pcfg_pull_none>; + }; + }; }; }; -- cgit v1.2.3 From e35e47ac521b69bc9c5c0654463278161ec92d72 Mon Sep 17 00:00:00 2001 From: Roger Chen Date: Mon, 29 Dec 2014 17:44:25 +0800 Subject: ARM: dts: rockchip: enable gmac on RK3288 evb board enable gmac in rk3288-evb-rk808.dts changes since v2: 1. add fixed regulator for PHY 2. remove power-gpio, reset-gpio, phyirq-gpio, pmu_regulator setting 3. add "snps,reset-gpio", "snps,reset-active-low;" "snps,reset-delays-us" Signed-off-by: Roger Chen Signed-off-by: David S. Miller --- arch/arm/boot/dts/rk3288-evb-rk808.dts | 23 +++++++++++++++++++++++ arch/arm/boot/dts/rk3288-evb.dtsi | 17 +++++++++++++++++ 2 files changed, 40 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/rk3288-evb-rk808.dts b/arch/arm/boot/dts/rk3288-evb-rk808.dts index d8c775e6d5fe..831a7aa85136 100644 --- a/arch/arm/boot/dts/rk3288-evb-rk808.dts +++ b/arch/arm/boot/dts/rk3288-evb-rk808.dts @@ -15,6 +15,13 @@ / { compatible = "rockchip,rk3288-evb-rk808", "rockchip,rk3288"; + + ext_gmac: external-gmac-clock { + compatible = "fixed-clock"; + clock-frequency = <125000000>; + clock-output-names = "ext_gmac"; + #clock-cells = <0>; + }; }; &cpu0 { @@ -152,3 +159,19 @@ }; }; }; + +&gmac { + phy_regulator = "vcc_phy"; + phy-mode = "rgmii"; + clock_in_out = "input"; + snps,reset-gpio = <&gpio4 7 0>; + snps,reset-active-low; + snps,reset-delays-us = <0 10000 1000000>; + assigned-clocks = <&cru SCLK_MAC>; + assigned-clock-parents = <&ext_gmac>; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + tx_delay = <0x30>; + rx_delay = <0x10>; + status = "ok"; +}; diff --git a/arch/arm/boot/dts/rk3288-evb.dtsi b/arch/arm/boot/dts/rk3288-evb.dtsi index 3e067dd65d0c..048cb170c884 100644 --- a/arch/arm/boot/dts/rk3288-evb.dtsi +++ b/arch/arm/boot/dts/rk3288-evb.dtsi @@ -90,6 +90,17 @@ regulator-always-on; regulator-boot-on; }; + + vcc_phy: vcc-phy-regulator { + compatible = "regulator-fixed"; + enable-active-high; + gpio = <&gpio0 6 GPIO_ACTIVE_HIGH>; + pinctrl-names = "default"; + pinctrl-0 = <ð_phy_pwr>; + regulator-name = "vcc_phy"; + regulator-always-on; + regulator-boot-on; + }; }; &emmc { @@ -178,6 +189,12 @@ rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>; }; }; + + eth_phy { + eth_phy_pwr: eth-phy-pwr { + rockchip,pins = <0 6 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; }; &usb_host0_ehci { -- cgit v1.2.3 From e0bed0774538bdb2e82d6999c8ed9556116e8559 Mon Sep 17 00:00:00 2001 From: Yingjoe Chen Date: Tue, 25 Nov 2014 09:04:00 +0100 Subject: ARM: mediatek: Add sysirq in mt6589/mt8135/mt8127 dtsi Add sysirq settings for mt6589/mt8135/mt8127 This also correct timer interrupt flag. The old setting works because boot loader already set polarity for timer interrupt. Without intpol support, the setting was not changed so gic can get the irq correctly. Signed-off-by: Yingjoe Chen Signed-off-by: Matthias Brugger --- arch/arm/boot/dts/mt6589.dtsi | 14 ++++++++++++-- arch/arm/boot/dts/mt8127.dtsi | 14 ++++++++++++-- arch/arm/boot/dts/mt8135.dtsi | 14 ++++++++++++-- 3 files changed, 36 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/mt6589.dtsi b/arch/arm/boot/dts/mt6589.dtsi index e3c7600ddb38..c91b2a9ebdc3 100644 --- a/arch/arm/boot/dts/mt6589.dtsi +++ b/arch/arm/boot/dts/mt6589.dtsi @@ -19,7 +19,7 @@ / { compatible = "mediatek,mt6589"; - interrupt-parent = <&gic>; + interrupt-parent = <&sysirq>; cpus { #address-cells = <1>; @@ -76,15 +76,25 @@ timer: timer@10008000 { compatible = "mediatek,mt6577-timer"; reg = <0x10008000 0x80>; - interrupts = ; + interrupts = ; clocks = <&system_clk>, <&rtc_clk>; clock-names = "system-clk", "rtc-clk"; }; + sysirq: interrupt-controller@10200100 { + compatible = "mediatek,mt6589-sysirq", + "mediatek,mt6577-sysirq"; + interrupt-controller; + #interrupt-cells = <3>; + interrupt-parent = <&gic>; + reg = <0x10200100 0x1c>; + }; + gic: interrupt-controller@10211000 { compatible = "arm,cortex-a7-gic"; interrupt-controller; #interrupt-cells = <3>; + interrupt-parent = <&gic>; reg = <0x10211000 0x1000>, <0x10212000 0x1000>, <0x10214000 0x2000>, diff --git a/arch/arm/boot/dts/mt8127.dtsi b/arch/arm/boot/dts/mt8127.dtsi index b24c0a2f3c44..a325404c714c 100644 --- a/arch/arm/boot/dts/mt8127.dtsi +++ b/arch/arm/boot/dts/mt8127.dtsi @@ -18,7 +18,7 @@ / { compatible = "mediatek,mt8127"; - interrupt-parent = <&gic>; + interrupt-parent = <&sysirq>; cpus { #address-cells = <1>; @@ -76,15 +76,25 @@ compatible = "mediatek,mt8127-timer", "mediatek,mt6577-timer"; reg = <0 0x10008000 0 0x80>; - interrupts = ; + interrupts = ; clocks = <&system_clk>, <&rtc_clk>; clock-names = "system-clk", "rtc-clk"; }; + sysirq: interrupt-controller@10200100 { + compatible = "mediatek,mt8127-sysirq", + "mediatek,mt6577-sysirq"; + interrupt-controller; + #interrupt-cells = <3>; + interrupt-parent = <&gic>; + reg = <0 0x10200100 0 0x1c>; + }; + gic: interrupt-controller@10211000 { compatible = "arm,cortex-a7-gic"; interrupt-controller; #interrupt-cells = <3>; + interrupt-parent = <&gic>; reg = <0 0x10211000 0 0x1000>, <0 0x10212000 0 0x1000>, <0 0x10214000 0 0x2000>, diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mt8135.dtsi index 7d56a986358e..2762fd57f739 100644 --- a/arch/arm/boot/dts/mt8135.dtsi +++ b/arch/arm/boot/dts/mt8135.dtsi @@ -18,7 +18,7 @@ / { compatible = "mediatek,mt8135"; - interrupt-parent = <&gic>; + interrupt-parent = <&sysirq>; cpu-map { cluster0 { @@ -98,15 +98,25 @@ compatible = "mediatek,mt8135-timer", "mediatek,mt6577-timer"; reg = <0 0x10008000 0 0x80>; - interrupts = ; + interrupts = ; clocks = <&system_clk>, <&rtc_clk>; clock-names = "system-clk", "rtc-clk"; }; + sysirq: interrupt-controller@10200030 { + compatible = "mediatek,mt8135-sysirq", + "mediatek,mt6577-sysirq"; + interrupt-controller; + #interrupt-cells = <3>; + interrupt-parent = <&gic>; + reg = <0 0x10200030 0 0x1c>; + }; + gic: interrupt-controller@10211000 { compatible = "arm,cortex-a15-gic"; interrupt-controller; #interrupt-cells = <3>; + interrupt-parent = <&gic>; reg = <0 0x10211000 0 0x1000>, <0 0x10212000 0 0x1000>, <0 0x10214000 0 0x2000>, -- cgit v1.2.3 From 7bae74f04d03f81c40c8b614e94b15975dd25ff6 Mon Sep 17 00:00:00 2001 From: Eddie Huang Date: Fri, 26 Dec 2014 10:55:00 +0100 Subject: ARM: Add mediatek SoC UART support in defconfig Add mediatek SoC UART support in multi_v7_defconfig Signed-off-by: Eddie Huang Signed-off-by: Matthias Brugger --- arch/arm/configs/multi_v7_defconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 2328fe752e9c..fd0ff955b2dd 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -195,6 +195,7 @@ CONFIG_SERIO_AMBAKMI=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_8250_MT6577=y CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y CONFIG_SERIAL_MESON=y -- cgit v1.2.3 From 801a55911432f582c8ab82c895d2821dc02b70e3 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 2 Jan 2015 06:11:16 +0100 Subject: x86: init_mem_mapping(): use capital BIOS in comment Use capital BIOS in comment. Its cleaner, and allows diference between BIOS and BIOs. Signed-off-by: Pavel Machek Signed-off-by: Jiri Kosina --- arch/x86/mm/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 66dba36f2343..452f9042e5b2 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -582,7 +582,7 @@ void __init init_mem_mapping(void) * * * On x86, access has to be given to the first megabyte of ram because that area - * contains bios code and data regions used by X and dosemu and similar apps. + * contains BIOS code and data regions used by X and dosemu and similar apps. * Access has to be given to non-kernel-ram areas as well, these contain the PCI * mmio resources as well as potential bios/acpi data regions. */ -- cgit v1.2.3 From 0714947369cdb2b9b8cc24aa07264d4b61ea4fd9 Mon Sep 17 00:00:00 2001 From: Eddie Huang Date: Wed, 22 Oct 2014 15:12:00 +0200 Subject: ARM: mediatek: add UART dts for mt8127 and mt8135 This add dts support for mt8127 and mt8135 SOC UART Signed-off-by: Eddie Huang Signed-off-by: Matthias Brugger --- arch/arm/boot/dts/mt8127.dtsi | 38 ++++++++++++++++++++++++++++++++++++++ arch/arm/boot/dts/mt8135.dtsi | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/mt8127.dtsi b/arch/arm/boot/dts/mt8127.dtsi index a325404c714c..aaa786233d93 100644 --- a/arch/arm/boot/dts/mt8127.dtsi +++ b/arch/arm/boot/dts/mt8127.dtsi @@ -64,6 +64,12 @@ clock-frequency = <32000>; #clock-cells = <0>; }; + + uart_clk: dummy26m { + compatible = "fixed-clock"; + clock-frequency = <26000000>; + #clock-cells = <0>; + }; }; soc { @@ -100,5 +106,37 @@ <0 0x10214000 0 0x2000>, <0 0x10216000 0 0x2000>; }; + + uart0: serial@11006000 { + compatible = "mediatek,mt8127-uart","mediatek,mt6577-uart"; + reg = <0 0x11002000 0 0x400>; + interrupts = ; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart1: serial@11007000 { + compatible = "mediatek,mt8127-uart","mediatek,mt6577-uart"; + reg = <0 0x11003000 0 0x400>; + interrupts = ; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart2: serial@11008000 { + compatible = "mediatek,mt8127-uart","mediatek,mt6577-uart"; + reg = <0 0x11004000 0 0x400>; + interrupts = ; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart3: serial@11009000 { + compatible = "mediatek,mt8127-uart","mediatek,mt6577-uart"; + reg = <0 0x11005000 0 0x400>; + interrupts = ; + clocks = <&uart_clk>; + status = "disabled"; + }; }; }; diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mt8135.dtsi index 2762fd57f739..a161e99ffcc4 100644 --- a/arch/arm/boot/dts/mt8135.dtsi +++ b/arch/arm/boot/dts/mt8135.dtsi @@ -86,6 +86,13 @@ clock-frequency = <32000>; #clock-cells = <0>; }; + + uart_clk: dummy26m { + compatible = "fixed-clock"; + clock-frequency = <26000000>; + #clock-cells = <0>; + }; + }; soc { @@ -122,5 +129,38 @@ <0 0x10214000 0 0x2000>, <0 0x10216000 0 0x2000>; }; + + uart0: serial@11006000 { + compatible = "mediatek,mt8135-uart","mediatek,mt6577-uart"; + reg = <0 0x11006000 0 0x400>; + interrupts = ; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart1: serial@11007000 { + compatible = "mediatek,mt8135-uart","mediatek,mt6577-uart"; + reg = <0 0x11007000 0 0x400>; + interrupts = ; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart2: serial@11008000 { + compatible = "mediatek,mt8135-uart","mediatek,mt6577-uart"; + reg = <0 0x11008000 0 0x400>; + interrupts = ; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart3: serial@11009000 { + compatible = "mediatek,mt8135-uart","mediatek,mt6577-uart"; + reg = <0 0x11009000 0 0x400>; + interrupts = ; + clocks = <&uart_clk>; + status = "disabled"; + }; + }; }; -- cgit v1.2.3 From 48e08d0fb265b007ebbb29a72297ff7e40938969 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Tue, 11 Nov 2014 12:49:41 -0800 Subject: x86, entry: Switch stacks on a paranoid entry from userspace This causes all non-NMI, non-double-fault kernel entries from userspace to run on the normal kernel stack. Double-fault is exempt to minimize confusion if we double-fault directly from userspace due to a bad kernel stack. This is, suprisingly, simpler and shorter than the current code. It removes the IMO rather frightening paranoid_userspace path, and it make sync_regs much simpler. There is no risk of stack overflow due to this change -- the kernel stack that we switch to is empty. This will also enable us to create non-atomic sections within machine checks from userspace, which will simplify memory failure handling. It will also allow the upcoming fsgsbase code to be simplified, because it doesn't need to worry about usergs when scheduling in paranoid_exit, as that code no longer exists. Cc: Oleg Nesterov Cc: Andi Kleen Cc: Tony Luck Acked-by: Borislav Petkov Signed-off-by: Andy Lutomirski --- arch/x86/kernel/entry_64.S | 86 ++++++++++++++++++++++++---------------------- arch/x86/kernel/traps.c | 23 +++---------- 2 files changed, 50 insertions(+), 59 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 9ebaf63ba182..931f32f4578b 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -1048,6 +1048,11 @@ ENTRY(\sym) CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15 .if \paranoid + .if \paranoid == 1 + CFI_REMEMBER_STATE + testl $3, CS(%rsp) /* If coming from userspace, switch */ + jnz 1f /* stacks. */ + .endif call save_paranoid .else call error_entry @@ -1088,6 +1093,36 @@ ENTRY(\sym) jmp error_exit /* %ebx: no swapgs flag */ .endif + .if \paranoid == 1 + CFI_RESTORE_STATE + /* + * Paranoid entry from userspace. Switch stacks and treat it + * as a normal entry. This means that paranoid handlers + * run in real process context if user_mode(regs). + */ +1: + call error_entry + + DEFAULT_FRAME 0 + + movq %rsp,%rdi /* pt_regs pointer */ + call sync_regs + movq %rax,%rsp /* switch stack */ + + movq %rsp,%rdi /* pt_regs pointer */ + + .if \has_error_code + movq ORIG_RAX(%rsp),%rsi /* get error code */ + movq $-1,ORIG_RAX(%rsp) /* no syscall to restart */ + .else + xorl %esi,%esi /* no error code */ + .endif + + call \do_sym + + jmp error_exit /* %ebx: no swapgs flag */ + .endif + CFI_ENDPROC END(\sym) .endm @@ -1108,7 +1143,7 @@ idtentry overflow do_overflow has_error_code=0 idtentry bounds do_bounds has_error_code=0 idtentry invalid_op do_invalid_op has_error_code=0 idtentry device_not_available do_device_not_available has_error_code=0 -idtentry double_fault do_double_fault has_error_code=1 paranoid=1 +idtentry double_fault do_double_fault has_error_code=1 paranoid=2 idtentry coprocessor_segment_overrun do_coprocessor_segment_overrun has_error_code=0 idtentry invalid_TSS do_invalid_TSS has_error_code=1 idtentry segment_not_present do_segment_not_present has_error_code=1 @@ -1289,16 +1324,14 @@ idtentry machine_check has_error_code=0 paranoid=1 do_sym=*machine_check_vector( #endif /* - * "Paranoid" exit path from exception stack. - * Paranoid because this is used by NMIs and cannot take - * any kernel state for granted. - * We don't do kernel preemption checks here, because only - * NMI should be common and it does not enable IRQs and - * cannot get reschedule ticks. + * "Paranoid" exit path from exception stack. This is invoked + * only on return from non-NMI IST interrupts that came + * from kernel space. * - * "trace" is 0 for the NMI handler only, because irq-tracing - * is fundamentally NMI-unsafe. (we cannot change the soft and - * hard flags at once, atomically) + * We may be returning to very strange contexts (e.g. very early + * in syscall entry), so checking for preemption here would + * be complicated. Fortunately, we there's no good reason + * to try to handle preemption here. */ /* ebx: no swapgs flag */ @@ -1308,43 +1341,14 @@ ENTRY(paranoid_exit) TRACE_IRQS_OFF_DEBUG testl %ebx,%ebx /* swapgs needed? */ jnz paranoid_restore - testl $3,CS(%rsp) - jnz paranoid_userspace -paranoid_swapgs: TRACE_IRQS_IRETQ 0 SWAPGS_UNSAFE_STACK RESTORE_ALL 8 - jmp irq_return + INTERRUPT_RETURN paranoid_restore: TRACE_IRQS_IRETQ_DEBUG 0 RESTORE_ALL 8 - jmp irq_return -paranoid_userspace: - GET_THREAD_INFO(%rcx) - movl TI_flags(%rcx),%ebx - andl $_TIF_WORK_MASK,%ebx - jz paranoid_swapgs - movq %rsp,%rdi /* &pt_regs */ - call sync_regs - movq %rax,%rsp /* switch stack for scheduling */ - testl $_TIF_NEED_RESCHED,%ebx - jnz paranoid_schedule - movl %ebx,%edx /* arg3: thread flags */ - TRACE_IRQS_ON - ENABLE_INTERRUPTS(CLBR_NONE) - xorl %esi,%esi /* arg2: oldset */ - movq %rsp,%rdi /* arg1: &pt_regs */ - call do_notify_resume - DISABLE_INTERRUPTS(CLBR_NONE) - TRACE_IRQS_OFF - jmp paranoid_userspace -paranoid_schedule: - TRACE_IRQS_ON - ENABLE_INTERRUPTS(CLBR_ANY) - SCHEDULE_USER - DISABLE_INTERRUPTS(CLBR_ANY) - TRACE_IRQS_OFF - jmp paranoid_userspace + INTERRUPT_RETURN CFI_ENDPROC END(paranoid_exit) diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 88900e288021..28f3e5ffc55d 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -466,27 +466,14 @@ NOKPROBE_SYMBOL(do_int3); #ifdef CONFIG_X86_64 /* - * Help handler running on IST stack to switch back to user stack - * for scheduling or signal handling. The actual stack switch is done in - * entry.S + * Help handler running on IST stack to switch off the IST stack if the + * interrupted code was in user mode. The actual stack switch is done in + * entry_64.S */ asmlinkage __visible notrace struct pt_regs *sync_regs(struct pt_regs *eregs) { - struct pt_regs *regs = eregs; - /* Did already sync */ - if (eregs == (struct pt_regs *)eregs->sp) - ; - /* Exception from user space */ - else if (user_mode(eregs)) - regs = task_pt_regs(current); - /* - * Exception from kernel and interrupts are enabled. Move to - * kernel process stack. - */ - else if (eregs->flags & X86_EFLAGS_IF) - regs = (struct pt_regs *)(eregs->sp -= sizeof(struct pt_regs)); - if (eregs != regs) - *regs = *eregs; + struct pt_regs *regs = task_pt_regs(current); + *regs = *eregs; return regs; } NOKPROBE_SYMBOL(sync_regs); -- cgit v1.2.3 From 959274753857efe9c5f1ba35fe727f51e9aa128d Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Wed, 19 Nov 2014 17:41:09 -0800 Subject: x86, traps: Track entry into and exit from IST context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We currently pretend that IST context is like standard exception context, but this is incorrect. IST entries from userspace are like standard exceptions except that they use per-cpu stacks, so they are atomic. IST entries from kernel space are like NMIs from RCU's perspective -- they are not quiescent states even if they interrupted the kernel during a quiescent state. Add and use ist_enter and ist_exit to track IST context. Even though x86_32 has no IST stacks, we track these interrupts the same way. This fixes two issues: - Scheduling from an IST interrupt handler will now warn. It would previously appear to work as long as we got lucky and nothing overwrote the stack frame. (I don't know of any bugs in this that would trigger the warning, but it's good to be on the safe side.) - RCU handling in IST context was dangerous. As far as I know, only machine checks were likely to trigger this, but it's good to be on the safe side. Note that the machine check handlers appears to have been missing any context tracking at all before this patch. Cc: "Paul E. McKenney" Cc: Josh Triplett Cc: Frédéric Weisbecker Signed-off-by: Andy Lutomirski --- arch/x86/include/asm/traps.h | 4 +++ arch/x86/kernel/cpu/mcheck/mce.c | 5 ++++ arch/x86/kernel/cpu/mcheck/p5.c | 6 +++++ arch/x86/kernel/cpu/mcheck/winchip.c | 5 ++++ arch/x86/kernel/traps.c | 47 +++++++++++++++++++++++++++++++----- 5 files changed, 61 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h index 707adc6549d8..3cf525ec762d 100644 --- a/arch/x86/include/asm/traps.h +++ b/arch/x86/include/asm/traps.h @@ -1,6 +1,7 @@ #ifndef _ASM_X86_TRAPS_H #define _ASM_X86_TRAPS_H +#include #include #include @@ -110,6 +111,9 @@ asmlinkage void smp_thermal_interrupt(void); asmlinkage void mce_threshold_interrupt(void); #endif +extern enum ctx_state ist_enter(struct pt_regs *regs); +extern void ist_exit(struct pt_regs *regs, enum ctx_state prev_state); + /* Interrupts/Exceptions */ enum { X86_TRAP_DE = 0, /* 0, Divide-by-zero */ diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index d2c611699cd9..800d423f1e92 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -43,6 +43,7 @@ #include #include +#include #include #include @@ -1063,6 +1064,7 @@ void do_machine_check(struct pt_regs *regs, long error_code) { struct mca_config *cfg = &mca_cfg; struct mce m, *final; + enum ctx_state prev_state; int i; int worst = 0; int severity; @@ -1085,6 +1087,8 @@ void do_machine_check(struct pt_regs *regs, long error_code) DECLARE_BITMAP(valid_banks, MAX_NR_BANKS); char *msg = "Unknown"; + prev_state = ist_enter(regs); + this_cpu_inc(mce_exception_count); if (!cfg->banks) @@ -1216,6 +1220,7 @@ void do_machine_check(struct pt_regs *regs, long error_code) mce_wrmsrl(MSR_IA32_MCG_STATUS, 0); out: sync_core(); + ist_exit(regs, prev_state); } EXPORT_SYMBOL_GPL(do_machine_check); diff --git a/arch/x86/kernel/cpu/mcheck/p5.c b/arch/x86/kernel/cpu/mcheck/p5.c index a3042989398c..ec2663a708e4 100644 --- a/arch/x86/kernel/cpu/mcheck/p5.c +++ b/arch/x86/kernel/cpu/mcheck/p5.c @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -17,8 +18,11 @@ int mce_p5_enabled __read_mostly; /* Machine check handler for Pentium class Intel CPUs: */ static void pentium_machine_check(struct pt_regs *regs, long error_code) { + enum ctx_state prev_state; u32 loaddr, hi, lotype; + prev_state = ist_enter(regs); + rdmsr(MSR_IA32_P5_MC_ADDR, loaddr, hi); rdmsr(MSR_IA32_P5_MC_TYPE, lotype, hi); @@ -33,6 +37,8 @@ static void pentium_machine_check(struct pt_regs *regs, long error_code) } add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE); + + ist_exit(regs, prev_state); } /* Set up machine check reporting for processors with Intel style MCE: */ diff --git a/arch/x86/kernel/cpu/mcheck/winchip.c b/arch/x86/kernel/cpu/mcheck/winchip.c index 7dc5564d0cdf..bd5d46a32210 100644 --- a/arch/x86/kernel/cpu/mcheck/winchip.c +++ b/arch/x86/kernel/cpu/mcheck/winchip.c @@ -7,14 +7,19 @@ #include #include +#include #include #include /* Machine check handler for WinChip C6: */ static void winchip_machine_check(struct pt_regs *regs, long error_code) { + enum ctx_state prev_state = ist_enter(regs); + printk(KERN_EMERG "CPU0: Machine Check Exception.\n"); add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE); + + ist_exit(regs, prev_state); } /* Set up machine check reporting on the Winchip C6 series */ diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 28f3e5ffc55d..b3a9d24dba25 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -108,6 +108,39 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) preempt_count_dec(); } +enum ctx_state ist_enter(struct pt_regs *regs) +{ + /* + * We are atomic because we're on the IST stack (or we're on x86_32, + * in which case we still shouldn't schedule. + */ + preempt_count_add(HARDIRQ_OFFSET); + + if (user_mode_vm(regs)) { + /* Other than that, we're just an exception. */ + return exception_enter(); + } else { + /* + * We might have interrupted pretty much anything. In + * fact, if we're a machine check, we can even interrupt + * NMI processing. We don't want in_nmi() to return true, + * but we need to notify RCU. + */ + rcu_nmi_enter(); + return IN_KERNEL; /* the value is irrelevant. */ + } +} + +void ist_exit(struct pt_regs *regs, enum ctx_state prev_state) +{ + preempt_count_sub(HARDIRQ_OFFSET); + + if (user_mode_vm(regs)) + return exception_exit(prev_state); + else + rcu_nmi_exit(); +} + static nokprobe_inline int do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str, struct pt_regs *regs, long error_code) @@ -251,6 +284,8 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code) * end up promoting it to a doublefault. In that case, modify * the stack to make it look like we just entered the #GP * handler from user space, similar to bad_iret. + * + * No need for ist_enter here because we don't use RCU. */ if (((long)regs->sp >> PGDIR_SHIFT) == ESPFIX_PGD_ENTRY && regs->cs == __KERNEL_CS && @@ -263,12 +298,12 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code) normal_regs->orig_ax = 0; /* Missing (lost) #GP error code */ regs->ip = (unsigned long)general_protection; regs->sp = (unsigned long)&normal_regs->orig_ax; + return; } #endif - exception_enter(); - /* Return not checked because double check cannot be ignored */ + ist_enter(regs); /* Discard prev_state because we won't return. */ notify_die(DIE_TRAP, str, regs, error_code, X86_TRAP_DF, SIGSEGV); tsk->thread.error_code = error_code; @@ -434,7 +469,7 @@ dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code) if (poke_int3_handler(regs)) return; - prev_state = exception_enter(); + prev_state = ist_enter(regs); #ifdef CONFIG_KGDB_LOW_LEVEL_TRAP if (kgdb_ll_trap(DIE_INT3, "int3", regs, error_code, X86_TRAP_BP, SIGTRAP) == NOTIFY_STOP) @@ -460,7 +495,7 @@ dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code) preempt_conditional_cli(regs); debug_stack_usage_dec(); exit: - exception_exit(prev_state); + ist_exit(regs, prev_state); } NOKPROBE_SYMBOL(do_int3); @@ -541,7 +576,7 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code) unsigned long dr6; int si_code; - prev_state = exception_enter(); + prev_state = ist_enter(regs); get_debugreg(dr6, 6); @@ -616,7 +651,7 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code) debug_stack_usage_dec(); exit: - exception_exit(prev_state); + ist_exit(regs, prev_state); } NOKPROBE_SYMBOL(do_debug); -- cgit v1.2.3 From 83653c16da91112236292871b820cb8b367220e3 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 13 Nov 2014 15:57:07 -0800 Subject: x86: Clean up current_stack_pointer There's no good reason for it to be a macro, and x86_64 will want to use it, so it should be in a header. Acked-by: Borislav Petkov Signed-off-by: Andy Lutomirski --- arch/x86/include/asm/thread_info.h | 11 +++++++++++ arch/x86/kernel/irq_32.c | 13 +++---------- 2 files changed, 14 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index 547e344a6dc6..8b13b0fbda8e 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -170,6 +170,17 @@ static inline struct thread_info *current_thread_info(void) return ti; } +static inline unsigned long current_stack_pointer(void) +{ + unsigned long sp; +#ifdef CONFIG_X86_64 + asm("mov %%rsp,%0" : "=g" (sp)); +#else + asm("mov %%esp,%0" : "=g" (sp)); +#endif + return sp; +} + #else /* !__ASSEMBLY__ */ /* how to get the thread information struct from ASM */ diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index 63ce838e5a54..28d28f5eb8f4 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c @@ -69,16 +69,9 @@ static void call_on_stack(void *func, void *stack) : "memory", "cc", "edx", "ecx", "eax"); } -/* how to get the current stack pointer from C */ -#define current_stack_pointer ({ \ - unsigned long sp; \ - asm("mov %%esp,%0" : "=g" (sp)); \ - sp; \ -}) - static inline void *current_stack(void) { - return (void *)(current_stack_pointer & ~(THREAD_SIZE - 1)); + return (void *)(current_stack_pointer() & ~(THREAD_SIZE - 1)); } static inline int @@ -103,7 +96,7 @@ execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) /* Save the next esp at the bottom of the stack */ prev_esp = (u32 *)irqstk; - *prev_esp = current_stack_pointer; + *prev_esp = current_stack_pointer(); if (unlikely(overflow)) call_on_stack(print_stack_overflow, isp); @@ -156,7 +149,7 @@ void do_softirq_own_stack(void) /* Push the previous esp onto the stack */ prev_esp = (u32 *)irqstk; - *prev_esp = current_stack_pointer; + *prev_esp = current_stack_pointer(); call_on_stack(__do_softirq, isp); } -- cgit v1.2.3 From bced35b65aefe53a6f77a9ed0ce1aea86e9d65a2 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Wed, 19 Nov 2014 17:59:41 -0800 Subject: x86, traps: Add ist_begin_non_atomic and ist_end_non_atomic In some IST handlers, if the interrupt came from user mode, we can safely enable preemption. Add helpers to do it safely. This is intended to be used my the memory failure code in do_machine_check. Acked-by: Borislav Petkov Signed-off-by: Andy Lutomirski --- arch/x86/include/asm/traps.h | 2 ++ arch/x86/kernel/traps.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) (limited to 'arch') diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h index 3cf525ec762d..4e49d7dff78e 100644 --- a/arch/x86/include/asm/traps.h +++ b/arch/x86/include/asm/traps.h @@ -113,6 +113,8 @@ asmlinkage void mce_threshold_interrupt(void); extern enum ctx_state ist_enter(struct pt_regs *regs); extern void ist_exit(struct pt_regs *regs, enum ctx_state prev_state); +extern void ist_begin_non_atomic(struct pt_regs *regs); +extern void ist_end_non_atomic(void); /* Interrupts/Exceptions */ enum { diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index b3a9d24dba25..7176f84f95a4 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -141,6 +141,44 @@ void ist_exit(struct pt_regs *regs, enum ctx_state prev_state) rcu_nmi_exit(); } +/** + * ist_begin_non_atomic() - begin a non-atomic section in an IST exception + * @regs: regs passed to the IST exception handler + * + * IST exception handlers normally cannot schedule. As a special + * exception, if the exception interrupted userspace code (i.e. + * user_mode_vm(regs) would return true) and the exception was not + * a double fault, it can be safe to schedule. ist_begin_non_atomic() + * begins a non-atomic section within an ist_enter()/ist_exit() region. + * Callers are responsible for enabling interrupts themselves inside + * the non-atomic section, and callers must call is_end_non_atomic() + * before ist_exit(). + */ +void ist_begin_non_atomic(struct pt_regs *regs) +{ + BUG_ON(!user_mode_vm(regs)); + + /* + * Sanity check: we need to be on the normal thread stack. This + * will catch asm bugs and any attempt to use ist_preempt_enable + * from double_fault. + */ + BUG_ON(((current_stack_pointer() ^ this_cpu_read_stable(kernel_stack)) + & ~(THREAD_SIZE - 1)) != 0); + + preempt_count_sub(HARDIRQ_OFFSET); +} + +/** + * ist_end_non_atomic() - begin a non-atomic section in an IST exception + * + * Ends a non-atomic section started with ist_begin_non_atomic(). + */ +void ist_end_non_atomic(void) +{ + preempt_count_add(HARDIRQ_OFFSET); +} + static nokprobe_inline int do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str, struct pt_regs *regs, long error_code) -- cgit v1.2.3 From 5ce07a5cef5094168d25296773681bc287e21e3b Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Fri, 2 Jan 2015 20:22:09 +0100 Subject: microblaze: include the new timecounter header. The timecounter/cyclecounter code has moved, so users need the new include. Signed-off-by: Richard Cochran Signed-off-by: David S. Miller --- arch/microblaze/kernel/timer.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c index dd96f0e4bfa2..c8977450e28c 100644 --- a/arch/microblaze/kernel/timer.c +++ b/arch/microblaze/kernel/timer.c @@ -17,6 +17,7 @@ #include #include #include +#include #include static void __iomem *timer_baseaddr; -- cgit v1.2.3 From b0f2faa5ca02358ebfe404801e2ad604dc88c471 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 17 Dec 2014 18:18:14 +0100 Subject: ARM: sunxi: Add "allwinner,sun6i-a31s" to mach-sunxi So far the A31s is 100% compatible with the A31, still lets do the same as what we've done for the A13 / A10s and give it its own compatible string, in case we need to differentiate later. Signed-off-by: Hans de Goede [Maxime: Removed unusude CPU_OF_DECLARE_METHOD] Signed-off-by: Maxime Ripard --- arch/arm/mach-sunxi/platsmp.c | 2 +- arch/arm/mach-sunxi/sunxi.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-sunxi/platsmp.c b/arch/arm/mach-sunxi/platsmp.c index e44d028555a4..587b0468efcc 100644 --- a/arch/arm/mach-sunxi/platsmp.c +++ b/arch/arm/mach-sunxi/platsmp.c @@ -120,4 +120,4 @@ static struct smp_operations sun6i_smp_ops __initdata = { .smp_prepare_cpus = sun6i_smp_prepare_cpus, .smp_boot_secondary = sun6i_smp_boot_secondary, }; -CPU_METHOD_OF_DECLARE(sun6i_smp, "allwinner,sun6i-a31", &sun6i_smp_ops); +CPU_METHOD_OF_DECLARE(sun6i_a31_smp, "allwinner,sun6i-a31", &sun6i_smp_ops); diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c index 1f986758784a..d4bb2395d39c 100644 --- a/arch/arm/mach-sunxi/sunxi.c +++ b/arch/arm/mach-sunxi/sunxi.c @@ -29,6 +29,7 @@ MACHINE_END static const char * const sun6i_board_dt_compat[] = { "allwinner,sun6i-a31", + "allwinner,sun6i-a31s", NULL, }; -- cgit v1.2.3 From e236fe93e306055c0f927eb09b4d5b10deadbb28 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 1 Sep 2014 15:56:23 +0200 Subject: microblaze: Use empty asm-generic/linkage.h The difference between microblaze and default version in linux/linkage.h is just value stored in the padding bytes which was 0 and in generic is 0x90. Different value shouldn't have any effect. Signed-off-by: Michal Simek --- arch/microblaze/include/asm/linkage.h | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/microblaze/include/asm/linkage.h b/arch/microblaze/include/asm/linkage.h index 3a8e36d057eb..0540bbaad897 100644 --- a/arch/microblaze/include/asm/linkage.h +++ b/arch/microblaze/include/asm/linkage.h @@ -1,15 +1 @@ -/* - * Copyright (C) 2006 Atmark Techno, Inc. - * - * 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. - */ - -#ifndef _ASM_MICROBLAZE_LINKAGE_H -#define _ASM_MICROBLAZE_LINKAGE_H - -#define __ALIGN .align 4 -#define __ALIGN_STR ".align 4" - -#endif /* _ASM_MICROBLAZE_LINKAGE_H */ +#include -- cgit v1.2.3 From add4b1b02da7e7ec35c34dd04d351ac53f3f0dd8 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 18 Dec 2014 15:29:54 +0100 Subject: microblaze: Wire-up execveat syscall Add new execveat syscall. Signed-off-by: Michal Simek --- arch/microblaze/include/asm/unistd.h | 2 +- arch/microblaze/include/uapi/asm/unistd.h | 1 + arch/microblaze/kernel/syscall_table.S | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h index 0a53362d5548..76ed17b56fea 100644 --- a/arch/microblaze/include/asm/unistd.h +++ b/arch/microblaze/include/asm/unistd.h @@ -38,6 +38,6 @@ #endif /* __ASSEMBLY__ */ -#define __NR_syscalls 388 +#define __NR_syscalls 389 #endif /* _ASM_MICROBLAZE_UNISTD_H */ diff --git a/arch/microblaze/include/uapi/asm/unistd.h b/arch/microblaze/include/uapi/asm/unistd.h index c712677f8a2a..32850c73be09 100644 --- a/arch/microblaze/include/uapi/asm/unistd.h +++ b/arch/microblaze/include/uapi/asm/unistd.h @@ -403,5 +403,6 @@ #define __NR_getrandom 385 #define __NR_memfd_create 386 #define __NR_bpf 387 +#define __NR_execveat 388 #endif /* _UAPI_ASM_MICROBLAZE_UNISTD_H */ diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S index 0166e890486c..29c8568ec55c 100644 --- a/arch/microblaze/kernel/syscall_table.S +++ b/arch/microblaze/kernel/syscall_table.S @@ -388,3 +388,4 @@ ENTRY(sys_call_table) .long sys_getrandom /* 385 */ .long sys_memfd_create .long sys_bpf + .long sys_execveat -- cgit v1.2.3 From 32db31da49ffc969d95c434cc47864b30b1bff9c Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 18 Dec 2014 15:30:49 +0100 Subject: microblaze: Remove unused prom_parse.c of_parse_dma_window is completely unused. Signed-off-by: Michal Simek --- arch/microblaze/kernel/Makefile | 2 +- arch/microblaze/kernel/prom_parse.c | 35 ----------------------------------- 2 files changed, 1 insertion(+), 36 deletions(-) delete mode 100644 arch/microblaze/kernel/prom_parse.c (limited to 'arch') diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile index 08d50cc55e7d..f08bacaf8a95 100644 --- a/arch/microblaze/kernel/Makefile +++ b/arch/microblaze/kernel/Makefile @@ -16,7 +16,7 @@ extra-y := head.o vmlinux.lds obj-y += dma.o exceptions.o \ hw_exception_handler.o intc.o irq.o \ - platform.o process.o prom.o prom_parse.o ptrace.o \ + platform.o process.o prom.o ptrace.o \ reset.o setup.o signal.o sys_microblaze.o timer.o traps.o unwind.o obj-y += cpu/ diff --git a/arch/microblaze/kernel/prom_parse.c b/arch/microblaze/kernel/prom_parse.c deleted file mode 100644 index 068762f55fd6..000000000000 --- a/arch/microblaze/kernel/prom_parse.c +++ /dev/null @@ -1,35 +0,0 @@ -#undef DEBUG - -#include -#include -#include -#include -#include -#include -#include - -void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, - unsigned long *busno, unsigned long *phys, unsigned long *size) -{ - const u32 *dma_window; - u32 cells; - const unsigned char *prop; - - dma_window = dma_window_prop; - - /* busno is always one cell */ - *busno = *(dma_window++); - - prop = of_get_property(dn, "ibm,#dma-address-cells", NULL); - if (!prop) - prop = of_get_property(dn, "#address-cells", NULL); - - cells = prop ? *(u32 *)prop : of_n_addr_cells(dn); - *phys = of_read_number(dma_window, cells); - - dma_window += cells; - - prop = of_get_property(dn, "ibm,#dma-size-cells", NULL); - cells = prop ? *(u32 *)prop : of_n_size_cells(dn); - *size = of_read_number(dma_window, cells); -} -- cgit v1.2.3 From b366f11b9a81ad0cc7ed3cbdaca15bb98f96db25 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 18 Dec 2014 15:31:59 +0100 Subject: microblaze: Remove unused prom header from reset.c Completely unused header by this file. Signed-off-by: Michal Simek --- arch/microblaze/kernel/reset.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/microblaze/kernel/reset.c b/arch/microblaze/kernel/reset.c index fbe58c6554a8..bab4c8330ef4 100644 --- a/arch/microblaze/kernel/reset.c +++ b/arch/microblaze/kernel/reset.c @@ -9,7 +9,6 @@ #include #include -#include /* Trigger specific functions */ #ifdef CONFIG_GPIOLIB -- cgit v1.2.3 From f396a4d2314bf1cb83148d9b8fc47995e6c27e1f Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 18 Dec 2014 15:32:57 +0100 Subject: microblaze: Declare microblaze_kgdb_break in header This patch removes the warning: arch/microblaze/kernel/kgdb.c:81:6: warning: no previous prototype for 'microblaze_kgdb_break' [-Wmissing-prototypes] Signed-off-by: Michal Simek --- arch/microblaze/include/asm/kgdb.h | 3 +++ arch/microblaze/kernel/kgdb.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/microblaze/include/asm/kgdb.h b/arch/microblaze/include/asm/kgdb.h index 78b17d40b235..ad27acb2b15f 100644 --- a/arch/microblaze/include/asm/kgdb.h +++ b/arch/microblaze/include/asm/kgdb.h @@ -23,6 +23,9 @@ static inline void arch_kgdb_breakpoint(void) __asm__ __volatile__("brki r16, 0x18;"); } +struct pt_regs; +asmlinkage void microblaze_kgdb_break(struct pt_regs *regs); + #endif /* __ASSEMBLY__ */ #endif /* __MICROBLAZE_KGDB_H__ */ #endif /* __KERNEL__ */ diff --git a/arch/microblaze/kernel/kgdb.c b/arch/microblaze/kernel/kgdb.c index 09a5e8286137..4bd44b6cbc3b 100644 --- a/arch/microblaze/kernel/kgdb.c +++ b/arch/microblaze/kernel/kgdb.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #define GDB_REG 0 @@ -77,7 +78,7 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) pt_regb[i] = gdb_regs[i]; } -void microblaze_kgdb_break(struct pt_regs *regs) +asmlinkage void microblaze_kgdb_break(struct pt_regs *regs) { if (kgdb_handle_exception(1, SIGTRAP, 0, regs) != 0) return; -- cgit v1.2.3 From 8543e6c96762fcc930af5725088c2b9e4865c3aa Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 18 Dec 2014 15:41:13 +0100 Subject: microblaze: Use unsigned return type in do_syscall_trace_enter Registers are not signed types. The patch removes warnings: arch/microblaze/kernel/ptrace.c: In function 'do_syscall_trace_enter': arch/microblaze/kernel/ptrace.c:152:14: warning: signed and unsigned type in conditional expression [-Wsign-compare] return ret ?: regs->r12; Signed-off-by: Michal Simek --- arch/microblaze/include/asm/syscall.h | 2 +- arch/microblaze/kernel/ptrace.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/microblaze/include/asm/syscall.h b/arch/microblaze/include/asm/syscall.h index 53cfaf34c343..04a5bece8168 100644 --- a/arch/microblaze/include/asm/syscall.h +++ b/arch/microblaze/include/asm/syscall.h @@ -97,7 +97,7 @@ static inline void syscall_set_arguments(struct task_struct *task, microblaze_set_syscall_arg(regs, i++, *args++); } -asmlinkage long do_syscall_trace_enter(struct pt_regs *regs); +asmlinkage unsigned long do_syscall_trace_enter(struct pt_regs *regs); asmlinkage void do_syscall_trace_leave(struct pt_regs *regs); static inline int syscall_get_arch(void) diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c index bb10637ce688..8cfa98cadf3d 100644 --- a/arch/microblaze/kernel/ptrace.c +++ b/arch/microblaze/kernel/ptrace.c @@ -132,9 +132,9 @@ long arch_ptrace(struct task_struct *child, long request, return rval; } -asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) +asmlinkage unsigned long do_syscall_trace_enter(struct pt_regs *regs) { - long ret = 0; + unsigned long ret = 0; secure_computing_strict(regs->r12); -- cgit v1.2.3 From e14ebe417c7c4e58c50ef143d99d797757749762 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 18 Dec 2014 15:45:38 +0100 Subject: microblaze: Mark get_frame_size as static It is used only locally in unwind.c. The patch removes warning: arch/microblaze/kernel/unwind.c:62:13: warning: no previous prototype for 'get_frame_size' [-Wmissing-prototypes] inline long get_frame_size(unsigned long instr) Signed-off-by: Michal Simek --- arch/microblaze/kernel/unwind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/microblaze/kernel/unwind.c b/arch/microblaze/kernel/unwind.c index 1f7b8d449668..61c04eed14d5 100644 --- a/arch/microblaze/kernel/unwind.c +++ b/arch/microblaze/kernel/unwind.c @@ -59,7 +59,7 @@ struct stack_trace; * * Return - Number of stack bytes the instruction reserves or reclaims */ -inline long get_frame_size(unsigned long instr) +static inline long get_frame_size(unsigned long instr) { return abs((s16)(instr & 0xFFFF)); } -- cgit v1.2.3 From b6db0a56218c38455e52780338ad61e284a67e4c Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 18 Dec 2014 15:51:30 +0100 Subject: microblaze: Change extern inline to static inline With compilers which follow the C99 standard (like modern versions of gcc and clang), "extern inline" does the opposite thing from older versions of gcc (emits code for an externally linkable version of the inline function). "static inline" does the intended behavior in all cases instead. Description taken from: "staging, rtl8192e, LLVMLinux: Change extern inline to static inline" (sha1: 6d91857d4826b382b3fd4fad95f52713be646f96) The patch removes compilation warnings W=1: ./arch/microblaze/include/asm/delay.h:18:20: warning: no previous prototype for '__delay' [-Wmissing-prototypes] extern inline void __delay(unsigned long loops) ./arch/microblaze/include/asm/delay.h:46:20: warning: no previous prototype for '__udelay' [-Wmissing-prototypes] extern inline void __udelay(unsigned int x) ./arch/microblaze/include/asm/pgalloc.h:63:22: warning: no previous prototype for 'get_pgd_slow' [-Wmissing-prototypes] extern inline pgd_t *get_pgd_slow(void) ./arch/microblaze/include/asm/pgalloc.h:73:22: warning: no previous prototype for 'get_pgd_fast' [-Wmissing-prototypes] extern inline pgd_t *get_pgd_fast(void) ./arch/microblaze/include/asm/pgalloc.h:87:20: warning: no previous prototype for 'free_pgd_fast' [-Wmissing-prototypes] extern inline void free_pgd_fast(pgd_t *pgd) ./arch/microblaze/include/asm/pgalloc.h:94:20: warning: no previous prototype for 'free_pgd_slow' [-Wmissing-prototypes] extern inline void free_pgd_slow(pgd_t *pgd) ./arch/microblaze/include/asm/pgalloc.h:149:20: warning: no previous prototype for 'pte_free_fast' [-Wmissing-prototypes] extern inline void pte_free_fast(pte_t *pte) ./arch/microblaze/include/asm/pgalloc.h:156:20: warning: no previous prototype for 'pte_free_kernel' [-Wmissing-prototypes] extern inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) ./arch/microblaze/include/asm/pgalloc.h:161:20: warning: no previous prototype for 'pte_free_slow' [-Wmissing-prototypes] extern inline void pte_free_slow(struct page *ptepage) Signed-off-by: Michal Simek --- arch/microblaze/include/asm/delay.h | 4 ++-- arch/microblaze/include/asm/pgalloc.h | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/microblaze/include/asm/delay.h b/arch/microblaze/include/asm/delay.h index 60cb39deb533..ea2a9cd9b159 100644 --- a/arch/microblaze/include/asm/delay.h +++ b/arch/microblaze/include/asm/delay.h @@ -15,7 +15,7 @@ #include -extern inline void __delay(unsigned long loops) +static inline void __delay(unsigned long loops) { asm volatile ("# __delay \n\t" \ "1: addi %0, %0, -1\t\n" \ @@ -43,7 +43,7 @@ extern inline void __delay(unsigned long loops) extern unsigned long loops_per_jiffy; -extern inline void __udelay(unsigned int x) +static inline void __udelay(unsigned int x) { unsigned long long tmp = diff --git a/arch/microblaze/include/asm/pgalloc.h b/arch/microblaze/include/asm/pgalloc.h index 7fdf7fabc7d7..61436d69775c 100644 --- a/arch/microblaze/include/asm/pgalloc.h +++ b/arch/microblaze/include/asm/pgalloc.h @@ -60,7 +60,7 @@ extern unsigned long get_zero_page_fast(void); extern void __bad_pte(pmd_t *pmd); -extern inline pgd_t *get_pgd_slow(void) +static inline pgd_t *get_pgd_slow(void) { pgd_t *ret; @@ -70,7 +70,7 @@ extern inline pgd_t *get_pgd_slow(void) return ret; } -extern inline pgd_t *get_pgd_fast(void) +static inline pgd_t *get_pgd_fast(void) { unsigned long *ret; @@ -84,14 +84,14 @@ extern inline pgd_t *get_pgd_fast(void) return (pgd_t *)ret; } -extern inline void free_pgd_fast(pgd_t *pgd) +static inline void free_pgd_fast(pgd_t *pgd) { *(unsigned long **)pgd = pgd_quicklist; pgd_quicklist = (unsigned long *) pgd; pgtable_cache_size++; } -extern inline void free_pgd_slow(pgd_t *pgd) +static inline void free_pgd_slow(pgd_t *pgd) { free_page((unsigned long)pgd); } @@ -146,19 +146,19 @@ static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, return (pte_t *)ret; } -extern inline void pte_free_fast(pte_t *pte) +static inline void pte_free_fast(pte_t *pte) { *(unsigned long **)pte = pte_quicklist; pte_quicklist = (unsigned long *) pte; pgtable_cache_size++; } -extern inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) +static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) { free_page((unsigned long)pte); } -extern inline void pte_free_slow(struct page *ptepage) +static inline void pte_free_slow(struct page *ptepage) { __free_page(ptepage); } -- cgit v1.2.3 From e76fdb324844cc0367f8c6ea5d13278a81568ccb Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 18 Dec 2014 15:56:17 +0100 Subject: microblaze: Use unsigned type for "for" loop because of comparison-kgdb.c This patch removes warnings reported by W=1: arch/microblaze/kernel/kgdb.c: In function 'pt_regs_to_gdb_regs': arch/microblaze/kernel/kgdb.c:43:16: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] arch/microblaze/kernel/kgdb.c:51:16: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] arch/microblaze/kernel/kgdb.c: In function 'gdb_regs_to_pt_regs': arch/microblaze/kernel/kgdb.c:77:16: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] arch/microblaze/kernel/kgdb.c: In function 'sleeping_thread_to_gdb_regs': arch/microblaze/kernel/kgdb.c:99:16: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] arch/microblaze/kernel/kgdb.c:103:16: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] Signed-off-by: Michal Simek --- arch/microblaze/kernel/kgdb.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/microblaze/kernel/kgdb.c b/arch/microblaze/kernel/kgdb.c index 4bd44b6cbc3b..8736af5806ae 100644 --- a/arch/microblaze/kernel/kgdb.c +++ b/arch/microblaze/kernel/kgdb.c @@ -36,9 +36,10 @@ struct pvr_s pvr; void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) { - int i; + unsigned int i; unsigned long *pt_regb = (unsigned long *)regs; int temp; + /* registers r0 - r31, pc, msr, ear, esr, fsr + do not save pt_mode */ for (i = 0; i < (sizeof(struct pt_regs) / 4) - 1; i++) gdb_regs[i] = pt_regb[i]; @@ -68,7 +69,7 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) { - int i; + unsigned int i; unsigned long *pt_regb = (unsigned long *)regs; /* pt_regs and gdb_regs have the same 37 values. @@ -92,7 +93,7 @@ asmlinkage void microblaze_kgdb_break(struct pt_regs *regs) /* untested */ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) { - int i; + unsigned int i; unsigned long *pt_regb = (unsigned long *)(p->thread.regs); /* registers r0 - r31, pc, msr, ear, esr, fsr + do not save pt_mode */ -- cgit v1.2.3 From bdb96e3cad21f5973c95f0e6687db4a57eff7c53 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 18 Dec 2014 16:02:00 +0100 Subject: microblaze: Use unsigned type for proper comparison in cpuinfo*.c Compare the same types together. Compilation warnings: arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c: In function 'set_cpuinfo_pvr_full': arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c:47:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c:52:19: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c:57:18: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c:94:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] arch/microblaze/kernel/cpu/cpuinfo-static.c: In function 'set_cpuinfo_static': arch/microblaze/kernel/cpu/cpuinfo-static.c:40:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c | 2 +- arch/microblaze/kernel/cpu/cpuinfo-static.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c index 93c26cf50de5..a32daec96c12 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c +++ b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c @@ -33,7 +33,7 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu) { struct pvr_s pvr; - int temp; /* for saving temp value */ + u32 temp; /* for saving temp value */ get_pvr(&pvr); CI(ver_code, VERSION); diff --git a/arch/microblaze/kernel/cpu/cpuinfo-static.c b/arch/microblaze/kernel/cpu/cpuinfo-static.c index 4854285b26e7..85dbda4a08a8 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo-static.c +++ b/arch/microblaze/kernel/cpu/cpuinfo-static.c @@ -22,7 +22,7 @@ static const char cpu_ver_string[] = CONFIG_XILINX_MICROBLAZE0_HW_VER; void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu) { - int i = 0; + u32 i = 0; ci->use_instr = (fcpu(cpu, "xlnx,use-barrel") ? PVR0_USE_BARREL_MASK : 0) | -- cgit v1.2.3 From 985782d1241718c632839a284d07e84be3bb344c Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Thu, 27 Nov 2014 21:33:59 +0100 Subject: apf27dev: add max5821 to the dts Signed-off-by: Philippe Reynes Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx27-apf27dev.dts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/imx27-apf27dev.dts b/arch/arm/boot/dts/imx27-apf27dev.dts index da306c5dd678..bba3f41b89ef 100644 --- a/arch/arm/boot/dts/imx27-apf27dev.dts +++ b/arch/arm/boot/dts/imx27-apf27dev.dts @@ -59,6 +59,21 @@ linux,default-trigger = "heartbeat"; }; }; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + reg_max5821: regulator@0 { + compatible = "regulator-fixed"; + reg = <0>; + regulator-name = "max5821-reg"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + }; + }; }; &cspi1 { @@ -107,6 +122,12 @@ compatible = "dallas,ds1374"; reg = <0x68>; }; + + max5821@38 { + compatible = "maxim,max5821"; + reg = <0x38>; + vref-supply = <®_max5821>; + }; }; &i2c2 { -- cgit v1.2.3 From c134e09fc59381ffd445922019b72aed998bdc8f Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 28 Nov 2014 00:35:36 +0100 Subject: ARM: dts: vf610: enable watchdog for Cortex-A5 dt's During restructuring of the device tree files the watchdog was changed to be disabled by default. However, since the watchdog instance is dedicated to the Cortex-A5, enable the peripheral by default in the base device tree vf500.dtsi. Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vf500.dtsi | 5 +++++ arch/arm/boot/dts/vfxxx.dtsi | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/vf500.dtsi b/arch/arm/boot/dts/vf500.dtsi index de6700542714..ea0f74f6eeb3 100644 --- a/arch/arm/boot/dts/vf500.dtsi +++ b/arch/arm/boot/dts/vf500.dtsi @@ -169,3 +169,8 @@ &usbphy1 { interrupts = ; }; + +&wdoga5 { + interrupts = ; + status = "okay"; +}; diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi index 505969ae8093..712646814cc6 100644 --- a/arch/arm/boot/dts/vfxxx.dtsi +++ b/arch/arm/boot/dts/vfxxx.dtsi @@ -184,7 +184,7 @@ status = "disabled"; }; - wdog@4003e000 { + wdoga5: wdog@4003e000 { compatible = "fsl,vf610-wdt", "fsl,imx21-wdt"; reg = <0x4003e000 0x1000>; clocks = <&clks VF610_CLK_WDT>; -- cgit v1.2.3 From eddb00fa125bb77452dd875e7d8170c8d3c4d546 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 28 Nov 2014 00:40:06 +0100 Subject: ARM: dts: vf-colibri: add CLKOUT pin to pinctrl of FEC1 On the Colibri module, the RMII clock for the Ethernet PHY is generated by the SoC. This patch adds that missing pin to the pinctrl of FEC1. Because the boot loader initializes this pin, ethernet worked even without this pin so far. Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vf-colibri.dtsi | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/vf-colibri.dtsi b/arch/arm/boot/dts/vf-colibri.dtsi index 82f5728be5c9..95b6ff222eee 100644 --- a/arch/arm/boot/dts/vf-colibri.dtsi +++ b/arch/arm/boot/dts/vf-colibri.dtsi @@ -121,6 +121,7 @@ pinctrl_fec1: fec1grp { fsl,pins = < + VF610_PAD_PTA6__RMII_CLKOUT 0x30d2 VF610_PAD_PTC9__ENET_RMII1_MDC 0x30d2 VF610_PAD_PTC10__ENET_RMII1_MDIO 0x30d3 VF610_PAD_PTC11__ENET_RMII1_CRS 0x30d1 -- cgit v1.2.3 From 7194661924531d02935bc752238202299bb0dcb1 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 27 Nov 2014 10:18:19 -0200 Subject: ARM: dts: imx: Update VPU compatible strings Update the VPU compatible strings to also use "cnm,coda". Signed-off-by: Fabio Estevam Acked-by: Philipp Zabel Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx27.dtsi | 2 +- arch/arm/boot/dts/imx53.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi index 107d713e1cbe..4b063b68db44 100644 --- a/arch/arm/boot/dts/imx27.dtsi +++ b/arch/arm/boot/dts/imx27.dtsi @@ -464,7 +464,7 @@ }; coda: coda@10023000 { - compatible = "fsl,imx27-vpu"; + compatible = "fsl,imx27-vpu", "cnm,codadx6"; reg = <0x10023000 0x0200>; interrupts = <53>; clocks = <&clks IMX27_CLK_VPU_BAUD_GATE>, diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi index a30bddfdbdb6..b96213ba0671 100644 --- a/arch/arm/boot/dts/imx53.dtsi +++ b/arch/arm/boot/dts/imx53.dtsi @@ -756,7 +756,7 @@ }; vpu: vpu@63ff4000 { - compatible = "fsl,imx53-vpu"; + compatible = "fsl,imx53-vpu", "cnm,coda7541"; reg = <0x63ff4000 0x1000>; interrupts = <9>; clocks = <&clks IMX5_CLK_VPU_REFERENCE_GATE>, -- cgit v1.2.3 From 0d018d7387bd3c2d25ca7ed1a6b3631c071cd918 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 2 Dec 2014 18:11:59 +0100 Subject: ARM: dts: vf610: add system reset controller and syscon-reboot Add the system reset controller (SRC) module and use syscon-reboot to register a restart handler which restarts the SoC using the SRC SW_RST bit. Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vf500.dtsi | 4 ++++ arch/arm/boot/dts/vfxxx.dtsi | 12 ++++++++++++ 2 files changed, 16 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/vf500.dtsi b/arch/arm/boot/dts/vf500.dtsi index ea0f74f6eeb3..29016090d060 100644 --- a/arch/arm/boot/dts/vf500.dtsi +++ b/arch/arm/boot/dts/vf500.dtsi @@ -130,6 +130,10 @@ interrupts = ; }; +&src { + interrupts = ; +}; + &uart0 { interrupts = ; }; diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi index 712646814cc6..a55e1f9a414d 100644 --- a/arch/arm/boot/dts/vfxxx.dtsi +++ b/arch/arm/boot/dts/vfxxx.dtsi @@ -43,6 +43,13 @@ clock-frequency = <32768>; }; + reboot: syscon-reboot { + compatible = "syscon-reboot"; + regmap = <&src>; + offset = <0x0>; + mask = <0x1000>; + }; + soc { #address-cells = <1>; #size-cells = <1>; @@ -318,6 +325,11 @@ clocks = <&clks VF610_CLK_USBC0>; status = "disabled"; }; + + src: src@4006e000 { + compatible = "fsl,vf610-src", "syscon"; + reg = <0x4006e000 0x1000>; + }; }; aips1: aips-bus@40080000 { -- cgit v1.2.3 From d951534606661349a95b707111fdd04cecda62c8 Mon Sep 17 00:00:00 2001 From: Eric Nelson Date: Tue, 2 Dec 2014 15:37:16 -0700 Subject: ARM: dts: sabrelite: add i2c2 Signed-off-by: Eric Nelson Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-sabrelite.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi index 0a36129152e0..37f53f3ddcb8 100644 --- a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi +++ b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi @@ -188,6 +188,13 @@ }; }; +&i2c2 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + status = "okay"; +}; + &iomuxc { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hog>; @@ -265,6 +272,13 @@ >; }; + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 + >; + }; + pinctrl_pwm1: pwm1grp { fsl,pins = < MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1 -- cgit v1.2.3 From 8eedffe54e92a8e3345fad7a4463d81364d6c452 Mon Sep 17 00:00:00 2001 From: Eric Nelson Date: Tue, 2 Dec 2014 15:37:17 -0700 Subject: ARM: dts: sabrelite: add hdmi Signed-off-by: Eric Nelson Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-sabrelite.dtsi | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi index 37f53f3ddcb8..3bddc8fe8144 100644 --- a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi +++ b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi @@ -173,6 +173,11 @@ status = "okay"; }; +&hdmi { + ddc-i2c-bus = <&i2c2>; + status = "okay"; +}; + &i2c1 { clock-frequency = <100000>; pinctrl-names = "default"; -- cgit v1.2.3 From 0a3e41ff90a53360bb4c39e1e45f4b4ac5949fef Mon Sep 17 00:00:00 2001 From: Eric Nelson Date: Tue, 2 Dec 2014 15:37:18 -0700 Subject: ARM: dts: sabrelite: add i2c3 Signed-off-by: Eric Nelson Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-sabrelite.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi index 3bddc8fe8144..0b28a9d5241e 100644 --- a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi +++ b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi @@ -200,6 +200,13 @@ status = "okay"; }; +&i2c3 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c3>; + status = "okay"; +}; + &iomuxc { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hog>; @@ -284,6 +291,13 @@ >; }; + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1 + MX6QDL_PAD_GPIO_16__I2C3_SDA 0x4001b8b1 + >; + }; + pinctrl_pwm1: pwm1grp { fsl,pins = < MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1 -- cgit v1.2.3 From eabb3227d912f554237bf2a0920108cb6e372eb0 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 5 Dec 2014 16:23:48 +0800 Subject: ARM: dts: imx6q: update cpufreq volt/freq table According to latest i.MX6Q datasheet Rev. 3, 02/2014, the latest cpufreq volt/freq table is as below: LDO enabled/bypassed(min value): 996MHz: VDDARM: 1.225V, VDDSOC: 1.150V; 792MHz: VDDARM: 1.150V, VDDSOC: 1.150V; 396MHz: VDDARM: 0.925V, VDDSOC: 1.150V; the 792MHz setpoint's VDDARM min voltage is updated from 1.125V to 1.150V, adding 25mV to cover board IR drop, 1.175V is the right voltage we should use. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6q.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index 85f72e6b5bad..37ee4e588910 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi @@ -31,7 +31,7 @@ 1200000 1275000 996000 1250000 852000 1250000 - 792000 1150000 + 792000 1175000 396000 975000 >; fsl,soc-operating-points = < -- cgit v1.2.3 From 4c61a1e75cd9247c624de8481efe85208b97ac85 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Fri, 5 Dec 2014 16:23:49 +0800 Subject: ARM: dts: imx6dl: correct cpufreq volt/freq table Currently the cpufreq volt/freq table we used is for LDO enable mode, according to latest datasheet Rev. 3, 03/2014, the volt/freq table is as below: LDO enabled(min value): 996MHz: VDDARM: 1.225V, VDDSOC: 1.150V; 792MHz: VDDARM: 1.150V, VDDSOC: 1.150V; 396MHz: VDDARM: 1.050V, VDDSOC: 1.150V; LDO bypassed(min value): 996MHz: VDDARM: 1.250V, VDDSOC: 1.150V; 792MHz: VDDARM: 1.150V, VDDSOC: 1.150V; 396MHz: VDDARM: 1.050V, VDDSOC: 1.150V; Adding 25mV to cover board IR drop, for LDO enabled mode of 996MHz, VDDARM should be 1.250V, so this patch updates it. Signed-off-by: Anson Huang Reviewed-by: Philipp Zabel Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6dl.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi index 1ac2fe732867..f94bf72832af 100644 --- a/arch/arm/boot/dts/imx6dl.dtsi +++ b/arch/arm/boot/dts/imx6dl.dtsi @@ -28,7 +28,7 @@ next-level-cache = <&L2>; operating-points = < /* kHz uV */ - 996000 1275000 + 996000 1250000 792000 1175000 396000 1075000 >; -- cgit v1.2.3 From 60811cc24e6101717928ef3e27fe7bcd8f342a9f Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Tue, 9 Dec 2014 09:56:52 +0100 Subject: ARM: i.MX53: dts: add sahara module The i.MX53 has a SAHARA v4 core. Add it to the dtsi. Signed-off-by: Steffen Trumtrar Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx53.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi index b96213ba0671..ff4fa7ecacd8 100644 --- a/arch/arm/boot/dts/imx53.dtsi +++ b/arch/arm/boot/dts/imx53.dtsi @@ -765,6 +765,15 @@ resets = <&src 1>; iram = <&ocram>; }; + + sahara: crypto@63ff8000 { + compatible = "fsl,imx53-sahara"; + reg = <0x63ff8000 0x4000>; + interrupts = <19 20>; + clocks = <&clks IMX5_CLK_SAHARA_IPG_GATE>, + <&clks IMX5_CLK_SAHARA_IPG_GATE>; + clock-names = "ipg", "ahb"; + }; }; ocram: sram@f8000000 { -- cgit v1.2.3 From 44ae1244ae787dfcf767b179dbd5ca7c06c418e8 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 2 Dec 2014 18:12:00 +0100 Subject: ARM: imx_v6_v7_defconfig: add POWER_RESET_SYSCON Add POWER_RESET_SYSCON since Vybrid SoC's now make use of this driver to provide software reset capabilities through the SRC module. Also regenerated using savedefconfig which removed the config BACKLIGHT_LCD_SUPPORT which is now selected by default since commit 9c8ee3c734139 ("video: mx3fb: always enable BACKLIGHT_LCD_SUPPORT"). Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- arch/arm/configs/imx_v6_v7_defconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 7c2075a07eba..96ac3a7d5609 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -163,13 +163,14 @@ CONFIG_SPI_IMX=y CONFIG_GPIO_SYSFS=y CONFIG_GPIO_MC9S08DZ60=y CONFIG_GPIO_STMPE=y +CONFIG_POWER_SUPPLY=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_IMX=y +CONFIG_POWER_RESET_SYSCON=y CONFIG_SENSORS_GPIO_FAN=y CONFIG_THERMAL=y CONFIG_CPU_THERMAL=y CONFIG_IMX_THERMAL=y -CONFIG_POWER_SUPPLY=y -CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_IMX=y CONFIG_WATCHDOG=y CONFIG_IMX2_WDT=y CONFIG_MFD_DA9052_I2C=y @@ -198,7 +199,6 @@ CONFIG_SOC_CAMERA_OV2640=y CONFIG_IMX_IPUV3_CORE=y CONFIG_DRM=y CONFIG_DRM_PANEL_SIMPLE=y -CONFIG_BACKLIGHT_LCD_SUPPORT=y CONFIG_LCD_CLASS_DEVICE=y CONFIG_LCD_L4F00242T03=y CONFIG_LCD_PLATFORM=y -- cgit v1.2.3 From da06aae8b5cae1bd0ac5b7518c9693fe07c06488 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 28 Nov 2014 00:27:05 +0100 Subject: ARM vf610: add compatibilty strings of supported Vybrid SoC's The Vybrid SoC family (in the kernel known as vf610) is a familiy of multiple similar SoC's. The VF5xx series comes without secondary Cortex-M4 core, while the second number VFx1x indicates the presence of a L2 cache controller. Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- arch/arm/mach-imx/mach-vf610.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/mach-vf610.c b/arch/arm/mach-imx/mach-vf610.c index c11ab6a1dc87..2e7c75b66fe0 100644 --- a/arch/arm/mach-imx/mach-vf610.c +++ b/arch/arm/mach-imx/mach-vf610.c @@ -13,11 +13,14 @@ #include static const char * const vf610_dt_compat[] __initconst = { + "fsl,vf500", + "fsl,vf510", + "fsl,vf600", "fsl,vf610", NULL, }; -DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF610 (Device Tree)") +DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF5xx/VF6xx (Device Tree)") .l2c_aux_val = 0, .l2c_aux_mask = ~0, .dt_compat = vf610_dt_compat, -- cgit v1.2.3 From 60ad8467c1bf0cae19ccc9d142914a2288ac85e7 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 2 Dec 2014 17:59:42 +0100 Subject: ARM: imx: pllv3: add shift for frequency multiplier Add shift capabilties for the frequency multiplier (DIV_SELECT) to support Vybrid's USB PLL oddity. The PLL3 and PLL7 are the only PLL control registers which have the DIV_SELECT bit shifted by one. Be aware, there are known documentation errors in the reference manual too. Signed-off-by: Stefan Agner Signed-off-by: Shawn Guo --- arch/arm/mach-imx/clk-pllv3.c | 10 +++++++--- arch/arm/mach-imx/clk-vf610.c | 4 ++-- arch/arm/mach-imx/clk.h | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/clk-pllv3.c b/arch/arm/mach-imx/clk-pllv3.c index 0ad6e5442fd8..641ebc508920 100644 --- a/arch/arm/mach-imx/clk-pllv3.c +++ b/arch/arm/mach-imx/clk-pllv3.c @@ -31,6 +31,7 @@ * @base: base address of PLL registers * @powerup_set: set POWER bit to power up the PLL * @div_mask: mask of divider bits + * @div_shift: shift of divider bits * * IMX PLL clock version 3, found on i.MX6 series. Divider for pllv3 * is actually a multiplier, and always sits at bit 0. @@ -40,6 +41,7 @@ struct clk_pllv3 { void __iomem *base; bool powerup_set; u32 div_mask; + u32 div_shift; }; #define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw) @@ -97,7 +99,7 @@ static unsigned long clk_pllv3_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_pllv3 *pll = to_clk_pllv3(hw); - u32 div = readl_relaxed(pll->base) & pll->div_mask; + u32 div = (readl_relaxed(pll->base) >> pll->div_shift) & pll->div_mask; return (div == 1) ? parent_rate * 22 : parent_rate * 20; } @@ -125,8 +127,8 @@ static int clk_pllv3_set_rate(struct clk_hw *hw, unsigned long rate, return -EINVAL; val = readl_relaxed(pll->base); - val &= ~pll->div_mask; - val |= div; + val &= ~(pll->div_mask << pll->div_shift); + val |= (div << pll->div_shift); writel_relaxed(val, pll->base); return clk_pllv3_wait_lock(pll); @@ -295,6 +297,8 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, case IMX_PLLV3_SYS: ops = &clk_pllv3_sys_ops; break; + case IMX_PLLV3_USB_VF610: + pll->div_shift = 1; case IMX_PLLV3_USB: ops = &clk_pllv3_ops; pll->powerup_set = true; diff --git a/arch/arm/mach-imx/clk-vf610.c b/arch/arm/mach-imx/clk-vf610.c index 5937ddee1a99..cb21777c3ab6 100644 --- a/arch/arm/mach-imx/clk-vf610.c +++ b/arch/arm/mach-imx/clk-vf610.c @@ -172,11 +172,11 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) clk[VF610_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll1", "pll1_bypass_src", PLL1_CTRL, 0x1); clk[VF610_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", PLL2_CTRL, 0x1); - clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "pll3_bypass_src", PLL3_CTRL, 0x1); + clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB_VF610, "pll3", "pll3_bypass_src", PLL3_CTRL, 0x2); clk[VF610_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "pll4_bypass_src", PLL4_CTRL, 0x7f); clk[VF610_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll5", "pll5_bypass_src", PLL5_CTRL, 0x3); clk[VF610_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_AV, "pll6", "pll6_bypass_src", PLL6_CTRL, 0x7f); - clk[VF610_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "pll7_bypass_src", PLL7_CTRL, 0x1); + clk[VF610_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB_VF610, "pll7", "pll7_bypass_src", PLL7_CTRL, 0x2); clk[VF610_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", PLL1_CTRL, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT); clk[VF610_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", PLL2_CTRL, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT); diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h index 5ef82e2f8fc5..6a07903a28bc 100644 --- a/arch/arm/mach-imx/clk.h +++ b/arch/arm/mach-imx/clk.h @@ -20,6 +20,7 @@ enum imx_pllv3_type { IMX_PLLV3_GENERIC, IMX_PLLV3_SYS, IMX_PLLV3_USB, + IMX_PLLV3_USB_VF610, IMX_PLLV3_AV, IMX_PLLV3_ENET, }; -- cgit v1.2.3 From 3d27bc5c313ef9f953d1a8eb6927307cdda3aa52 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 10 Dec 2014 17:51:42 +0800 Subject: ARM: imx: correct the hardware clock gate setting for shared nodes For those clk gates which hold share count, since its is_enabled callback is only checking the share count rather than reading the hardware register setting, in the late phase of kernel bootup, the clk_disable_unused action will NOT handle the scenario of share_count is 0 but the hardware setting is enabled, actually, U-Boot normally enables all clk gates, then those shared clk gates will be always enabled until they are used by some modules. So the problem would be: when kernel boot up, the usecount cat from clk tree is 0, but the clk gates actually is enabled in hardware register, it will confuse user and bring unnecessary power consumption. This patch adds .disable_unused callback and using hardware register check for .is_enabled callback of shared nodes to handle such scenario in late phase of kernel boot up, then the hardware status will match the clk tree info. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/mach-imx/clk-gate2.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/clk-gate2.c b/arch/arm/mach-imx/clk-gate2.c index 5a75cdc81891..8935bff99fe7 100644 --- a/arch/arm/mach-imx/clk-gate2.c +++ b/arch/arm/mach-imx/clk-gate2.c @@ -96,15 +96,30 @@ static int clk_gate2_is_enabled(struct clk_hw *hw) { struct clk_gate2 *gate = to_clk_gate2(hw); - if (gate->share_count) - return !!__clk_get_enable_count(hw->clk); - else - return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx); + return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx); +} + +static void clk_gate2_disable_unused(struct clk_hw *hw) +{ + struct clk_gate2 *gate = to_clk_gate2(hw); + unsigned long flags = 0; + u32 reg; + + spin_lock_irqsave(gate->lock, flags); + + if (!gate->share_count || *gate->share_count == 0) { + reg = readl(gate->reg); + reg &= ~(3 << gate->bit_idx); + writel(reg, gate->reg); + } + + spin_unlock_irqrestore(gate->lock, flags); } static struct clk_ops clk_gate2_ops = { .enable = clk_gate2_enable, .disable = clk_gate2_disable, + .disable_unused = clk_gate2_disable_unused, .is_enabled = clk_gate2_is_enabled, }; -- cgit v1.2.3 From f76129d0ed2945b470adc96478d6347c58d22721 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Tue, 16 Dec 2014 12:20:57 +0100 Subject: ARM: imx: apf51dev: add gpio-backlight support Signed-off-by: Gwenhael Goavec-Merou Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx51-apf51dev.dts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/imx51-apf51dev.dts b/arch/arm/boot/dts/imx51-apf51dev.dts index c5a9a24c280a..93d3ea12328c 100644 --- a/arch/arm/boot/dts/imx51-apf51dev.dts +++ b/arch/arm/boot/dts/imx51-apf51dev.dts @@ -16,6 +16,14 @@ model = "Armadeus Systems APF51Dev docking/development board"; compatible = "armadeus,imx51-apf51dev", "armadeus,imx51-apf51", "fsl,imx51"; + backlight@bl1{ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_backlight>; + compatible = "gpio-backlight"; + gpios = <&gpio3 4 GPIO_ACTIVE_HIGH>; + default-on; + }; + display@di1 { compatible = "fsl,imx-parallel-display"; interface-pix-fmt = "bgr666"; @@ -114,6 +122,12 @@ pinctrl-0 = <&pinctrl_hog>; imx51-apf51dev { + pinctrl_backlight: bl1grp { + fsl,pins = < + MX51_PAD_DI1_D1_CS__GPIO3_4 0x1F5 + >; + }; + pinctrl_hog: hoggrp { fsl,pins = < MX51_PAD_EIM_EB2__GPIO2_22 0x0C5 -- cgit v1.2.3 From c9997ba2aa6803eec44dd498d58b18e1b0784231 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 16 Dec 2014 11:02:41 -0200 Subject: ARM: dts: imx6qdl: Remove OCRAM clock from VPU node According to Documentation/devicetree/bindings/media/coda.txt: - clock-names : Should be "ahb", "per" The OCRAM clock is already provided inside the ocram node, so remove the OCRAM clock from the VPU node. Signed-off-by: Fabio Estevam Acked-by: Philipp Zabel Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl.dtsi | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index 4fc03b7f1cee..f6c6a6e1cf3d 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -339,9 +339,8 @@ <0 12 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "bit", "jpeg"; clocks = <&clks IMX6QDL_CLK_VPU_AXI>, - <&clks IMX6QDL_CLK_MMDC_CH0_AXI>, - <&clks IMX6QDL_CLK_OCRAM>; - clock-names = "per", "ahb", "ocram"; + <&clks IMX6QDL_CLK_MMDC_CH0_AXI>; + clock-names = "per", "ahb"; resets = <&src 1>; iram = <&ocram>; }; -- cgit v1.2.3 From c565e146e6152f09177f214f3667f45522a90325 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 16 Dec 2014 17:30:29 -0200 Subject: ARM: dts: imx6sx-sdb: Add QSPI support imx6sx-sdb has two s25fl128s quad spi flash. Add support for them. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6sx-sdb.dts | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/imx6sx-sdb.dts b/arch/arm/boot/dts/imx6sx-sdb.dts index 1e6e5cc1c14c..cdffe8465c46 100644 --- a/arch/arm/boot/dts/imx6sx-sdb.dts +++ b/arch/arm/boot/dts/imx6sx-sdb.dts @@ -340,6 +340,28 @@ status = "okay"; }; +&qspi2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_qspi2>; + status = "okay"; + + flash0: s25fl128s@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + compatible = "spansion,s25fl128s"; + spi-max-frequency = <66000000>; + }; + + flash1: s25fl128s@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <1>; + compatible = "spansion,s25fl128s"; + spi-max-frequency = <66000000>; + }; +}; + &ssi2 { status = "okay"; }; @@ -524,6 +546,23 @@ >; }; + pinctrl_qspi2: qspi2grp { + fsl,pins = < + MX6SX_PAD_NAND_WP_B__QSPI2_A_DATA_0 0x70f1 + MX6SX_PAD_NAND_READY_B__QSPI2_A_DATA_1 0x70f1 + MX6SX_PAD_NAND_CE0_B__QSPI2_A_DATA_2 0x70f1 + MX6SX_PAD_NAND_CE1_B__QSPI2_A_DATA_3 0x70f1 + MX6SX_PAD_NAND_CLE__QSPI2_A_SCLK 0x70f1 + MX6SX_PAD_NAND_ALE__QSPI2_A_SS0_B 0x70f1 + MX6SX_PAD_NAND_DATA01__QSPI2_B_DATA_0 0x70f1 + MX6SX_PAD_NAND_DATA00__QSPI2_B_DATA_1 0x70f1 + MX6SX_PAD_NAND_WE_B__QSPI2_B_DATA_2 0x70f1 + MX6SX_PAD_NAND_RE_B__QSPI2_B_DATA_3 0x70f1 + MX6SX_PAD_NAND_DATA02__QSPI2_B_SCLK 0x70f1 + MX6SX_PAD_NAND_DATA03__QSPI2_B_SS0_B 0x70f1 + >; + }; + pinctrl_vcc_sd3: vccsd3grp { fsl,pins = < MX6SX_PAD_KEY_COL1__GPIO2_IO_11 0x17059 -- cgit v1.2.3 From 8decfb05400d937265e1632d22967bbabc73feeb Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 16 Dec 2014 17:30:30 -0200 Subject: ARM: imx_v6_v7_defconfig: Select SPI_FSL_QUADSPI by default SPI_FSL_QUADSPI can be used by Vybrid and mx6sx, so select it by default. Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/configs/imx_v6_v7_defconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index 96ac3a7d5609..9575af804939 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -97,6 +97,7 @@ CONFIG_MTD_NAND=y CONFIG_MTD_NAND_GPMI_NAND=y CONFIG_MTD_NAND_MXC=y CONFIG_MTD_SPI_NOR=y +CONFIG_SPI_FSL_QUADSPI=y CONFIG_MTD_UBI=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y -- cgit v1.2.3 From 99fc5ba0bfb6df59ac22faa48406108e7203ceae Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 17 Dec 2014 12:22:09 +0800 Subject: ARM: dts: imx6sx: add i.mx6sx sabreauto board support Add basic i.MX6SoloX Sabre Auto board support, currently only debug UART and uSDHC are supported on this board. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/imx6sx-sabreauto.dts | 146 +++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 arch/arm/boot/dts/imx6sx-sabreauto.dts (limited to 'arch') diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 91bd5bd62857..c0d5c6619c91 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -266,6 +266,7 @@ dtb-$(CONFIG_ARCH_MXC) += \ imx6q-tx6q-1020-comtft.dtb \ imx6q-tx6q-1110.dtb \ imx6sl-evk.dtb \ + imx6sx-sabreauto.dtb \ imx6sx-sdb.dtb \ ls1021a-qds.dtb \ ls1021a-twr.dtb \ diff --git a/arch/arm/boot/dts/imx6sx-sabreauto.dts b/arch/arm/boot/dts/imx6sx-sabreauto.dts new file mode 100644 index 000000000000..e3c0b63c2205 --- /dev/null +++ b/arch/arm/boot/dts/imx6sx-sabreauto.dts @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor, 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. + */ + +/dts-v1/; + +#include "imx6sx.dtsi" + +/ { + model = "Freescale i.MX6 SoloX Sabre Auto Board"; + compatible = "fsl,imx6sx-sabreauto", "fsl,imx6sx"; + + memory { + reg = <0x80000000 0x80000000>; + }; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + vcc_sd3: regulator@0 { + compatible = "regulator-fixed"; + reg = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_vcc_sd3>; + regulator-name = "VCC_SD3"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + gpio = <&gpio2 11 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + }; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +&usdhc3 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc3>; + pinctrl-1 = <&pinctrl_usdhc3_100mhz>; + pinctrl-2 = <&pinctrl_usdhc3_200mhz>; + bus-width = <8>; + cd-gpios = <&gpio7 10 GPIO_ACTIVE_HIGH>; + wp-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>; + keep-power-in-suspend; + enable-sdio-wakeup; + vmmc-supply = <&vcc_sd3>; + status = "okay"; +}; + +&usdhc4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc4>; + bus-width = <8>; + cd-gpios = <&gpio7 11 GPIO_ACTIVE_HIGH>; + no-1-8-v; + keep-power-in-suspend; + enable-sdio-wakup; + status = "okay"; +}; + +&iomuxc { + imx6x-sabreauto { + pinctrl_uart1: uart1grp { + fsl,pins = < + MX6SX_PAD_GPIO1_IO04__UART1_TX 0x1b0b1 + MX6SX_PAD_GPIO1_IO05__UART1_RX 0x1b0b1 + >; + }; + + pinctrl_usdhc3: usdhc3grp { + fsl,pins = < + MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x17059 + MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x10059 + MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x17059 + MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x17059 + MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x17059 + MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x17059 + MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x17059 + MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x17059 + MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x17059 + MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x17059 + MX6SX_PAD_KEY_COL0__GPIO2_IO_10 0x17059 /* CD */ + MX6SX_PAD_KEY_ROW0__GPIO2_IO_15 0x17059 /* WP */ + >; + }; + + pinctrl_usdhc3_100mhz: usdhc3grp-100mhz { + fsl,pins = < + MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170b9 + MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100b9 + MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170b9 + MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170b9 + MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170b9 + MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170b9 + MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170b9 + MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170b9 + MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170b9 + MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170b9 + >; + }; + + pinctrl_usdhc3_200mhz: usdhc3grp-200mhz { + fsl,pins = < + MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170f9 + MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100f9 + MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170f9 + MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170f9 + MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170f9 + MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170f9 + MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170f9 + MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170f9 + MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170f9 + MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170f9 + >; + }; + + pinctrl_usdhc4: usdhc4grp { + fsl,pins = < + MX6SX_PAD_SD4_CMD__USDHC4_CMD 0x17059 + MX6SX_PAD_SD4_CLK__USDHC4_CLK 0x10059 + MX6SX_PAD_SD4_DATA0__USDHC4_DATA0 0x17059 + MX6SX_PAD_SD4_DATA1__USDHC4_DATA1 0x17059 + MX6SX_PAD_SD4_DATA2__USDHC4_DATA2 0x17059 + MX6SX_PAD_SD4_DATA3__USDHC4_DATA3 0x17059 + MX6SX_PAD_SD4_DATA7__GPIO6_IO_21 0x17059 /* CD */ + MX6SX_PAD_SD4_DATA6__GPIO6_IO_20 0x17059 /* WP */ + >; + }; + + pinctrl_vcc_sd3: vccsd3grp { + fsl,pins = < + MX6SX_PAD_KEY_COL1__GPIO2_IO_11 0x17059 + >; + }; + }; +}; -- cgit v1.2.3 From df096fde0889a7a624fcc9616ff5ebd7446d131e Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 17 Dec 2014 12:23:19 +0800 Subject: ARM: imx: remove unnecessary setting for DSM Now we support DSM in OCRAM for all i.MX6 SoCs, the resume entry point is set in asm code of suspend-imx6.S, so no need to set the resume entry point for SRC in pre-suspend flow. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/mach-imx/pm-imx6.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c index 5d2c1bd5f5ef..661ffcf1031e 100644 --- a/arch/arm/mach-imx/pm-imx6.c +++ b/arch/arm/mach-imx/pm-imx6.c @@ -362,7 +362,6 @@ static int imx6q_pm_enter(suspend_state_t state) imx6q_enable_rbc(true); imx_gpc_pre_suspend(true); imx_anatop_pre_suspend(); - imx_set_cpu_jump(0, v7_cpu_resume); /* Zzz ... */ cpu_suspend(0, imx6q_suspend_finish); if (cpu_is_imx6q() || cpu_is_imx6dl()) -- cgit v1.2.3 From 05136f0897b526b9cd090c93b95bbd1b67c18cc5 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 17 Dec 2014 12:24:12 +0800 Subject: ARM: imx: support arm power off in cpuidle for i.mx6sx This patch introduces an independent cpuidle driver for i.MX6SX, and supports arm power off in idle, totally 3 levels of cpuidle are supported as below: 1. ARM WFI; 2. SOC in WAIT mode; 3. SOC in WAIT mode + ARM power off. ARM power off can save at least 5mW power. This patch also replaces imx6q_enable_rbc with imx6_enable_rbc. Signed-off-by: Anson Huang Signed-off-by: Shawn Guo --- arch/arm/mach-imx/Makefile | 3 +- arch/arm/mach-imx/common.h | 4 ++ arch/arm/mach-imx/cpuidle-imx6sx.c | 107 +++++++++++++++++++++++++++++++++++++ arch/arm/mach-imx/cpuidle.h | 5 ++ arch/arm/mach-imx/gpc.c | 25 ++++++++- arch/arm/mach-imx/mach-imx6sx.c | 2 +- arch/arm/mach-imx/pm-imx6.c | 6 +-- 7 files changed, 144 insertions(+), 8 deletions(-) create mode 100644 arch/arm/mach-imx/cpuidle-imx6sx.c (limited to 'arch') diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index f5ac685a29fc..8d1b10180908 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -32,8 +32,7 @@ ifeq ($(CONFIG_CPU_IDLE),y) obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o -# i.MX6SX reuses i.MX6Q cpuidle driver -obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6q.o +obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6sx.o endif ifdef CONFIG_SND_IMX_SOC diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index cfcdb623d78f..1028b6c505c4 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -70,6 +70,10 @@ void imx_set_soc_revision(unsigned int rev); unsigned int imx_get_soc_revision(void); void imx_init_revision_from_anatop(void); struct device *imx_soc_device_init(void); +void imx6_enable_rbc(bool enable); +void imx_gpc_set_arm_power_in_lpm(bool power_off); +void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw); +void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw); enum mxc_cpu_pwr_mode { WAIT_CLOCKED, /* wfi only */ diff --git a/arch/arm/mach-imx/cpuidle-imx6sx.c b/arch/arm/mach-imx/cpuidle-imx6sx.c new file mode 100644 index 000000000000..d8a9f219e028 --- /dev/null +++ b/arch/arm/mach-imx/cpuidle-imx6sx.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor, 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 +#include +#include +#include +#include +#include + +#include "common.h" +#include "cpuidle.h" + +static int imx6sx_idle_finish(unsigned long val) +{ + cpu_do_idle(); + + return 0; +} + +static int imx6sx_enter_wait(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + imx6q_set_lpm(WAIT_UNCLOCKED); + + switch (index) { + case 1: + cpu_do_idle(); + break; + case 2: + imx6_enable_rbc(true); + imx_gpc_set_arm_power_in_lpm(true); + imx_set_cpu_jump(0, v7_cpu_resume); + /* Need to notify there is a cpu pm operation. */ + cpu_pm_enter(); + cpu_cluster_pm_enter(); + + cpu_suspend(0, imx6sx_idle_finish); + + cpu_cluster_pm_exit(); + cpu_pm_exit(); + imx_gpc_set_arm_power_in_lpm(false); + imx6_enable_rbc(false); + break; + default: + break; + } + + imx6q_set_lpm(WAIT_CLOCKED); + + return index; +} + +static struct cpuidle_driver imx6sx_cpuidle_driver = { + .name = "imx6sx_cpuidle", + .owner = THIS_MODULE, + .states = { + /* WFI */ + ARM_CPUIDLE_WFI_STATE, + /* WAIT */ + { + .exit_latency = 50, + .target_residency = 75, + .flags = CPUIDLE_FLAG_TIME_VALID | + CPUIDLE_FLAG_TIMER_STOP, + .enter = imx6sx_enter_wait, + .name = "WAIT", + .desc = "Clock off", + }, + /* WAIT + ARM power off */ + { + /* + * ARM gating 31us * 5 + RBC clear 65us + * and some margin for SW execution, here set it + * to 300us. + */ + .exit_latency = 300, + .target_residency = 500, + .flags = CPUIDLE_FLAG_TIME_VALID, + .enter = imx6sx_enter_wait, + .name = "LOW-POWER-IDLE", + .desc = "ARM power off", + }, + }, + .state_count = 3, + .safe_state_index = 0, +}; + +int __init imx6sx_cpuidle_init(void) +{ + imx6_enable_rbc(false); + /* + * set ARM power up/down timing to the fastest, + * sw2iso and sw can be set to one 32K cycle = 31us + * except for power up sw2iso which need to be + * larger than LDO ramp up time. + */ + imx_gpc_set_arm_power_up_timing(2, 1); + imx_gpc_set_arm_power_down_timing(1, 1); + + return cpuidle_register(&imx6sx_cpuidle_driver, NULL); +} diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h index 24e33670417c..f9140128ba05 100644 --- a/arch/arm/mach-imx/cpuidle.h +++ b/arch/arm/mach-imx/cpuidle.h @@ -14,6 +14,7 @@ extern int imx5_cpuidle_init(void); extern int imx6q_cpuidle_init(void); extern int imx6sl_cpuidle_init(void); +extern int imx6sx_cpuidle_init(void); #else static inline int imx5_cpuidle_init(void) { @@ -27,4 +28,8 @@ static inline int imx6sl_cpuidle_init(void) { return 0; } +static inline int imx6sx_cpuidle_init(void) +{ + return 0; +} #endif diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c index 5f3602ec74fa..745caa18ab2c 100644 --- a/arch/arm/mach-imx/gpc.c +++ b/arch/arm/mach-imx/gpc.c @@ -20,6 +20,10 @@ #define GPC_IMR1 0x008 #define GPC_PGC_CPU_PDN 0x2a0 +#define GPC_PGC_CPU_PUPSCR 0x2a4 +#define GPC_PGC_CPU_PDNSCR 0x2a8 +#define GPC_PGC_SW2ISO_SHIFT 0x8 +#define GPC_PGC_SW_SHIFT 0x0 #define IMR_NUM 4 @@ -27,6 +31,23 @@ static void __iomem *gpc_base; static u32 gpc_wake_irqs[IMR_NUM]; static u32 gpc_saved_imrs[IMR_NUM]; +void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw) +{ + writel_relaxed((sw2iso << GPC_PGC_SW2ISO_SHIFT) | + (sw << GPC_PGC_SW_SHIFT), gpc_base + GPC_PGC_CPU_PUPSCR); +} + +void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw) +{ + writel_relaxed((sw2iso << GPC_PGC_SW2ISO_SHIFT) | + (sw << GPC_PGC_SW_SHIFT), gpc_base + GPC_PGC_CPU_PDNSCR); +} + +void imx_gpc_set_arm_power_in_lpm(bool power_off) +{ + writel_relaxed(power_off, gpc_base + GPC_PGC_CPU_PDN); +} + void imx_gpc_pre_suspend(bool arm_power_off) { void __iomem *reg_imr1 = gpc_base + GPC_IMR1; @@ -34,7 +55,7 @@ void imx_gpc_pre_suspend(bool arm_power_off) /* Tell GPC to power off ARM core when suspend */ if (arm_power_off) - writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN); + imx_gpc_set_arm_power_in_lpm(arm_power_off); for (i = 0; i < IMR_NUM; i++) { gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4); @@ -48,7 +69,7 @@ void imx_gpc_post_resume(void) int i; /* Keep ARM core powered on for other low-power modes */ - writel_relaxed(0x0, gpc_base + GPC_PGC_CPU_PDN); + imx_gpc_set_arm_power_in_lpm(false); for (i = 0; i < IMR_NUM; i++) writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4); diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c index 7a96c6577234..66988eb6a3a4 100644 --- a/arch/arm/mach-imx/mach-imx6sx.c +++ b/arch/arm/mach-imx/mach-imx6sx.c @@ -90,7 +90,7 @@ static void __init imx6sx_init_irq(void) static void __init imx6sx_init_late(void) { - imx6q_cpuidle_init(); + imx6sx_cpuidle_init(); if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0); diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c index 661ffcf1031e..46fd695203c7 100644 --- a/arch/arm/mach-imx/pm-imx6.c +++ b/arch/arm/mach-imx/pm-imx6.c @@ -205,7 +205,7 @@ void imx6q_set_int_mem_clk_lpm(bool enable) writel_relaxed(val, ccm_base + CGPR); } -static void imx6q_enable_rbc(bool enable) +void imx6_enable_rbc(bool enable) { u32 val; @@ -359,7 +359,7 @@ static int imx6q_pm_enter(suspend_state_t state) * RBC setting, so we do NOT need to do that here. */ if (!imx6_suspend_in_ocram_fn) - imx6q_enable_rbc(true); + imx6_enable_rbc(true); imx_gpc_pre_suspend(true); imx_anatop_pre_suspend(); /* Zzz ... */ @@ -368,7 +368,7 @@ static int imx6q_pm_enter(suspend_state_t state) imx_smp_prepare(); imx_anatop_post_resume(); imx_gpc_post_resume(); - imx6q_enable_rbc(false); + imx6_enable_rbc(false); imx6q_enable_wb(false); imx6q_set_int_mem_clk_lpm(true); imx6q_set_lpm(WAIT_CLOCKED); -- cgit v1.2.3 From dd7d2be1d2b8abb3754b19e4ebe72a4293253e4e Mon Sep 17 00:00:00 2001 From: Evgeni Dobrev Date: Sun, 28 Dec 2014 11:46:54 +0100 Subject: Kirkwood: add support for Seagate BlackArmor NAS220 This patch adds support for Seagate BlackArmor NAS220. The Seagate BlackArmor NAS 220 is a NAS system based on Marvell 88f6192. It has 32MB NAND and 128MB DRAM. It has two SATA slots, one Gigabit Ethernet port, two USB 2.0 ports, two buttons and three LEDs. There is a serial port available on the CN5 connector on the board (1 - TX, 4 - RX, 6 - GND). The only functionality still not implemented is the bi-color led on the front panel (status). Pins mpp22 and mpp23 control this led. Setting mpp22 to high and mpp23 to low results in orange color. Setting mpp22 to low and mpp23 to high results in blue color. The third led is wired to show the SATA activity on the two drives. Signed-off-by: Evgeni Dobrev Acked-by: Sebastian Hesselbarth Signed-off-by: Andrew Lunn --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/kirkwood-blackarmor-nas220.dts | 173 +++++++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 arch/arm/boot/dts/kirkwood-blackarmor-nas220.dts (limited to 'arch') diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 91bd5bd62857..6dc9c17f9ff5 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -112,6 +112,7 @@ dtb-$(CONFIG_ARCH_KEYSTONE) += k2hk-evm.dtb \ k2l-evm.dtb \ k2e-evm.dtb dtb-$(CONFIG_MACH_KIRKWOOD) += kirkwood-b3.dtb \ + kirkwood-blackarmor-nas220.dtb \ kirkwood-cloudbox.dtb \ kirkwood-d2net.dtb \ kirkwood-db-88f6281.dtb \ diff --git a/arch/arm/boot/dts/kirkwood-blackarmor-nas220.dts b/arch/arm/boot/dts/kirkwood-blackarmor-nas220.dts new file mode 100644 index 000000000000..fa02a9aff05e --- /dev/null +++ b/arch/arm/boot/dts/kirkwood-blackarmor-nas220.dts @@ -0,0 +1,173 @@ +/* + * Device Tree file for Seagate Blackarmor NAS220 + * + * Copyright (C) 2014 Evgeni Dobrev + * + * Licensed under GPLv2 or later. + */ + +/dts-v1/; + +#include +#include +#include "kirkwood.dtsi" +#include "kirkwood-6192.dtsi" + +/ { + model = "Seagate Blackarmor NAS220"; + compatible = "seagate,blackarmor-nas220","marvell,kirkwood-88f6192", + "marvell,kirkwood"; + + memory { /* 128 MB */ + device_type = "memory"; + reg = <0x00000000 0x8000000>; + }; + + chosen { + bootargs = "console=ttyS0,115200n8"; + stdout-path = &uart0; + }; + + gpio_poweroff { + compatible = "gpio-poweroff"; + gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + }; + + gpio_keys { + compatible = "gpio-keys"; + + button@1{ + label = "Reset"; + linux,code = ; + gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>; + }; + + button@2{ + label = "Power"; + linux,code = ; + gpios = <&gpio0 26 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + blue-power { + label = "nas220:blue:power"; + gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "default-on"; + }; + }; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-0 = <&pmx_power_sata0 &pmx_power_sata1>; + pinctrl-names = "default"; + + sata0_power: regulator@1 { + compatible = "regulator-fixed"; + reg = <1>; + regulator-name = "SATA0 Power"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpio = <&gpio0 24 GPIO_ACTIVE_LOW>; + }; + + sata1_power: regulator@2 { + compatible = "regulator-fixed"; + reg = <2>; + regulator-name = "SATA1 Power"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpio = <&gpio0 28 GPIO_ACTIVE_LOW>; + }; + }; +}; + +/* + * Serial port routed to connector CN5 + * + * pin 1 - TX (CPU's TX) + * pin 4 - RX (CPU's RX) + * pin 6 - GND + */ +&uart0 { + status = "okay"; +}; + +&pinctrl { + pinctrl-0 = <&pmx_button_reset &pmx_button_power>; + pinctrl-names = "default"; + + pmx_act_sata0: pmx-act-sata0 { + marvell,pins = "mpp15"; + marvell,function = "sata0"; + }; + + pmx_act_sata1: pmx-act-sata1 { + marvell,pins = "mpp16"; + marvell,function = "sata1"; + }; + + pmx_power_sata0: pmx-power-sata0 { + marvell,pins = "mpp24"; + marvell,function = "gpio"; + }; + + pmx_power_sata1: pmx-power-sata1 { + marvell,pins = "mpp28"; + marvell,function = "gpio"; + }; + + pmx_button_reset: pmx-button-reset { + marvell,pins = "mpp29"; + marvell,function = "gpio"; + }; + + pmx_button_power: pmx-button-power { + marvell,pins = "mpp26"; + marvell,function = "gpio"; + }; +}; + +&sata { + status = "okay"; + nr-ports = <2>; +}; + +&i2c0 { + status = "okay"; + + adt7476: thermal@2e { + compatible = "adi,adt7476"; + reg = <0x2e>; + }; +}; + +&nand { + status = "okay"; +}; + +&mdio { + status = "okay"; + + ethphy0: ethernet-phy@8 { + reg = <8>; + }; +}; + +ð0 { + status = "okay"; + + ethernet0-port@0 { + phy-handle = <ðphy0>; + }; +}; -- cgit v1.2.3 From 8325aa30f8ada22731276b19a72310150f30b3ec Mon Sep 17 00:00:00 2001 From: Dylan Reid Date: Thu, 2 Oct 2014 09:43:32 -0700 Subject: ARM: tegra: Enable the mic-detect gpio on Acer Chromebook 13 Enables the gpio-base mic detection on the Acer Chromebook 13. This gpio is set by the jack-detection chip when it notices either of the TRRS type headsets with a microphone. Signed-off-by: Dylan Reid Acked-by: Stephen Warren Signed-off-by: Thierry Reding --- arch/arm/boot/dts/tegra124-nyan-big.dts | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/tegra124-nyan-big.dts b/arch/arm/boot/dts/tegra124-nyan-big.dts index 53181d310247..004e8e4e1c04 100644 --- a/arch/arm/boot/dts/tegra124-nyan-big.dts +++ b/arch/arm/boot/dts/tegra124-nyan-big.dts @@ -1131,6 +1131,8 @@ clock-names = "pll_a", "pll_a_out0", "mclk"; nvidia,hp-det-gpios = <&gpio TEGRA_GPIO(I, 7) GPIO_ACTIVE_HIGH>; + nvidia,mic-det-gpios = + <&gpio TEGRA_GPIO(R, 7) GPIO_ACTIVE_HIGH>; }; }; -- cgit v1.2.3 From cbd54fe0b2bc39cf64ee2f50a22249ae1ddd37c9 Mon Sep 17 00:00:00 2001 From: Robert Nelson Date: Mon, 22 Dec 2014 11:29:21 -0600 Subject: ARM: dts: imx6dl-udoo: Add board support based off imx6q-udoo For more information about the Udoo boards: http://www.udoo.org/ Signed-off-by: Robert Nelson Reviewed-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/imx6dl-udoo.dts | 18 +++++ arch/arm/boot/dts/imx6q-udoo.dts | 124 +-------------------------------- arch/arm/boot/dts/imx6qdl-udoo.dtsi | 134 ++++++++++++++++++++++++++++++++++++ 4 files changed, 154 insertions(+), 123 deletions(-) create mode 100644 arch/arm/boot/dts/imx6dl-udoo.dts create mode 100644 arch/arm/boot/dts/imx6qdl-udoo.dtsi (limited to 'arch') diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index c0d5c6619c91..1236b8c0eb60 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -234,6 +234,7 @@ dtb-$(CONFIG_ARCH_MXC) += \ imx6dl-tx6dl-comtft.dtb \ imx6dl-tx6u-801x.dtb \ imx6dl-tx6u-811x.dtb \ + imx6dl-udoo.dtb \ imx6dl-wandboard.dtb \ imx6dl-wandboard-revb1.dtb \ imx6q-arm2.dtb \ diff --git a/arch/arm/boot/dts/imx6dl-udoo.dts b/arch/arm/boot/dts/imx6dl-udoo.dts new file mode 100644 index 000000000000..e3713f00e819 --- /dev/null +++ b/arch/arm/boot/dts/imx6dl-udoo.dts @@ -0,0 +1,18 @@ +/* + * Copyright 2013 Freescale Semiconductor, Inc. + * + * Author: Fabio Estevam + * + * 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. + * + */ +/dts-v1/; +#include "imx6dl.dtsi" +#include "imx6qdl-udoo.dtsi" + +/ { + model = "Udoo i.MX6 Dual-lite Board"; + compatible = "udoo,imx6dl-udoo", "fsl,imx6dl"; +}; diff --git a/arch/arm/boot/dts/imx6q-udoo.dts b/arch/arm/boot/dts/imx6q-udoo.dts index e3bff2ac00db..c3e64ff3d544 100644 --- a/arch/arm/boot/dts/imx6q-udoo.dts +++ b/arch/arm/boot/dts/imx6q-udoo.dts @@ -8,137 +8,15 @@ * published by the Free Software Foundation. * */ - /dts-v1/; #include "imx6q.dtsi" +#include "imx6qdl-udoo.dtsi" / { model = "Udoo i.MX6 Quad Board"; compatible = "udoo,imx6q-udoo", "fsl,imx6q"; - - chosen { - stdout-path = &uart2; - }; - - memory { - reg = <0x10000000 0x40000000>; - }; - - regulators { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <0>; - - reg_usb_h1_vbus: regulator@0 { - compatible = "regulator-fixed"; - reg = <0>; - regulator-name = "usb_h1_vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - enable-active-high; - startup-delay-us = <2>; /* USB2415 requires a POR of 1 us minimum */ - gpio = <&gpio7 12 0>; - }; - }; -}; - -&fec { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_enet>; - phy-mode = "rgmii"; - status = "okay"; -}; - -&hdmi { - ddc-i2c-bus = <&i2c2>; - status = "okay"; -}; - -&i2c2 { - clock-frequency = <100000>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_i2c2>; - status = "okay"; -}; - -&iomuxc { - imx6q-udoo { - pinctrl_enet: enetgrp { - fsl,pins = < - MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 - MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 - MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 - MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 - MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 - MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 - MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 - MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 - MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 - MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 - MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 - MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 - MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 - MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 - MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 - MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 - >; - }; - - pinctrl_i2c2: i2c2grp { - fsl,pins = < - MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 - MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 - >; - }; - - pinctrl_uart2: uart2grp { - fsl,pins = < - MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1 - MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1 - >; - }; - - pinctrl_usbh: usbhgrp { - fsl,pins = < - MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000 - MX6QDL_PAD_NANDF_CS2__CCM_CLKO2 0x130b0 - >; - }; - - pinctrl_usdhc3: usdhc3grp { - fsl,pins = < - MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 - MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 - MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 - MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 - MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 - MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 - >; - }; - }; }; &sata { status = "okay"; }; - -&uart2 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_uart2>; - status = "okay"; -}; - -&usbh1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usbh>; - vbus-supply = <®_usb_h1_vbus>; - clocks = <&clks 201>; - status = "okay"; -}; - -&usdhc3 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usdhc3>; - non-removable; - status = "okay"; -}; diff --git a/arch/arm/boot/dts/imx6qdl-udoo.dtsi b/arch/arm/boot/dts/imx6qdl-udoo.dtsi new file mode 100644 index 000000000000..1211da894ee9 --- /dev/null +++ b/arch/arm/boot/dts/imx6qdl-udoo.dtsi @@ -0,0 +1,134 @@ +/* + * Copyright 2013 Freescale Semiconductor, Inc. + * + * Author: Fabio Estevam + * + * 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. + * + */ + +/ { + chosen { + stdout-path = &uart2; + }; + + memory { + reg = <0x10000000 0x40000000>; + }; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + reg_usb_h1_vbus: regulator@0 { + compatible = "regulator-fixed"; + reg = <0>; + regulator-name = "usb_h1_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + startup-delay-us = <2>; /* USB2415 requires a POR of 1 us minimum */ + gpio = <&gpio7 12 0>; + }; + }; +}; + +&fec { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet>; + phy-mode = "rgmii"; + status = "okay"; +}; + +&hdmi { + ddc-i2c-bus = <&i2c2>; + status = "okay"; +}; + +&i2c2 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + status = "okay"; +}; + +&iomuxc { + imx6q-udoo { + pinctrl_enet: enetgrp { + fsl,pins = < + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 + MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 + >; + }; + + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1 + MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1 + >; + }; + + pinctrl_usbh: usbhgrp { + fsl,pins = < + MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x80000000 + MX6QDL_PAD_NANDF_CS2__CCM_CLKO2 0x130b0 + >; + }; + + pinctrl_usdhc3: usdhc3grp { + fsl,pins = < + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 + >; + }; + }; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + status = "okay"; +}; + +&usbh1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbh>; + vbus-supply = <®_usb_h1_vbus>; + clocks = <&clks 201>; + status = "okay"; +}; + +&usdhc3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc3>; + non-removable; + status = "okay"; +}; -- cgit v1.2.3 From c8aeb7dfe6e815906c3d9c23ce17a00e8d01b3d5 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 6 Jan 2015 20:06:16 +0800 Subject: ARM: imx: drop CPUIDLE_FLAG_TIME_VALID from cpuidle-imx6sx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As the result of commit b82b6cca4880 ("cpuidle: Invert CPUIDLE_FLAG_TIME_VALID logic"), the flag gets removed and hence we see the compile error below. CC arch/arm/mach-imx/cpuidle-imx6sx.o arch/arm/mach-imx/cpuidle-imx6sx.c:69:13: error: ‘CPUIDLE_FLAG_TIME_VALID’ undeclared here (not in a function) Since the behavior of the original flag has been the default, we can simply drop the flag now. Reported-by: kbuild test robot Signed-off-by: Shawn Guo --- arch/arm/mach-imx/cpuidle-imx6sx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/cpuidle-imx6sx.c b/arch/arm/mach-imx/cpuidle-imx6sx.c index d8a9f219e028..5a36722b089d 100644 --- a/arch/arm/mach-imx/cpuidle-imx6sx.c +++ b/arch/arm/mach-imx/cpuidle-imx6sx.c @@ -66,8 +66,7 @@ static struct cpuidle_driver imx6sx_cpuidle_driver = { { .exit_latency = 50, .target_residency = 75, - .flags = CPUIDLE_FLAG_TIME_VALID | - CPUIDLE_FLAG_TIMER_STOP, + .flags = CPUIDLE_FLAG_TIMER_STOP, .enter = imx6sx_enter_wait, .name = "WAIT", .desc = "Clock off", @@ -81,7 +80,6 @@ static struct cpuidle_driver imx6sx_cpuidle_driver = { */ .exit_latency = 300, .target_residency = 500, - .flags = CPUIDLE_FLAG_TIME_VALID, .enter = imx6sx_enter_wait, .name = "LOW-POWER-IDLE", .desc = "ARM power off", -- cgit v1.2.3 From fe07e48964c6f21020eeeb7f83e35a5bf1977a65 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 6 Jan 2015 14:10:57 +0100 Subject: ARM: tegra: Regenerate defconfig based on v3.19-rc1 Removes the following entries from the default configuration: - PM: enabled by default (via PM_SLEEP -> SUSPEND) - RESOURCE_COUNTERS: removed Signed-off-by: Thierry Reding --- arch/arm/configs/tegra_defconfig | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig index 3ea9c3377ccb..d199eb249151 100644 --- a/arch/arm/configs/tegra_defconfig +++ b/arch/arm/configs/tegra_defconfig @@ -8,7 +8,6 @@ CONFIG_CGROUPS=y CONFIG_CGROUP_DEBUG=y CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_CPUACCT=y -CONFIG_RESOURCE_COUNTERS=y CONFIG_CGROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y CONFIG_BLK_DEV_INITRD=y @@ -46,7 +45,6 @@ CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y CONFIG_CPU_IDLE=y CONFIG_VFP=y CONFIG_NEON=y -CONFIG_PM=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y -- cgit v1.2.3 From bb247d1e75e6514400c1efe7e1106e29ca9490d9 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 6 Jan 2015 10:35:26 +0800 Subject: ARM: sunxi_defconfig: Enable TOUCHSCREEN_SUN4I, CPUFREQ_DT, CPU_THERMAL This patch enables TOUCHSCREEN_SUN4I, CPUFREQ_DT, and CPU_THERMAL to enable cpufreq support with passive cpu cooling (thermal throttling) by default. Signed-off-by: Chen-Yu Tsai Acked-by: Eduardo Valentin Signed-off-by: Maxime Ripard --- arch/arm/configs/sunxi_defconfig | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig index 7a342d2780a8..46a8688bd49a 100644 --- a/arch/arm/configs/sunxi_defconfig +++ b/arch/arm/configs/sunxi_defconfig @@ -9,6 +9,8 @@ CONFIG_HIGHMEM=y CONFIG_HIGHPTE=y CONFIG_ARM_APPENDED_DTB=y CONFIG_ARM_ATAG_DTB_COMPAT=y +CONFIG_CPU_FREQ=y +CONFIG_CPUFREQ_DT=y CONFIG_VFP=y CONFIG_NEON=y CONFIG_PM=y @@ -54,6 +56,8 @@ CONFIG_STMMAC_ETH=y # CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_SUN4I=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=8 @@ -71,7 +75,8 @@ CONFIG_GPIO_SYSFS=y CONFIG_POWER_SUPPLY=y CONFIG_POWER_RESET=y CONFIG_POWER_RESET_SUN6I=y -# CONFIG_HWMON is not set +CONFIG_THERMAL=y +CONFIG_CPU_THERMAL=y CONFIG_WATCHDOG=y CONFIG_SUNXI_WATCHDOG=y CONFIG_MFD_AXP20X=y -- cgit v1.2.3 From 4c3e125df0d47c2a737993f077e662a0495e23c9 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 6 Jan 2015 10:35:27 +0800 Subject: ARM: multi_v7_defconfig: Enable TOUCHSCREEN_SUN4I, CPU_THERMAL This patch enables TOUCHSCREEN_SUN4I and CPU_THERMAL to enable cpufreq support with passive cpu cooling (thermal throttling) on sunxi by default. Signed-off-by: Chen-Yu Tsai Acked-by: Eduardo Valentin Signed-off-by: Maxime Ripard --- arch/arm/configs/multi_v7_defconfig | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 2328fe752e9c..0e7159ad269b 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -189,6 +189,7 @@ CONFIG_MOUSE_PS2_ELANTECH=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_ATMEL_MXT=y CONFIG_TOUCHSCREEN_STMPE=y +CONFIG_TOUCHSCREEN_SUN4I=y CONFIG_INPUT_MISC=y CONFIG_INPUT_MPU3050=y CONFIG_SERIO_AMBAKMI=y @@ -267,6 +268,7 @@ CONFIG_POWER_RESET_SUN6I=y CONFIG_SENSORS_LM90=y CONFIG_SENSORS_LM95245=y CONFIG_THERMAL=y +CONFIG_CPU_THERMAL=y CONFIG_ARMADA_THERMAL=y CONFIG_ST_THERMAL_SYSCFG=y CONFIG_ST_THERMAL_MEMMAP=y -- cgit v1.2.3 From 314fcb230cad7eea311f065f20f03ed9d08d8edf Mon Sep 17 00:00:00 2001 From: Carlo Caione Date: Tue, 23 Dec 2014 10:53:13 +0800 Subject: ARM: sunxi: Add AXP20x support in defconfig Signed-off-by: Carlo Caione Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/configs/sunxi_defconfig | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig index 46a8688bd49a..38840a812924 100644 --- a/arch/arm/configs/sunxi_defconfig +++ b/arch/arm/configs/sunxi_defconfig @@ -56,6 +56,8 @@ CONFIG_STMMAC_ETH=y # CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_MISC=y +CONFIG_INPUT_AXP20X_PEK=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_SUN4I=y CONFIG_SERIAL_8250=y @@ -82,6 +84,7 @@ CONFIG_SUNXI_WATCHDOG=y CONFIG_MFD_AXP20X=y CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_AXP20X=y CONFIG_REGULATOR_GPIO=y CONFIG_USB=y CONFIG_USB_EHCI_HCD=y -- cgit v1.2.3 From fef3f0dde681a32f148b765ee8e1465fba9b3cd4 Mon Sep 17 00:00:00 2001 From: Carlo Caione Date: Tue, 23 Dec 2014 10:53:14 +0800 Subject: ARM: sunxi: Add AXP20x support multi_v7_defconfig Signed-off-by: Carlo Caione Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/configs/multi_v7_defconfig | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 0e7159ad269b..65ca0e72882e 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -192,6 +192,7 @@ CONFIG_TOUCHSCREEN_STMPE=y CONFIG_TOUCHSCREEN_SUN4I=y CONFIG_INPUT_MISC=y CONFIG_INPUT_MPU3050=y +CONFIG_INPUT_AXP20X_PEK=y CONFIG_SERIO_AMBAKMI=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y @@ -280,6 +281,7 @@ CONFIG_SUNXI_WATCHDOG=y CONFIG_MESON_WATCHDOG=y CONFIG_MFD_AS3722=y CONFIG_MFD_BCM590XX=y +CONFIG_MFD_AXP20X=y CONFIG_MFD_CROS_EC=y CONFIG_MFD_CROS_EC_SPI=y CONFIG_MFD_MAX77686=y @@ -292,6 +294,7 @@ CONFIG_MFD_TPS6586X=y CONFIG_MFD_TPS65910=y CONFIG_REGULATOR_AB8500=y CONFIG_REGULATOR_AS3722=y +CONFIG_REGULATOR_AXP20X=y CONFIG_REGULATOR_BCM590XX=y CONFIG_REGULATOR_GPIO=y CONFIG_MFD_SYSCON=y -- cgit v1.2.3 From 83fe27ea531161a655f02dc7732d14cfaa27fd5d Mon Sep 17 00:00:00 2001 From: Pranith Kumar Date: Fri, 5 Dec 2014 11:24:45 -0500 Subject: rcu: Make SRCU optional by using CONFIG_SRCU SRCU is not necessary to be compiled by default in all cases. For tinification efforts not compiling SRCU unless necessary is desirable. The current patch tries to make compiling SRCU optional by introducing a new Kconfig option CONFIG_SRCU which is selected when any of the components making use of SRCU are selected. If we do not select CONFIG_SRCU, srcu.o will not be compiled at all. text data bss dec hex filename 2007 0 0 2007 7d7 kernel/rcu/srcu.o Size of arch/powerpc/boot/zImage changes from text data bss dec hex filename 831552 64180 23944 919676 e087c arch/powerpc/boot/zImage : before 829504 64180 23952 917636 e0084 arch/powerpc/boot/zImage : after so the savings are about ~2000 bytes. Signed-off-by: Pranith Kumar CC: Paul E. McKenney CC: Josh Triplett CC: Lai Jiangshan Signed-off-by: Paul E. McKenney [ paulmck: resolve conflict due to removal of arch/ia64/kvm/Kconfig. ] --- arch/arm/kvm/Kconfig | 1 + arch/arm64/kvm/Kconfig | 1 + arch/mips/kvm/Kconfig | 1 + arch/powerpc/kvm/Kconfig | 1 + arch/s390/kvm/Kconfig | 1 + arch/tile/kvm/Kconfig | 1 + arch/x86/Kconfig | 1 + arch/x86/kvm/Kconfig | 1 + 8 files changed, 8 insertions(+) (limited to 'arch') diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig index 466bd299b1a8..3afee5f40f4f 100644 --- a/arch/arm/kvm/Kconfig +++ b/arch/arm/kvm/Kconfig @@ -23,6 +23,7 @@ config KVM select HAVE_KVM_CPU_RELAX_INTERCEPT select KVM_MMIO select KVM_ARM_HOST + select SRCU depends on ARM_VIRT_EXT && ARM_LPAE ---help--- Support hosting virtualized guest machines. You will also diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig index 8ba85e9ea388..b334084d3675 100644 --- a/arch/arm64/kvm/Kconfig +++ b/arch/arm64/kvm/Kconfig @@ -26,6 +26,7 @@ config KVM select KVM_ARM_HOST select KVM_ARM_VGIC select KVM_ARM_TIMER + select SRCU ---help--- Support hosting virtualized guest machines. diff --git a/arch/mips/kvm/Kconfig b/arch/mips/kvm/Kconfig index 30e334e823bd..2ae12825529f 100644 --- a/arch/mips/kvm/Kconfig +++ b/arch/mips/kvm/Kconfig @@ -20,6 +20,7 @@ config KVM select PREEMPT_NOTIFIERS select ANON_INODES select KVM_MMIO + select SRCU ---help--- Support for hosting Guest kernels. Currently supported on MIPS32 processors. diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig index f5769f19ae25..11850f310fb4 100644 --- a/arch/powerpc/kvm/Kconfig +++ b/arch/powerpc/kvm/Kconfig @@ -21,6 +21,7 @@ config KVM select PREEMPT_NOTIFIERS select ANON_INODES select HAVE_KVM_EVENTFD + select SRCU config KVM_BOOK3S_HANDLER bool diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig index 646db9c467d1..5fce52cf0e57 100644 --- a/arch/s390/kvm/Kconfig +++ b/arch/s390/kvm/Kconfig @@ -28,6 +28,7 @@ config KVM select HAVE_KVM_IRQCHIP select HAVE_KVM_IRQFD select HAVE_KVM_IRQ_ROUTING + select SRCU ---help--- Support hosting paravirtualized guest machines using the SIE virtualization capability on the mainframe. This should work diff --git a/arch/tile/kvm/Kconfig b/arch/tile/kvm/Kconfig index 2298cb1daff7..1e968f7550dc 100644 --- a/arch/tile/kvm/Kconfig +++ b/arch/tile/kvm/Kconfig @@ -21,6 +21,7 @@ config KVM depends on HAVE_KVM && MODULES select PREEMPT_NOTIFIERS select ANON_INODES + select SRCU ---help--- Support hosting paravirtualized guest machines. diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index ba397bde7948..661269953c1a 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -138,6 +138,7 @@ config X86 select HAVE_ACPI_APEI_NMI if ACPI select ACPI_LEGACY_TABLES_LOOKUP if ACPI select X86_FEATURE_NAMES if PROC_FS + select SRCU config INSTRUCTION_DECODER def_bool y diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index f9d16ff56c6b..7dc7ba577ecd 100644 --- a/arch/x86/kvm/Kconfig +++ b/arch/x86/kvm/Kconfig @@ -40,6 +40,7 @@ config KVM select HAVE_KVM_MSI select HAVE_KVM_CPU_RELAX_INTERCEPT select KVM_VFIO + select SRCU ---help--- Support hosting fully virtualized guest machines using hardware virtualization extensions. You will need a fairly recent -- cgit v1.2.3 From f91b7c62e0cdb8a1a72b61b16fcd48858a7d9193 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 6 Jan 2015 10:35:11 +0800 Subject: ARM: sunxi: Register cpufreq-dt for sun[45678]i On sun[45678]i, we have one cluster of identical cores sharing a clock, which is ideal for using cpufreq-dt. Register a platform device for cpufreq-dt. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm/mach-sunxi/sunxi.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c index d4bb2395d39c..1bc811a74a9f 100644 --- a/arch/arm/mach-sunxi/sunxi.c +++ b/arch/arm/mach-sunxi/sunxi.c @@ -13,9 +13,15 @@ #include #include #include +#include #include +static void __init sunxi_dt_cpufreq_init(void) +{ + platform_device_register_simple("cpufreq-dt", -1, NULL, 0); +} + static const char * const sunxi_board_dt_compat[] = { "allwinner,sun4i-a10", "allwinner,sun5i-a10s", @@ -25,6 +31,7 @@ static const char * const sunxi_board_dt_compat[] = { DT_MACHINE_START(SUNXI_DT, "Allwinner A1X (Device Tree)") .dt_compat = sunxi_board_dt_compat, + .init_late = sunxi_dt_cpufreq_init, MACHINE_END static const char * const sun6i_board_dt_compat[] = { @@ -45,6 +52,7 @@ static void __init sun6i_timer_init(void) DT_MACHINE_START(SUN6I_DT, "Allwinner sun6i (A31) Family") .init_time = sun6i_timer_init, .dt_compat = sun6i_board_dt_compat, + .init_late = sunxi_dt_cpufreq_init, MACHINE_END static const char * const sun7i_board_dt_compat[] = { @@ -54,6 +62,7 @@ static const char * const sun7i_board_dt_compat[] = { DT_MACHINE_START(SUN7I_DT, "Allwinner sun7i (A20) Family") .dt_compat = sun7i_board_dt_compat, + .init_late = sunxi_dt_cpufreq_init, MACHINE_END static const char * const sun8i_board_dt_compat[] = { @@ -63,6 +72,7 @@ static const char * const sun8i_board_dt_compat[] = { DT_MACHINE_START(SUN8I_DT, "Allwinner sun8i (A23) Family") .dt_compat = sun8i_board_dt_compat, + .init_late = sunxi_dt_cpufreq_init, MACHINE_END static const char * const sun9i_board_dt_compat[] = { -- cgit v1.2.3 From 6341e62b212a2541efb0160c470e90bd226d5496 Mon Sep 17 00:00:00 2001 From: Christoph Jaeger Date: Sat, 20 Dec 2014 15:41:11 -0500 Subject: kconfig: use bool instead of boolean for type definition attributes Support for keyword 'boolean' will be dropped later on. No functional change. Reference: http://lkml.kernel.org/r/cover.1418003065.git.cj@linux.com Signed-off-by: Christoph Jaeger Signed-off-by: Michal Marek --- arch/mips/pmcs-msp71xx/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mips/pmcs-msp71xx/Kconfig b/arch/mips/pmcs-msp71xx/Kconfig index 6073ca456d11..4190093d3053 100644 --- a/arch/mips/pmcs-msp71xx/Kconfig +++ b/arch/mips/pmcs-msp71xx/Kconfig @@ -36,14 +36,14 @@ config PMC_MSP7120_FPGA endchoice config MSP_HAS_USB - boolean + bool depends on PMC_MSP config MSP_ETH - boolean + bool select MSP_HAS_MAC depends on PMC_MSP config MSP_HAS_MAC - boolean + bool depends on PMC_MSP -- cgit v1.2.3 From d4ce8042bf736aee0f60e5165adacd0f6bfafbb4 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Fri, 26 Dec 2014 16:57:59 +0800 Subject: ARM: dts: berlin: add pmu node for BG2Q and BG2CD This patch adds the pmu node, enabling the PMU unit on Marvell BG2Q and BG2CD SoCs. Signed-off-by: Jisheng Zhang Signed-off-by: Sebastian Hesselbarth --- arch/arm/boot/dts/berlin2cd.dtsi | 5 +++++ arch/arm/boot/dts/berlin2q.dtsi | 8 ++++++++ 2 files changed, 13 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/berlin2cd.dtsi b/arch/arm/boot/dts/berlin2cd.dtsi index 230df3b1770e..a318bc32dc17 100644 --- a/arch/arm/boot/dts/berlin2cd.dtsi +++ b/arch/arm/boot/dts/berlin2cd.dtsi @@ -45,6 +45,11 @@ ranges = <0 0xf7000000 0x1000000>; + pmu { + compatible = "arm,cortex-a9-pmu"; + interrupts = ; + }; + sdhci0: sdhci@ab0000 { compatible = "mrvl,pxav3-mmc"; reg = <0xab0000 0x200>; diff --git a/arch/arm/boot/dts/berlin2q.dtsi b/arch/arm/boot/dts/berlin2q.dtsi index 35253c947a7c..933dcbbcfc5d 100644 --- a/arch/arm/boot/dts/berlin2q.dtsi +++ b/arch/arm/boot/dts/berlin2q.dtsi @@ -63,6 +63,14 @@ ranges = <0 0xf7000000 0x1000000>; interrupt-parent = <&gic>; + pmu { + compatible = "arm,cortex-a9-pmu"; + interrupts = , + , + , + ; + }; + sdhci0: sdhci@ab0000 { compatible = "mrvl,pxav3-mmc"; reg = <0xab0000 0x200>; -- cgit v1.2.3 From 2356d2f3d1b742dacdeb1b0a038ec17f7cc2947f Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Fri, 26 Dec 2014 16:58:00 +0800 Subject: ARM: dts: berlin: add PPI cpu mask to twd timer interrupts According to the gic binding document, "bits[15:8] PPI interrupt cpu mask. Each bit corresponds to each of the 8 possible cpus attached to the GIC. A bit set to '1' indicated the interrupt is wired to that CPU." This patch wants to add the PPI cpu mask for completeness. Signed-off-by: Jisheng Zhang Signed-off-by: Sebastian Hesselbarth --- arch/arm/boot/dts/berlin2.dtsi | 2 +- arch/arm/boot/dts/berlin2cd.dtsi | 2 +- arch/arm/boot/dts/berlin2q.dtsi | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/berlin2.dtsi b/arch/arm/boot/dts/berlin2.dtsi index 015a06c67c91..63d00a63cfa6 100644 --- a/arch/arm/boot/dts/berlin2.dtsi +++ b/arch/arm/boot/dts/berlin2.dtsi @@ -104,7 +104,7 @@ local-timer@ad0600 { compatible = "arm,cortex-a9-twd-timer"; reg = <0xad0600 0x20>; - interrupts = ; + interrupts = ; clocks = <&chip CLKID_TWD>; }; diff --git a/arch/arm/boot/dts/berlin2cd.dtsi b/arch/arm/boot/dts/berlin2cd.dtsi index a318bc32dc17..81b670ac494a 100644 --- a/arch/arm/boot/dts/berlin2cd.dtsi +++ b/arch/arm/boot/dts/berlin2cd.dtsi @@ -76,7 +76,7 @@ local-timer@ad0600 { compatible = "arm,cortex-a9-twd-timer"; reg = <0xad0600 0x20>; - interrupts = ; + interrupts = ; clocks = <&chip CLKID_TWD>; }; diff --git a/arch/arm/boot/dts/berlin2q.dtsi b/arch/arm/boot/dts/berlin2q.dtsi index 933dcbbcfc5d..41a683fd079c 100644 --- a/arch/arm/boot/dts/berlin2q.dtsi +++ b/arch/arm/boot/dts/berlin2q.dtsi @@ -112,7 +112,7 @@ compatible = "arm,cortex-a9-twd-timer"; reg = <0xad0600 0x20>; clocks = <&chip CLKID_TWD>; - interrupts = ; + interrupts = ; }; gic: interrupt-controller@ad1000 { -- cgit v1.2.3 From de47699d005996b41cea590c6098078ac12058be Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Fri, 12 Dec 2014 18:19:19 +0300 Subject: ARM: dts: tegra20: fix GR3D, DSI unit and reg base addresses Commit 58ecb23f64ee ("ARM: tegra: add missing unit addresses to DT") added unit address and changed reg base for GR3D and DSI host1x modules, but these addresses belongs to GR2D and TVO modules respectively. Fix it by changing modules unit and reg base addresses to proper ones. Signed-off-by: Dmitry Osipenko Fixes: 58ecb23f64ee (ARM: tegra: add missing unit addresses to DT) Cc: # v3.13+ Reviewed-by: Alexandre Courbot Signed-off-by: Thierry Reding --- arch/arm/boot/dts/tegra20.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index 8acf5d85c99d..f76fe94267d6 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi @@ -68,9 +68,9 @@ reset-names = "2d"; }; - gr3d@54140000 { + gr3d@54180000 { compatible = "nvidia,tegra20-gr3d"; - reg = <0x54140000 0x00040000>; + reg = <0x54180000 0x00040000>; clocks = <&tegra_car TEGRA20_CLK_GR3D>; resets = <&tegra_car 24>; reset-names = "3d"; @@ -130,9 +130,9 @@ status = "disabled"; }; - dsi@542c0000 { + dsi@54300000 { compatible = "nvidia,tegra20-dsi"; - reg = <0x542c0000 0x00040000>; + reg = <0x54300000 0x00040000>; clocks = <&tegra_car TEGRA20_CLK_DSI>; resets = <&tegra_car 48>; reset-names = "dsi"; -- cgit v1.2.3 From d4812e169de44f4ab53ff671c6193c67de24da62 Mon Sep 17 00:00:00 2001 From: "Luck, Tony" Date: Mon, 5 Jan 2015 16:44:42 -0800 Subject: x86, mce: Get rid of TIF_MCE_NOTIFY and associated mce tricks We now switch to the kernel stack when a machine check interrupts during user mode. This means that we can perform recovery actions in the tail of do_machine_check() Acked-by: Borislav Petkov Signed-off-by: Tony Luck Signed-off-by: Andy Lutomirski --- arch/x86/include/asm/mce.h | 1 - arch/x86/include/asm/thread_info.h | 4 +- arch/x86/kernel/cpu/mcheck/mce.c | 109 +++++++++---------------------------- arch/x86/kernel/signal.c | 6 -- 4 files changed, 26 insertions(+), 94 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index 51b26e895933..9b3de99dc004 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h @@ -190,7 +190,6 @@ enum mcp_flags { void machine_check_poll(enum mcp_flags flags, mce_banks_t *b); int mce_notify_irq(void); -void mce_notify_process(void); DECLARE_PER_CPU(struct mce, injectm); diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index 8b13b0fbda8e..e82e95abc92b 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -75,7 +75,6 @@ struct thread_info { #define TIF_SYSCALL_EMU 6 /* syscall emulation active */ #define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */ #define TIF_SECCOMP 8 /* secure computing */ -#define TIF_MCE_NOTIFY 10 /* notify userspace of an MCE */ #define TIF_USER_RETURN_NOTIFY 11 /* notify kernel of userspace return */ #define TIF_UPROBE 12 /* breakpointed or singlestepping */ #define TIF_NOTSC 16 /* TSC is not accessible in userland */ @@ -100,7 +99,6 @@ struct thread_info { #define _TIF_SYSCALL_EMU (1 << TIF_SYSCALL_EMU) #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) #define _TIF_SECCOMP (1 << TIF_SECCOMP) -#define _TIF_MCE_NOTIFY (1 << TIF_MCE_NOTIFY) #define _TIF_USER_RETURN_NOTIFY (1 << TIF_USER_RETURN_NOTIFY) #define _TIF_UPROBE (1 << TIF_UPROBE) #define _TIF_NOTSC (1 << TIF_NOTSC) @@ -140,7 +138,7 @@ struct thread_info { /* Only used for 64 bit */ #define _TIF_DO_NOTIFY_MASK \ - (_TIF_SIGPENDING | _TIF_MCE_NOTIFY | _TIF_NOTIFY_RESUME | \ + (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | \ _TIF_USER_RETURN_NOTIFY | _TIF_UPROBE) /* flags to check in __switch_to() */ diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 800d423f1e92..d23179900755 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -1003,51 +1003,6 @@ static void mce_clear_state(unsigned long *toclear) } } -/* - * Need to save faulting physical address associated with a process - * in the machine check handler some place where we can grab it back - * later in mce_notify_process() - */ -#define MCE_INFO_MAX 16 - -struct mce_info { - atomic_t inuse; - struct task_struct *t; - __u64 paddr; - int restartable; -} mce_info[MCE_INFO_MAX]; - -static void mce_save_info(__u64 addr, int c) -{ - struct mce_info *mi; - - for (mi = mce_info; mi < &mce_info[MCE_INFO_MAX]; mi++) { - if (atomic_cmpxchg(&mi->inuse, 0, 1) == 0) { - mi->t = current; - mi->paddr = addr; - mi->restartable = c; - return; - } - } - - mce_panic("Too many concurrent recoverable errors", NULL, NULL); -} - -static struct mce_info *mce_find_info(void) -{ - struct mce_info *mi; - - for (mi = mce_info; mi < &mce_info[MCE_INFO_MAX]; mi++) - if (atomic_read(&mi->inuse) && mi->t == current) - return mi; - return NULL; -} - -static void mce_clear_info(struct mce_info *mi) -{ - atomic_set(&mi->inuse, 0); -} - /* * The actual machine check handler. This only handles real * exceptions when something got corrupted coming in through int 18. @@ -1086,6 +1041,8 @@ void do_machine_check(struct pt_regs *regs, long error_code) DECLARE_BITMAP(toclear, MAX_NR_BANKS); DECLARE_BITMAP(valid_banks, MAX_NR_BANKS); char *msg = "Unknown"; + u64 recover_paddr = ~0ull; + int flags = MF_ACTION_REQUIRED; prev_state = ist_enter(regs); @@ -1207,9 +1164,9 @@ void do_machine_check(struct pt_regs *regs, long error_code) if (no_way_out) mce_panic("Fatal machine check on current CPU", &m, msg); if (worst == MCE_AR_SEVERITY) { - /* schedule action before return to userland */ - mce_save_info(m.addr, m.mcgstatus & MCG_STATUS_RIPV); - set_thread_flag(TIF_MCE_NOTIFY); + recover_paddr = m.addr; + if (!(m.mcgstatus & MCG_STATUS_RIPV)) + flags |= MF_MUST_KILL; } else if (kill_it) { force_sig(SIGBUS, current); } @@ -1220,6 +1177,26 @@ void do_machine_check(struct pt_regs *regs, long error_code) mce_wrmsrl(MSR_IA32_MCG_STATUS, 0); out: sync_core(); + + if (recover_paddr == ~0ull) + goto done; + + pr_err("Uncorrected hardware memory error in user-access at %llx", + recover_paddr); + /* + * We must call memory_failure() here even if the current process is + * doomed. We still need to mark the page as poisoned and alert any + * other users of the page. + */ + ist_begin_non_atomic(regs); + local_irq_enable(); + if (memory_failure(recover_paddr >> PAGE_SHIFT, MCE_VECTOR, flags) < 0) { + pr_err("Memory error not recovered"); + force_sig(SIGBUS, current); + } + local_irq_disable(); + ist_end_non_atomic(); +done: ist_exit(regs, prev_state); } EXPORT_SYMBOL_GPL(do_machine_check); @@ -1237,42 +1214,6 @@ int memory_failure(unsigned long pfn, int vector, int flags) } #endif -/* - * Called in process context that interrupted by MCE and marked with - * TIF_MCE_NOTIFY, just before returning to erroneous userland. - * This code is allowed to sleep. - * Attempt possible recovery such as calling the high level VM handler to - * process any corrupted pages, and kill/signal current process if required. - * Action required errors are handled here. - */ -void mce_notify_process(void) -{ - unsigned long pfn; - struct mce_info *mi = mce_find_info(); - int flags = MF_ACTION_REQUIRED; - - if (!mi) - mce_panic("Lost physical address for unconsumed uncorrectable error", NULL, NULL); - pfn = mi->paddr >> PAGE_SHIFT; - - clear_thread_flag(TIF_MCE_NOTIFY); - - pr_err("Uncorrected hardware memory error in user-access at %llx", - mi->paddr); - /* - * We must call memory_failure() here even if the current process is - * doomed. We still need to mark the page as poisoned and alert any - * other users of the page. - */ - if (!mi->restartable) - flags |= MF_MUST_KILL; - if (memory_failure(pfn, MCE_VECTOR, flags) < 0) { - pr_err("Memory error not recovered"); - force_sig(SIGBUS, current); - } - mce_clear_info(mi); -} - /* * Action optional processing happens here (picking up * from the list of faulting pages that do_machine_check() diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index ed37a768d0fc..2a33c8f68319 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -740,12 +740,6 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) { user_exit(); -#ifdef CONFIG_X86_MCE - /* notify userspace of pending MCEs */ - if (thread_info_flags & _TIF_MCE_NOTIFY) - mce_notify_process(); -#endif /* CONFIG_X86_64 && CONFIG_X86_MCE */ - if (thread_info_flags & _TIF_UPROBE) uprobe_notify_resume(regs); -- cgit v1.2.3 From 4b2171876b6e93f32ad0576a07d823783ccd1f16 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 7 Dec 2014 22:49:34 +0100 Subject: ARM: OMAP2+: clkt2xxx_apll.c: Remove some unused functions Removes some functions that are not used anywhere: omap2_clk_apll54_disable() omap2_clk_apll96_disable() omap2_clk_apll54_enable() omap2_clk_apll96_enable() omap2xxx_get_apll_clkin() omap2_clk_apll96_recalc() omap2_clk_apll54_recalc() This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist [tony@atomide.com: updated to fix a build warning] Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/clkt2xxx_apll.c | 71 ------------------------------------- arch/arm/mach-omap2/clock2xxx.h | 9 ----- 2 files changed, 80 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/clkt2xxx_apll.c b/arch/arm/mach-omap2/clkt2xxx_apll.c index c78e893eba7d..02cb08875326 100644 --- a/arch/arm/mach-omap2/clkt2xxx_apll.c +++ b/arch/arm/mach-omap2/clkt2xxx_apll.c @@ -38,35 +38,6 @@ /* Private functions */ -/** - * omap2xxx_clk_apll_locked - is the APLL locked? - * @hw: struct clk_hw * of the APLL to check - * - * If the APLL IP block referred to by @hw indicates that it's locked, - * return true; otherwise, return false. - */ -static bool omap2xxx_clk_apll_locked(struct clk_hw *hw) -{ - struct clk_hw_omap *clk = to_clk_hw_omap(hw); - u32 r, apll_mask; - - apll_mask = EN_APLL_LOCKED << clk->enable_bit; - - r = omap2xxx_cm_get_pll_status(); - - return ((r & apll_mask) == apll_mask) ? true : false; -} - -int omap2_clk_apll96_enable(struct clk_hw *hw) -{ - return omap2xxx_cm_apll96_enable(); -} - -int omap2_clk_apll54_enable(struct clk_hw *hw) -{ - return omap2xxx_cm_apll54_enable(); -} - static void _apll96_allow_idle(struct clk_hw_omap *clk) { omap2xxx_cm_set_apll96_auto_low_power_stop(); @@ -87,28 +58,6 @@ static void _apll54_deny_idle(struct clk_hw_omap *clk) omap2xxx_cm_set_apll54_disable_autoidle(); } -void omap2_clk_apll96_disable(struct clk_hw *hw) -{ - omap2xxx_cm_apll96_disable(); -} - -void omap2_clk_apll54_disable(struct clk_hw *hw) -{ - omap2xxx_cm_apll54_disable(); -} - -unsigned long omap2_clk_apll54_recalc(struct clk_hw *hw, - unsigned long parent_rate) -{ - return (omap2xxx_clk_apll_locked(hw)) ? 54000000 : 0; -} - -unsigned long omap2_clk_apll96_recalc(struct clk_hw *hw, - unsigned long parent_rate) -{ - return (omap2xxx_clk_apll_locked(hw)) ? 96000000 : 0; -} - /* Public data */ const struct clk_hw_omap_ops clkhwops_apll54 = { .allow_idle = _apll54_allow_idle, @@ -120,23 +69,3 @@ const struct clk_hw_omap_ops clkhwops_apll96 = { .deny_idle = _apll96_deny_idle, }; -/* Public functions */ - -u32 omap2xxx_get_apll_clkin(void) -{ - u32 aplls, srate = 0; - - aplls = omap2xxx_cm_get_pll_config(); - aplls &= OMAP24XX_APLLS_CLKIN_MASK; - aplls >>= OMAP24XX_APLLS_CLKIN_SHIFT; - - if (aplls == APLLS_CLKIN_19_2MHZ) - srate = 19200000; - else if (aplls == APLLS_CLKIN_13MHZ) - srate = 13000000; - else if (aplls == APLLS_CLKIN_12MHZ) - srate = 12000000; - - return srate; -} - diff --git a/arch/arm/mach-omap2/clock2xxx.h b/arch/arm/mach-omap2/clock2xxx.h index a090225ceeba..364a4cc7f11b 100644 --- a/arch/arm/mach-omap2/clock2xxx.h +++ b/arch/arm/mach-omap2/clock2xxx.h @@ -22,12 +22,7 @@ unsigned long omap2xxx_sys_clk_recalc(struct clk_hw *clk, unsigned long omap2_osc_clk_recalc(struct clk_hw *clk, unsigned long parent_rate); void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw); -unsigned long omap2_clk_apll54_recalc(struct clk_hw *hw, - unsigned long parent_rate); -unsigned long omap2_clk_apll96_recalc(struct clk_hw *hw, - unsigned long parent_rate); unsigned long omap2xxx_clk_get_core_rate(void); -u32 omap2xxx_get_apll_clkin(void); u32 omap2xxx_get_sysclkdiv(void); void omap2xxx_clk_prepare_for_reboot(void); void omap2xxx_clkt_vps_check_bootloader_rates(void); @@ -48,9 +43,5 @@ int omap2430_clk_init(void); extern struct clk_hw *dclk_hw; int omap2_enable_osc_ck(struct clk_hw *hw); void omap2_disable_osc_ck(struct clk_hw *hw); -int omap2_clk_apll96_enable(struct clk_hw *hw); -int omap2_clk_apll54_enable(struct clk_hw *hw); -void omap2_clk_apll96_disable(struct clk_hw *hw); -void omap2_clk_apll54_disable(struct clk_hw *hw); #endif -- cgit v1.2.3 From 40fd5106948004092a61a24fb1ceadd17f6cd74a Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 7 Dec 2014 23:27:38 +0100 Subject: ARM: OMAP2+: cm33xx.c: Remove some unused functions Removes some functions that are not used anywhere: am33xx_cm_read_reg_bits() am33xx_cm_clear_reg_bits() am33xx_cm_set_reg_bits() This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/cm33xx.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/cm33xx.c b/arch/arm/mach-omap2/cm33xx.c index b9ad463a368a..cc5aac784278 100644 --- a/arch/arm/mach-omap2/cm33xx.c +++ b/arch/arm/mach-omap2/cm33xx.c @@ -72,27 +72,6 @@ static inline u32 am33xx_cm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx) return v; } -static inline u32 am33xx_cm_set_reg_bits(u32 bits, s16 inst, s16 idx) -{ - return am33xx_cm_rmw_reg_bits(bits, bits, inst, idx); -} - -static inline u32 am33xx_cm_clear_reg_bits(u32 bits, s16 inst, s16 idx) -{ - return am33xx_cm_rmw_reg_bits(bits, 0x0, inst, idx); -} - -static inline u32 am33xx_cm_read_reg_bits(u16 inst, s16 idx, u32 mask) -{ - u32 v; - - v = am33xx_cm_read_reg(inst, idx); - v &= mask; - v >>= __ffs(mask); - - return v; -} - /** * _clkctrl_idlest - read a CM_*_CLKCTRL register; mask & shift IDLEST bitfield * @inst: CM instance register offset (*_INST macro) -- cgit v1.2.3 From cecec93df8be3a2ad49b3fb519fa37dba357843e Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 7 Dec 2014 23:30:13 +0100 Subject: ARM: OMAP2+: dpll44xx.c: Remove unused function Remove the function omap4_dpllmx_gatectrl_read() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/clock.h | 1 - arch/arm/mach-omap2/dpll44xx.c | 20 -------------------- 2 files changed, 21 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index a4282e79143e..1cf9dd85248a 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -177,7 +177,6 @@ struct clksel { u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk); void omap3_dpll_allow_idle(struct clk_hw_omap *clk); void omap3_dpll_deny_idle(struct clk_hw_omap *clk); -int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk); void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk); void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk); diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c index 0e58e5a85d53..fc712240e5fd 100644 --- a/arch/arm/mach-omap2/dpll44xx.c +++ b/arch/arm/mach-omap2/dpll44xx.c @@ -36,26 +36,6 @@ /* Static rate multiplier for OMAP4 REGM4XEN clocks */ #define OMAP4430_REGM4XEN_MULT 4 -/* Supported only on OMAP4 */ -int omap4_dpllmx_gatectrl_read(struct clk_hw_omap *clk) -{ - u32 v; - u32 mask; - - if (!clk || !clk->clksel_reg) - return -EINVAL; - - mask = clk->flags & CLOCK_CLKOUTX2 ? - OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK : - OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK; - - v = omap2_clk_readl(clk, clk->clksel_reg); - v &= mask; - v >>= __ffs(mask); - - return v; -} - void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk) { u32 v; -- cgit v1.2.3 From 1bbc360bb7eb7c40d074c9279b3cff20755131ef Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 7 Dec 2014 18:24:07 +0100 Subject: ARM: OMAP2+: omap_hwmod.c: Remove some unused functions Removes some functions that are not used anywhere: omap_hwmod_pad_route_irq() omap_hwmod_no_setup_reset() omap_hwmod_read_hardreset() omap_hwmod_del_initiator_dep() omap_hwmod_enable_clocks() omap_hwmod_reset() omap_hwmod_ocp_barrier() omap_hwmod_disable_clocks() omap_hwmod_add_initiator_dep() This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap_hwmod.c | 232 --------------------------------------- arch/arm/mach-omap2/omap_hwmod.h | 16 --- 2 files changed, 248 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index cbb908dc5cf0..e341e5dfff2d 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -3384,91 +3384,6 @@ int omap_hwmod_shutdown(struct omap_hwmod *oh) return 0; } -/** - * omap_hwmod_enable_clocks - enable main_clk, all interface clocks - * @oh: struct omap_hwmod *oh - * - * Intended to be called by the omap_device code. - */ -int omap_hwmod_enable_clocks(struct omap_hwmod *oh) -{ - unsigned long flags; - - spin_lock_irqsave(&oh->_lock, flags); - _enable_clocks(oh); - spin_unlock_irqrestore(&oh->_lock, flags); - - return 0; -} - -/** - * omap_hwmod_disable_clocks - disable main_clk, all interface clocks - * @oh: struct omap_hwmod *oh - * - * Intended to be called by the omap_device code. - */ -int omap_hwmod_disable_clocks(struct omap_hwmod *oh) -{ - unsigned long flags; - - spin_lock_irqsave(&oh->_lock, flags); - _disable_clocks(oh); - spin_unlock_irqrestore(&oh->_lock, flags); - - return 0; -} - -/** - * omap_hwmod_ocp_barrier - wait for posted writes against the hwmod to complete - * @oh: struct omap_hwmod *oh - * - * Intended to be called by drivers and core code when all posted - * writes to a device must complete before continuing further - * execution (for example, after clearing some device IRQSTATUS - * register bits) - * - * XXX what about targets with multiple OCP threads? - */ -void omap_hwmod_ocp_barrier(struct omap_hwmod *oh) -{ - BUG_ON(!oh); - - if (!oh->class->sysc || !oh->class->sysc->sysc_flags) { - WARN(1, "omap_device: %s: OCP barrier impossible due to device configuration\n", - oh->name); - return; - } - - /* - * Forces posted writes to complete on the OCP thread handling - * register writes - */ - omap_hwmod_read(oh, oh->class->sysc->sysc_offs); -} - -/** - * omap_hwmod_reset - reset the hwmod - * @oh: struct omap_hwmod * - * - * Under some conditions, a driver may wish to reset the entire device. - * Called from omap_device code. Returns -EINVAL on error or passes along - * the return value from _reset(). - */ -int omap_hwmod_reset(struct omap_hwmod *oh) -{ - int r; - unsigned long flags; - - if (!oh) - return -EINVAL; - - spin_lock_irqsave(&oh->_lock, flags); - r = _reset(oh); - spin_unlock_irqrestore(&oh->_lock, flags); - - return r; -} - /* * IP block data retrieval functions */ @@ -3723,51 +3638,11 @@ void __iomem *omap_hwmod_get_mpu_rt_va(struct omap_hwmod *oh) return oh->_mpu_rt_va; } -/** - * omap_hwmod_add_initiator_dep - add sleepdep from @init_oh to @oh - * @oh: struct omap_hwmod * - * @init_oh: struct omap_hwmod * (initiator) - * - * Add a sleep dependency between the initiator @init_oh and @oh. - * Intended to be called by DSP/Bridge code via platform_data for the - * DSP case; and by the DMA code in the sDMA case. DMA code, *Bridge - * code needs to add/del initiator dependencies dynamically - * before/after accessing a device. Returns the return value from - * _add_initiator_dep(). - * - * XXX Keep a usecount in the clockdomain code - */ -int omap_hwmod_add_initiator_dep(struct omap_hwmod *oh, - struct omap_hwmod *init_oh) -{ - return _add_initiator_dep(oh, init_oh); -} - /* * XXX what about functions for drivers to save/restore ocp_sysconfig * for context save/restore operations? */ -/** - * omap_hwmod_del_initiator_dep - remove sleepdep from @init_oh to @oh - * @oh: struct omap_hwmod * - * @init_oh: struct omap_hwmod * (initiator) - * - * Remove a sleep dependency between the initiator @init_oh and @oh. - * Intended to be called by DSP/Bridge code via platform_data for the - * DSP case; and by the DMA code in the sDMA case. DMA code, *Bridge - * code needs to add/del initiator dependencies dynamically - * before/after accessing a device. Returns the return value from - * _del_initiator_dep(). - * - * XXX Keep a usecount in the clockdomain code - */ -int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh, - struct omap_hwmod *init_oh) -{ - return _del_initiator_dep(oh, init_oh); -} - /** * omap_hwmod_enable_wakeup - allow device to wake up the system * @oh: struct omap_hwmod * @@ -3888,33 +3763,6 @@ int omap_hwmod_deassert_hardreset(struct omap_hwmod *oh, const char *name) return ret; } -/** - * omap_hwmod_read_hardreset - read the HW reset line state of submodules - * contained in the hwmod module - * @oh: struct omap_hwmod * - * @name: name of the reset line to look up and read - * - * Return the current state of the hwmod @oh's reset line named @name: - * returns -EINVAL upon parameter error or if this operation - * is unsupported on the current OMAP; otherwise, passes along the return - * value from _read_hardreset(). - */ -int omap_hwmod_read_hardreset(struct omap_hwmod *oh, const char *name) -{ - int ret; - unsigned long flags; - - if (!oh) - return -EINVAL; - - spin_lock_irqsave(&oh->_lock, flags); - ret = _read_hardreset(oh, name); - spin_unlock_irqrestore(&oh->_lock, flags); - - return ret; -} - - /** * omap_hwmod_for_each_by_class - call @fn for each hwmod of class @classname * @classname: struct omap_hwmod_class name to search for @@ -4024,86 +3872,6 @@ int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh) return ret; } -/** - * omap_hwmod_no_setup_reset - prevent a hwmod from being reset upon setup - * @oh: struct omap_hwmod * - * - * Prevent the hwmod @oh from being reset during the setup process. - * Intended for use by board-*.c files on boards with devices that - * cannot tolerate being reset. Must be called before the hwmod has - * been set up. Returns 0 upon success or negative error code upon - * failure. - */ -int omap_hwmod_no_setup_reset(struct omap_hwmod *oh) -{ - if (!oh) - return -EINVAL; - - if (oh->_state != _HWMOD_STATE_REGISTERED) { - pr_err("omap_hwmod: %s: cannot prevent setup reset; in wrong state\n", - oh->name); - return -EINVAL; - } - - oh->flags |= HWMOD_INIT_NO_RESET; - - return 0; -} - -/** - * omap_hwmod_pad_route_irq - route an I/O pad wakeup to a particular MPU IRQ - * @oh: struct omap_hwmod * containing hwmod mux entries - * @pad_idx: array index in oh->mux of the hwmod mux entry to route wakeup - * @irq_idx: the hwmod mpu_irqs array index of the IRQ to trigger on wakeup - * - * When an I/O pad wakeup arrives for the dynamic or wakeup hwmod mux - * entry number @pad_idx for the hwmod @oh, trigger the interrupt - * service routine for the hwmod's mpu_irqs array index @irq_idx. If - * this function is not called for a given pad_idx, then the ISR - * associated with @oh's first MPU IRQ will be triggered when an I/O - * pad wakeup occurs on that pad. Note that @pad_idx is the index of - * the _dynamic or wakeup_ entry: if there are other entries not - * marked with OMAP_DEVICE_PAD_WAKEUP or OMAP_DEVICE_PAD_REMUX, these - * entries are NOT COUNTED in the dynamic pad index. This function - * must be called separately for each pad that requires its interrupt - * to be re-routed this way. Returns -EINVAL if there is an argument - * problem or if @oh does not have hwmod mux entries or MPU IRQs; - * returns -ENOMEM if memory cannot be allocated; or 0 upon success. - * - * XXX This function interface is fragile. Rather than using array - * indexes, which are subject to unpredictable change, it should be - * using hwmod IRQ names, and some other stable key for the hwmod mux - * pad records. - */ -int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx) -{ - int nr_irqs; - - might_sleep(); - - if (!oh || !oh->mux || !oh->mpu_irqs || pad_idx < 0 || - pad_idx >= oh->mux->nr_pads_dynamic) - return -EINVAL; - - /* Check the number of available mpu_irqs */ - for (nr_irqs = 0; oh->mpu_irqs[nr_irqs].irq >= 0; nr_irqs++) - ; - - if (irq_idx >= nr_irqs) - return -EINVAL; - - if (!oh->mux->irqs) { - /* XXX What frees this? */ - oh->mux->irqs = kzalloc(sizeof(int) * oh->mux->nr_pads_dynamic, - GFP_KERNEL); - if (!oh->mux->irqs) - return -ENOMEM; - } - oh->mux->irqs[pad_idx] = irq_idx; - - return 0; -} - /** * omap_hwmod_init - initialize the hwmod code * diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h index 35ca6efbec31..2678d2144ca8 100644 --- a/arch/arm/mach-omap2/omap_hwmod.h +++ b/arch/arm/mach-omap2/omap_hwmod.h @@ -702,13 +702,6 @@ int omap_hwmod_shutdown(struct omap_hwmod *oh); int omap_hwmod_assert_hardreset(struct omap_hwmod *oh, const char *name); int omap_hwmod_deassert_hardreset(struct omap_hwmod *oh, const char *name); -int omap_hwmod_read_hardreset(struct omap_hwmod *oh, const char *name); - -int omap_hwmod_enable_clocks(struct omap_hwmod *oh); -int omap_hwmod_disable_clocks(struct omap_hwmod *oh); - -int omap_hwmod_reset(struct omap_hwmod *oh); -void omap_hwmod_ocp_barrier(struct omap_hwmod *oh); void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs); u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs); @@ -723,11 +716,6 @@ int omap_hwmod_get_resource_byname(struct omap_hwmod *oh, unsigned int type, struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh); void __iomem *omap_hwmod_get_mpu_rt_va(struct omap_hwmod *oh); -int omap_hwmod_add_initiator_dep(struct omap_hwmod *oh, - struct omap_hwmod *init_oh); -int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh, - struct omap_hwmod *init_oh); - int omap_hwmod_enable_wakeup(struct omap_hwmod *oh); int omap_hwmod_disable_wakeup(struct omap_hwmod *oh); @@ -739,10 +727,6 @@ int omap_hwmod_for_each_by_class(const char *classname, int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state); int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh); -int omap_hwmod_no_setup_reset(struct omap_hwmod *oh); - -int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx); - extern void __init omap_hwmod_init(void); const char *omap_hwmod_get_main_clk(struct omap_hwmod *oh); -- cgit v1.2.3 From 10637afb9157c5da28aef0465cd9e6135af5148b Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 7 Dec 2014 14:58:27 +0100 Subject: ARM: OMAP2+: powerdomain.c: Remove some unused functions Removes some functions that are not used anywhere: pwrdm_get_voltdm() pwrdm_for_each_clkdm() pwrdm_del_clkdm() This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Acked-by: Nishanth Menon Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/powerdomain.c | 81 --------------------------------------- arch/arm/mach-omap2/powerdomain.h | 5 --- 2 files changed, 86 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 7fb033eca0a5..6bd6025716ea 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -483,87 +483,6 @@ pac_exit: return ret; } -/** - * pwrdm_del_clkdm - remove a clockdomain from a powerdomain - * @pwrdm: struct powerdomain * to add the clockdomain to - * @clkdm: struct clockdomain * to associate with a powerdomain - * - * Dissociate the clockdomain @clkdm from the powerdomain - * @pwrdm. Returns -EINVAL if presented with invalid pointers; -ENOENT - * if @clkdm was not associated with the powerdomain, or 0 upon - * success. - */ -int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm) -{ - int ret = -EINVAL; - int i; - - if (!pwrdm || !clkdm) - return -EINVAL; - - pr_debug("powerdomain: %s: dissociating clockdomain %s\n", - pwrdm->name, clkdm->name); - - for (i = 0; i < PWRDM_MAX_CLKDMS; i++) - if (pwrdm->pwrdm_clkdms[i] == clkdm) - break; - - if (i == PWRDM_MAX_CLKDMS) { - pr_debug("powerdomain: %s: clkdm %s not associated?!\n", - pwrdm->name, clkdm->name); - ret = -ENOENT; - goto pdc_exit; - } - - pwrdm->pwrdm_clkdms[i] = NULL; - - ret = 0; - -pdc_exit: - return ret; -} - -/** - * pwrdm_for_each_clkdm - call function on each clkdm in a pwrdm - * @pwrdm: struct powerdomain * to iterate over - * @fn: callback function * - * - * Call the supplied function @fn for each clockdomain in the powerdomain - * @pwrdm. The callback function can return anything but 0 to bail - * out early from the iterator. Returns -EINVAL if presented with - * invalid pointers; or passes along the last return value of the - * callback function, which should be 0 for success or anything else - * to indicate failure. - */ -int pwrdm_for_each_clkdm(struct powerdomain *pwrdm, - int (*fn)(struct powerdomain *pwrdm, - struct clockdomain *clkdm)) -{ - int ret = 0; - int i; - - if (!fn) - return -EINVAL; - - for (i = 0; i < PWRDM_MAX_CLKDMS && !ret; i++) - if (pwrdm->pwrdm_clkdms[i]) - ret = (*fn)(pwrdm, pwrdm->pwrdm_clkdms[i]); - - return ret; -} - -/** - * pwrdm_get_voltdm - return a ptr to the voltdm that this pwrdm resides in - * @pwrdm: struct powerdomain * - * - * Return a pointer to the struct voltageomain that the specified powerdomain - * @pwrdm exists in. - */ -struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm) -{ - return pwrdm->voltdm.ptr; -} - /** * pwrdm_get_mem_bank_count - get number of memory banks in this powerdomain * @pwrdm: struct powerdomain * diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h index 11bd4dd7d8d6..28a796ce07d7 100644 --- a/arch/arm/mach-omap2/powerdomain.h +++ b/arch/arm/mach-omap2/powerdomain.h @@ -212,11 +212,6 @@ int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user), void *user); int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm); -int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm); -int pwrdm_for_each_clkdm(struct powerdomain *pwrdm, - int (*fn)(struct powerdomain *pwrdm, - struct clockdomain *clkdm)); -struct voltagedomain *pwrdm_get_voltdm(struct powerdomain *pwrdm); int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm); -- cgit v1.2.3 From b91dc63b2d59a03618abdf19d9172dcce5c4921e Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sat, 3 Jan 2015 01:37:43 +0100 Subject: ARM: OMAP2+: voltage: Remove some unused functions Removes some functions that are not used anywhere: omap_change_voltscale_method() voltdm_add_pwrdm() voltdm_for_each() voltdm_for_each_pwrdm() And remove define VOLTSCALE_VPFORCEUPDATE and VOLTSCALE_VCBYPASS This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/powerdomain.c | 1 - arch/arm/mach-omap2/voltage.c | 110 -------------------------------------- arch/arm/mach-omap2/voltage.h | 13 ----- 3 files changed, 124 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 6bd6025716ea..78af6d8cf2e2 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -115,7 +115,6 @@ static int _pwrdm_register(struct powerdomain *pwrdm) } pwrdm->voltdm.ptr = voltdm; INIT_LIST_HEAD(&pwrdm->voltdm_node); - voltdm_add_pwrdm(voltdm, pwrdm); skip_voltdm: spin_lock_init(&pwrdm->_lock); diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c index 3783b8625f0f..cba8cada8c81 100644 --- a/arch/arm/mach-omap2/voltage.c +++ b/arch/arm/mach-omap2/voltage.c @@ -223,37 +223,6 @@ int omap_voltage_register_pmic(struct voltagedomain *voltdm, return 0; } -/** - * omap_change_voltscale_method() - API to change the voltage scaling method. - * @voltdm: pointer to the VDD whose voltage scaling method - * has to be changed. - * @voltscale_method: the method to be used for voltage scaling. - * - * This API can be used by the board files to change the method of voltage - * scaling between vpforceupdate and vcbypass. The parameter values are - * defined in voltage.h - */ -void omap_change_voltscale_method(struct voltagedomain *voltdm, - int voltscale_method) -{ - if (!voltdm || IS_ERR(voltdm)) { - pr_warn("%s: VDD specified does not exist!\n", __func__); - return; - } - - switch (voltscale_method) { - case VOLTSCALE_VPFORCEUPDATE: - voltdm->scale = omap_vp_forceupdate_scale; - return; - case VOLTSCALE_VCBYPASS: - voltdm->scale = omap_vc_bypass_scale; - return; - default: - pr_warn("%s: Trying to change the method of voltage scaling to an unsupported one!\n", - __func__); - } -} - /** * omap_voltage_late_init() - Init the various voltage parameters * @@ -316,90 +285,11 @@ static struct voltagedomain *_voltdm_lookup(const char *name) return voltdm; } -/** - * voltdm_add_pwrdm - add a powerdomain to a voltagedomain - * @voltdm: struct voltagedomain * to add the powerdomain to - * @pwrdm: struct powerdomain * to associate with a voltagedomain - * - * Associate the powerdomain @pwrdm with a voltagedomain @voltdm. This - * enables the use of voltdm_for_each_pwrdm(). Returns -EINVAL if - * presented with invalid pointers; -ENOMEM if memory could not be allocated; - * or 0 upon success. - */ -int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm) -{ - if (!voltdm || !pwrdm) - return -EINVAL; - - pr_debug("voltagedomain: %s: associating powerdomain %s\n", - voltdm->name, pwrdm->name); - - list_add(&pwrdm->voltdm_node, &voltdm->pwrdm_list); - - return 0; -} - -/** - * voltdm_for_each_pwrdm - call function for each pwrdm in a voltdm - * @voltdm: struct voltagedomain * to iterate over - * @fn: callback function * - * - * Call the supplied function @fn for each powerdomain in the - * voltagedomain @voltdm. Returns -EINVAL if presented with invalid - * pointers; or passes along the last return value of the callback - * function, which should be 0 for success or anything else to - * indicate failure. - */ -int voltdm_for_each_pwrdm(struct voltagedomain *voltdm, - int (*fn)(struct voltagedomain *voltdm, - struct powerdomain *pwrdm)) -{ - struct powerdomain *pwrdm; - int ret = 0; - - if (!fn) - return -EINVAL; - - list_for_each_entry(pwrdm, &voltdm->pwrdm_list, voltdm_node) - ret = (*fn)(voltdm, pwrdm); - - return ret; -} - -/** - * voltdm_for_each - call function on each registered voltagedomain - * @fn: callback function * - * - * Call the supplied function @fn for each registered voltagedomain. - * The callback function @fn can return anything but 0 to bail out - * early from the iterator. Returns the last return value of the - * callback function, which should be 0 for success or anything else - * to indicate failure; or -EINVAL if the function pointer is null. - */ -int voltdm_for_each(int (*fn)(struct voltagedomain *voltdm, void *user), - void *user) -{ - struct voltagedomain *temp_voltdm; - int ret = 0; - - if (!fn) - return -EINVAL; - - list_for_each_entry(temp_voltdm, &voltdm_list, node) { - ret = (*fn)(temp_voltdm, user); - if (ret) - break; - } - - return ret; -} - static int _voltdm_register(struct voltagedomain *voltdm) { if (!voltdm || !voltdm->name) return -EINVAL; - INIT_LIST_HEAD(&voltdm->pwrdm_list); list_add(&voltdm->node, &voltdm_list); pr_debug("voltagedomain: registered %s\n", voltdm->name); diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h index f7f2879b31b0..e64550321510 100644 --- a/arch/arm/mach-omap2/voltage.h +++ b/arch/arm/mach-omap2/voltage.h @@ -23,10 +23,6 @@ struct powerdomain; -/* XXX document */ -#define VOLTSCALE_VPFORCEUPDATE 1 -#define VOLTSCALE_VCBYPASS 2 - /* * OMAP3 GENERIC setup times. Revisit to see if these needs to be * passed from board or PMIC file @@ -55,7 +51,6 @@ struct omap_vfsm_instance { * @name: Name of the voltage domain which can be used as a unique identifier. * @scalable: Whether or not this voltage domain is scalable * @node: list_head linking all voltage domains - * @pwrdm_list: list_head linking all powerdomains in this voltagedomain * @vc: pointer to VC channel associated with this voltagedomain * @vp: pointer to VP associated with this voltagedomain * @read: read a VC/VP register @@ -71,7 +66,6 @@ struct voltagedomain { char *name; bool scalable; struct list_head node; - struct list_head pwrdm_list; struct omap_vc_channel *vc; const struct omap_vfsm_instance *vfsm; struct omap_vp_instance *vp; @@ -163,8 +157,6 @@ struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm, unsigned long volt); int omap_voltage_register_pmic(struct voltagedomain *voltdm, struct omap_voltdm_pmic *pmic); -void omap_change_voltscale_method(struct voltagedomain *voltdm, - int voltscale_method); int omap_voltage_late_init(void); extern void omap2xxx_voltagedomains_init(void); @@ -175,11 +167,6 @@ extern void omap54xx_voltagedomains_init(void); struct voltagedomain *voltdm_lookup(const char *name); void voltdm_init(struct voltagedomain **voltdm_list); int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm); -int voltdm_for_each(int (*fn)(struct voltagedomain *voltdm, void *user), - void *user); -int voltdm_for_each_pwrdm(struct voltagedomain *voltdm, - int (*fn)(struct voltagedomain *voltdm, - struct powerdomain *pwrdm)); int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt); void voltdm_reset(struct voltagedomain *voltdm); unsigned long voltdm_get_voltage(struct voltagedomain *voltdm); -- cgit v1.2.3 From cd0007e283326ec98ea56853195abdde111ee661 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 7 Dec 2014 21:49:06 +0100 Subject: ARM: OMAP2+: omap-pm-noop.c: Remove some unused functions Removes some functions that are not used anywhere: omap_pm_set_max_dev_wakeup_lat() omap_pm_if_exit() omap_pm_cpu_get_freq() omap_pm_cpu_set_freq() omap_pm_cpu_get_freq_table() omap_pm_dsp_get_opp() omap_pm_dsp_set_min_opp() omap_pm_dsp_get_opp_table() omap_pm_set_min_clk_rate() omap_pm_set_max_sdma_lat() This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap-pm-noop.c | 196 ------------------------------------- arch/arm/mach-omap2/omap-pm.h | 192 ------------------------------------ 2 files changed, 388 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/omap-pm-noop.c b/arch/arm/mach-omap2/omap-pm-noop.c index 6a3be2bebddb..a1ee8066958e 100644 --- a/arch/arm/mach-omap2/omap-pm-noop.c +++ b/arch/arm/mach-omap2/omap-pm-noop.c @@ -86,200 +86,10 @@ int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r) return 0; } -int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, - long t) -{ - if (!req_dev || !dev || t < -1) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - } - - if (t == -1) - pr_debug("OMAP PM: remove max device latency constraint: dev %s\n", - dev_name(dev)); - else - pr_debug("OMAP PM: add max device latency constraint: dev %s, t = %ld usec\n", - dev_name(dev), t); - - /* - * For current Linux, this needs to map the device to a - * powerdomain, then go through the list of current max lat - * constraints on that powerdomain and find the smallest. If - * the latency constraint has changed, the code should - * recompute the state to enter for the next powerdomain - * state. Conceivably, this code should also determine - * whether to actually disable the device clocks or not, - * depending on how long it takes to re-enable the clocks. - * - * TI CDP code can call constraint_set here. - */ - - return 0; -} - -int omap_pm_set_max_sdma_lat(struct device *dev, long t) -{ - if (!dev || t < -1) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - } - - if (t == -1) - pr_debug("OMAP PM: remove max DMA latency constraint: dev %s\n", - dev_name(dev)); - else - pr_debug("OMAP PM: add max DMA latency constraint: dev %s, t = %ld usec\n", - dev_name(dev), t); - - /* - * For current Linux PM QOS params, this code should scan the - * list of maximum CPU and DMA latencies and select the - * smallest, then set cpu_dma_latency pm_qos_param - * accordingly. - * - * For future Linux PM QOS params, with separate CPU and DMA - * latency params, this code should just set the dma_latency param. - * - * TI CDP code can call constraint_set here. - */ - - return 0; -} - -int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r) -{ - if (!dev || !c || r < 0) { - WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__); - return -EINVAL; - } - - if (r == 0) - pr_debug("OMAP PM: remove min clk rate constraint: dev %s\n", - dev_name(dev)); - else - pr_debug("OMAP PM: add min clk rate constraint: dev %s, rate = %ld Hz\n", - dev_name(dev), r); - - /* - * Code in a real implementation should keep track of these - * constraints on the clock, and determine the highest minimum - * clock rate. It should iterate over each OPP and determine - * whether the OPP will result in a clock rate that would - * satisfy this constraint (and any other PM constraint in effect - * at that time). Once it finds the lowest-voltage OPP that - * meets those conditions, it should switch to it, or return - * an error if the code is not capable of doing so. - */ - - return 0; -} - /* * DSP Bridge-specific constraints */ -const struct omap_opp *omap_pm_dsp_get_opp_table(void) -{ - pr_debug("OMAP PM: DSP request for OPP table\n"); - - /* - * Return DSP frequency table here: The final item in the - * array should have .rate = .opp_id = 0. - */ - - return NULL; -} - -void omap_pm_dsp_set_min_opp(u8 opp_id) -{ - if (opp_id == 0) { - WARN_ON(1); - return; - } - - pr_debug("OMAP PM: DSP requests minimum VDD1 OPP to be %d\n", opp_id); - - /* - * - * For l-o dev tree, our VDD1 clk is keyed on OPP ID, so we - * can just test to see which is higher, the CPU's desired OPP - * ID or the DSP's desired OPP ID, and use whichever is - * highest. - * - * In CDP12.14+, the VDD1 OPP custom clock that controls the DSP - * rate is keyed on MPU speed, not the OPP ID. So we need to - * map the OPP ID to the MPU speed for use with clk_set_rate() - * if it is higher than the current OPP clock rate. - * - */ -} - - -u8 omap_pm_dsp_get_opp(void) -{ - pr_debug("OMAP PM: DSP requests current DSP OPP ID\n"); - - /* - * For l-o dev tree, call clk_get_rate() on VDD1 OPP clock - * - * CDP12.14+: - * Call clk_get_rate() on the OPP custom clock, map that to an - * OPP ID using the tables defined in board-*.c/chip-*.c files. - */ - - return 0; -} - -/* - * CPUFreq-originated constraint - * - * In the future, this should be handled by custom OPP clocktype - * functions. - */ - -struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void) -{ - pr_debug("OMAP PM: CPUFreq request for frequency table\n"); - - /* - * Return CPUFreq frequency table here: loop over - * all VDD1 clkrates, pull out the mpu_ck frequencies, build - * table - */ - - return NULL; -} - -void omap_pm_cpu_set_freq(unsigned long f) -{ - if (f == 0) { - WARN_ON(1); - return; - } - - pr_debug("OMAP PM: CPUFreq requests CPU frequency to be set to %lu\n", - f); - - /* - * For l-o dev tree, determine whether MPU freq or DSP OPP id - * freq is higher. Find the OPP ID corresponding to the - * higher frequency. Call clk_round_rate() and clk_set_rate() - * on the OPP custom clock. - * - * CDP should just be able to set the VDD1 OPP clock rate here. - */ -} - -unsigned long omap_pm_cpu_get_freq(void) -{ - pr_debug("OMAP PM: CPUFreq requests current CPU frequency\n"); - - /* - * Call clk_get_rate() on the mpu_ck. - */ - - return 0; -} /** * omap_pm_enable_off_mode - notify OMAP PM that off-mode is enabled @@ -363,9 +173,3 @@ int __init omap_pm_if_init(void) { return 0; } - -void omap_pm_if_exit(void) -{ - /* Deallocate CPUFreq frequency table here */ -} - diff --git a/arch/arm/mach-omap2/omap-pm.h b/arch/arm/mach-omap2/omap-pm.h index 1d777e63e05c..109bef5538eb 100644 --- a/arch/arm/mach-omap2/omap-pm.h +++ b/arch/arm/mach-omap2/omap-pm.h @@ -50,14 +50,6 @@ int __init omap_pm_if_early_init(void); */ int __init omap_pm_if_init(void); -/** - * omap_pm_if_exit - OMAP PM exit code - * - * Exit code; currently unused. The "_if_" is to avoid name - * collisions with the PM idle-loop code. - */ -void omap_pm_if_exit(void); - /* * Device-driver-originated constraints (via board-*.c files, platform_data) */ @@ -132,163 +124,6 @@ int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t); int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r); -/** - * omap_pm_set_max_dev_wakeup_lat - set the maximum device enable latency - * @req_dev: struct device * requesting the constraint, or NULL if none - * @dev: struct device * to set the constraint one - * @t: maximum device wakeup latency in microseconds - * - * Request that the maximum amount of time necessary for a device @dev - * to become accessible after its clocks are enabled should be no - * greater than @t microseconds. Specifically, this represents the - * time from when a device driver enables device clocks with - * clk_enable(), to when the register reads and writes on the device - * will succeed. This function should be called before clk_disable() - * is called, since the power state transition decision may be made - * during clk_disable(). - * - * It is intended that underlying PM code will use this information to - * determine what power state to put the powerdomain enclosing this - * device into. - * - * Multiple calls to omap_pm_set_max_dev_wakeup_lat() will replace the - * previous wakeup latency values for this device. To remove the - * wakeup latency restriction for this device, call with t = -1. - * - * Returns -EINVAL for an invalid argument, -ERANGE if the constraint - * is not satisfiable, or 0 upon success. - */ -int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev, - long t); - - -/** - * omap_pm_set_max_sdma_lat - set the maximum system DMA transfer start latency - * @dev: struct device * - * @t: maximum DMA transfer start latency in microseconds - * - * Request that the maximum system DMA transfer start latency for this - * device 'dev' should be no greater than 't' microseconds. "DMA - * transfer start latency" here is defined as the elapsed time from - * when a device (e.g., McBSP) requests that a system DMA transfer - * start or continue, to the time at which data starts to flow into - * that device from the system DMA controller. - * - * It is intended that underlying PM code will use this information to - * determine what power state to put the CORE powerdomain into. - * - * Since system DMA transfers may not involve the MPU, this function - * will not affect MPU wakeup latency. Use set_max_cpu_lat() to do - * so. Similarly, this function will not affect device wakeup latency - * -- use set_max_dev_wakeup_lat() to affect that. - * - * Multiple calls to set_max_sdma_lat() will replace the previous t - * value for this device. To remove the maximum DMA latency for this - * device, call with t = -1. - * - * Returns -EINVAL for an invalid argument, -ERANGE if the constraint - * is not satisfiable, or 0 upon success. - */ -int omap_pm_set_max_sdma_lat(struct device *dev, long t); - - -/** - * omap_pm_set_min_clk_rate - set minimum clock rate requested by @dev - * @dev: struct device * requesting the constraint - * @clk: struct clk * to set the minimum rate constraint on - * @r: minimum rate in Hz - * - * Request that the minimum clock rate on the device @dev's clk @clk - * be no less than @r Hz. - * - * It is expected that the OMAP PM code will use this information to - * find an OPP or clock setting that will satisfy this clock rate - * constraint, along with any other applicable system constraints on - * the clock rate or corresponding voltage, etc. - * - * omap_pm_set_min_clk_rate() differs from the clock code's - * clk_set_rate() in that it considers other constraints before taking - * any hardware action, and may change a system OPP rather than just a - * clock rate. clk_set_rate() is intended to be a low-level - * interface. - * - * omap_pm_set_min_clk_rate() is easily open to abuse. A better API - * would be something like "omap_pm_set_min_dev_performance()"; - * however, there is no easily-generalizable concept of performance - * that applies to all devices. Only a device (and possibly the - * device subsystem) has both the subsystem-specific knowledge, and - * the hardware IP block-specific knowledge, to translate a constraint - * on "touchscreen sampling accuracy" or "number of pixels or polygons - * rendered per second" to a clock rate. This translation can be - * dependent on the hardware IP block's revision, or firmware version, - * and the driver is the only code on the system that has this - * information and can know how to translate that into a clock rate. - * - * The intended use-case for this function is for userspace or other - * kernel code to communicate a particular performance requirement to - * a subsystem; then for the subsystem to communicate that requirement - * to something that is meaningful to the device driver; then for the - * device driver to convert that requirement to a clock rate, and to - * then call omap_pm_set_min_clk_rate(). - * - * Users of this function (such as device drivers) should not simply - * call this function with some high clock rate to ensure "high - * performance." Rather, the device driver should take a performance - * constraint from its subsystem, such as "render at least X polygons - * per second," and use some formula or table to convert that into a - * clock rate constraint given the hardware type and hardware - * revision. Device drivers or subsystems should not assume that they - * know how to make a power/performance tradeoff - some device use - * cases may tolerate a lower-fidelity device function for lower power - * consumption; others may demand a higher-fidelity device function, - * no matter what the power consumption. - * - * Multiple calls to omap_pm_set_min_clk_rate() will replace the - * previous rate value for the device @dev. To remove the minimum clock - * rate constraint for the device, call with r = 0. - * - * Returns -EINVAL for an invalid argument, -ERANGE if the constraint - * is not satisfiable, or 0 upon success. - */ -int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r); - -/* - * DSP Bridge-specific constraints - */ - -/** - * omap_pm_dsp_get_opp_table - get OPP->DSP clock frequency table - * - * Intended for use by DSPBridge. Returns an array of OPP->DSP clock - * frequency entries. The final item in the array should have .rate = - * .opp_id = 0. - */ -const struct omap_opp *omap_pm_dsp_get_opp_table(void); - -/** - * omap_pm_dsp_set_min_opp - receive desired OPP target ID from DSP Bridge - * @opp_id: target DSP OPP ID - * - * Set a minimum OPP ID for the DSP. This is intended to be called - * only from the DSP Bridge MPU-side driver. Unfortunately, the only - * information that code receives from the DSP/BIOS load estimator is the - * target OPP ID; hence, this interface. No return value. - */ -void omap_pm_dsp_set_min_opp(u8 opp_id); - -/** - * omap_pm_dsp_get_opp - report the current DSP OPP ID - * - * Report the current OPP for the DSP. Since on OMAP3, the DSP and - * MPU share a single voltage domain, the OPP ID returned back may - * represent a higher DSP speed than the OPP requested via - * omap_pm_dsp_set_min_opp(). - * - * Returns the current VDD1 OPP ID, or 0 upon error. - */ -u8 omap_pm_dsp_get_opp(void); - - /* * CPUFreq-originated constraint * @@ -296,33 +131,6 @@ u8 omap_pm_dsp_get_opp(void); * functions. */ -/** - * omap_pm_cpu_get_freq_table - return a cpufreq_frequency_table array ptr - * - * Provide a frequency table usable by CPUFreq for the current chip/board. - * Returns a pointer to a struct cpufreq_frequency_table array or NULL - * upon error. - */ -struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void); - -/** - * omap_pm_cpu_set_freq - set the current minimum MPU frequency - * @f: MPU frequency in Hz - * - * Set the current minimum CPU frequency. The actual CPU frequency - * used could end up higher if the DSP requested a higher OPP. - * Intended to be called by plat-omap/cpu_omap.c:omap_target(). No - * return value. - */ -void omap_pm_cpu_set_freq(unsigned long f); - -/** - * omap_pm_cpu_get_freq - report the current CPU frequency - * - * Returns the current MPU frequency, or 0 upon error. - */ -unsigned long omap_pm_cpu_get_freq(void); - /* * Device context loss tracking -- cgit v1.2.3 From 25644f8e7f84ec6b235ccc6d48f278f7c1410d0f Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 7 Dec 2014 13:26:49 +0100 Subject: ARM: OMAP1: irq.c: Remove unused function Remove the function irq_bank_readl() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/irq.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c index 122ef67939a2..a8a533df24e1 100644 --- a/arch/arm/mach-omap1/irq.c +++ b/arch/arm/mach-omap1/irq.c @@ -64,11 +64,6 @@ u32 omap_irq_flags; static unsigned int irq_bank_count; static struct omap_irq_bank *irq_banks; -static inline unsigned int irq_bank_readl(int bank, int offset) -{ - return omap_readl(irq_banks[bank].base_reg + offset); -} - static inline void irq_bank_writel(unsigned long value, int bank, int offset) { omap_writel(value, irq_banks[bank].base_reg + offset); -- cgit v1.2.3 From a61a141db8b384456ca7f3c8762e81f236c93aa1 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Sun, 7 Dec 2014 13:28:56 +0100 Subject: ARM: OMAP1: timer32k.c: Remove unused function Remove the function omap_32k_timer_read() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/timer32k.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c index 107e7ab3edba..36bf174b3fac 100644 --- a/arch/arm/mach-omap1/timer32k.c +++ b/arch/arm/mach-omap1/timer32k.c @@ -91,11 +91,6 @@ static inline void omap_32k_timer_write(int val, int reg) omap_writew(val, OMAP1_32K_TIMER_BASE + reg); } -static inline unsigned long omap_32k_timer_read(int reg) -{ - return omap_readl(OMAP1_32K_TIMER_BASE + reg) & 0xffffff; -} - static inline void omap_32k_timer_start(unsigned long load_val) { if (!load_val) -- cgit v1.2.3 From 9b455e8d7cd5a9523bb0f696070173681cb45238 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Thu, 1 Jan 2015 17:45:05 +0100 Subject: ARM: OMAP: dma.c: Remove unused function Remove the function get_gdma_dev() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dma.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'arch') diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 24770e5a5081..6416e03b4482 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -151,14 +151,6 @@ static int omap_dma_in_1510_mode(void) #endif #ifdef CONFIG_ARCH_OMAP1 -static inline int get_gdma_dev(int req) -{ - u32 reg = OMAP_FUNC_MUX_ARM_BASE + ((req - 1) / 5) * 4; - int shift = ((req - 1) % 5) * 6; - - return ((omap_readl(reg) >> shift) & 0x3f) + 1; -} - static inline void set_gdma_dev(int req, int dev) { u32 reg = OMAP_FUNC_MUX_ARM_BASE + ((req - 1) / 5) * 4; -- cgit v1.2.3 From d58cf5ff6500522880683ce90d9caa79af385ed8 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 7 Jan 2015 17:15:00 +0200 Subject: spi: dw-pci: describe Intel MID controllers better There are more that one SPI controller on the Intel MID boards. This patch describes the status and IDs of them. From now on we also have to care about bus number that must be unique per host. According to the specification the SPI1 has 5 bits for chip selects and SPI2 only 2 bits. The patch makes it depend to PCI ID. The first controller (SPI1) is DMA capable, meanwhile SPI2 can share same channels (via software switch) such functionality is not in the scope of this patch. Thus, attempt to init DMA for SPI2 will always fail for now. Signed-off-by: Andy Shevchenko Signed-off-by: Mark Brown --- arch/x86/pci/intel_mid_pci.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c index 44b9271580b5..852aa4c92da0 100644 --- a/arch/x86/pci/intel_mid_pci.c +++ b/arch/x86/pci/intel_mid_pci.c @@ -293,7 +293,6 @@ static void mrst_power_off_unused_dev(struct pci_dev *dev) DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0801, mrst_power_off_unused_dev); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0809, mrst_power_off_unused_dev); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x080C, mrst_power_off_unused_dev); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0812, mrst_power_off_unused_dev); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0815, mrst_power_off_unused_dev); /* -- cgit v1.2.3 From 56ad669184a0455c096eeb525a14e8a5ab7c1b25 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Thu, 27 Nov 2014 17:51:35 +0200 Subject: ARM: OMAP2: clock: remove unused apll code APLL clock type is no longer needed as the legacy clock support is removed. Signed-off-by: Tero Kristo [tony@atomide.com: updated to apply] Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Makefile | 1 - arch/arm/mach-omap2/clkt2xxx_apll.c | 71 ------------------------------------- arch/arm/mach-omap2/clock2xxx.h | 2 -- 3 files changed, 74 deletions(-) delete mode 100644 arch/arm/mach-omap2/clkt2xxx_apll.c (limited to 'arch') diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 5d27dfdef66b..9fee2ad1c0ee 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -181,7 +181,6 @@ obj-$(CONFIG_SOC_DRA7XX) += clockdomains7xx_data.o obj-$(CONFIG_ARCH_OMAP2) += $(clock-common) clock2xxx.o obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_dpllcore.o obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_virt_prcm_set.o -obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_apll.o obj-$(CONFIG_ARCH_OMAP2) += clkt2xxx_dpll.o clkt_iclk.o obj-$(CONFIG_SOC_OMAP2430) += clock2430.o obj-$(CONFIG_ARCH_OMAP3) += $(clock-common) clock3xxx.o diff --git a/arch/arm/mach-omap2/clkt2xxx_apll.c b/arch/arm/mach-omap2/clkt2xxx_apll.c deleted file mode 100644 index 02cb08875326..000000000000 --- a/arch/arm/mach-omap2/clkt2xxx_apll.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * OMAP2xxx APLL clock control functions - * - * Copyright (C) 2005-2008 Texas Instruments, Inc. - * Copyright (C) 2004-2010 Nokia Corporation - * - * Contacts: - * Richard Woodruff - * Paul Walmsley - * - * Based on earlier work by Tuukka Tikkanen, Tony Lindgren, - * Gordon McNutt and RidgeRun, 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. - */ -#undef DEBUG - -#include -#include -#include - - -#include "clock.h" -#include "clock2xxx.h" -#include "cm2xxx.h" -#include "cm-regbits-24xx.h" - -/* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */ -#define EN_APLL_STOPPED 0 -#define EN_APLL_LOCKED 3 - -/* CM_CLKSEL1_PLL.APLLS_CLKIN options (24XX) */ -#define APLLS_CLKIN_19_2MHZ 0 -#define APLLS_CLKIN_13MHZ 2 -#define APLLS_CLKIN_12MHZ 3 - -/* Private functions */ - -static void _apll96_allow_idle(struct clk_hw_omap *clk) -{ - omap2xxx_cm_set_apll96_auto_low_power_stop(); -} - -static void _apll96_deny_idle(struct clk_hw_omap *clk) -{ - omap2xxx_cm_set_apll96_disable_autoidle(); -} - -static void _apll54_allow_idle(struct clk_hw_omap *clk) -{ - omap2xxx_cm_set_apll54_auto_low_power_stop(); -} - -static void _apll54_deny_idle(struct clk_hw_omap *clk) -{ - omap2xxx_cm_set_apll54_disable_autoidle(); -} - -/* Public data */ -const struct clk_hw_omap_ops clkhwops_apll54 = { - .allow_idle = _apll54_allow_idle, - .deny_idle = _apll54_deny_idle, -}; - -const struct clk_hw_omap_ops clkhwops_apll96 = { - .allow_idle = _apll96_allow_idle, - .deny_idle = _apll96_deny_idle, -}; - diff --git a/arch/arm/mach-omap2/clock2xxx.h b/arch/arm/mach-omap2/clock2xxx.h index 364a4cc7f11b..125c37614848 100644 --- a/arch/arm/mach-omap2/clock2xxx.h +++ b/arch/arm/mach-omap2/clock2xxx.h @@ -41,7 +41,5 @@ int omap2430_clk_init(void); #endif extern struct clk_hw *dclk_hw; -int omap2_enable_osc_ck(struct clk_hw *hw); -void omap2_disable_osc_ck(struct clk_hw *hw); #endif -- cgit v1.2.3 From 2740cf7a96a1391df7a97cf2e474677ae4578ae4 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Thu, 27 Nov 2014 17:51:36 +0200 Subject: ARM: OMAP2: CM: remove unused PLL functions omap2xxx_cm_get_pll_config and omap2xxx_cm_get_pll_status are not used for anything, so remove these. Signed-off-by: Tero Kristo Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/cm2xxx.c | 10 ---------- arch/arm/mach-omap2/cm2xxx.h | 2 -- 2 files changed, 12 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/cm2xxx.c b/arch/arm/mach-omap2/cm2xxx.c index a96d901b1d5d..ef62ac9dcd05 100644 --- a/arch/arm/mach-omap2/cm2xxx.c +++ b/arch/arm/mach-omap2/cm2xxx.c @@ -370,16 +370,6 @@ u32 omap2xxx_cm_get_core_pll_config(void) return omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL2); } -u32 omap2xxx_cm_get_pll_config(void) -{ - return omap2_cm_read_mod_reg(PLL_MOD, CM_CLKSEL1); -} - -u32 omap2xxx_cm_get_pll_status(void) -{ - return omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN); -} - void omap2xxx_cm_set_mod_dividers(u32 mpu, u32 dsp, u32 gfx, u32 core, u32 mdm) { u32 tmp; diff --git a/arch/arm/mach-omap2/cm2xxx.h b/arch/arm/mach-omap2/cm2xxx.h index c89502b168ae..83b6c597b0e1 100644 --- a/arch/arm/mach-omap2/cm2xxx.h +++ b/arch/arm/mach-omap2/cm2xxx.h @@ -60,8 +60,6 @@ extern int omap2xxx_cm_fclks_active(void); extern int omap2xxx_cm_mpu_retention_allowed(void); extern u32 omap2xxx_cm_get_core_clk_src(void); extern u32 omap2xxx_cm_get_core_pll_config(void); -extern u32 omap2xxx_cm_get_pll_config(void); -extern u32 omap2xxx_cm_get_pll_status(void); extern void omap2xxx_cm_set_mod_dividers(u32 mpu, u32 dsp, u32 gfx, u32 core, u32 mdm); -- cgit v1.2.3 From fc24fc650620cbf94b277af5f25fa38cc9fe6656 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Thu, 27 Nov 2014 17:51:39 +0200 Subject: ARM: OMAP3+: PRM: remove prm_get_reset_sources declaration from headers There is no implementation for this anywhere, so remove it from the header files also. Signed-off-by: Tero Kristo [tony@atomide.com: updated to apply] Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/prm3xxx.h | 1 - arch/arm/mach-omap2/prm44xx_54xx.h | 1 - 2 files changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-omap2/prm3xxx.h b/arch/arm/mach-omap2/prm3xxx.h index cfde3f4a03cc..ed8a3d8b739a 100644 --- a/arch/arm/mach-omap2/prm3xxx.h +++ b/arch/arm/mach-omap2/prm3xxx.h @@ -145,7 +145,6 @@ extern void omap3_prm_vcvp_write(u32 val, u8 offset); extern u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset); extern int __init omap3xxx_prm_init(void); -extern u32 omap3xxx_prm_get_reset_sources(void); int omap3xxx_prm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits); void omap3xxx_prm_iva_idle(void); void omap3_prm_reset_modem(void); diff --git a/arch/arm/mach-omap2/prm44xx_54xx.h b/arch/arm/mach-omap2/prm44xx_54xx.h index f7512515fde5..714329565b90 100644 --- a/arch/arm/mach-omap2/prm44xx_54xx.h +++ b/arch/arm/mach-omap2/prm44xx_54xx.h @@ -39,7 +39,6 @@ extern void omap4_prm_vcvp_write(u32 val, u8 offset); extern u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset); extern int __init omap44xx_prm_init(void); -extern u32 omap44xx_prm_get_reset_sources(void); #endif -- cgit v1.2.3 From 3e1fe45125f35a866ac0e5780815c34ad55ce46c Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Thu, 4 Dec 2014 09:24:39 -0600 Subject: ARM: dts: am437x-sk-evm: Hook dcdc2 as the cpu0-supply Hook dcdc2 as the cpu0-supply. Signed-off-by: Dave Gerlach Tested-by: Felipe Balbi Signed-off-by: Felipe Balbi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am437x-sk-evm.dts | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts index 53bbfc90b26a..ab357b6d9c1e 100644 --- a/arch/arm/boot/dts/am437x-sk-evm.dts +++ b/arch/arm/boot/dts/am437x-sk-evm.dts @@ -610,3 +610,7 @@ &wdt { status = "okay"; }; + +&cpu { + cpu0-supply = <&dcdc2>; +}; -- cgit v1.2.3 From fad7ca8bcbda10e9fef5bcd0f5be5d7dc2f86142 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 4 Dec 2014 11:01:54 -0600 Subject: ARM: dts: am437x-sk: remove internal pulls from QSPI QSPI doesn't need any pullups of any sort, let's remove them. Signed-off-by: Felipe Balbi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am437x-sk-evm.dts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts index ab357b6d9c1e..59226e7f70b2 100644 --- a/arch/arm/boot/dts/am437x-sk-evm.dts +++ b/arch/arm/boot/dts/am437x-sk-evm.dts @@ -300,12 +300,12 @@ qspi_pins: qspi_pins { pinctrl-single,pins = < - 0x7c (PIN_OUTPUT_PULLUP | MUX_MODE3) /* gpmc_csn0.qspi_csn */ - 0x88 (PIN_OUTPUT | MUX_MODE2) /* gpmc_csn3.qspi_clk */ - 0x90 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_advn_ale.qspi_d0 */ - 0x94 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_oen_ren.qspi_d1 */ - 0x98 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_wen.qspi_d2 */ - 0x9c (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_be0n_cle.qspi_d3 */ + 0x7c (PIN_OUTPUT | MUX_MODE3) /* gpmc_csn0.qspi_csn */ + 0x88 (PIN_OUTPUT | MUX_MODE2) /* gpmc_csn3.qspi_clk */ + 0x90 (PIN_INPUT | MUX_MODE3) /* gpmc_advn_ale.qspi_d0 */ + 0x94 (PIN_INPUT | MUX_MODE3) /* gpmc_oen_ren.qspi_d1 */ + 0x98 (PIN_INPUT | MUX_MODE3) /* gpmc_wen.qspi_d2 */ + 0x9c (PIN_INPUT | MUX_MODE3) /* gpmc_be0n_cle.qspi_d3 */ >; }; -- cgit v1.2.3 From f76452fdfe3fdd930b83d108158d4f0507a32f5f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 6 Jan 2015 21:01:51 +0100 Subject: ARM: shmobile: sh73a0 dtsi: Add SoC-specific FSI2 compatible property The FSI2 sound node used the generic compatible property only. Add the SoC-specific one, to make it future proof. Signed-off-by: Geert Uytterhoeven Acked-by: Kuninori Morimoto Signed-off-by: Simon Horman --- arch/arm/boot/dts/sh73a0.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi index d8def5a529da..d4cfb0662643 100644 --- a/arch/arm/boot/dts/sh73a0.dtsi +++ b/arch/arm/boot/dts/sh73a0.dtsi @@ -317,7 +317,7 @@ sh_fsi2: sound@ec230000 { #sound-dai-cells = <1>; - compatible = "renesas,sh_fsi2"; + compatible = "renesas,fsi2-sh73a0", "renesas,sh_fsi2"; reg = <0xec230000 0x400>; interrupts = <0 146 0x4>; status = "disabled"; -- cgit v1.2.3 From fb135053436554afd29cd2b7e74a6101ce51f19c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 4 Dec 2014 11:01:55 -0600 Subject: ARM: dts: am437x-sk: add explicit MMC0 pinmux By don't relying on implicit MMC0 pulldown we make sure that pins are marked busy and even if we have a broken bootloader, MMC0 will remain functional. Signed-off-by: Felipe Balbi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am437x-sk-evm.dts | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts index 59226e7f70b2..dd1ea0bd3e58 100644 --- a/arch/arm/boot/dts/am437x-sk-evm.dts +++ b/arch/arm/boot/dts/am437x-sk-evm.dts @@ -167,6 +167,12 @@ mmc1_pins: pinmux_mmc1_pins { pinctrl-single,pins = < + 0x0f0 (PIN_INPUT | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */ + 0x0f4 (PIN_INPUT | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */ + 0x0f8 (PIN_INPUT | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */ + 0x0fc (PIN_INPUT | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */ + 0x100 (PIN_INPUT | MUX_MODE0) /* mmc0_clk.mmc0_clk */ + 0x104 (PIN_INPUT | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */ 0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */ >; }; -- cgit v1.2.3 From a2db983a9436a7038f300dd79030a6d62154d5a5 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 4 Dec 2014 11:01:56 -0600 Subject: ARM: dts: am437x-sk: remove ethernet pulls AM437x Starter Kit already has discrete pulls where they are necessary. It's safe (and actually better) to remove internal pulls. Signed-off-by: Felipe Balbi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am437x-sk-evm.dts | 52 ++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts index dd1ea0bd3e58..9e86cedab466 100644 --- a/arch/arm/boot/dts/am437x-sk-evm.dts +++ b/arch/arm/boot/dts/am437x-sk-evm.dts @@ -193,32 +193,32 @@ cpsw_default: cpsw_default { pinctrl-single,pins = < /* Slave 1 */ - 0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txclk.rmii1_tclk */ - 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_tctl */ - 0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td0 */ - 0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td1 */ - 0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td2 */ - 0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td3 */ - 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxclk.rmii1_rclk */ - 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */ - 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rd0 */ - 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rd1 */ - 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rd2 */ - 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rd3 */ + 0x12c (PIN_OUTPUT | MUX_MODE2) /* mii1_txclk.rmii1_tclk */ + 0x114 (PIN_OUTPUT | MUX_MODE2) /* mii1_txen.rgmii1_tctl */ + 0x128 (PIN_OUTPUT | MUX_MODE2) /* mii1_txd0.rgmii1_td0 */ + 0x124 (PIN_OUTPUT | MUX_MODE2) /* mii1_txd1.rgmii1_td1 */ + 0x120 (PIN_OUTPUT | MUX_MODE2) /* mii1_txd0.rgmii1_td2 */ + 0x11c (PIN_OUTPUT | MUX_MODE2) /* mii1_txd1.rgmii1_td3 */ + 0x130 (PIN_INPUT | MUX_MODE2) /* mii1_rxclk.rmii1_rclk */ + 0x118 (PIN_INPUT | MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */ + 0x140 (PIN_INPUT | MUX_MODE2) /* mii1_rxd0.rgmii1_rd0 */ + 0x13c (PIN_INPUT | MUX_MODE2) /* mii1_rxd1.rgmii1_rd1 */ + 0x138 (PIN_INPUT | MUX_MODE2) /* mii1_rxd0.rgmii1_rd2 */ + 0x134 (PIN_INPUT | MUX_MODE2) /* mii1_rxd1.rgmii1_rd3 */ /* Slave 2 */ - 0x58 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a6.rgmii2_tclk */ - 0x40 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a0.rgmii2_tctl */ - 0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a5.rgmii2_td0 */ - 0x50 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a4.rgmii2_td1 */ - 0x4c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a3.rgmii2_td2 */ - 0x48 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a2.rgmii2_td3 */ - 0x5c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a7.rgmii2_rclk */ - 0x44 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a1.rgmii2_rtcl */ - 0x6c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a11.rgmii2_rd0 */ - 0x68 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a10.rgmii2_rd1 */ - 0x64 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a9.rgmii2_rd2 */ - 0x60 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a8.rgmii2_rd3 */ + 0x58 (PIN_OUTPUT | MUX_MODE2) /* gpmc_a6.rgmii2_tclk */ + 0x40 (PIN_OUTPUT | MUX_MODE2) /* gpmc_a0.rgmii2_tctl */ + 0x54 (PIN_OUTPUT | MUX_MODE2) /* gpmc_a5.rgmii2_td0 */ + 0x50 (PIN_OUTPUT | MUX_MODE2) /* gpmc_a4.rgmii2_td1 */ + 0x4c (PIN_OUTPUT | MUX_MODE2) /* gpmc_a3.rgmii2_td2 */ + 0x48 (PIN_OUTPUT | MUX_MODE2) /* gpmc_a2.rgmii2_td3 */ + 0x5c (PIN_INPUT | MUX_MODE2) /* gpmc_a7.rgmii2_rclk */ + 0x44 (PIN_INPUT | MUX_MODE2) /* gpmc_a1.rgmii2_rtcl */ + 0x6c (PIN_INPUT | MUX_MODE2) /* gpmc_a11.rgmii2_rd0 */ + 0x68 (PIN_INPUT | MUX_MODE2) /* gpmc_a10.rgmii2_rd1 */ + 0x64 (PIN_INPUT | MUX_MODE2) /* gpmc_a9.rgmii2_rd2 */ + 0x60 (PIN_INPUT | MUX_MODE2) /* gpmc_a8.rgmii2_rd3 */ >; }; @@ -257,8 +257,8 @@ davinci_mdio_default: davinci_mdio_default { pinctrl-single,pins = < /* MDIO */ - 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ - 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ + 0x148 (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ + 0x14c (PIN_OUTPUT | MUX_MODE0) /* mdio_clk.mdio_clk */ >; }; -- cgit v1.2.3 From 221fed3cb527ab73ec645557ec6e0493b6869114 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 4 Dec 2014 11:01:57 -0600 Subject: ARM: dts: am437x-sk: add explicit pinmux for both USB instances This patch just makes USB[01]_DRVVBUS signal explicitly muxed. Note that board already has a discrete pulldown, so we're not adding any pulls here. Signed-off-by: Felipe Balbi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am437x-sk-evm.dts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts index 9e86cedab466..f7775c79ee96 100644 --- a/arch/arm/boot/dts/am437x-sk-evm.dts +++ b/arch/arm/boot/dts/am437x-sk-evm.dts @@ -329,6 +329,18 @@ 0x1c (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpcm_ad7.gpio1_7 */ >; }; + + usb1_pins: usb1_pins { + pinctrl-single,pins = < + 0x2c0 (PIN_OUTPUT | MUX_MODE0) /* usb0_drvvbus.usb0_drvvbus */ + >; + }; + + usb2_pins: usb2_pins { + pinctrl-single,pins = < + 0x2c4 (PIN_OUTPUT | MUX_MODE0) /* usb0_drvvbus.usb0_drvvbus */ + >; + }; }; &i2c0 { @@ -485,6 +497,8 @@ &usb1 { dr_mode = "peripheral"; status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&usb1_pins>; }; &usb2_phy2 { @@ -494,6 +508,8 @@ &usb2 { dr_mode = "host"; status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&usb2_pins>; }; &qspi { -- cgit v1.2.3 From 3cca412ef6f15b557c6df66647e50a3ce4d7b8ce Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 4 Dec 2014 11:01:58 -0600 Subject: ARM: dts: am437x-sk: remove internal i2c pullups AM437x Starter Kit already has discrete pullups for all I2C buses, so we can (and should) remove internal pulls. Signed-off-by: Felipe Balbi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am437x-sk-evm.dts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts index f7775c79ee96..5fab43798b2c 100644 --- a/arch/arm/boot/dts/am437x-sk-evm.dts +++ b/arch/arm/boot/dts/am437x-sk-evm.dts @@ -153,15 +153,15 @@ i2c0_pins: i2c0_pins { pinctrl-single,pins = < - 0x188 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_sda.i2c0_sda */ - 0x18c (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_scl.i2c0_scl */ + 0x188 (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_sda.i2c0_sda */ + 0x18c (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_scl.i2c0_scl */ >; }; i2c1_pins: i2c1_pins { pinctrl-single,pins = < - 0x15c (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2) /* spi0_cs0.i2c1_scl */ - 0x158 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE2) /* spi0_d1.i2c1_sda */ + 0x15c (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE2) /* spi0_cs0.i2c1_scl */ + 0x158 (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE2) /* spi0_d1.i2c1_sda */ >; }; -- cgit v1.2.3 From 2d8a28c27db6f6138a70d271c24797471bb31002 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 4 Dec 2014 11:01:59 -0600 Subject: ARM: dts: am437x-sk: remove DSS pulls The DSS data lines don't need pulls, it's best to remove them to guarantee signal integrity. Signed-off-by: Felipe Balbi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am437x-sk-evm.dts | 56 ++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts index 5fab43798b2c..3a7979e2db1a 100644 --- a/arch/arm/boot/dts/am437x-sk-evm.dts +++ b/arch/arm/boot/dts/am437x-sk-evm.dts @@ -272,34 +272,34 @@ dss_pins: dss_pins { pinctrl-single,pins = < - 0x020 (PIN_OUTPUT_PULLUP | MUX_MODE1) /* gpmc ad 8 -> DSS DATA 23 */ - 0x024 (PIN_OUTPUT_PULLUP | MUX_MODE1) - 0x028 (PIN_OUTPUT_PULLUP | MUX_MODE1) - 0x02c (PIN_OUTPUT_PULLUP | MUX_MODE1) - 0x030 (PIN_OUTPUT_PULLUP | MUX_MODE1) - 0x034 (PIN_OUTPUT_PULLUP | MUX_MODE1) - 0x038 (PIN_OUTPUT_PULLUP | MUX_MODE1) - 0x03c (PIN_OUTPUT_PULLUP | MUX_MODE1) /* gpmc ad 15 -> DSS DATA 16 */ - 0x0a0 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS DATA 0 */ - 0x0a4 (PIN_OUTPUT_PULLUP | MUX_MODE0) - 0x0a8 (PIN_OUTPUT_PULLUP | MUX_MODE0) - 0x0ac (PIN_OUTPUT_PULLUP | MUX_MODE0) - 0x0b0 (PIN_OUTPUT_PULLUP | MUX_MODE0) - 0x0b4 (PIN_OUTPUT_PULLUP | MUX_MODE0) - 0x0b8 (PIN_OUTPUT_PULLUP | MUX_MODE0) - 0x0bc (PIN_OUTPUT_PULLUP | MUX_MODE0) - 0x0c0 (PIN_OUTPUT_PULLUP | MUX_MODE0) - 0x0c4 (PIN_OUTPUT_PULLUP | MUX_MODE0) - 0x0c8 (PIN_OUTPUT_PULLUP | MUX_MODE0) - 0x0cc (PIN_OUTPUT_PULLUP | MUX_MODE0) - 0x0d0 (PIN_OUTPUT_PULLUP | MUX_MODE0) - 0x0d4 (PIN_OUTPUT_PULLUP | MUX_MODE0) - 0x0d8 (PIN_OUTPUT_PULLUP | MUX_MODE0) - 0x0dc (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS DATA 15 */ - 0x0e0 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS VSYNC */ - 0x0e4 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS HSYNC */ - 0x0e8 (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS PCLK */ - 0x0ec (PIN_OUTPUT_PULLUP | MUX_MODE0) /* DSS AC BIAS EN */ + 0x020 (PIN_OUTPUT | MUX_MODE1) /* gpmc ad 8 -> DSS DATA 23 */ + 0x024 (PIN_OUTPUT | MUX_MODE1) + 0x028 (PIN_OUTPUT | MUX_MODE1) + 0x02c (PIN_OUTPUT | MUX_MODE1) + 0x030 (PIN_OUTPUT | MUX_MODE1) + 0x034 (PIN_OUTPUT | MUX_MODE1) + 0x038 (PIN_OUTPUT | MUX_MODE1) + 0x03c (PIN_OUTPUT | MUX_MODE1) /* gpmc ad 15 -> DSS DATA 16 */ + 0x0a0 (PIN_OUTPUT | MUX_MODE0) /* DSS DATA 0 */ + 0x0a4 (PIN_OUTPUT | MUX_MODE0) + 0x0a8 (PIN_OUTPUT | MUX_MODE0) + 0x0ac (PIN_OUTPUT | MUX_MODE0) + 0x0b0 (PIN_OUTPUT | MUX_MODE0) + 0x0b4 (PIN_OUTPUT | MUX_MODE0) + 0x0b8 (PIN_OUTPUT | MUX_MODE0) + 0x0bc (PIN_OUTPUT | MUX_MODE0) + 0x0c0 (PIN_OUTPUT | MUX_MODE0) + 0x0c4 (PIN_OUTPUT | MUX_MODE0) + 0x0c8 (PIN_OUTPUT | MUX_MODE0) + 0x0cc (PIN_OUTPUT | MUX_MODE0) + 0x0d0 (PIN_OUTPUT | MUX_MODE0) + 0x0d4 (PIN_OUTPUT | MUX_MODE0) + 0x0d8 (PIN_OUTPUT | MUX_MODE0) + 0x0dc (PIN_OUTPUT | MUX_MODE0) /* DSS DATA 15 */ + 0x0e0 (PIN_OUTPUT | MUX_MODE0) /* DSS VSYNC */ + 0x0e4 (PIN_OUTPUT | MUX_MODE0) /* DSS HSYNC */ + 0x0e8 (PIN_OUTPUT | MUX_MODE0) /* DSS PCLK */ + 0x0ec (PIN_OUTPUT | MUX_MODE0) /* DSS AC BIAS EN */ >; }; -- cgit v1.2.3 From a75dacf8204a8ace6d42a28a157af3cc65ed3ddc Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 4 Dec 2014 15:02:57 -0600 Subject: ARM: dts: am57xx-beagle-x15: Add dual ethernet Add CPSW DT binding to beagle X15 DTS in order to get ethernet working with this board. Note that we're also adding sleep state which will place all pins in mux mode 15 - which means "driver off" - thus conserving power. Signed-off-by: Nishanth Menon Signed-off-by: Sekhar Nori Signed-off-by: Felipe Balbi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am57xx-beagle-x15.dts | 106 ++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts index 49edbda68cd5..6c2e8e41b1e9 100644 --- a/arch/arm/boot/dts/am57xx-beagle-x15.dts +++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts @@ -140,6 +140,86 @@ >; }; + cpsw_pins_default: cpsw_pins_default { + pinctrl-single,pins = < + /* Slave 1 */ + 0x250 (PIN_OUTPUT | MUX_MODE0) /* rgmii1_tclk */ + 0x254 (PIN_OUTPUT | MUX_MODE0) /* rgmii1_tctl */ + 0x258 (PIN_OUTPUT | MUX_MODE0) /* rgmii1_td3 */ + 0x25c (PIN_OUTPUT | MUX_MODE0) /* rgmii1_td2 */ + 0x260 (PIN_OUTPUT | MUX_MODE0) /* rgmii1_td1 */ + 0x264 (PIN_OUTPUT | MUX_MODE0) /* rgmii1_td0 */ + 0x268 (PIN_INPUT | MUX_MODE0) /* rgmii1_rclk */ + 0x26c (PIN_INPUT | MUX_MODE0) /* rgmii1_rctl */ + 0x270 (PIN_INPUT | MUX_MODE0) /* rgmii1_rd3 */ + 0x274 (PIN_INPUT | MUX_MODE0) /* rgmii1_rd2 */ + 0x278 (PIN_INPUT | MUX_MODE0) /* rgmii1_rd1 */ + 0x27c (PIN_INPUT | MUX_MODE0) /* rgmii1_rd0 */ + + /* Slave 2 */ + 0x198 (PIN_OUTPUT | MUX_MODE3) /* rgmii2_tclk */ + 0x19c (PIN_OUTPUT | MUX_MODE3) /* rgmii2_tctl */ + 0x1a0 (PIN_OUTPUT | MUX_MODE3) /* rgmii2_td3 */ + 0x1a4 (PIN_OUTPUT | MUX_MODE3) /* rgmii2_td2 */ + 0x1a8 (PIN_OUTPUT | MUX_MODE3) /* rgmii2_td1 */ + 0x1ac (PIN_OUTPUT | MUX_MODE3) /* rgmii2_td0 */ + 0x1b0 (PIN_INPUT | MUX_MODE3) /* rgmii2_rclk */ + 0x1b4 (PIN_INPUT | MUX_MODE3) /* rgmii2_rctl */ + 0x1b8 (PIN_INPUT | MUX_MODE3) /* rgmii2_rd3 */ + 0x1bc (PIN_INPUT | MUX_MODE3) /* rgmii2_rd2 */ + 0x1c0 (PIN_INPUT | MUX_MODE3) /* rgmii2_rd1 */ + 0x1c4 (PIN_INPUT | MUX_MODE3) /* rgmii2_rd0 */ + >; + + }; + + cpsw_pins_sleep: cpsw_pins_sleep { + pinctrl-single,pins = < + /* Slave 1 */ + 0x250 (PIN_INPUT | MUX_MODE15) + 0x254 (PIN_INPUT | MUX_MODE15) + 0x258 (PIN_INPUT | MUX_MODE15) + 0x25c (PIN_INPUT | MUX_MODE15) + 0x260 (PIN_INPUT | MUX_MODE15) + 0x264 (PIN_INPUT | MUX_MODE15) + 0x268 (PIN_INPUT | MUX_MODE15) + 0x26c (PIN_INPUT | MUX_MODE15) + 0x270 (PIN_INPUT | MUX_MODE15) + 0x274 (PIN_INPUT | MUX_MODE15) + 0x278 (PIN_INPUT | MUX_MODE15) + 0x27c (PIN_INPUT | MUX_MODE15) + + /* Slave 2 */ + 0x198 (PIN_INPUT | MUX_MODE15) + 0x19c (PIN_INPUT | MUX_MODE15) + 0x1a0 (PIN_INPUT | MUX_MODE15) + 0x1a4 (PIN_INPUT | MUX_MODE15) + 0x1a8 (PIN_INPUT | MUX_MODE15) + 0x1ac (PIN_INPUT | MUX_MODE15) + 0x1b0 (PIN_INPUT | MUX_MODE15) + 0x1b4 (PIN_INPUT | MUX_MODE15) + 0x1b8 (PIN_INPUT | MUX_MODE15) + 0x1bc (PIN_INPUT | MUX_MODE15) + 0x1c0 (PIN_INPUT | MUX_MODE15) + 0x1c4 (PIN_INPUT | MUX_MODE15) + >; + }; + + davinci_mdio_pins_default: davinci_mdio_pins_default { + pinctrl-single,pins = < + /* MDIO */ + 0x23c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_mclk */ + 0x240 (PIN_INPUT_PULLUP | MUX_MODE0) /* mdio_d */ + >; + }; + + davinci_mdio_pins_sleep: davinci_mdio_pins_sleep { + pinctrl-single,pins = < + 0x23c (PIN_INPUT | MUX_MODE15) + 0x240 (PIN_INPUT | MUX_MODE15) + >; + }; + tps659038_pins_default: tps659038_pins_default { pinctrl-single,pins = < 0x418 (PIN_INPUT_PULLUP | MUX_MODE14) /* wakeup0.gpio1_0 */ @@ -365,6 +445,32 @@ pinctrl-0 = <&uart3_pins_default>; }; +&mac { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cpsw_pins_default>; + pinctrl-1 = <&cpsw_pins_sleep>; + dual_emac; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <1>; + phy-mode = "rgmii"; + dual_emac_res_vlan = <1>; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <2>; + phy-mode = "rgmii"; + dual_emac_res_vlan = <2>; +}; + +&davinci_mdio { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&davinci_mdio_pins_default>; + pinctrl-1 = <&davinci_mdio_pins_sleep>; +}; + &mmc1 { status = "okay"; -- cgit v1.2.3 From 14fd7330db5f497f563f99367ebb19f2b50c83bd Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 7 Dec 2014 17:11:47 +0100 Subject: ARM: dts: omap3-n900: cleanup english This fixes english in comments and removes extra empty newline. Signed-off-by: Pavel Machek Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-n900.dts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts index 53f3ca064140..abf1daf84926 100644 --- a/arch/arm/boot/dts/omap3-n900.dts +++ b/arch/arm/boot/dts/omap3-n900.dts @@ -307,7 +307,7 @@ regulator-name = "V28"; regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; - regulator-always-on; /* due battery cover sensor */ + regulator-always-on; /* due to battery cover sensor */ }; &vaux2 { @@ -365,7 +365,6 @@ regulator-name = "VIO"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; - }; &vintana1 { -- cgit v1.2.3 From 4d5837d14cbb3d6a7d8c15b66c21f5bce17703a0 Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Tue, 16 Dec 2014 14:52:51 +0530 Subject: ARM: dts: DRA7X: drop id property in pcie_phy Since phyid is no longer used by pcie driver, this field can be dropped from the DT. Signed-off-by: Vignesh R Acked-by: Kishon Vijay Abraham I Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/dra7.dtsi | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi index 22771bc1643a..fffe768477da 100644 --- a/arch/arm/boot/dts/dra7.dtsi +++ b/arch/arm/boot/dts/dra7.dtsi @@ -1111,7 +1111,6 @@ "wkupclk", "refclk", "div-clk", "phy-div"; #phy-cells = <0>; - id = <1>; ti,hwmods = "pcie1-phy"; }; @@ -1132,7 +1131,6 @@ "div-clk", "phy-div"; #phy-cells = <0>; ti,hwmods = "pcie2-phy"; - id = <2>; status = "disabled"; }; }; -- cgit v1.2.3 From 9d0df0a65509b0a815ba02de9b3c5d4ea1b0a7de Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Thu, 18 Dec 2014 21:54:11 +0530 Subject: ARM: dts: am4372: add VPFE DT node entries Add Video Processing Front End (VPFE) device tree nodes for AM34xx family of devices. Signed-off-by: Benoit Parrot Signed-off-by: Darren Etheridge Signed-off-by: Felipe Balbi Signed-off-by: Lad, Prabhakar Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am4372.dtsi | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi index b62a1cd776cd..1943fc333e7c 100644 --- a/arch/arm/boot/dts/am4372.dtsi +++ b/arch/arm/boot/dts/am4372.dtsi @@ -948,6 +948,22 @@ interrupts = ; status = "disabled"; }; + + vpfe0: vpfe@48326000 { + compatible = "ti,am437x-vpfe"; + reg = <0x48326000 0x2000>; + interrupts = ; + ti,hwmods = "vpfe0"; + status = "disabled"; + }; + + vpfe1: vpfe@48328000 { + compatible = "ti,am437x-vpfe"; + reg = <0x48328000 0x2000>; + interrupts = ; + ti,hwmods = "vpfe1"; + status = "disabled"; + }; }; }; -- cgit v1.2.3 From d890edcd3f9d0d7176490ecd5330ebad2166192f Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Thu, 18 Dec 2014 21:54:12 +0530 Subject: ARM: dts: am43x-epos-evm: add VPFE device tree data Add device tree nodes and pinmux entries for Video Processing Front End (VPFE) on am43x epos evm. Signed-off-by: Benoit Parrot Signed-off-by: Darren Etheridge Signed-off-by: Felipe Balbi Signed-off-by: Lad, Prabhakar Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am43x-epos-evm.dts | 53 ++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts index 662261d6b2ca..257c099c347e 100644 --- a/arch/arm/boot/dts/am43x-epos-evm.dts +++ b/arch/arm/boot/dts/am43x-epos-evm.dts @@ -243,6 +243,42 @@ 0x08C (PIN_OUTPUT_PULLUP | MUX_MODE7) >; }; + + vpfe1_pins_default: vpfe1_pins_default { + pinctrl-single,pins = < + 0x1cc (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data9 mode 0 */ + 0x1d0 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data8 mode 0 */ + 0x1d4 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_hd mode 0 */ + 0x1d8 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_vd mode 0 */ + 0x1dc (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_pclk mode 0 */ + 0x1e8 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data0 mode 0 */ + 0x1ec (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data1 mode 0 */ + 0x1f0 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data2 mode 0 */ + 0x1f4 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data3 mode 0 */ + 0x1f8 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data4 mode 0 */ + 0x1fc (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data5 mode 0 */ + 0x200 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data6 mode 0 */ + 0x204 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data7 mode 0 */ + >; + }; + + vpfe1_pins_sleep: vpfe1_pins_sleep { + pinctrl-single,pins = < + 0x1cc (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1d0 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1d4 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1d8 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1dc (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1e8 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1ec (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1f0 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1f4 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1f8 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1fc (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x200 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x204 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + >; + }; }; matrix_keypad: matrix_keypad@0 { @@ -634,3 +670,20 @@ }; }; }; + +&vpfe1 { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&vpfe1_pins_default>; + pinctrl-1 = <&vpfe1_pins_sleep>; + + port { + vpfe1_ep: endpoint { + /* remote-endpoint = <&sensor>; add once we have it */ + ti,am437x-vpfe-interface = <0>; + bus-width = <8>; + hsync-active = <0>; + vsync-active = <0>; + }; + }; +}; -- cgit v1.2.3 From 5ccaa6ec0d466301857e3ae12b6c92071c0592a5 Mon Sep 17 00:00:00 2001 From: Darren Etheridge Date: Thu, 18 Dec 2014 21:54:13 +0530 Subject: ARM: dts: am437x-sk-evm: add VPFE device tree data Add device tree nodes and pinmux entries for Video Processing Front End (VPFE) on am437x sk evm. Signed-off-by: Darren Etheridge Signed-off-by: Felipe Balbi Signed-off-by: Lad, Prabhakar Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am437x-sk-evm.dts | 58 +++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts index 3a7979e2db1a..e12199ed161b 100644 --- a/arch/arm/boot/dts/am437x-sk-evm.dts +++ b/arch/arm/boot/dts/am437x-sk-evm.dts @@ -190,6 +190,46 @@ >; }; + vpfe0_pins_default: vpfe0_pins_default { + pinctrl-single,pins = < + 0x1b0 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_hd mode 0*/ + 0x1b4 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_vd mode 0*/ + 0x1b8 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_field mode 0*/ + 0x1bc (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_wen mode 0*/ + 0x1c0 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_pclk mode 0*/ + 0x1c4 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data8 mode 0*/ + 0x1c8 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data9 mode 0*/ + 0x208 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data0 mode 0*/ + 0x20c (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data1 mode 0*/ + 0x210 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data2 mode 0*/ + 0x214 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data3 mode 0*/ + 0x218 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data4 mode 0*/ + 0x21c (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data5 mode 0*/ + 0x220 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data6 mode 0*/ + 0x224 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data7 mode 0*/ + >; + }; + + vpfe0_pins_sleep: vpfe0_pins_sleep { + pinctrl-single,pins = < + 0x1b0 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1b4 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1b8 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1bc (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1c0 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1c4 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x1c8 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x208 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x20c (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x210 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x214 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x218 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x21c (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x220 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + 0x224 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) + >; + }; + cpsw_default: cpsw_default { pinctrl-single,pins = < /* Slave 1 */ @@ -636,3 +676,21 @@ &cpu { cpu0-supply = <&dcdc2>; }; + +&vpfe0 { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&vpfe0_pins_default>; + pinctrl-1 = <&vpfe0_pins_sleep>; + + /* Camera port */ + port { + vpfe0_ep: endpoint { + /* remote-endpoint = <&sensor>; add once we have it */ + ti,am437x-vpfe-interface = <0>; + bus-width = <8>; + hsync-active = <0>; + vsync-active = <0>; + }; + }; +}; -- cgit v1.2.3 From c788a7f4ed0b196a77a8be24f4eabdcc8b5cf3f8 Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Thu, 18 Dec 2014 21:54:14 +0530 Subject: ARM: dts: am437x-gp-evm: add VPFE device tree data Add device tree nodes and pinmux entries for Video Processing Front End (VPFE) on am437x gp evm. Signed-off-by: Benoit Parrot Signed-off-by: Lad, Prabhakar Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am437x-gp-evm.dts | 106 ++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts b/arch/arm/boot/dts/am437x-gp-evm.dts index 7eaae4cf9f89..f84d9715a4a9 100644 --- a/arch/arm/boot/dts/am437x-gp-evm.dts +++ b/arch/arm/boot/dts/am437x-gp-evm.dts @@ -268,6 +268,78 @@ 0x184 (PIN_INPUT_PULLUP | MUX_MODE2) /* uart1_txd.d_can1_rx */ >; }; + + vpfe0_pins_default: vpfe0_pins_default { + pinctrl-single,pins = < + 0x1B0 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_hd mode 0*/ + 0x1B4 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_vd mode 0*/ + 0x1C0 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_pclk mode 0*/ + 0x1C4 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data8 mode 0*/ + 0x1C8 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data9 mode 0*/ + 0x208 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data0 mode 0*/ + 0x20C (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data1 mode 0*/ + 0x210 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data2 mode 0*/ + 0x214 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data3 mode 0*/ + 0x218 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data4 mode 0*/ + 0x21C (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data5 mode 0*/ + 0x220 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data6 mode 0*/ + 0x224 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam0_data7 mode 0*/ + >; + }; + + vpfe0_pins_sleep: vpfe0_pins_sleep { + pinctrl-single,pins = < + 0x1B0 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_hd mode 0*/ + 0x1B4 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_vd mode 0*/ + 0x1C0 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_pclk mode 0*/ + 0x1C4 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_data8 mode 0*/ + 0x1C8 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_data9 mode 0*/ + 0x208 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_data0 mode 0*/ + 0x20C (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_data1 mode 0*/ + 0x210 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_data2 mode 0*/ + 0x214 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_data3 mode 0*/ + 0x218 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_data4 mode 0*/ + 0x21C (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_data5 mode 0*/ + 0x220 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_data6 mode 0*/ + 0x224 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam0_data7 mode 0*/ + >; + }; + + vpfe1_pins_default: vpfe1_pins_default { + pinctrl-single,pins = < + 0x1CC (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data9 mode 0*/ + 0x1D0 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data8 mode 0*/ + 0x1D4 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_hd mode 0*/ + 0x1D8 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_vd mode 0*/ + 0x1DC (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_pclk mode 0*/ + 0x1E8 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data0 mode 0*/ + 0x1EC (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data1 mode 0*/ + 0x1F0 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data2 mode 0*/ + 0x1F4 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data3 mode 0*/ + 0x1F8 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data4 mode 0*/ + 0x1FC (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data5 mode 0*/ + 0x200 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data6 mode 0*/ + 0x204 (PIN_INPUT_PULLUP | MUX_MODE0) /* cam1_data7 mode 0*/ + >; + }; + + vpfe1_pins_sleep: vpfe1_pins_sleep { + pinctrl-single,pins = < + 0x1CC (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data9 mode 0*/ + 0x1D0 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data8 mode 0*/ + 0x1D4 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_hd mode 0*/ + 0x1D8 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_vd mode 0*/ + 0x1DC (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_pclk mode 0*/ + 0x1E8 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data0 mode 0*/ + 0x1EC (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data1 mode 0*/ + 0x1F0 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data2 mode 0*/ + 0x1F4 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data3 mode 0*/ + 0x1F8 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data4 mode 0*/ + 0x1FC (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data5 mode 0*/ + 0x200 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data6 mode 0*/ + 0x204 (DS0_PULL_UP_DOWN_EN | INPUT_EN | MUX_MODE7) /* cam1_data7 mode 0*/ + >; + }; }; &i2c0 { @@ -545,3 +617,37 @@ pinctrl-0 = <&dcan1_default>; status = "okay"; }; + +&vpfe0 { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&vpfe0_pins_default>; + pinctrl-1 = <&vpfe0_pins_sleep>; + + port { + vpfe0_ep: endpoint { + /* remote-endpoint = <&sensor>; add once we have it */ + ti,am437x-vpfe-interface = <0>; + bus-width = <8>; + hsync-active = <0>; + vsync-active = <0>; + }; + }; +}; + +&vpfe1 { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&vpfe1_pins_default>; + pinctrl-1 = <&vpfe1_pins_sleep>; + + port { + vpfe1_ep: endpoint { + /* remote-endpoint = <&sensor>; add once we have it */ + ti,am437x-vpfe-interface = <0>; + bus-width = <8>; + hsync-active = <0>; + vsync-active = <0>; + }; + }; +}; -- cgit v1.2.3 From 47e0920cca5354acf7185b7a28e630f84b72bd16 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 22 Dec 2014 16:30:14 -0600 Subject: ARM: dts: add support for AM437x IDK The AM437x Industrial Development Kit (IDK) is an application development platform targeted at industrial communication and control applications. It comes with a 3-phase motor driver, PROFINET, PROFIBUS and a few other industrial communication interfaces. The board has 1GiB of DDR3 RAM, QSPI NOR flash, a 100% discrete power design (no PMIC) and an on-board 2MP camera (not supported with Linux as of this writing). Signed-off-by: Felipe Balbi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/am437x-idk-evm.dts | 381 +++++++++++++++++++++++++++++++++++ 2 files changed, 382 insertions(+) create mode 100644 arch/arm/boot/dts/am437x-idk-evm.dts (limited to 'arch') diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 91bd5bd62857..1b2c7de17cf3 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -366,6 +366,7 @@ dtb-$(CONFIG_ARCH_OMAP4) += omap4-duovero-parlor.dtb \ omap4-var-stk-om44.dtb dtb-$(CONFIG_SOC_AM43XX) += am43x-epos-evm.dtb \ am437x-sk-evm.dtb \ + am437x-idk-evm.dtb \ am437x-gp-evm.dtb dtb-$(CONFIG_SOC_OMAP5) += omap5-cm-t54.dtb \ omap5-sbc-t54.dtb \ diff --git a/arch/arm/boot/dts/am437x-idk-evm.dts b/arch/arm/boot/dts/am437x-idk-evm.dts new file mode 100644 index 000000000000..b52dd0a72d61 --- /dev/null +++ b/arch/arm/boot/dts/am437x-idk-evm.dts @@ -0,0 +1,381 @@ +/* + * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.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. + */ + +/dts-v1/; + +#include "am4372.dtsi" +#include +#include +#include +#include + +/ { + model = "TI AM437x Industrial Development Kit"; + compatible = "ti,am437x-idk-evm","ti,am4372","ti,am43"; + + v24_0d: fixed-regulator-v24_0d { + compatible = "regulator-fixed"; + regulator-name = "V24_0D"; + regulator-min-microvolt = <24000000>; + regulator-max-microvolt = <24000000>; + regulator-always-on; + regulator-boot-on; + }; + + v3_3d: fixed-regulator-v3_3d { + compatible = "regulator-fixed"; + regulator-name = "V3_3D"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&v24_0d>; + }; + + vdd_corereg: fixed-regulator-vdd_corereg { + compatible = "regulator-fixed"; + regulator-name = "VDD_COREREG"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&v24_0d>; + }; + + vdd_core: fixed-regulator-vdd_core { + compatible = "regulator-fixed"; + regulator-name = "VDD_CORE"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&vdd_corereg>; + }; + + v1_8dreg: fixed-regulator-v1_8dreg{ + compatible = "regulator-fixed"; + regulator-name = "V1_8DREG"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&v24_0d>; + }; + + v1_8d: fixed-regulator-v1_8d{ + compatible = "regulator-fixed"; + regulator-name = "V1_8D"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&v1_8dreg>; + }; + + v1_5dreg: fixed-regulator-v1_5dreg{ + compatible = "regulator-fixed"; + regulator-name = "V1_5DREG"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&v24_0d>; + }; + + v1_5d: fixed-regulator-v1_5d{ + compatible = "regulator-fixed"; + regulator-name = "V1_5D"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + regulator-boot-on; + vin-supply = <&v1_5dreg>; + }; +}; + +&am43xx_pinmux { + i2c0_pins_default: i2c0_pins_default { + pinctrl-single,pins = < + 0x188 (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_sda.i2c0_sda */ + 0x18c (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_scl.i2c0_scl */ + >; + }; + + i2c0_pins_sleep: i2c0_pins_sleep { + pinctrl-single,pins = < + 0x188 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x18c (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + i2c1_pins_default: i2c1_pins_default { + pinctrl-single,pins = < + 0x15c (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE2) /* spi0_cs0.i2c1_scl */ + 0x158 (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE2) /* spi0_d1.i2c1_sda */ + >; + }; + + i2c1_pins_sleep: i2c1_pins_sleep { + pinctrl-single,pins = < + 0x15c (PIN_INPUT_PULLDOWN | MUX_MODE7) /* spi0_cs0.i2c1_scl */ + 0x158 (PIN_INPUT_PULLDOWN | MUX_MODE7) /* spi0_d1.i2c1_sda */ + >; + }; + + mmc1_pins_default: pinmux_mmc1_pins_default { + pinctrl-single,pins = < + 0x100 (PIN_INPUT | MUX_MODE0) /* mmc0_clk.mmc0_clk */ + 0x104 (PIN_INPUT | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */ + 0x1f0 (PIN_INPUT | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */ + 0x1f4 (PIN_INPUT | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */ + 0x1f8 (PIN_INPUT | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */ + 0x1fc (PIN_INPUT | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */ + 0x160 (PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */ + >; + }; + + mmc1_pins_sleep: pinmux_mmc1_pins_sleep { + pinctrl-single,pins = < + 0x100 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x104 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x1f0 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x1f4 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x1f8 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x1fc (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x160 (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + ecap0_pins_default: backlight_pins_default { + pinctrl-single,pins = < + 0x164 (PIN_OUTPUT | MUX_MODE0) /* ecap0_in_pwm0_out.ecap0_in_pwm0_out */ + >; + }; + + cpsw_default: cpsw_default { + pinctrl-single,pins = < + 0x12c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txclk.rgmii1_tclk */ + 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_tctl */ + 0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td0 */ + 0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td1 */ + 0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td2 */ + 0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td3 */ + 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxclk.rmii1_rclk */ + 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */ + 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rd0 */ + 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rd1 */ + 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rd2 */ + 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rd3 */ + >; + }; + + cpsw_sleep: cpsw_sleep { + pinctrl-single,pins = < + 0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + davinci_mdio_default: davinci_mdio_default { + pinctrl-single,pins = < + /* MDIO */ + 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ + 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ + >; + }; + + davinci_mdio_sleep: davinci_mdio_sleep { + pinctrl-single,pins = < + /* MDIO reset value */ + 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + qspi_pins_default: qspi_pins_default { + pinctrl-single,pins = < + 0x7c (PIN_OUTPUT_PULLUP | MUX_MODE3) /* gpmc_csn0.qspi_csn */ + 0x88 (PIN_OUTPUT | MUX_MODE2) /* gpmc_csn3.qspi_clk */ + 0x90 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_advn_ale.qspi_d0 */ + 0x94 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_oen_ren.qspi_d1 */ + 0x98 (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_wen.qspi_d2 */ + 0x9c (PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_be0n_cle.qspi_d3 */ + >; + }; + + qspi_pins_sleep: qspi_pins_sleep{ + pinctrl-single,pins = < + 0x7c (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x88 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x90 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x94 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x98 (PIN_INPUT_PULLDOWN | MUX_MODE7) + 0x9c (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; +}; + +&i2c0 { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&i2c0_pins_default>; + pinctrl-1 = <&i2c0_pins_default>; + clock-frequency = <400000>; + + at24@50 { + compatible = "at24,24c256"; + pagesize = <64>; + reg = <0x50>; + }; +}; + +&i2c1 { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&i2c1_pins_default>; + pinctrl-1 = <&i2c1_pins_default>; + clock-frequency = <400000>; + + tps: tps62362@60 { + compatible = "ti,tps62362"; + regulator-name = "VDD_MPU"; + regulator-min-microvolt = <950000>; + regulator-max-microvolt = <1330000>; + regulator-boot-on; + regulator-always-on; + ti,vsel0-state-high; + ti,vsel1-state-high; + vin-supply = <&v3_3d>; + }; +}; + +&epwmss0 { + status = "okay"; +}; + +&ecap0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&ecap0_pins_default>; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio5 { + status = "okay"; +}; + +&mmc1 { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&mmc1_pins_default>; + pinctrl-1 = <&mmc1_pins_sleep>; + vmmc-supply = <&v3_3d>; + bus-width = <4>; + cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>; +}; + +&qspi { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&qspi_pins_default>; + pinctrl-1 = <&qspi_pins_sleep>; + + spi-max-frequency = <48000000>; + m25p80@0 { + compatible = "mx66l51235l"; + spi-max-frequency = <48000000>; + reg = <0>; + spi-cpol; + spi-cpha; + spi-tx-bus-width = <1>; + spi-rx-bus-width = <4>; + #address-cells = <1>; + #size-cells = <1>; + + /* + * MTD partition table. The ROM checks the first 512KiB for a + * valid file to boot(XIP). + */ + partition@0 { + label = "QSPI.U_BOOT"; + reg = <0x00000000 0x000080000>; + }; + partition@1 { + label = "QSPI.U_BOOT.backup"; + reg = <0x00080000 0x00080000>; + }; + partition@2 { + label = "QSPI.U-BOOT-SPL_OS"; + reg = <0x00100000 0x00010000>; + }; + partition@3 { + label = "QSPI.U_BOOT_ENV"; + reg = <0x00110000 0x00010000>; + }; + partition@4 { + label = "QSPI.U-BOOT-ENV.backup"; + reg = <0x00120000 0x00010000>; + }; + partition@5 { + label = "QSPI.KERNEL"; + reg = <0x00130000 0x0800000>; + }; + partition@6 { + label = "QSPI.FILESYSTEM"; + reg = <0x00930000 0x36D0000>; + }; + }; +}; + +&mac { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cpsw_default>; + pinctrl-1 = <&cpsw_sleep>; + status = "okay"; +}; + +&davinci_mdio { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&davinci_mdio_default>; + pinctrl-1 = <&davinci_mdio_sleep>; + status = "okay"; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <0>; + phy-mode = "rgmii"; +}; + +&rtc { + status = "okay"; +}; + +&wdt { + status = "okay"; +}; + +&cpu { + cpu0-supply = <&tps>; +}; -- cgit v1.2.3 From bb1c5fe1263d762ff0db45b6e97682e5047e54b4 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 26 Dec 2014 13:28:23 -0600 Subject: ARM: dts: am437x-sk: add power button binding Let this board report KEY_POWER so upper layers can decide what to do when power button is pressed. Signed-off-by: Felipe Balbi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am437x-sk-evm.dts | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts index e12199ed161b..832d24318f62 100644 --- a/arch/arm/boot/dts/am437x-sk-evm.dts +++ b/arch/arm/boot/dts/am437x-sk-evm.dts @@ -444,6 +444,11 @@ regulator-always-on; }; + power-button { + compatible = "ti,tps65218-pwrbutton"; + status = "okay"; + interrupts = <3 IRQ_TYPE_EDGE_BOTH>; + }; }; at24@50 { -- cgit v1.2.3 From f4b36909353ada35374dc51676f73362443bf206 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Fri, 26 Dec 2014 22:09:49 +0200 Subject: ARM: dts: N950/N9: add twl_power Add twl_power for N950/N9. Start with the simplest configuration to just enable power off. Signed-off-by: Aaro Koskinen Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-n950-n9.dtsi | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/omap3-n950-n9.dtsi b/arch/arm/boot/dts/omap3-n950-n9.dtsi index 1e49dfe7e212..c41db94ee9c2 100644 --- a/arch/arm/boot/dts/omap3-n950-n9.dtsi +++ b/arch/arm/boot/dts/omap3-n950-n9.dtsi @@ -60,6 +60,11 @@ &twl { compatible = "ti,twl5031"; + + twl_power: power { + compatible = "ti,twl4030-power"; + ti,use_poweroff; + }; }; &twl_gpio { -- cgit v1.2.3 From cd5bca6f627442b63012ac0cafc6452bc929832e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 26 Dec 2014 14:53:13 -0600 Subject: ARM: dts: am437x-idk: add gpio-based power key AM437x IDK board has a User Switch which we can program to whatever we want. Because this board doesn't have a PMIC which can give us power button presses, let's use this user switch as a gpio-keys power button. Signed-off-by: Felipe Balbi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am437x-idk-evm.dts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/am437x-idk-evm.dts b/arch/arm/boot/dts/am437x-idk-evm.dts index b52dd0a72d61..f9a17e2ca8cb 100644 --- a/arch/arm/boot/dts/am437x-idk-evm.dts +++ b/arch/arm/boot/dts/am437x-idk-evm.dts @@ -96,9 +96,29 @@ regulator-boot-on; vin-supply = <&v1_5dreg>; }; + + gpio_keys: gpio_keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&gpio_keys_pins_default>; + #address-cells = <1>; + #size-cells = <0>; + + switch@0 { + label = "power-button"; + linux,code = ; + gpios = <&gpio4 2 GPIO_ACTIVE_LOW>; + }; + }; }; &am43xx_pinmux { + gpio_keys_pins_default: gpio_keys_pins_default { + pinctrl-single,pins = < + 0x1b8 (PIN_INPUT | MUX_MODE7) /* cam0_field.gpio4_2 */ + >; + }; + i2c0_pins_default: i2c0_pins_default { pinctrl-single,pins = < 0x188 (PIN_INPUT | SLEWCTRL_FAST | MUX_MODE0) /* i2c0_sda.i2c0_sda */ @@ -282,6 +302,10 @@ status = "okay"; }; +&gpio4 { + status = "okay"; +}; + &gpio5 { status = "okay"; }; -- cgit v1.2.3 From 7a03f2c08d62371a6459331036e214bd7288ed10 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Mon, 5 Jan 2015 10:32:29 -0600 Subject: ARM: dts: am57xx-beagle-x15: Add GPIO controlled fan node TPS gpio now controls a 5v 500mA TL5209 regulator which may be supply a fan (such as AFB02505HHB) over J1 connector for various purposes. Provide device tree node to enable the same. Signed-off-by: Nishanth Menon Reviewed-by: Felipe Balbi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/am57xx-beagle-x15.dts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts index 6c2e8e41b1e9..c5d4ceabdd80 100644 --- a/arch/arm/boot/dts/am57xx-beagle-x15.dts +++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts @@ -80,6 +80,14 @@ default-state = "off"; }; }; + + gpio_fan: gpio_fan { + /* Based on 5v 500mA AFB02505HHB */ + compatible = "gpio-fan"; + gpios = <&tps659038_gpio 1 GPIO_ACTIVE_HIGH>; + gpio-fan,speed-map = <0 0>, + <13000 1>; + }; }; &dra7_pmx_core { @@ -394,6 +402,12 @@ wakeup-source; ti,palmas-long-press-seconds = <12>; }; + + tps659038_gpio: tps659038_gpio { + compatible = "ti,palmas-gpio"; + gpio-controller; + #gpio-cells = <2>; + }; }; tmp102: tmp102@48 { -- cgit v1.2.3 From 40b2091fba26439fead7e3737737454dba94897f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 22 Dec 2014 11:56:27 -0600 Subject: ARM: omap2plus_defconfig: reduce zImage size on omap2plus_defconfig By converting a few drivers to modules because they won't be needed during boot anyways, we can shave off about 700KiB of text. Note that while at that, and after discussions with Tony Lindgren, a few extra drivers were either removed because they weren't needed, or added because they're useful for debugging/testing. Below is output of size for pre and post vmlinux binaries: text data bss dec hex filename 8514799 765532 8416064 17696395 10e068b vmlinux-post-patch 9069110 800316 8419072 18288498 1170f72 vmlinux-pre-patch Signed-off-by: Felipe Balbi Signed-off-by: Tony Lindgren --- arch/arm/configs/omap2plus_defconfig | 116 ++++++++++++++++++++++------------- 1 file changed, 72 insertions(+), 44 deletions(-) (limited to 'arch') diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index c2c3a852af9f..efb0810e1b2b 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -13,7 +13,6 @@ CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_DEVICE=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y -CONFIG_RESOURCE_COUNTERS=y CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y CONFIG_MEMCG_KMEM=y @@ -68,7 +67,6 @@ CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y CONFIG_CPU_FREQ_GOV_POWERSAVE=y CONFIG_CPU_FREQ_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_GENERIC_CPUFREQ_CPU0=y # CONFIG_ARM_OMAP2PLUS_CPUFREQ is not set CONFIG_CPU_IDLE=y CONFIG_BINFMT_MISC=y @@ -103,7 +101,7 @@ CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_DMA_CMA=y CONFIG_OMAP_OCP2SCP=y -CONFIG_CONNECTOR=y +CONFIG_CONNECTOR=m CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_BLOCK=y @@ -122,14 +120,12 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=16384 CONFIG_SENSORS_TSL2550=m CONFIG_BMP085_I2C=m -CONFIG_SENSORS_LIS3_I2C=m CONFIG_SRAM=y -CONFIG_SCSI=y +CONFIG_SENSORS_LIS3_I2C=m CONFIG_BLK_DEV_SD=y CONFIG_SCSI_SCAN_ASYNC=y CONFIG_ATA=y CONFIG_SATA_AHCI_PLATFORM=y -CONFIG_MD=y CONFIG_NETDEVICES=y # CONFIG_NET_VENDOR_ARC is not set # CONFIG_NET_CADENCE is not set @@ -154,8 +150,8 @@ CONFIG_TI_CPSW=y # CONFIG_NET_VENDOR_WIZNET is not set CONFIG_AT803X_PHY=y CONFIG_SMSC_PHY=y -CONFIG_USB_USBNET=y -CONFIG_USB_NET_SMSC95XX=y +CONFIG_USB_USBNET=m +CONFIG_USB_NET_SMSC95XX=m CONFIG_USB_ALI_M5632=y CONFIG_USB_AN2720=y CONFIG_USB_EPSON2888=y @@ -172,18 +168,22 @@ CONFIG_WLCORE_SDIO=m CONFIG_MWIFIEX=m CONFIG_MWIFIEX_SDIO=m CONFIG_MWIFIEX_USB=m -CONFIG_INPUT_JOYDEV=y -CONFIG_INPUT_EVDEV=y -CONFIG_KEYBOARD_GPIO=y +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=m +CONFIG_KEYBOARD_ATKBD=m +CONFIG_KEYBOARD_GPIO=m CONFIG_KEYBOARD_MATRIX=m -CONFIG_KEYBOARD_TWL4030=y +CONFIG_KEYBOARD_OMAP4=m +CONFIG_KEYBOARD_TWL4030=m +# CONFIG_INPUT_MOUSE is not set CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_ADS7846=m CONFIG_TOUCHSCREEN_EDT_FT5X06=m CONFIG_TOUCHSCREEN_TSC2005=m CONFIG_TOUCHSCREEN_TSC2007=m CONFIG_INPUT_MISC=y -CONFIG_INPUT_TWL4030_PWRBUTTON=y +CONFIG_INPUT_TWL4030_PWRBUTTON=m +CONFIG_SERIO=m # CONFIG_LEGACY_PTYS is not set CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y @@ -196,15 +196,16 @@ CONFIG_SERIAL_8250_RSA=y CONFIG_SERIAL_OF_PLATFORM=y CONFIG_SERIAL_OMAP=y CONFIG_SERIAL_OMAP_CONSOLE=y -CONFIG_HW_RANDOM=y CONFIG_I2C_CHARDEV=y CONFIG_SPI=y CONFIG_SPI_OMAP24XX=y +CONFIG_SPI_TI_QSPI=m CONFIG_PINCTRL_SINGLE=y CONFIG_DEBUG_GPIO=y CONFIG_GPIO_SYSFS=y CONFIG_GPIO_TWL4030=y -CONFIG_W1=y +CONFIG_W1=m +CONFIG_HDQ_MASTER_OMAP=m CONFIG_BATTERY_BQ27x00=m CONFIG_CHARGER_ISP1704=m CONFIG_CHARGER_TWL4030=m @@ -213,20 +214,21 @@ CONFIG_CHARGER_BQ24190=m CONFIG_CHARGER_BQ24735=m CONFIG_POWER_RESET=y CONFIG_POWER_AVS=y +CONFIG_HWMON=m CONFIG_SENSORS_LM75=m -CONFIG_THERMAL=y +CONFIG_SENSORS_TMP102=m +CONFIG_THERMAL=m CONFIG_THERMAL_GOV_FAIR_SHARE=y CONFIG_THERMAL_GOV_USER_SPACE=y CONFIG_CPU_THERMAL=y -CONFIG_TI_SOC_THERMAL=y +CONFIG_TI_SOC_THERMAL=m CONFIG_TI_THERMAL=y CONFIG_OMAP4_THERMAL=y CONFIG_OMAP5_THERMAL=y CONFIG_DRA752_THERMAL=y CONFIG_WATCHDOG=y -CONFIG_OMAP_WATCHDOG=y -CONFIG_TWL4030_WATCHDOG=y -CONFIG_MFD_SYSCON=y +CONFIG_OMAP_WATCHDOG=m +CONFIG_TWL4030_WATCHDOG=m CONFIG_MFD_PALMAS=y CONFIG_MFD_TPS65217=y CONFIG_MFD_TPS65218=y @@ -289,51 +291,77 @@ CONFIG_SND_OMAP_SOC=m CONFIG_SND_OMAP_SOC_OMAP_TWL4030=m CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040=m CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m -CONFIG_USB=y +CONFIG_HID_GENERIC=m +CONFIG_USB_HIDDEV=y +CONFIG_USB_KBD=m +CONFIG_USB_MOUSE=m +CONFIG_USB=m CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -CONFIG_USB_MON=y +CONFIG_USB_MON=m CONFIG_USB_XHCI_HCD=m -CONFIG_USB_WDM=y -CONFIG_USB_STORAGE=y +CONFIG_USB_WDM=m +CONFIG_USB_STORAGE=m +CONFIG_USB_MUSB_HDRC=m +CONFIG_USB_MUSB_OMAP2PLUS=m +CONFIG_USB_MUSB_AM35X=m +CONFIG_USB_MUSB_DSPS=m CONFIG_USB_DWC3=m -CONFIG_USB_TEST=y +CONFIG_USB_TEST=m CONFIG_AM335X_PHY_USB=y -CONFIG_USB_GADGET=y +CONFIG_USB_GADGET=m CONFIG_USB_GADGET_DEBUG=y CONFIG_USB_GADGET_DEBUG_FILES=y CONFIG_USB_GADGET_DEBUG_FS=y +CONFIG_USB_CONFIGFS=m +CONFIG_USB_CONFIGFS_SERIAL=y +CONFIG_USB_CONFIGFS_ACM=y +CONFIG_USB_CONFIGFS_OBEX=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_ECM=y +CONFIG_USB_CONFIGFS_ECM_SUBSET=y +CONFIG_USB_CONFIGFS_RNDIS=y +CONFIG_USB_CONFIGFS_EEM=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_LB_SS=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_F_UAC1=y +CONFIG_USB_CONFIGFS_F_UAC2=y +CONFIG_USB_CONFIGFS_F_MIDI=y +CONFIG_USB_CONFIGFS_F_HID=y CONFIG_USB_ZERO=m CONFIG_MMC=y CONFIG_SDIO_UART=y CONFIG_MMC_OMAP=y CONFIG_MMC_OMAP_HS=y CONFIG_NEW_LEDS=y -CONFIG_LEDS_CLASS=y -CONFIG_LEDS_GPIO=y +CONFIG_LEDS_CLASS=m +CONFIG_LEDS_GPIO=m CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_TRIGGER_TIMER=y -CONFIG_LEDS_TRIGGER_ONESHOT=y -CONFIG_LEDS_TRIGGER_HEARTBEAT=y -CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_ONESHOT=m +CONFIG_LEDS_TRIGGER_HEARTBEAT=m +CONFIG_LEDS_TRIGGER_BACKLIGHT=m CONFIG_LEDS_TRIGGER_CPU=y -CONFIG_LEDS_TRIGGER_GPIO=y -CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_LEDS_TRIGGER_GPIO=m +CONFIG_LEDS_TRIGGER_DEFAULT_ON=m CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_TWL92330=y -CONFIG_RTC_DRV_TWL4030=y -CONFIG_RTC_DRV_OMAP=y +CONFIG_RTC_DRV_TWL4030=m +CONFIG_RTC_DRV_OMAP=m CONFIG_DMADEVICES=y CONFIG_TI_EDMA=y CONFIG_DMA_OMAP=y -CONFIG_EXTCON=y -CONFIG_EXTCON_PALMAS=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXTCON=m +CONFIG_EXTCON_PALMAS=m +CONFIG_TI_EMIF=m CONFIG_PWM=y -CONFIG_PWM_TIECAP=y -CONFIG_PWM_TIEHRPWM=y -CONFIG_PWM_TWL=y -CONFIG_PWM_TWL_LED=y -CONFIG_OMAP_USB2=y -CONFIG_TI_PIPE3=y +CONFIG_PWM_TIECAP=m +CONFIG_PWM_TIEHRPWM=m +CONFIG_PWM_TWL=m +CONFIG_PWM_TWL_LED=m +CONFIG_OMAP_USB2=m +CONFIG_TI_PIPE3=m CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set -- cgit v1.2.3 From 4af41284e83cc1cc5c527063716b3defa2e6f911 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 26 Dec 2014 13:28:24 -0600 Subject: ARM: omap2plus_defconfig: enable TPS65218 power button Enable tps65218 power button driver by default as a dynamically linked module so AM437x SK can report power button presses. Signed-off-by: Felipe Balbi Signed-off-by: Tony Lindgren --- arch/arm/configs/omap2plus_defconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index efb0810e1b2b..b5ccb36c599b 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -182,6 +182,7 @@ CONFIG_TOUCHSCREEN_EDT_FT5X06=m CONFIG_TOUCHSCREEN_TSC2005=m CONFIG_TOUCHSCREEN_TSC2007=m CONFIG_INPUT_MISC=y +CONFIG_INPUT_TPS65218_PWRBUTTON=m CONFIG_INPUT_TWL4030_PWRBUTTON=m CONFIG_SERIO=m # CONFIG_LEGACY_PTYS is not set -- cgit v1.2.3 From 2558cd8cab793e9c8c3b17bdf06552bfb98d49e5 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 18 Dec 2014 15:38:00 +0100 Subject: microblaze: Use unsigned type for limit comparison in cache.c The patch removes warnings: arch/microblaze/kernel/cpu/cache.c:146:14: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits] Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/cache.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c index a6e44410672d..0bde47e4fa69 100644 --- a/arch/microblaze/kernel/cpu/cache.c +++ b/arch/microblaze/kernel/cpu/cache.c @@ -140,10 +140,10 @@ do { \ /* It is used only first parameter for OP - for wic, wdc */ #define CACHE_RANGE_LOOP_1(start, end, line_length, op) \ do { \ - int volatile temp = 0; \ - int align = ~(line_length - 1); \ + unsigned int volatile temp = 0; \ + unsigned int align = ~(line_length - 1); \ end = ((end & align) == end) ? end - line_length : end & align; \ - WARN_ON(end - start < 0); \ + WARN_ON(end < start); \ \ __asm__ __volatile__ (" 1: " #op " %1, r0;" \ "cmpu %0, %1, %2;" \ -- cgit v1.2.3 From ed4602e13f8d7b764308d6db58ff9932353f16a3 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 18 Dec 2014 15:38:07 +0100 Subject: microblaze: Fix variable types to remove W=1 warning This patch removes this warning: arch/microblaze/kernel/signal.c: In function 'setup_rt_frame': arch/microblaze/kernel/signal.c:177:3: warning: signed and unsigned type in conditional expression [-Wsign-compare] Signed-off-by: Michal Simek --- arch/microblaze/kernel/signal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index 8955a3829cf0..235706055b7f 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c @@ -158,7 +158,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, { struct rt_sigframe __user *frame; int err = 0, sig = ksig->sig; - int signal; + unsigned long signal; unsigned long address = 0; #ifdef CONFIG_MMU pmd_t *pmdp; @@ -174,7 +174,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, && current_thread_info()->exec_domain->signal_invmap && sig < 32 ? current_thread_info()->exec_domain->signal_invmap[sig] - : sig; + : (unsigned long)sig; if (ksig->ka.sa.sa_flags & SA_SIGINFO) err |= copy_siginfo_to_user(&frame->info, &ksig->info); -- cgit v1.2.3 From 81653edd99ee2297ad6ab49a4f91a1d5dce577f1 Mon Sep 17 00:00:00 2001 From: Erico Nunes Date: Fri, 2 Jan 2015 00:40:33 -0200 Subject: microblaze: Add missing PVR version codes PVR version code was missing in the cpu_ver_lookup table for the following versions: 8.50.b 8.50.c 9.2 9.3 This caused /proc/cpuinfo to display "CPU-Ver: Unknown" for these versions. This was detected and the patch tested with MicroBlaze version 8.50.c. The other codes were taken from the Xilinx MicroBlaze Processor Reference Guides UG081 (v14.7) and UG984 (v2014.1). Signed-off-by: Erico Nunes Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/cpuinfo.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c index 234acad79b9e..b60442dcdedc 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo.c +++ b/arch/microblaze/kernel/cpu/cpuinfo.c @@ -41,8 +41,12 @@ const struct cpu_ver_key cpu_ver_lookup[] = { {"8.40.a", 0x18}, {"8.40.b", 0x19}, {"8.50.a", 0x1a}, + {"8.50.b", 0x1c}, + {"8.50.c", 0x1e}, {"9.0", 0x1b}, {"9.1", 0x1d}, + {"9.2", 0x1f}, + {"9.3", 0x20}, {NULL, 0}, }; -- cgit v1.2.3 From ed89466f2368fc15c72ce5344d582c640dcf53a6 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 5 Jan 2015 12:01:17 +0100 Subject: microblaze: Add target architecture Add missing target architectures - virtex7, ultrascale virtex and ultrascale kintex. Signed-off-by: Michal Simek --- arch/microblaze/kernel/cpu/cpuinfo.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c index b60442dcdedc..d1dd6e83d59b 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo.c +++ b/arch/microblaze/kernel/cpu/cpuinfo.c @@ -65,11 +65,14 @@ const struct family_string_key family_string_lookup[] = { {"spartan3adsp", 0xc}, {"spartan6", 0xd}, {"virtex6", 0xe}, + {"virtex7", 0xf}, /* FIXME There is no key code defined for spartan2 */ {"spartan2", 0xf0}, {"kintex7", 0x10}, {"artix7", 0x11}, {"zynq7000", 0x12}, + {"UltraScale Virtex", 0x13}, + {"UltraScale Kintex", 0x14}, {NULL, 0}, }; -- cgit v1.2.3 From 2c80a072a6c1cc4490fbbde5ba82bc7faf0374f0 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Fri, 19 Dec 2014 10:21:04 -0800 Subject: microblaze: intc: Don't override error codes Just pass on error codes instead of overriding them. Signed-off-by: Soren Brinkmann Signed-off-by: Michal Simek --- arch/microblaze/kernel/intc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c index 15c7c12ea0e7..01ae73088578 100644 --- a/arch/microblaze/kernel/intc.c +++ b/arch/microblaze/kernel/intc.c @@ -148,13 +148,13 @@ static int __init xilinx_intc_of_init(struct device_node *intc, ret = of_property_read_u32(intc, "xlnx,num-intr-inputs", &nr_irq); if (ret < 0) { pr_err("%s: unable to read xlnx,num-intr-inputs\n", __func__); - return -EINVAL; + return ret; } ret = of_property_read_u32(intc, "xlnx,kind-of-intr", &intr_mask); if (ret < 0) { pr_err("%s: unable to read xlnx,kind-of-intr\n", __func__); - return -EINVAL; + return ret; } if (intr_mask > (u32)((1ULL << nr_irq) - 1)) -- cgit v1.2.3 From d50466c90724d5aae4d38a9a9bc163bea6f94098 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Fri, 19 Dec 2014 10:21:05 -0800 Subject: microblaze: intc: Refactor DT sanity check Avoid funky casts and arithmetic. Signed-off-by: Soren Brinkmann Signed-off-by: Michal Simek --- arch/microblaze/kernel/intc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c index 01ae73088578..8965fd379570 100644 --- a/arch/microblaze/kernel/intc.c +++ b/arch/microblaze/kernel/intc.c @@ -157,7 +157,7 @@ static int __init xilinx_intc_of_init(struct device_node *intc, return ret; } - if (intr_mask > (u32)((1ULL << nr_irq) - 1)) + if (intr_mask >> nr_irq) pr_info(" ERROR: Mismatch in kind-of-intr param\n"); pr_info("%s: num_irq=%d, edge=0x%x\n", -- cgit v1.2.3 From 231856ae7ccb5ee49b2f722e1d8ba7a45df1a978 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Fri, 19 Dec 2014 10:21:06 -0800 Subject: microblaze: intc: Reformat output A message was using pr_info level output for a message including "ERROR" which is not really a fatal error. Remove the 'ERROR' from that message, use pr_warn loglevel and add the function name to the output to give users a chance to find the culprit in case the warning triggers. Signed-off-by: Soren Brinkmann Signed-off-by: Michal Simek --- arch/microblaze/kernel/intc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c index 8965fd379570..719feee1e043 100644 --- a/arch/microblaze/kernel/intc.c +++ b/arch/microblaze/kernel/intc.c @@ -158,7 +158,7 @@ static int __init xilinx_intc_of_init(struct device_node *intc, } if (intr_mask >> nr_irq) - pr_info(" ERROR: Mismatch in kind-of-intr param\n"); + pr_warn("%s: mismatch in kind-of-intr param\n", __func__); pr_info("%s: num_irq=%d, edge=0x%x\n", intc->full_name, nr_irq, intr_mask); -- cgit v1.2.3 From 0774bf6a8b49ccd35fad58a1eed0d2382f34912e Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 17:44:02 +0200 Subject: microblaze/uaccess: fix sparse errors virtio wants to read bitwise types from userspace using get_user. At the moment this triggers sparse errors, since the value is passed through an integer. Fix that up using __force. Signed-off-by: Michael S. Tsirkin Signed-off-by: Michal Simek --- arch/microblaze/include/asm/uaccess.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h index 59a89a64a865..e41bebf8d473 100644 --- a/arch/microblaze/include/asm/uaccess.h +++ b/arch/microblaze/include/asm/uaccess.h @@ -220,7 +220,7 @@ extern long __user_bad(void); } else { \ __gu_err = -EFAULT; \ } \ - x = (typeof(*(ptr)))__gu_val; \ + x = (__force typeof(*(ptr)))__gu_val; \ __gu_err; \ }) @@ -242,7 +242,7 @@ extern long __user_bad(void); default: \ /* __gu_val = 0; __gu_err = -EINVAL;*/ __gu_err = __user_bad();\ } \ - x = (__typeof__(*(ptr))) __gu_val; \ + x = (__force __typeof__(*(ptr))) __gu_val; \ __gu_err; \ }) -- cgit v1.2.3 From 132d5dfc04698e4226ca9787214bd4e277ed39f2 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 17:45:03 +0200 Subject: microblaze: whitespace fix Align using tabs to make code prettier. Signed-off-by: Michael S. Tsirkin Signed-off-by: Michal Simek --- arch/microblaze/include/asm/uaccess.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h index e41bebf8d473..62942fd12672 100644 --- a/arch/microblaze/include/asm/uaccess.h +++ b/arch/microblaze/include/asm/uaccess.h @@ -306,7 +306,7 @@ extern long __user_bad(void); #define __put_user_check(x, ptr, size) \ ({ \ - typeof(*(ptr)) volatile __pu_val = x; \ + typeof(*(ptr)) volatile __pu_val = x; \ typeof(*(ptr)) __user *__pu_addr = (ptr); \ int __pu_err = 0; \ \ -- cgit v1.2.3 From 1643b31658c44767a85469733c6bff4f6d0371c7 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Tue, 2 Dec 2014 08:07:11 -0800 Subject: ARM: zynq: DT: Add USB to device tree Add USB nodes to zc702, zc706 and zed device trees. Signed-off-by: Soren Brinkmann Signed-off-by: Michal Simek --- arch/arm/boot/dts/zynq-7000.dtsi | 20 ++++++++++++++++++++ arch/arm/boot/dts/zynq-zc702.dts | 11 +++++++++++ arch/arm/boot/dts/zynq-zc706.dts | 10 ++++++++++ arch/arm/boot/dts/zynq-zed.dts | 10 ++++++++++ 4 files changed, 51 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi index ee3e5d675b05..f1dd2a7020ae 100644 --- a/arch/arm/boot/dts/zynq-7000.dtsi +++ b/arch/arm/boot/dts/zynq-7000.dtsi @@ -314,6 +314,26 @@ clocks = <&clkc 4>; }; + usb0: usb@e0002000 { + compatible = "xlnx,zynq-usb-2.20a", "chipidea,usb2"; + status = "disabled"; + clocks = <&clkc 28>; + interrupt-parent = <&intc>; + interrupts = <0 21 4>; + reg = <0xe0002000 0x1000>; + phy_type = "ulpi"; + }; + + usb1: usb@e0003000 { + compatible = "xlnx,zynq-usb-2.20a", "chipidea,usb2"; + status = "disabled"; + clocks = <&clkc 29>; + interrupt-parent = <&intc>; + interrupts = <0 44 4>; + reg = <0xe0003000 0x1000>; + phy_type = "ulpi"; + }; + watchdog0: watchdog@f8005000 { clocks = <&clkc 45>; compatible = "xlnx,zynq-wdt-r1p2"; diff --git a/arch/arm/boot/dts/zynq-zc702.dts b/arch/arm/boot/dts/zynq-zc702.dts index 280f02dd4ddc..399fed4d9c19 100644 --- a/arch/arm/boot/dts/zynq-zc702.dts +++ b/arch/arm/boot/dts/zynq-zc702.dts @@ -36,6 +36,11 @@ linux,default-trigger = "heartbeat"; }; }; + + usb_phy0: phy0 { + compatible = "usb-nop-xceiv"; + #phy-cells = <0>; + }; }; &can0 { @@ -139,3 +144,9 @@ &uart1 { status = "okay"; }; + +&usb0 { + status = "okay"; + dr_mode = "host"; + usb-phy = <&usb_phy0>; +}; diff --git a/arch/arm/boot/dts/zynq-zc706.dts b/arch/arm/boot/dts/zynq-zc706.dts index 34f7812d2ee8..89cc9adc569d 100644 --- a/arch/arm/boot/dts/zynq-zc706.dts +++ b/arch/arm/boot/dts/zynq-zc706.dts @@ -27,6 +27,10 @@ bootargs = "console=ttyPS0,115200 earlyprintk"; }; + usb_phy0: phy0 { + compatible = "usb-nop-xceiv"; + #phy-cells = <0>; + }; }; &clkc { @@ -118,3 +122,9 @@ &uart1 { status = "okay"; }; + +&usb0 { + status = "okay"; + dr_mode = "host"; + usb-phy = <&usb_phy0>; +}; diff --git a/arch/arm/boot/dts/zynq-zed.dts b/arch/arm/boot/dts/zynq-zed.dts index 1c7cc990b47a..e20956e5e720 100644 --- a/arch/arm/boot/dts/zynq-zed.dts +++ b/arch/arm/boot/dts/zynq-zed.dts @@ -27,6 +27,10 @@ bootargs = "console=ttyPS0,115200 earlyprintk"; }; + usb_phy0: phy0 { + compatible = "usb-nop-xceiv"; + #phy-cells = <0>; + }; }; &clkc { @@ -50,3 +54,9 @@ &uart1 { status = "okay"; }; + +&usb0 { + status = "okay"; + dr_mode = "host"; + usb-phy = <&usb_phy0>; +}; -- cgit v1.2.3 From 58498ee3e573dc03be651b6839dbdf865ae7ee38 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 9 Dec 2014 10:18:49 +0100 Subject: s390/ftrace: add code replacement sanity checks Always verify that the to be replaced code matches what we expect to see. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/ftrace.c | 95 ++++++++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 46 deletions(-) (limited to 'arch') diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c index b86bb8823f15..3dabcae40e04 100644 --- a/arch/s390/kernel/ftrace.c +++ b/arch/s390/kernel/ftrace.c @@ -59,62 +59,65 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr) { - struct ftrace_insn insn; - unsigned short op; - void *from, *to; - size_t size; - - ftrace_generate_nop_insn(&insn); - size = sizeof(insn); - from = &insn; - to = (void *) rec->ip; - if (probe_kernel_read(&op, (void *) rec->ip, sizeof(op))) + struct ftrace_insn orig, new, old; + + if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old))) return -EFAULT; - /* - * If we find a breakpoint instruction, a kprobe has been placed - * at the beginning of the function. We write the constant - * KPROBE_ON_FTRACE_NOP into the remaining four bytes of the original - * instruction so that the kprobes handler can execute a nop, if it - * reaches this breakpoint. - */ - if (op == BREAKPOINT_INSTRUCTION) { - size -= 2; - from += 2; - to += 2; - insn.disp = KPROBE_ON_FTRACE_NOP; + if (addr == MCOUNT_ADDR) { + /* Initial code replacement; we expect to see stg r14,8(r15) */ + orig.opc = 0xe3e0; + orig.disp = 0xf0080024; + ftrace_generate_nop_insn(&new); + } else if (old.opc == BREAKPOINT_INSTRUCTION) { + /* + * If we find a breakpoint instruction, a kprobe has been + * placed at the beginning of the function. We write the + * constant KPROBE_ON_FTRACE_NOP into the remaining four + * bytes of the original instruction so that the kprobes + * handler can execute a nop, if it reaches this breakpoint. + */ + new.opc = orig.opc = BREAKPOINT_INSTRUCTION; + orig.disp = KPROBE_ON_FTRACE_CALL; + new.disp = KPROBE_ON_FTRACE_NOP; + } else { + /* Replace ftrace call with a nop. */ + ftrace_generate_call_insn(&orig, rec->ip); + ftrace_generate_nop_insn(&new); } - if (probe_kernel_write(to, from, size)) + /* Verify that the to be replaced code matches what we expect. */ + if (memcmp(&orig, &old, sizeof(old))) + return -EINVAL; + if (probe_kernel_write((void *) rec->ip, &new, sizeof(new))) return -EPERM; return 0; } int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) { - struct ftrace_insn insn; - unsigned short op; - void *from, *to; - size_t size; - - ftrace_generate_call_insn(&insn, rec->ip); - size = sizeof(insn); - from = &insn; - to = (void *) rec->ip; - if (probe_kernel_read(&op, (void *) rec->ip, sizeof(op))) + struct ftrace_insn orig, new, old; + + if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old))) return -EFAULT; - /* - * If we find a breakpoint instruction, a kprobe has been placed - * at the beginning of the function. We write the constant - * KPROBE_ON_FTRACE_CALL into the remaining four bytes of the original - * instruction so that the kprobes handler can execute a brasl if it - * reaches this breakpoint. - */ - if (op == BREAKPOINT_INSTRUCTION) { - size -= 2; - from += 2; - to += 2; - insn.disp = KPROBE_ON_FTRACE_CALL; + if (old.opc == BREAKPOINT_INSTRUCTION) { + /* + * If we find a breakpoint instruction, a kprobe has been + * placed at the beginning of the function. We write the + * constant KPROBE_ON_FTRACE_CALL into the remaining four + * bytes of the original instruction so that the kprobes + * handler can execute a brasl if it reaches this breakpoint. + */ + new.opc = orig.opc = BREAKPOINT_INSTRUCTION; + orig.disp = KPROBE_ON_FTRACE_NOP; + new.disp = KPROBE_ON_FTRACE_CALL; + } else { + /* Replace nop with an ftrace call. */ + ftrace_generate_nop_insn(&orig); + ftrace_generate_call_insn(&new, rec->ip); } - if (probe_kernel_write(to, from, size)) + /* Verify that the to be replaced code matches what we expect. */ + if (memcmp(&orig, &old, sizeof(old))) + return -EINVAL; + if (probe_kernel_write((void *) rec->ip, &new, sizeof(new))) return -EPERM; return 0; } -- cgit v1.2.3 From eba8452525e3fd0b982f78365dea8bd2ce11a20a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 12 Dec 2014 12:46:35 +0100 Subject: s390/pci: add missing address space annotation Signed-off-by: Heiko Carstens --- arch/s390/pci/pci_mmio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/s390/pci/pci_mmio.c b/arch/s390/pci/pci_mmio.c index 62c5ea6d8682..8aa271b3d1ad 100644 --- a/arch/s390/pci/pci_mmio.c +++ b/arch/s390/pci/pci_mmio.c @@ -55,7 +55,7 @@ SYSCALL_DEFINE3(s390_pci_mmio_write, unsigned long, mmio_addr, ret = get_pfn(mmio_addr, VM_WRITE, &pfn); if (ret) goto out; - io_addr = (void *)((pfn << PAGE_SHIFT) | (mmio_addr & ~PAGE_MASK)); + io_addr = (void __iomem *)((pfn << PAGE_SHIFT) | (mmio_addr & ~PAGE_MASK)); ret = -EFAULT; if ((unsigned long) io_addr < ZPCI_IOMAP_ADDR_BASE) @@ -96,7 +96,7 @@ SYSCALL_DEFINE3(s390_pci_mmio_read, unsigned long, mmio_addr, ret = get_pfn(mmio_addr, VM_READ, &pfn); if (ret) goto out; - io_addr = (void *)((pfn << PAGE_SHIFT) | (mmio_addr & ~PAGE_MASK)); + io_addr = (void __iomem *)((pfn << PAGE_SHIFT) | (mmio_addr & ~PAGE_MASK)); ret = -EFAULT; if ((unsigned long) io_addr < ZPCI_IOMAP_ADDR_BASE) -- cgit v1.2.3 From 8d1f211ebbdfd57843a52fa7efe34251530beec1 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 12 Dec 2014 12:52:00 +0100 Subject: s390/disassembler: remove indentical initializer Remove one of the two identical initializer entries. Signed-off-by: Heiko Carstens --- arch/s390/kernel/dis.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c index f3762937dd82..d46d0b0b2cda 100644 --- a/arch/s390/kernel/dis.c +++ b/arch/s390/kernel/dis.c @@ -226,7 +226,6 @@ static const struct s390_operand operands[] = [U16_32] = { 16, 32, 0 }, [J16_16] = { 16, 16, OPERAND_PCREL }, [J16_32] = { 16, 32, OPERAND_PCREL }, - [I16_32] = { 16, 32, OPERAND_SIGNED }, [I24_24] = { 24, 24, OPERAND_SIGNED }, [J32_16] = { 32, 16, OPERAND_PCREL }, [I32_16] = { 32, 16, OPERAND_SIGNED }, -- cgit v1.2.3 From 925dfc020a41ce484172a43b603437e58aecd1c1 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 12 Dec 2014 13:04:21 +0100 Subject: s390/pgtable: add unsigned long casts Get rid of warnings like this one: warning: constant 0xffe0000000000000 is so big it is unsigned long Signed-off-by: Heiko Carstens --- arch/s390/mm/pgtable.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 601deb85d2a0..47cbca079740 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -527,7 +527,7 @@ int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr) table += (gaddr >> 53) & 0x7ff; if ((*table & _REGION_ENTRY_INVALID) && gmap_alloc_table(gmap, table, _REGION2_ENTRY_EMPTY, - gaddr & 0xffe0000000000000)) + gaddr & 0xffe0000000000000UL)) return -ENOMEM; table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN); } @@ -535,7 +535,7 @@ int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr) table += (gaddr >> 42) & 0x7ff; if ((*table & _REGION_ENTRY_INVALID) && gmap_alloc_table(gmap, table, _REGION3_ENTRY_EMPTY, - gaddr & 0xfffffc0000000000)) + gaddr & 0xfffffc0000000000UL)) return -ENOMEM; table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN); } @@ -543,7 +543,7 @@ int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr) table += (gaddr >> 31) & 0x7ff; if ((*table & _REGION_ENTRY_INVALID) && gmap_alloc_table(gmap, table, _SEGMENT_ENTRY_EMPTY, - gaddr & 0xffffffff80000000)) + gaddr & 0xffffffff80000000UL)) return -ENOMEM; table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN); } -- cgit v1.2.3 From e0a50545480de0936ab867168d9bd086e56f465c Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 12 Dec 2014 13:11:08 +0100 Subject: s390/signal: add sys_sigreturn and sys_rt_sigreturn declarations Get rid of sparse warnings like this one: arch/s390/kernel/signal.c:244:1: warning: symbol 'sys_sigreturn' was not declared. Should it be static? Signed-off-by: Heiko Carstens --- arch/s390/kernel/entry.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h index 8e61393c8275..834df047d35f 100644 --- a/arch/s390/kernel/entry.h +++ b/arch/s390/kernel/entry.h @@ -71,9 +71,11 @@ struct s390_mmap_arg_struct; struct fadvise64_64_args; struct old_sigaction; +long sys_rt_sigreturn(void); +long sys_sigreturn(void); + long sys_s390_personality(unsigned int personality); long sys_s390_runtime_instr(int command, int signum); - long sys_s390_pci_mmio_write(unsigned long, const void __user *, size_t); long sys_s390_pci_mmio_read(unsigned long, void __user *, size_t); #endif /* _ENTRY_H */ -- cgit v1.2.3 From 47523c983f55448c3a09cc3f1a885bf81cd422e3 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 22 Dec 2014 10:07:04 +0100 Subject: s390: keep Kconfig sorted Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 68b68d755fdf..e79c3eab40b9 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -66,6 +66,7 @@ config S390 select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE select ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS select ARCH_HAS_GCOV_PROFILE_ALL + select ARCH_HAS_SG_CHAIN select ARCH_HAVE_NMI_SAFE_CMPXCHG select ARCH_INLINE_READ_LOCK select ARCH_INLINE_READ_LOCK_BH @@ -151,7 +152,6 @@ config S390 select TTY select VIRT_CPU_ACCOUNTING select VIRT_TO_BUS - select ARCH_HAS_SG_CHAIN config SCHED_OMIT_FRAME_POINTER def_bool y -- cgit v1.2.3 From fbf87dff6706d412fe69b8158f7ae415e5e7380b Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Sat, 3 Jan 2015 17:29:07 +0800 Subject: s390/sclp: fix declaration of _sclp_print_early() _sclp_print_early() has return value: at present, return 0 for OK, 1 for failure. It returns '%r2', so use 'long' as return value (upper caller can check '%r2' directly). The related warning: CC arch/s390/boot/compressed/misc.o arch/s390/boot/compressed/misc.c:66:8: warning: type defaults to 'int' in declaration of '_sclp_print_early' [-Wimplicit-int] extern _sclp_print_early(const char *); ^ At present, _sclp_print_early() is only used by puts(), so can still remain its declaration in 'misc.c' file. [heiko.carstens@de.ibm.com]: move declaration to sclp.h header file Signed-off-by: Chen Gang Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/boot/compressed/misc.c | 3 +-- arch/s390/include/asm/sclp.h | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/s390/boot/compressed/misc.c b/arch/s390/boot/compressed/misc.c index 57cbaff1f397..42506b371b74 100644 --- a/arch/s390/boot/compressed/misc.c +++ b/arch/s390/boot/compressed/misc.c @@ -8,6 +8,7 @@ #include #include +#include #include #include "sizes.h" @@ -63,8 +64,6 @@ static unsigned long free_mem_end_ptr; #include "../../../../lib/decompress_unxz.c" #endif -extern _sclp_print_early(const char *); - static int puts(const char *s) { _sclp_print_early(s); diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h index 1aba89b53cb9..b6f8066789c1 100644 --- a/arch/s390/include/asm/sclp.h +++ b/arch/s390/include/asm/sclp.h @@ -68,4 +68,6 @@ void sclp_early_detect(void); int sclp_has_siif(void); unsigned int sclp_get_ibc(void); +long _sclp_print_early(const char *); + #endif /* _ASM_S390_SCLP_H */ -- cgit v1.2.3 From a7e75d434b53b45ae60779903904d4fbdbd145a5 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 5 Jan 2015 10:10:14 +0100 Subject: s390/sclp: sign extend return value of _sclp_print_early() _sclp_print_early() has a return value, but misses to sign extend it if called from 64 bit code. This is not really a bug, since currently no caller cares what the return value is. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/sclp.S | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/s390/kernel/sclp.S b/arch/s390/kernel/sclp.S index a41f2c99dcc8..7e77e03378f3 100644 --- a/arch/s390/kernel/sclp.S +++ b/arch/s390/kernel/sclp.S @@ -294,7 +294,8 @@ ENTRY(_sclp_print_early) #ifdef CONFIG_64BIT tm LC_AR_MODE_ID,1 jno .Lesa3 - lmh %r6,%r15,96(%r15) # store upper register halves + lgfr %r2,%r2 # sign extend return value + lmh %r6,%r15,96(%r15) # restore upper register halves ahi %r15,80 .Lesa3: #endif -- cgit v1.2.3 From 91c0837e6dee8c694c8849c70e1f0f770d92d072 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 5 Jan 2015 04:29:18 -0800 Subject: s390: remove unnecessary KERN_CONT This has no effect as KERN_CONT is an empty string, It's probably just a missing conversion artifact as the other pr_cont uses in the same file don't have this prefix. Signed-off-by: Joe Perches Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/mm/fault.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 811937bb90be..232c14ea4269 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -171,7 +171,7 @@ static void dump_pagetable(unsigned long asce, unsigned long address) table = table + ((address >> 20) & 0x7ff); if (bad_address(table)) goto bad; - pr_cont(KERN_CONT "S:%016lx ", *table); + pr_cont("S:%016lx ", *table); if (*table & (_SEGMENT_ENTRY_INVALID | _SEGMENT_ENTRY_LARGE)) goto out; table = (unsigned long *)(*table & _SEGMENT_ENTRY_ORIGIN); -- cgit v1.2.3 From e6a67ad0e29087201536792f7d5cecec4ff6fc64 Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Thu, 1 Jan 2015 22:56:02 +0800 Subject: s390/crypto: remove 'const' to avoid compiler warnings In aes_encrypt() and aes_decrypt(), need let 'sctx->key' be modified, so remove 'const' for it. The related warnings: CC [M] arch/s390/crypto/aes_s390.o arch/s390/crypto/aes_s390.c: In function 'aes_encrypt': arch/s390/crypto/aes_s390.c:146:37: warning: passing argument 2 of 'crypt_s390_km' discards 'const' qualifier from pointer target type [-Wdiscarded-array-qualifiers] crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, ^ ... In file included from arch/s390/crypto/aes_s390.c:29:0: arch/s390/crypto/crypt_s390.h:154:19: note: expected 'void *' but argument is of type 'const u8 (*)[32] {aka const unsigned char (*)[32]}' static inline int crypt_s390_km(long func, void *param, ^ Signed-off-by: Chen Gang Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/crypto/aes_s390.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c index 1f272b24fc0b..5566ce80abdb 100644 --- a/arch/s390/crypto/aes_s390.c +++ b/arch/s390/crypto/aes_s390.c @@ -134,7 +134,7 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { - const struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); + struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); if (unlikely(need_fallback(sctx->key_len))) { crypto_cipher_encrypt_one(sctx->fallback.cip, out, in); @@ -159,7 +159,7 @@ static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) { - const struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); + struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); if (unlikely(need_fallback(sctx->key_len))) { crypto_cipher_decrypt_one(sctx->fallback.cip, out, in); -- cgit v1.2.3 From d97d929f06d0e072cd36fba6bd9d25b29bae34fd Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Thu, 8 Jan 2015 07:41:52 +0000 Subject: s390: move cacheinfo sysfs to generic cacheinfo infrastructure This patch removes the redundant sysfs cacheinfo code by reusing the newly introduced generic cacheinfo infrastructure through the commit 246246cbde5e ("drivers: base: support cpu cache information interface to userspace via sysfs") Signed-off-by: Sudeep Holla Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/cache.c | 388 +++++++++++------------------------------------ 1 file changed, 92 insertions(+), 296 deletions(-) (limited to 'arch') diff --git a/arch/s390/kernel/cache.c b/arch/s390/kernel/cache.c index c0b03c28d157..fe21f074cf9f 100644 --- a/arch/s390/kernel/cache.c +++ b/arch/s390/kernel/cache.c @@ -5,37 +5,11 @@ * Author(s): Heiko Carstens */ -#include #include -#include -#include -#include #include +#include #include -struct cache { - unsigned long size; - unsigned int line_size; - unsigned int associativity; - unsigned int nr_sets; - unsigned int level : 3; - unsigned int type : 2; - unsigned int private : 1; - struct list_head list; -}; - -struct cache_dir { - struct kobject *kobj; - struct cache_index_dir *index; -}; - -struct cache_index_dir { - struct kobject kobj; - int cpu; - struct cache *cache; - struct cache_index_dir *next; -}; - enum { CACHE_SCOPE_NOTEXISTS, CACHE_SCOPE_PRIVATE, @@ -44,10 +18,10 @@ enum { }; enum { - CACHE_TYPE_SEPARATE, - CACHE_TYPE_DATA, - CACHE_TYPE_INSTRUCTION, - CACHE_TYPE_UNIFIED, + CTYPE_SEPARATE, + CTYPE_DATA, + CTYPE_INSTRUCTION, + CTYPE_UNIFIED, }; enum { @@ -70,39 +44,59 @@ struct cache_info { }; #define CACHE_MAX_LEVEL 8 - union cache_topology { struct cache_info ci[CACHE_MAX_LEVEL]; unsigned long long raw; }; static const char * const cache_type_string[] = { - "Data", + "", "Instruction", + "Data", + "", "Unified", }; -static struct cache_dir *cache_dir_cpu[NR_CPUS]; -static LIST_HEAD(cache_list); +static const enum cache_type cache_type_map[] = { + [CTYPE_SEPARATE] = CACHE_TYPE_SEPARATE, + [CTYPE_DATA] = CACHE_TYPE_DATA, + [CTYPE_INSTRUCTION] = CACHE_TYPE_INST, + [CTYPE_UNIFIED] = CACHE_TYPE_UNIFIED, +}; void show_cacheinfo(struct seq_file *m) { - struct cache *cache; - int index = 0; + int cpu = smp_processor_id(), idx; + struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); + struct cacheinfo *cache; - list_for_each_entry(cache, &cache_list, list) { - seq_printf(m, "cache%-11d: ", index); + for (idx = 0; idx < this_cpu_ci->num_leaves; idx++) { + cache = this_cpu_ci->info_list + idx; + seq_printf(m, "cache%-11d: ", idx); seq_printf(m, "level=%d ", cache->level); seq_printf(m, "type=%s ", cache_type_string[cache->type]); - seq_printf(m, "scope=%s ", cache->private ? "Private" : "Shared"); - seq_printf(m, "size=%luK ", cache->size >> 10); - seq_printf(m, "line_size=%u ", cache->line_size); - seq_printf(m, "associativity=%d", cache->associativity); + seq_printf(m, "scope=%s ", + cache->disable_sysfs ? "Shared" : "Private"); + seq_printf(m, "size=%dK ", cache->size >> 10); + seq_printf(m, "line_size=%u ", cache->coherency_line_size); + seq_printf(m, "associativity=%d", cache->ways_of_associativity); seq_puts(m, "\n"); - index++; } } +static inline enum cache_type get_cache_type(struct cache_info *ci, int level) +{ + if (level >= CACHE_MAX_LEVEL) + return CACHE_TYPE_NOCACHE; + + ci += level; + + if (ci->scope != CACHE_SCOPE_SHARED && ci->scope != CACHE_SCOPE_PRIVATE) + return CACHE_TYPE_NOCACHE; + + return cache_type_map[ci->type]; +} + static inline unsigned long ecag(int ai, int li, int ti) { unsigned long cmd, val; @@ -113,277 +107,79 @@ static inline unsigned long ecag(int ai, int li, int ti) return val; } -static int __init cache_add(int level, int private, int type) +static void ci_leaf_init(struct cacheinfo *this_leaf, int private, + enum cache_type type, unsigned int level) { - struct cache *cache; - int ti; + int ti, num_sets; + int cpu = smp_processor_id(); - cache = kzalloc(sizeof(*cache), GFP_KERNEL); - if (!cache) - return -ENOMEM; - if (type == CACHE_TYPE_INSTRUCTION) + if (type == CACHE_TYPE_INST) ti = CACHE_TI_INSTRUCTION; else ti = CACHE_TI_UNIFIED; - cache->size = ecag(EXTRACT_SIZE, level, ti); - cache->line_size = ecag(EXTRACT_LINE_SIZE, level, ti); - cache->associativity = ecag(EXTRACT_ASSOCIATIVITY, level, ti); - cache->nr_sets = cache->size / cache->associativity; - cache->nr_sets /= cache->line_size; - cache->private = private; - cache->level = level + 1; - cache->type = type - 1; - list_add_tail(&cache->list, &cache_list); - return 0; -} - -static void __init cache_build_info(void) -{ - struct cache *cache, *next; - union cache_topology ct; - int level, private, rc; - - ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0); - for (level = 0; level < CACHE_MAX_LEVEL; level++) { - switch (ct.ci[level].scope) { - case CACHE_SCOPE_SHARED: - private = 0; - break; - case CACHE_SCOPE_PRIVATE: - private = 1; - break; - default: - return; - } - if (ct.ci[level].type == CACHE_TYPE_SEPARATE) { - rc = cache_add(level, private, CACHE_TYPE_DATA); - rc |= cache_add(level, private, CACHE_TYPE_INSTRUCTION); - } else { - rc = cache_add(level, private, ct.ci[level].type); - } - if (rc) - goto error; - } - return; -error: - list_for_each_entry_safe(cache, next, &cache_list, list) { - list_del(&cache->list); - kfree(cache); - } -} - -static struct cache_dir *cache_create_cache_dir(int cpu) -{ - struct cache_dir *cache_dir; - struct kobject *kobj = NULL; - struct device *dev; - - dev = get_cpu_device(cpu); - if (!dev) - goto out; - kobj = kobject_create_and_add("cache", &dev->kobj); - if (!kobj) - goto out; - cache_dir = kzalloc(sizeof(*cache_dir), GFP_KERNEL); - if (!cache_dir) - goto out; - cache_dir->kobj = kobj; - cache_dir_cpu[cpu] = cache_dir; - return cache_dir; -out: - kobject_put(kobj); - return NULL; -} - -static struct cache_index_dir *kobj_to_cache_index_dir(struct kobject *kobj) -{ - return container_of(kobj, struct cache_index_dir, kobj); -} - -static void cache_index_release(struct kobject *kobj) -{ - struct cache_index_dir *index; - - index = kobj_to_cache_index_dir(kobj); - kfree(index); -} - -static ssize_t cache_index_show(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - struct kobj_attribute *kobj_attr; - - kobj_attr = container_of(attr, struct kobj_attribute, attr); - return kobj_attr->show(kobj, kobj_attr, buf); -} - -#define DEFINE_CACHE_ATTR(_name, _format, _value) \ -static ssize_t cache_##_name##_show(struct kobject *kobj, \ - struct kobj_attribute *attr, \ - char *buf) \ -{ \ - struct cache_index_dir *index; \ - \ - index = kobj_to_cache_index_dir(kobj); \ - return sprintf(buf, _format, _value); \ -} \ -static struct kobj_attribute cache_##_name##_attr = \ - __ATTR(_name, 0444, cache_##_name##_show, NULL); -DEFINE_CACHE_ATTR(size, "%luK\n", index->cache->size >> 10); -DEFINE_CACHE_ATTR(coherency_line_size, "%u\n", index->cache->line_size); -DEFINE_CACHE_ATTR(number_of_sets, "%u\n", index->cache->nr_sets); -DEFINE_CACHE_ATTR(ways_of_associativity, "%u\n", index->cache->associativity); -DEFINE_CACHE_ATTR(type, "%s\n", cache_type_string[index->cache->type]); -DEFINE_CACHE_ATTR(level, "%d\n", index->cache->level); + this_leaf->level = level + 1; + this_leaf->type = type; + this_leaf->coherency_line_size = ecag(EXTRACT_LINE_SIZE, level, ti); + this_leaf->ways_of_associativity = ecag(EXTRACT_ASSOCIATIVITY, + level, ti); + this_leaf->size = ecag(EXTRACT_SIZE, level, ti); -static ssize_t shared_cpu_map_func(struct kobject *kobj, int type, char *buf) -{ - struct cache_index_dir *index; - int len; - - index = kobj_to_cache_index_dir(kobj); - len = type ? - cpulist_scnprintf(buf, PAGE_SIZE - 2, cpumask_of(index->cpu)) : - cpumask_scnprintf(buf, PAGE_SIZE - 2, cpumask_of(index->cpu)); - len += sprintf(&buf[len], "\n"); - return len; -} - -static ssize_t shared_cpu_map_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) -{ - return shared_cpu_map_func(kobj, 0, buf); + num_sets = this_leaf->size / this_leaf->coherency_line_size; + num_sets /= this_leaf->ways_of_associativity; + this_leaf->number_of_sets = num_sets; + cpumask_set_cpu(cpu, &this_leaf->shared_cpu_map); + if (!private) + this_leaf->disable_sysfs = true; } -static struct kobj_attribute cache_shared_cpu_map_attr = - __ATTR(shared_cpu_map, 0444, shared_cpu_map_show, NULL); -static ssize_t shared_cpu_list_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) +int init_cache_level(unsigned int cpu) { - return shared_cpu_map_func(kobj, 1, buf); -} -static struct kobj_attribute cache_shared_cpu_list_attr = - __ATTR(shared_cpu_list, 0444, shared_cpu_list_show, NULL); - -static struct attribute *cache_index_default_attrs[] = { - &cache_type_attr.attr, - &cache_size_attr.attr, - &cache_number_of_sets_attr.attr, - &cache_ways_of_associativity_attr.attr, - &cache_level_attr.attr, - &cache_coherency_line_size_attr.attr, - &cache_shared_cpu_map_attr.attr, - &cache_shared_cpu_list_attr.attr, - NULL, -}; - -static const struct sysfs_ops cache_index_ops = { - .show = cache_index_show, -}; - -static struct kobj_type cache_index_type = { - .sysfs_ops = &cache_index_ops, - .release = cache_index_release, - .default_attrs = cache_index_default_attrs, -}; - -static int cache_create_index_dir(struct cache_dir *cache_dir, - struct cache *cache, int index, int cpu) -{ - struct cache_index_dir *index_dir; - int rc; - - index_dir = kzalloc(sizeof(*index_dir), GFP_KERNEL); - if (!index_dir) - return -ENOMEM; - index_dir->cache = cache; - index_dir->cpu = cpu; - rc = kobject_init_and_add(&index_dir->kobj, &cache_index_type, - cache_dir->kobj, "index%d", index); - if (rc) - goto out; - index_dir->next = cache_dir->index; - cache_dir->index = index_dir; - return 0; -out: - kfree(index_dir); - return rc; -} + struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); + unsigned int level = 0, leaves = 0; + union cache_topology ct; + enum cache_type ctype; -static int cache_add_cpu(int cpu) -{ - struct cache_dir *cache_dir; - struct cache *cache; - int rc, index = 0; + if (!this_cpu_ci) + return -EINVAL; - if (list_empty(&cache_list)) - return 0; - cache_dir = cache_create_cache_dir(cpu); - if (!cache_dir) - return -ENOMEM; - list_for_each_entry(cache, &cache_list, list) { - if (!cache->private) + ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0); + do { + ctype = get_cache_type(&ct.ci[0], level); + if (ctype == CACHE_TYPE_NOCACHE) break; - rc = cache_create_index_dir(cache_dir, cache, index, cpu); - if (rc) - return rc; - index++; - } - return 0; -} + /* Separate instruction and data caches */ + leaves += (ctype == CACHE_TYPE_SEPARATE) ? 2 : 1; + } while (++level < CACHE_MAX_LEVEL); -static void cache_remove_cpu(int cpu) -{ - struct cache_index_dir *index, *next; - struct cache_dir *cache_dir; + this_cpu_ci->num_levels = level; + this_cpu_ci->num_leaves = leaves; - cache_dir = cache_dir_cpu[cpu]; - if (!cache_dir) - return; - index = cache_dir->index; - while (index) { - next = index->next; - kobject_put(&index->kobj); - index = next; - } - kobject_put(cache_dir->kobj); - kfree(cache_dir); - cache_dir_cpu[cpu] = NULL; + return 0; } -static int cache_hotplug(struct notifier_block *nfb, unsigned long action, - void *hcpu) +int populate_cache_leaves(unsigned int cpu) { - int cpu = (long)hcpu; - int rc = 0; + unsigned int level, idx, pvt; + union cache_topology ct; + enum cache_type ctype; + struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); + struct cacheinfo *this_leaf = this_cpu_ci->info_list; - switch (action & ~CPU_TASKS_FROZEN) { - case CPU_ONLINE: - rc = cache_add_cpu(cpu); - if (rc) - cache_remove_cpu(cpu); - break; - case CPU_DEAD: - cache_remove_cpu(cpu); - break; + ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0); + for (idx = 0, level = 0; level < this_cpu_ci->num_levels && + idx < this_cpu_ci->num_leaves; idx++, level++) { + if (!this_leaf) + return -EINVAL; + + pvt = (ct.ci[level].scope == CACHE_SCOPE_PRIVATE) ? 1 : 0; + ctype = get_cache_type(&ct.ci[0], level); + if (ctype == CACHE_TYPE_SEPARATE) { + ci_leaf_init(this_leaf++, pvt, CACHE_TYPE_DATA, level); + ci_leaf_init(this_leaf++, pvt, CACHE_TYPE_INST, level); + } else { + ci_leaf_init(this_leaf++, pvt, ctype, level); + } } - return rc ? NOTIFY_BAD : NOTIFY_OK; -} - -static int __init cache_init(void) -{ - int cpu; - - if (!test_facility(34)) - return 0; - cache_build_info(); - - cpu_notifier_register_begin(); - for_each_online_cpu(cpu) - cache_add_cpu(cpu); - __hotcpu_notifier(cache_hotplug, 0); - cpu_notifier_register_done(); return 0; } -device_initcall(cache_init); -- cgit v1.2.3 From ac00aa4dcd085e4cf01761095ec1e2a141f86f38 Mon Sep 17 00:00:00 2001 From: Eddie Huang Date: Fri, 1 May 2015 13:28:00 +0200 Subject: ARM: mediatek: dts: Add UART dts for MT8127 and MT8135 boards This patch enable UART for MT8127 moose board and MT8135 evalution board. Adding the dts, these two boards can show log and shell prompts. Signed-off-by: Eddie Huang Signed-off-by: Matthias Brugger --- arch/arm/boot/dts/mt8127-moose.dts | 4 ++++ arch/arm/boot/dts/mt8135-evbp1.dts | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/mt8127-moose.dts b/arch/arm/boot/dts/mt8127-moose.dts index 13cba0e77e08..073e295a1cb4 100644 --- a/arch/arm/boot/dts/mt8127-moose.dts +++ b/arch/arm/boot/dts/mt8127-moose.dts @@ -23,3 +23,7 @@ reg = <0 0x80000000 0 0x40000000>; }; }; + +&uart0 { + status = "okay"; +}; diff --git a/arch/arm/boot/dts/mt8135-evbp1.dts b/arch/arm/boot/dts/mt8135-evbp1.dts index a5adf9742308..36677382bdd8 100644 --- a/arch/arm/boot/dts/mt8135-evbp1.dts +++ b/arch/arm/boot/dts/mt8135-evbp1.dts @@ -23,3 +23,7 @@ reg = <0 0x80000000 0 0x40000000>; }; }; + +&uart3 { + status = "okay"; +}; -- cgit v1.2.3 From c6b3a64f7040520c0f0d6d15a6dbe2f41789e21b Mon Sep 17 00:00:00 2001 From: Howard Chen Date: Thu, 8 Jan 2015 14:23:10 +0800 Subject: ARM: mediatek: Add sysirq device node to mt6592 dtsi Add sysirq node to mt6592.dtsi and also correct timer interrupt flag. The old setting works because boot loader already set it. With a sysirq device node, the timer interrupt can use a correct value. Signed-off-by: Howard Chen Signed-off-by: Matthias Brugger --- arch/arm/boot/dts/mt6592.dtsi | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/mt6592.dtsi b/arch/arm/boot/dts/mt6592.dtsi index 31e5a0979d78..67c817418392 100644 --- a/arch/arm/boot/dts/mt6592.dtsi +++ b/arch/arm/boot/dts/mt6592.dtsi @@ -18,7 +18,7 @@ / { compatible = "mediatek,mt6592"; - interrupt-parent = <&gic>; + interrupt-parent = <&sysirq>; cpus { #address-cells = <1>; @@ -81,18 +81,25 @@ timer: timer@10008000 { compatible = "mediatek,mt6577-timer"; reg = <0x10008000 0x80>; - interrupts = ; + interrupts = ; clocks = <&system_clk>, <&rtc_clk>; clock-names = "system-clk", "rtc-clk"; }; + sysirq: interrupt-controller@10200220 { + compatible = "mediatek,mt6592-sysirq", "mediatek,mt6577-sysirq"; + interrupt-controller; + #interrupt-cells = <3>; + interrupt-parent = <&gic>; + reg = <0x10200220 0x1c>; + }; + gic: interrupt-controller@10211000 { compatible = "arm,cortex-a7-gic"; interrupt-controller; #interrupt-cells = <3>; + interrupt-parent = <&gic>; reg = <0x10211000 0x1000>, <0x10212000 0x1000>; }; - }; - -- cgit v1.2.3 From 32b0aa9aaeb4a493135ea6368a614aa89c3c5488 Mon Sep 17 00:00:00 2001 From: Pankaj Dubey Date: Fri, 9 Jan 2015 01:14:23 +0900 Subject: ARM: EXYNOS: Remove i2c sys configuration related code As all these code has been moved into i2c driver, now we can safely remove them from machine files. CC: Russell King Signed-off-by: Pankaj Dubey Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/exynos.c | 39 ++------------------------------- arch/arm/mach-exynos/include/mach/map.h | 3 --- arch/arm/mach-exynos/pm.c | 3 ++- arch/arm/mach-exynos/regs-sys.h | 22 ------------------- arch/arm/mach-exynos/suspend.c | 7 ------ 5 files changed, 4 insertions(+), 70 deletions(-) delete mode 100644 arch/arm/mach-exynos/regs-sys.h (limited to 'arch') diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index c13d0837fa8c..2c844393cc4b 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -27,20 +27,16 @@ #include #include +#include + #include "common.h" #include "mfc.h" #include "regs-pmu.h" -#include "regs-sys.h" void __iomem *pmu_base_addr; static struct map_desc exynos4_iodesc[] __initdata = { { - .virtual = (unsigned long)S3C_VA_SYS, - .pfn = __phys_to_pfn(EXYNOS4_PA_SYSCON), - .length = SZ_64K, - .type = MT_DEVICE, - }, { .virtual = (unsigned long)S5P_VA_SROMC, .pfn = __phys_to_pfn(EXYNOS4_PA_SROMC), .length = SZ_4K, @@ -70,11 +66,6 @@ static struct map_desc exynos4_iodesc[] __initdata = { static struct map_desc exynos5_iodesc[] __initdata = { { - .virtual = (unsigned long)S3C_VA_SYS, - .pfn = __phys_to_pfn(EXYNOS5_PA_SYSCON), - .length = SZ_64K, - .type = MT_DEVICE, - }, { .virtual = (unsigned long)S5P_VA_SROMC, .pfn = __phys_to_pfn(EXYNOS5_PA_SROMC), .length = SZ_4K, @@ -213,32 +204,6 @@ static void __init exynos_init_irq(void) static void __init exynos_dt_machine_init(void) { - struct device_node *i2c_np; - const char *i2c_compat = "samsung,s3c2440-i2c"; - unsigned int tmp; - int id; - - /* - * Exynos5's legacy i2c controller and new high speed i2c - * controller have muxed interrupt sources. By default the - * interrupts for 4-channel HS-I2C controller are enabled. - * If node for first four channels of legacy i2c controller - * are available then re-configure the interrupts via the - * system register. - */ - if (soc_is_exynos5()) { - for_each_compatible_node(i2c_np, NULL, i2c_compat) { - if (of_device_is_available(i2c_np)) { - id = of_alias_get_id(i2c_np, "i2c"); - if (id < 4) { - tmp = readl(EXYNOS5_SYS_I2C_CFG); - writel(tmp & ~(0x1 << id), - EXYNOS5_SYS_I2C_CFG); - } - } - } - } - /* * This is called from smp_prepare_cpus if we've built for SMP, but * we still need to set it up for PM and firmware ops if not. diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h index 1ad3f496ef56..de3ae59e1cfb 100644 --- a/arch/arm/mach-exynos/include/mach/map.h +++ b/arch/arm/mach-exynos/include/mach/map.h @@ -24,9 +24,6 @@ #define EXYNOS_PA_CHIPID 0x10000000 -#define EXYNOS4_PA_SYSCON 0x10010000 -#define EXYNOS5_PA_SYSCON 0x10050100 - #define EXYNOS4_PA_CMU 0x10030000 #define EXYNOS5_PA_CMU 0x10010000 diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c index 86f3ecd88f78..dfc8594e5b1f 100644 --- a/arch/arm/mach-exynos/pm.c +++ b/arch/arm/mach-exynos/pm.c @@ -23,12 +23,13 @@ #include #include +#include + #include #include "common.h" #include "exynos-pmu.h" #include "regs-pmu.h" -#include "regs-sys.h" static inline void __iomem *exynos_boot_vector_addr(void) { diff --git a/arch/arm/mach-exynos/regs-sys.h b/arch/arm/mach-exynos/regs-sys.h deleted file mode 100644 index 84332b0dd7a6..000000000000 --- a/arch/arm/mach-exynos/regs-sys.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. - * http://www.samsung.com - * - * EXYNOS - system register definition - * - * 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. -*/ - -#ifndef __ASM_ARCH_REGS_SYS_H -#define __ASM_ARCH_REGS_SYS_H __FILE__ - -#include - -#define S5P_SYSREG(x) (S3C_VA_SYS + (x)) - -/* For EXYNOS5 */ -#define EXYNOS5_SYS_I2C_CFG S5P_SYSREG(0x0234) - -#endif /* __ASM_ARCH_REGS_SYS_H */ diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c index f8e7dcd17055..342797b9bf3b 100644 --- a/arch/arm/mach-exynos/suspend.c +++ b/arch/arm/mach-exynos/suspend.c @@ -34,7 +34,6 @@ #include "common.h" #include "regs-pmu.h" -#include "regs-sys.h" #include "exynos-pmu.h" #define S5P_CHECK_SLEEP 0x00000BAD @@ -53,10 +52,6 @@ struct exynos_wkup_irq { u32 mask; }; -static struct sleep_save exynos5_sys_save[] = { - SAVE_ITEM(EXYNOS5_SYS_I2C_CFG), -}; - static struct sleep_save exynos_core_save[] = { /* SROM side */ SAVE_ITEM(S5P_SROM_BW), @@ -497,8 +492,6 @@ static const struct exynos_pm_data exynos5250_pm_data = { .wkup_irq = exynos5250_wkup_irq, .wake_disable_mask = ((0xFF << 8) | (0x1F << 1)), .release_ret_regs = exynos_release_ret_regs, - .extra_save = exynos5_sys_save, - .num_extra_save = ARRAY_SIZE(exynos5_sys_save), .pm_suspend = exynos_pm_suspend, .pm_resume = exynos_pm_resume, .pm_prepare = exynos_pm_prepare, -- cgit v1.2.3 From ff651cb613b4cc8aa2e4284525948872b4d77d66 Mon Sep 17 00:00:00 2001 From: Wincy Van Date: Thu, 11 Dec 2014 08:52:58 +0300 Subject: KVM: nVMX: Add nested msr load/restore algorithm Several hypervisors need MSR auto load/restore feature. We read MSRs from VM-entry MSR load area which specified by L1, and load them via kvm_set_msr in the nested entry. When nested exit occurs, we get MSRs via kvm_get_msr, writing them to L1`s MSR store area. After this, we read MSRs from VM-exit MSR load area, and load them via kvm_set_msr. Signed-off-by: Wincy Van Signed-off-by: Paolo Bonzini --- arch/x86/include/uapi/asm/vmx.h | 5 ++ arch/x86/kvm/vmx.c | 101 +++++++++++++++++++++++++++++++++++----- arch/x86/kvm/x86.c | 1 + 3 files changed, 96 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/uapi/asm/vmx.h b/arch/x86/include/uapi/asm/vmx.h index b813bf9da1e2..ff2b8e28883e 100644 --- a/arch/x86/include/uapi/asm/vmx.h +++ b/arch/x86/include/uapi/asm/vmx.h @@ -56,6 +56,7 @@ #define EXIT_REASON_MSR_READ 31 #define EXIT_REASON_MSR_WRITE 32 #define EXIT_REASON_INVALID_STATE 33 +#define EXIT_REASON_MSR_LOAD_FAIL 34 #define EXIT_REASON_MWAIT_INSTRUCTION 36 #define EXIT_REASON_MONITOR_INSTRUCTION 39 #define EXIT_REASON_PAUSE_INSTRUCTION 40 @@ -116,10 +117,14 @@ { EXIT_REASON_APIC_WRITE, "APIC_WRITE" }, \ { EXIT_REASON_EOI_INDUCED, "EOI_INDUCED" }, \ { EXIT_REASON_INVALID_STATE, "INVALID_STATE" }, \ + { EXIT_REASON_MSR_LOAD_FAIL, "MSR_LOAD_FAIL" }, \ { EXIT_REASON_INVD, "INVD" }, \ { EXIT_REASON_INVVPID, "INVVPID" }, \ { EXIT_REASON_INVPCID, "INVPCID" }, \ { EXIT_REASON_XSAVES, "XSAVES" }, \ { EXIT_REASON_XRSTORS, "XRSTORS" } +#define VMX_ABORT_SAVE_GUEST_MSR_FAIL 1 +#define VMX_ABORT_LOAD_HOST_MSR_FAIL 4 + #endif /* _UAPIVMX_H */ diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index d4c58d884838..9137d2ba26a2 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -6143,6 +6143,13 @@ static void nested_vmx_failValid(struct kvm_vcpu *vcpu, */ } +static void nested_vmx_abort(struct kvm_vcpu *vcpu, u32 indicator) +{ + /* TODO: not to reset guest simply here. */ + kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); + pr_warn("kvm: nested vmx abort, indicator %d\n", indicator); +} + static enum hrtimer_restart vmx_preemption_timer_fn(struct hrtimer *timer) { struct vcpu_vmx *vmx = @@ -8286,6 +8293,67 @@ static void vmx_start_preemption_timer(struct kvm_vcpu *vcpu) ns_to_ktime(preemption_timeout), HRTIMER_MODE_REL); } +static inline int nested_vmx_msr_check_common(struct vmx_msr_entry *e) +{ + if (e->index >> 8 == 0x8 || e->reserved != 0) + return -EINVAL; + return 0; +} + +static inline int nested_vmx_load_msr_check(struct vmx_msr_entry *e) +{ + if (e->index == MSR_FS_BASE || + e->index == MSR_GS_BASE || + nested_vmx_msr_check_common(e)) + return -EINVAL; + return 0; +} + +/* + * Load guest's/host's msr at nested entry/exit. + * return 0 for success, entry index for failure. + */ +static u32 nested_vmx_load_msr(struct kvm_vcpu *vcpu, u64 gpa, u32 count) +{ + u32 i; + struct vmx_msr_entry e; + struct msr_data msr; + + msr.host_initiated = false; + for (i = 0; i < count; i++) { + kvm_read_guest(vcpu->kvm, gpa + i * sizeof(e), &e, sizeof(e)); + if (nested_vmx_load_msr_check(&e)) + goto fail; + msr.index = e.index; + msr.data = e.value; + if (kvm_set_msr(vcpu, &msr)) + goto fail; + } + return 0; +fail: + return i + 1; +} + +static int nested_vmx_store_msr(struct kvm_vcpu *vcpu, u64 gpa, u32 count) +{ + u32 i; + struct vmx_msr_entry e; + + for (i = 0; i < count; i++) { + kvm_read_guest(vcpu->kvm, gpa + i * sizeof(e), + &e, 2 * sizeof(u32)); + if (nested_vmx_msr_check_common(&e)) + return -EINVAL; + if (kvm_get_msr(vcpu, e.index, &e.value)) + return -EINVAL; + kvm_write_guest(vcpu->kvm, + gpa + i * sizeof(e) + + offsetof(struct vmx_msr_entry, value), + &e.value, sizeof(e.value)); + } + return 0; +} + /* * prepare_vmcs02 is called when the L1 guest hypervisor runs its nested * L2 guest. L1 has a vmcs for L2 (vmcs12), and this function "merges" it @@ -8582,6 +8650,7 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch) int cpu; struct loaded_vmcs *vmcs02; bool ia32e; + u32 msr_entry_idx; if (!nested_vmx_check_permission(vcpu) || !nested_vmx_check_vmcs12(vcpu)) @@ -8629,15 +8698,6 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch) return 1; } - if (vmcs12->vm_entry_msr_load_count > 0 || - vmcs12->vm_exit_msr_load_count > 0 || - vmcs12->vm_exit_msr_store_count > 0) { - pr_warn_ratelimited("%s: VMCS MSR_{LOAD,STORE} unsupported\n", - __func__); - nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD); - return 1; - } - if (!vmx_control_verify(vmcs12->cpu_based_vm_exec_control, nested_vmx_true_procbased_ctls_low, nested_vmx_procbased_ctls_high) || @@ -8739,10 +8799,21 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch) vmx_segment_cache_clear(vmx); - vmcs12->launch_state = 1; - prepare_vmcs02(vcpu, vmcs12); + msr_entry_idx = nested_vmx_load_msr(vcpu, + vmcs12->vm_entry_msr_load_addr, + vmcs12->vm_entry_msr_load_count); + if (msr_entry_idx) { + leave_guest_mode(vcpu); + vmx_load_vmcs01(vcpu); + nested_vmx_entry_failure(vcpu, vmcs12, + EXIT_REASON_MSR_LOAD_FAIL, msr_entry_idx); + return 1; + } + + vmcs12->launch_state = 1; + if (vmcs12->guest_activity_state == GUEST_ACTIVITY_HLT) return kvm_emulate_halt(vcpu); @@ -9172,6 +9243,10 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu, kvm_set_dr(vcpu, 7, 0x400); vmcs_write64(GUEST_IA32_DEBUGCTL, 0); + + if (nested_vmx_load_msr(vcpu, vmcs12->vm_exit_msr_load_addr, + vmcs12->vm_exit_msr_load_count)) + nested_vmx_abort(vcpu, VMX_ABORT_LOAD_HOST_MSR_FAIL); } /* @@ -9193,6 +9268,10 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason, prepare_vmcs12(vcpu, vmcs12, exit_reason, exit_intr_info, exit_qualification); + if (nested_vmx_store_msr(vcpu, vmcs12->vm_exit_msr_store_addr, + vmcs12->vm_exit_msr_store_count)) + nested_vmx_abort(vcpu, VMX_ABORT_SAVE_GUEST_MSR_FAIL); + vmx_load_vmcs01(vcpu); if ((exit_reason == EXIT_REASON_EXTERNAL_INTERRUPT) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index c259814200bd..af9faed270f1 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2324,6 +2324,7 @@ int kvm_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata) { return kvm_x86_ops->get_msr(vcpu, msr_index, pdata); } +EXPORT_SYMBOL_GPL(kvm_get_msr); static int get_msr_mtrr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) { -- cgit v1.2.3 From e9ac033e6b6970c7061725fc6824b3933eb5a0e7 Mon Sep 17 00:00:00 2001 From: Eugene Korenevsky Date: Thu, 11 Dec 2014 08:53:27 +0300 Subject: KVM: nVMX: Improve nested msr switch checking This patch improve checks required by Intel Software Developer Manual. - SMM MSRs are not allowed. - microcode MSRs are not allowed. - check x2apic MSRs only when LAPIC is in x2apic mode. - MSR switch areas must be aligned to 16 bytes. - address of first and last byte in MSR switch areas should not set any bits beyond the processor's physical-address width. Also it adds warning messages on failures during MSR switch. These messages are useful for people who debug their VMMs in nVMX. Signed-off-by: Eugene Korenevsky Signed-off-by: Paolo Bonzini --- arch/x86/include/uapi/asm/msr-index.h | 3 + arch/x86/kvm/vmx.c | 128 ++++++++++++++++++++++++++++++---- 2 files changed, 117 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/uapi/asm/msr-index.h b/arch/x86/include/uapi/asm/msr-index.h index c8aa65d56027..d0050f25ea80 100644 --- a/arch/x86/include/uapi/asm/msr-index.h +++ b/arch/x86/include/uapi/asm/msr-index.h @@ -356,6 +356,9 @@ #define MSR_IA32_UCODE_WRITE 0x00000079 #define MSR_IA32_UCODE_REV 0x0000008b +#define MSR_IA32_SMM_MONITOR_CTL 0x0000009b +#define MSR_IA32_SMBASE 0x0000009e + #define MSR_IA32_PERF_STATUS 0x00000198 #define MSR_IA32_PERF_CTL 0x00000199 #define MSR_AMD_PSTATE_DEF_BASE 0xc0010064 diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 9137d2ba26a2..70bdcf946f95 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -8293,18 +8293,80 @@ static void vmx_start_preemption_timer(struct kvm_vcpu *vcpu) ns_to_ktime(preemption_timeout), HRTIMER_MODE_REL); } -static inline int nested_vmx_msr_check_common(struct vmx_msr_entry *e) +static int nested_vmx_check_msr_switch(struct kvm_vcpu *vcpu, + unsigned long count_field, + unsigned long addr_field, + int maxphyaddr) { - if (e->index >> 8 == 0x8 || e->reserved != 0) + u64 count, addr; + + if (vmcs12_read_any(vcpu, count_field, &count) || + vmcs12_read_any(vcpu, addr_field, &addr)) { + WARN_ON(1); + return -EINVAL; + } + if (count == 0) + return 0; + if (!IS_ALIGNED(addr, 16) || addr >> maxphyaddr || + (addr + count * sizeof(struct vmx_msr_entry) - 1) >> maxphyaddr) { + pr_warn_ratelimited( + "nVMX: invalid MSR switch (0x%lx, %d, %llu, 0x%08llx)", + addr_field, maxphyaddr, count, addr); + return -EINVAL; + } + return 0; +} + +static int nested_vmx_check_msr_switch_controls(struct kvm_vcpu *vcpu, + struct vmcs12 *vmcs12) +{ + int maxphyaddr; + + if (vmcs12->vm_exit_msr_load_count == 0 && + vmcs12->vm_exit_msr_store_count == 0 && + vmcs12->vm_entry_msr_load_count == 0) + return 0; /* Fast path */ + maxphyaddr = cpuid_maxphyaddr(vcpu); + if (nested_vmx_check_msr_switch(vcpu, VM_EXIT_MSR_LOAD_COUNT, + VM_EXIT_MSR_LOAD_ADDR, maxphyaddr) || + nested_vmx_check_msr_switch(vcpu, VM_EXIT_MSR_STORE_COUNT, + VM_EXIT_MSR_STORE_ADDR, maxphyaddr) || + nested_vmx_check_msr_switch(vcpu, VM_ENTRY_MSR_LOAD_COUNT, + VM_ENTRY_MSR_LOAD_ADDR, maxphyaddr)) + return -EINVAL; + return 0; +} + +static int nested_vmx_msr_check_common(struct kvm_vcpu *vcpu, + struct vmx_msr_entry *e) +{ + /* x2APIC MSR accesses are not allowed */ + if (apic_x2apic_mode(vcpu->arch.apic) && e->index >> 8 == 0x8) + return -EINVAL; + if (e->index == MSR_IA32_UCODE_WRITE || /* SDM Table 35-2 */ + e->index == MSR_IA32_UCODE_REV) + return -EINVAL; + if (e->reserved != 0) return -EINVAL; return 0; } -static inline int nested_vmx_load_msr_check(struct vmx_msr_entry *e) +static int nested_vmx_load_msr_check(struct kvm_vcpu *vcpu, + struct vmx_msr_entry *e) { if (e->index == MSR_FS_BASE || e->index == MSR_GS_BASE || - nested_vmx_msr_check_common(e)) + e->index == MSR_IA32_SMM_MONITOR_CTL || /* SMM is not supported */ + nested_vmx_msr_check_common(vcpu, e)) + return -EINVAL; + return 0; +} + +static int nested_vmx_store_msr_check(struct kvm_vcpu *vcpu, + struct vmx_msr_entry *e) +{ + if (e->index == MSR_IA32_SMBASE || /* SMM is not supported */ + nested_vmx_msr_check_common(vcpu, e)) return -EINVAL; return 0; } @@ -8321,13 +8383,27 @@ static u32 nested_vmx_load_msr(struct kvm_vcpu *vcpu, u64 gpa, u32 count) msr.host_initiated = false; for (i = 0; i < count; i++) { - kvm_read_guest(vcpu->kvm, gpa + i * sizeof(e), &e, sizeof(e)); - if (nested_vmx_load_msr_check(&e)) + if (kvm_read_guest(vcpu->kvm, gpa + i * sizeof(e), + &e, sizeof(e))) { + pr_warn_ratelimited( + "%s cannot read MSR entry (%u, 0x%08llx)\n", + __func__, i, gpa + i * sizeof(e)); goto fail; + } + if (nested_vmx_load_msr_check(vcpu, &e)) { + pr_warn_ratelimited( + "%s check failed (%u, 0x%x, 0x%x)\n", + __func__, i, e.index, e.reserved); + goto fail; + } msr.index = e.index; msr.data = e.value; - if (kvm_set_msr(vcpu, &msr)) + if (kvm_set_msr(vcpu, &msr)) { + pr_warn_ratelimited( + "%s cannot write MSR (%u, 0x%x, 0x%llx)\n", + __func__, i, e.index, e.value); goto fail; + } } return 0; fail: @@ -8340,16 +8416,35 @@ static int nested_vmx_store_msr(struct kvm_vcpu *vcpu, u64 gpa, u32 count) struct vmx_msr_entry e; for (i = 0; i < count; i++) { - kvm_read_guest(vcpu->kvm, gpa + i * sizeof(e), - &e, 2 * sizeof(u32)); - if (nested_vmx_msr_check_common(&e)) + if (kvm_read_guest(vcpu->kvm, + gpa + i * sizeof(e), + &e, 2 * sizeof(u32))) { + pr_warn_ratelimited( + "%s cannot read MSR entry (%u, 0x%08llx)\n", + __func__, i, gpa + i * sizeof(e)); return -EINVAL; - if (kvm_get_msr(vcpu, e.index, &e.value)) + } + if (nested_vmx_store_msr_check(vcpu, &e)) { + pr_warn_ratelimited( + "%s check failed (%u, 0x%x, 0x%x)\n", + __func__, i, e.index, e.reserved); return -EINVAL; - kvm_write_guest(vcpu->kvm, - gpa + i * sizeof(e) + + } + if (kvm_get_msr(vcpu, e.index, &e.value)) { + pr_warn_ratelimited( + "%s cannot read MSR (%u, 0x%x)\n", + __func__, i, e.index); + return -EINVAL; + } + if (kvm_write_guest(vcpu->kvm, + gpa + i * sizeof(e) + offsetof(struct vmx_msr_entry, value), - &e.value, sizeof(e.value)); + &e.value, sizeof(e.value))) { + pr_warn_ratelimited( + "%s cannot write MSR (%u, 0x%x, 0x%llx)\n", + __func__, i, e.index, e.value); + return -EINVAL; + } } return 0; } @@ -8698,6 +8793,11 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch) return 1; } + if (nested_vmx_check_msr_switch_controls(vcpu, vmcs12)) { + nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD); + return 1; + } + if (!vmx_control_verify(vmcs12->cpu_based_vm_exec_control, nested_vmx_true_procbased_ctls_low, nested_vmx_procbased_ctls_high) || -- cgit v1.2.3 From 19d5f10b3ad08f596d2682404af9a3a9030aa684 Mon Sep 17 00:00:00 2001 From: Eugene Korenevsky Date: Tue, 16 Dec 2014 22:35:53 +0300 Subject: KVM: nVMX: consult PFEC_MASK and PFEC_MATCH when generating #PF VM-exit When generating #PF VM-exit, check equality: (PFEC & PFEC_MASK) == PFEC_MATCH If there is equality, the 14 bit of exception bitmap is used to take decision about generating #PF VM-exit. If there is inequality, inverted 14 bit is used. Signed-off-by: Eugene Korenevsky Signed-off-by: Paolo Bonzini --- arch/x86/kvm/vmx.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 70bdcf946f95..e14c96e574ff 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -8206,6 +8206,18 @@ static void nested_ept_uninit_mmu_context(struct kvm_vcpu *vcpu) vcpu->arch.walk_mmu = &vcpu->arch.mmu; } +static bool nested_vmx_is_page_fault_vmexit(struct vmcs12 *vmcs12, + u16 error_code) +{ + bool inequality, bit; + + bit = (vmcs12->exception_bitmap & (1u << PF_VECTOR)) != 0; + inequality = + (error_code & vmcs12->page_fault_error_code_mask) != + vmcs12->page_fault_error_code_match; + return inequality ^ bit; +} + static void vmx_inject_page_fault_nested(struct kvm_vcpu *vcpu, struct x86_exception *fault) { @@ -8213,8 +8225,7 @@ static void vmx_inject_page_fault_nested(struct kvm_vcpu *vcpu, WARN_ON(!is_guest_mode(vcpu)); - /* TODO: also check PFEC_MATCH/MASK, not just EB.PF. */ - if (vmcs12->exception_bitmap & (1u << PF_VECTOR)) + if (nested_vmx_is_page_fault_vmexit(vmcs12, fault->error_code)) nested_vmx_vmexit(vcpu, to_vmx(vcpu)->exit_reason, vmcs_read32(VM_EXIT_INTR_INFO), vmcs_readl(EXIT_QUALIFICATION)); -- cgit v1.2.3 From 5ff22e7ebf2e75e6300ad968a6e529b5e70877f1 Mon Sep 17 00:00:00 2001 From: Nicholas Krause Date: Thu, 18 Dec 2014 21:13:22 -0500 Subject: KVM: x86: Remove FIXMEs in emulate.c for the function,task_switch_32 Remove FIXME comments about needing fault addresses to be returned. These are propaagated from walk_addr_generic to gva_to_gpa and from there to ops->read_std and ops->write_std. Signed-off-by: Nicholas Krause Signed-off-by: Paolo Bonzini --- arch/x86/kvm/emulate.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 169b09d76ddd..feaba468cce6 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -2750,7 +2750,6 @@ static int task_switch_32(struct x86_emulate_ctxt *ctxt, ret = ops->read_std(ctxt, old_tss_base, &tss_seg, sizeof tss_seg, &ctxt->exception); if (ret != X86EMUL_CONTINUE) - /* FIXME: need to provide precise fault address */ return ret; save_state_to_tss32(ctxt, &tss_seg); @@ -2759,13 +2758,11 @@ static int task_switch_32(struct x86_emulate_ctxt *ctxt, ret = ops->write_std(ctxt, old_tss_base + eip_offset, &tss_seg.eip, ldt_sel_offset - eip_offset, &ctxt->exception); if (ret != X86EMUL_CONTINUE) - /* FIXME: need to provide precise fault address */ return ret; ret = ops->read_std(ctxt, new_tss_base, &tss_seg, sizeof tss_seg, &ctxt->exception); if (ret != X86EMUL_CONTINUE) - /* FIXME: need to provide precise fault address */ return ret; if (old_tss_sel != 0xffff) { @@ -2776,7 +2773,6 @@ static int task_switch_32(struct x86_emulate_ctxt *ctxt, sizeof tss_seg.prev_task_link, &ctxt->exception); if (ret != X86EMUL_CONTINUE) - /* FIXME: need to provide precise fault address */ return ret; } -- cgit v1.2.3 From b4eef9b36db461ca44832226fbca614db58c0c33 Mon Sep 17 00:00:00 2001 From: Tiejun Chen Date: Mon, 22 Dec 2014 10:32:57 +0100 Subject: kvm: x86: vmx: NULL out hwapic_isr_update() in case of !enable_apicv In most cases calling hwapic_isr_update(), we always check if kvm_apic_vid_enabled() == 1, but actually, kvm_apic_vid_enabled() -> kvm_x86_ops->vm_has_apicv() -> vmx_vm_has_apicv() or '0' in svm case -> return enable_apicv && irqchip_in_kernel(kvm) So its a little cost to recall vmx_vm_has_apicv() inside hwapic_isr_update(), here just NULL out hwapic_isr_update() in case of !enable_apicv inside hardware_setup() then make all related stuffs follow this. Note we don't check this under that condition of irqchip_in_kernel() since we should make sure definitely any caller don't work without in-kernel irqchip. Signed-off-by: Tiejun Chen Signed-off-by: Paolo Bonzini --- arch/x86/kvm/lapic.c | 8 +++++--- arch/x86/kvm/vmx.c | 4 +--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 4f0c0b954686..fe8bae511e99 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -402,7 +402,7 @@ static inline void apic_set_isr(int vec, struct kvm_lapic *apic) * because the processor can modify ISR under the hood. Instead * just set SVI. */ - if (unlikely(kvm_apic_vid_enabled(vcpu->kvm))) + if (unlikely(kvm_x86_ops->hwapic_isr_update)) kvm_x86_ops->hwapic_isr_update(vcpu->kvm, vec); else { ++apic->isr_count; @@ -450,7 +450,7 @@ static inline void apic_clear_isr(int vec, struct kvm_lapic *apic) * on the other hand isr_count and highest_isr_cache are unused * and must be left alone. */ - if (unlikely(kvm_apic_vid_enabled(vcpu->kvm))) + if (unlikely(kvm_x86_ops->hwapic_isr_update)) kvm_x86_ops->hwapic_isr_update(vcpu->kvm, apic_find_highest_isr(apic)); else { @@ -1742,7 +1742,9 @@ void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu, if (kvm_x86_ops->hwapic_irr_update) kvm_x86_ops->hwapic_irr_update(vcpu, apic_find_highest_irr(apic)); - kvm_x86_ops->hwapic_isr_update(vcpu->kvm, apic_find_highest_isr(apic)); + if (unlikely(kvm_x86_ops->hwapic_isr_update)) + kvm_x86_ops->hwapic_isr_update(vcpu->kvm, + apic_find_highest_isr(apic)); kvm_make_request(KVM_REQ_EVENT, vcpu); kvm_rtc_eoi_tracking_restore_one(vcpu); } diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index e14c96e574ff..6e71fac27d4e 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -5895,6 +5895,7 @@ static __init int hardware_setup(void) kvm_x86_ops->update_cr8_intercept = NULL; else { kvm_x86_ops->hwapic_irr_update = NULL; + kvm_x86_ops->hwapic_isr_update = NULL; kvm_x86_ops->deliver_posted_interrupt = NULL; kvm_x86_ops->sync_pir_to_irr = vmx_sync_pir_to_irr_dummy; } @@ -7478,9 +7479,6 @@ static void vmx_hwapic_isr_update(struct kvm *kvm, int isr) u16 status; u8 old; - if (!vmx_vm_has_apicv(kvm)) - return; - if (isr == -1) isr = 0; -- cgit v1.2.3 From 7c6a98dfa1ba9dc64a62e73624ecea9995736bbd Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Tue, 16 Dec 2014 09:08:14 -0500 Subject: KVM: x86: add method to test PIR bitmap vector kvm_x86_ops->test_posted_interrupt() returns true/false depending whether 'vector' is set. Next patch makes use of this interface. Signed-off-by: Marcelo Tosatti Signed-off-by: Paolo Bonzini --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/vmx.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+) (limited to 'arch') diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index d89c6b828c96..cb19d05af3cd 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -753,6 +753,7 @@ struct kvm_x86_ops { void (*set_virtual_x2apic_mode)(struct kvm_vcpu *vcpu, bool set); void (*set_apic_access_page_addr)(struct kvm_vcpu *vcpu, hpa_t hpa); void (*deliver_posted_interrupt)(struct kvm_vcpu *vcpu, int vector); + bool (*test_posted_interrupt)(struct kvm_vcpu *vcpu, int vector); void (*sync_pir_to_irr)(struct kvm_vcpu *vcpu); int (*set_tss_addr)(struct kvm *kvm, unsigned int addr); int (*get_tdp_level)(void); diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 6e71fac27d4e..3b97f8b3065e 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -435,6 +435,11 @@ static int pi_test_and_set_pir(int vector, struct pi_desc *pi_desc) return test_and_set_bit(vector, (unsigned long *)pi_desc->pir); } +static int pi_test_pir(int vector, struct pi_desc *pi_desc) +{ + return test_bit(vector, (unsigned long *)pi_desc->pir); +} + struct vcpu_vmx { struct kvm_vcpu vcpu; unsigned long host_rsp; @@ -5897,6 +5902,7 @@ static __init int hardware_setup(void) kvm_x86_ops->hwapic_irr_update = NULL; kvm_x86_ops->hwapic_isr_update = NULL; kvm_x86_ops->deliver_posted_interrupt = NULL; + kvm_x86_ops->test_posted_interrupt = NULL; kvm_x86_ops->sync_pir_to_irr = vmx_sync_pir_to_irr_dummy; } @@ -6968,6 +6974,13 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) return 1; } +static bool vmx_test_pir(struct kvm_vcpu *vcpu, int vector) +{ + struct vcpu_vmx *vmx = to_vmx(vcpu); + + return pi_test_pir(vector, &vmx->pi_desc); +} + /* * The exit handlers return 1 if the exit was handled fully and guest execution * may resume. Otherwise they set the kvm_run parameter to indicate what needs @@ -9562,6 +9575,7 @@ static struct kvm_x86_ops vmx_x86_ops = { .hwapic_isr_update = vmx_hwapic_isr_update, .sync_pir_to_irr = vmx_sync_pir_to_irr, .deliver_posted_interrupt = vmx_deliver_posted_interrupt, + .test_posted_interrupt = vmx_test_pir, .set_tss_addr = vmx_set_tss_addr, .get_tdp_level = get_ept_level, -- cgit v1.2.3 From d0659d946be05e098883b6955d2764595997f6a4 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Tue, 16 Dec 2014 09:08:15 -0500 Subject: KVM: x86: add option to advance tscdeadline hrtimer expiration For the hrtimer which emulates the tscdeadline timer in the guest, add an option to advance expiration, and busy spin on VM-entry waiting for the actual expiration time to elapse. This allows achieving low latencies in cyclictest (or any scenario which requires strict timing regarding timer expiration). Reduces average cyclictest latency from 12us to 8us on Core i5 desktop. Note: this option requires tuning to find the appropriate value for a particular hardware/guest combination. One method is to measure the average delay between apic_timer_fn and VM-entry. Another method is to start with 1000ns, and increase the value in say 500ns increments until avg cyclictest numbers stop decreasing. Signed-off-by: Marcelo Tosatti Signed-off-by: Paolo Bonzini --- arch/x86/kvm/lapic.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++- arch/x86/kvm/lapic.h | 3 +++ arch/x86/kvm/x86.c | 5 +++++ arch/x86/kvm/x86.h | 2 ++ 4 files changed, 66 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index fe8bae511e99..e1c0befaa9f6 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include "kvm_cache_regs.h" @@ -1073,6 +1074,7 @@ static void apic_timer_expired(struct kvm_lapic *apic) { struct kvm_vcpu *vcpu = apic->vcpu; wait_queue_head_t *q = &vcpu->wq; + struct kvm_timer *ktimer = &apic->lapic_timer; /* * Note: KVM_REQ_PENDING_TIMER is implicitly checked in @@ -1087,11 +1089,61 @@ static void apic_timer_expired(struct kvm_lapic *apic) if (waitqueue_active(q)) wake_up_interruptible(q); + + if (apic_lvtt_tscdeadline(apic)) + ktimer->expired_tscdeadline = ktimer->tscdeadline; +} + +/* + * On APICv, this test will cause a busy wait + * during a higher-priority task. + */ + +static bool lapic_timer_int_injected(struct kvm_vcpu *vcpu) +{ + struct kvm_lapic *apic = vcpu->arch.apic; + u32 reg = kvm_apic_get_reg(apic, APIC_LVTT); + + if (kvm_apic_hw_enabled(apic)) { + int vec = reg & APIC_VECTOR_MASK; + + if (kvm_x86_ops->test_posted_interrupt) + return kvm_x86_ops->test_posted_interrupt(vcpu, vec); + else { + if (apic_test_vector(vec, apic->regs + APIC_ISR)) + return true; + } + } + return false; +} + +void wait_lapic_expire(struct kvm_vcpu *vcpu) +{ + struct kvm_lapic *apic = vcpu->arch.apic; + u64 guest_tsc, tsc_deadline; + + if (!kvm_vcpu_has_lapic(vcpu)) + return; + + if (apic->lapic_timer.expired_tscdeadline == 0) + return; + + if (!lapic_timer_int_injected(vcpu)) + return; + + tsc_deadline = apic->lapic_timer.expired_tscdeadline; + apic->lapic_timer.expired_tscdeadline = 0; + guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu, native_read_tsc()); + + /* __delay is delay_tsc whenever the hardware has TSC, thus always. */ + if (guest_tsc < tsc_deadline) + __delay(tsc_deadline - guest_tsc); } static void start_apic_timer(struct kvm_lapic *apic) { ktime_t now; + atomic_set(&apic->lapic_timer.pending, 0); if (apic_lvtt_period(apic) || apic_lvtt_oneshot(apic)) { @@ -1137,6 +1189,7 @@ static void start_apic_timer(struct kvm_lapic *apic) /* lapic timer in tsc deadline mode */ u64 guest_tsc, tscdeadline = apic->lapic_timer.tscdeadline; u64 ns = 0; + ktime_t expire; struct kvm_vcpu *vcpu = apic->vcpu; unsigned long this_tsc_khz = vcpu->arch.virtual_tsc_khz; unsigned long flags; @@ -1151,8 +1204,10 @@ static void start_apic_timer(struct kvm_lapic *apic) if (likely(tscdeadline > guest_tsc)) { ns = (tscdeadline - guest_tsc) * 1000000ULL; do_div(ns, this_tsc_khz); + expire = ktime_add_ns(now, ns); + expire = ktime_sub_ns(expire, lapic_timer_advance_ns); hrtimer_start(&apic->lapic_timer.timer, - ktime_add_ns(now, ns), HRTIMER_MODE_ABS); + expire, HRTIMER_MODE_ABS); } else apic_timer_expired(apic); diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index c674fce53cf9..7054437944cd 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h @@ -14,6 +14,7 @@ struct kvm_timer { u32 timer_mode; u32 timer_mode_mask; u64 tscdeadline; + u64 expired_tscdeadline; atomic_t pending; /* accumulated triggered timers */ }; @@ -170,4 +171,6 @@ static inline bool kvm_apic_has_events(struct kvm_vcpu *vcpu) bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector); +void wait_lapic_expire(struct kvm_vcpu *vcpu); + #endif diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index af9faed270f1..559e3fd6c897 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -108,6 +108,10 @@ EXPORT_SYMBOL_GPL(kvm_max_guest_tsc_khz); static u32 tsc_tolerance_ppm = 250; module_param(tsc_tolerance_ppm, uint, S_IRUGO | S_IWUSR); +/* lapic timer advance (tscdeadline mode only) in nanoseconds */ +unsigned int lapic_timer_advance_ns = 0; +module_param(lapic_timer_advance_ns, uint, S_IRUGO | S_IWUSR); + static bool backwards_tsc_observed = false; #define KVM_NR_SHARED_MSRS 16 @@ -6312,6 +6316,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) } trace_kvm_entry(vcpu->vcpu_id); + wait_lapic_expire(vcpu); kvm_x86_ops->run(vcpu); /* diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index cc1d61af6140..07994f38dacf 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -170,5 +170,7 @@ extern u64 kvm_supported_xcr0(void); extern unsigned int min_timer_period_us; +extern unsigned int lapic_timer_advance_ns; + extern struct static_key kvm_no_apic_vcpu; #endif -- cgit v1.2.3 From 6c19b7538f5ae2b6cdf91ab29f7fddf7320ece5b Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Tue, 16 Dec 2014 09:08:16 -0500 Subject: KVM: x86: add tracepoint to wait_lapic_expire Add tracepoint to wait_lapic_expire. Signed-off-by: Marcelo Tosatti [Remind reader if early or late. - Paolo] Signed-off-by: Paolo Bonzini --- arch/x86/kvm/lapic.c | 1 + arch/x86/kvm/trace.h | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) (limited to 'arch') diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index e1c0befaa9f6..3eb7f8d9992c 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1134,6 +1134,7 @@ void wait_lapic_expire(struct kvm_vcpu *vcpu) tsc_deadline = apic->lapic_timer.expired_tscdeadline; apic->lapic_timer.expired_tscdeadline = 0; guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu, native_read_tsc()); + trace_kvm_wait_lapic_expire(vcpu->vcpu_id, guest_tsc - tsc_deadline); /* __delay is delay_tsc whenever the hardware has TSC, thus always. */ if (guest_tsc < tsc_deadline) diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h index c2a34bb5ad93..587149bd6f76 100644 --- a/arch/x86/kvm/trace.h +++ b/arch/x86/kvm/trace.h @@ -914,6 +914,26 @@ TRACE_EVENT(kvm_pvclock_update, __entry->flags) ); +TRACE_EVENT(kvm_wait_lapic_expire, + TP_PROTO(unsigned int vcpu_id, s64 delta), + TP_ARGS(vcpu_id, delta), + + TP_STRUCT__entry( + __field( unsigned int, vcpu_id ) + __field( s64, delta ) + ), + + TP_fast_assign( + __entry->vcpu_id = vcpu_id; + __entry->delta = delta; + ), + + TP_printk("vcpu %u: delta %lld (%s)", + __entry->vcpu_id, + __entry->delta, + __entry->delta < 0 ? "early" : "late") +); + #endif /* _TRACE_KVM_H */ #undef TRACE_INCLUDE_PATH -- cgit v1.2.3 From e0c6db3e22f564d91832547a2432ab00f215108e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 23 Dec 2014 13:39:46 +0100 Subject: KVM: x86: mmu: do not use return to tail-call functions that return void This is, pedantically, not valid C. It also looks weird. Signed-off-by: Paolo Bonzini --- arch/x86/kvm/mmu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index f83fc6c5e0ba..8ddbcb570fce 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -3900,11 +3900,11 @@ static void init_kvm_nested_mmu(struct kvm_vcpu *vcpu) static void init_kvm_mmu(struct kvm_vcpu *vcpu) { if (mmu_is_nested(vcpu)) - return init_kvm_nested_mmu(vcpu); + init_kvm_nested_mmu(vcpu); else if (tdp_enabled) - return init_kvm_tdp_mmu(vcpu); + init_kvm_tdp_mmu(vcpu); else - return init_kvm_softmmu(vcpu); + init_kvm_softmmu(vcpu); } void kvm_mmu_reset_context(struct kvm_vcpu *vcpu) -- cgit v1.2.3 From ad896af0b50ed656e38a31fca1fdb7bb7533db45 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 2 Oct 2013 16:56:14 +0200 Subject: KVM: x86: mmu: remove argument to kvm_init_shadow_mmu and kvm_init_shadow_ept_mmu The initialization function in mmu.c can always use walk_mmu, which is known to be vcpu->arch.mmu. Only init_kvm_nested_mmu is used to initialize vcpu->arch.nested_mmu. Signed-off-by: Paolo Bonzini --- arch/x86/kvm/mmu.c | 35 ++++++++++++++++++++--------------- arch/x86/kvm/mmu.h | 5 ++--- arch/x86/kvm/svm.c | 4 ++-- arch/x86/kvm/vmx.c | 4 ++-- 4 files changed, 26 insertions(+), 22 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 8ddbcb570fce..d6d3d6f0ff1b 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -3763,7 +3763,7 @@ static void paging32E_init_context(struct kvm_vcpu *vcpu, static void init_kvm_tdp_mmu(struct kvm_vcpu *vcpu) { - struct kvm_mmu *context = vcpu->arch.walk_mmu; + struct kvm_mmu *context = &vcpu->arch.mmu; context->base_role.word = 0; context->page_fault = tdp_page_fault; @@ -3803,11 +3803,13 @@ static void init_kvm_tdp_mmu(struct kvm_vcpu *vcpu) update_last_pte_bitmap(vcpu, context); } -void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *context) +void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu) { bool smep = kvm_read_cr4_bits(vcpu, X86_CR4_SMEP); + struct kvm_mmu *context = &vcpu->arch.mmu; + ASSERT(vcpu); - ASSERT(!VALID_PAGE(vcpu->arch.mmu.root_hpa)); + ASSERT(!VALID_PAGE(context->root_hpa)); if (!is_paging(vcpu)) nonpaging_init_context(vcpu, context); @@ -3818,19 +3820,20 @@ void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *context) else paging32_init_context(vcpu, context); - vcpu->arch.mmu.base_role.nxe = is_nx(vcpu); - vcpu->arch.mmu.base_role.cr4_pae = !!is_pae(vcpu); - vcpu->arch.mmu.base_role.cr0_wp = is_write_protection(vcpu); - vcpu->arch.mmu.base_role.smep_andnot_wp + context->base_role.nxe = is_nx(vcpu); + context->base_role.cr4_pae = !!is_pae(vcpu); + context->base_role.cr0_wp = is_write_protection(vcpu); + context->base_role.smep_andnot_wp = smep && !is_write_protection(vcpu); } EXPORT_SYMBOL_GPL(kvm_init_shadow_mmu); -void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *context, - bool execonly) +void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly) { + struct kvm_mmu *context = &vcpu->arch.mmu; + ASSERT(vcpu); - ASSERT(!VALID_PAGE(vcpu->arch.mmu.root_hpa)); + ASSERT(!VALID_PAGE(context->root_hpa)); context->shadow_root_level = kvm_x86_ops->get_tdp_level(); @@ -3851,11 +3854,13 @@ EXPORT_SYMBOL_GPL(kvm_init_shadow_ept_mmu); static void init_kvm_softmmu(struct kvm_vcpu *vcpu) { - kvm_init_shadow_mmu(vcpu, vcpu->arch.walk_mmu); - vcpu->arch.walk_mmu->set_cr3 = kvm_x86_ops->set_cr3; - vcpu->arch.walk_mmu->get_cr3 = get_cr3; - vcpu->arch.walk_mmu->get_pdptr = kvm_pdptr_read; - vcpu->arch.walk_mmu->inject_page_fault = kvm_inject_page_fault; + struct kvm_mmu *context = &vcpu->arch.mmu; + + kvm_init_shadow_mmu(vcpu); + context->set_cr3 = kvm_x86_ops->set_cr3; + context->get_cr3 = get_cr3; + context->get_pdptr = kvm_pdptr_read; + context->inject_page_fault = kvm_inject_page_fault; } static void init_kvm_nested_mmu(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h index bde8ee725754..a7f9a121690d 100644 --- a/arch/x86/kvm/mmu.h +++ b/arch/x86/kvm/mmu.h @@ -81,9 +81,8 @@ enum { }; int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct); -void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *context); -void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, struct kvm_mmu *context, - bool execonly); +void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu); +void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly); void update_permission_bitmask(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, bool ept); diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 41dd0387cccb..a17d848c6d42 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -2003,8 +2003,8 @@ static void nested_svm_inject_npf_exit(struct kvm_vcpu *vcpu, static void nested_svm_init_mmu_context(struct kvm_vcpu *vcpu) { - kvm_init_shadow_mmu(vcpu, &vcpu->arch.mmu); - + WARN_ON(mmu_is_nested(vcpu)); + kvm_init_shadow_mmu(vcpu); vcpu->arch.mmu.set_cr3 = nested_svm_set_tdp_cr3; vcpu->arch.mmu.get_cr3 = nested_svm_get_tdp_cr3; vcpu->arch.mmu.get_pdptr = nested_svm_get_tdp_pdptr; diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 3b97f8b3065e..ce350718eb88 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -8202,9 +8202,9 @@ static unsigned long nested_ept_get_cr3(struct kvm_vcpu *vcpu) static void nested_ept_init_mmu_context(struct kvm_vcpu *vcpu) { - kvm_init_shadow_ept_mmu(vcpu, &vcpu->arch.mmu, + WARN_ON(mmu_is_nested(vcpu)); + kvm_init_shadow_ept_mmu(vcpu, nested_vmx_ept_caps & VMX_EPT_EXECUTE_ONLY_BIT); - vcpu->arch.mmu.set_cr3 = vmx_set_cr3; vcpu->arch.mmu.get_cr3 = nested_ept_get_cr3; vcpu->arch.mmu.inject_page_fault = nested_ept_inject_page_fault; -- cgit v1.2.3 From 4c1a50de9223e1bb7ce5decdd69bdf34a864f03e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 2 Oct 2013 16:56:15 +0200 Subject: KVM: x86: mmu: remove ASSERT(vcpu) Because ASSERT is just a printk, these would oops right away. The assertion thus hardly adds anything. Signed-off-by: Paolo Bonzini --- arch/x86/kvm/mmu.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index d6d3d6f0ff1b..b31eff8fa43d 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -3329,7 +3329,6 @@ static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva, if (r) return r; - ASSERT(vcpu); ASSERT(VALID_PAGE(vcpu->arch.mmu.root_hpa)); gfn = gva >> PAGE_SHIFT; @@ -3396,7 +3395,6 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code, int write = error_code & PFERR_WRITE_MASK; bool map_writable; - ASSERT(vcpu); ASSERT(VALID_PAGE(vcpu->arch.mmu.root_hpa)); if (unlikely(error_code & PFERR_RSVD_MASK)) { @@ -3808,7 +3806,6 @@ void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu) bool smep = kvm_read_cr4_bits(vcpu, X86_CR4_SMEP); struct kvm_mmu *context = &vcpu->arch.mmu; - ASSERT(vcpu); ASSERT(!VALID_PAGE(context->root_hpa)); if (!is_paging(vcpu)) @@ -3832,7 +3829,6 @@ void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly) { struct kvm_mmu *context = &vcpu->arch.mmu; - ASSERT(vcpu); ASSERT(!VALID_PAGE(context->root_hpa)); context->shadow_root_level = kvm_x86_ops->get_tdp_level(); @@ -3914,8 +3910,6 @@ static void init_kvm_mmu(struct kvm_vcpu *vcpu) void kvm_mmu_reset_context(struct kvm_vcpu *vcpu) { - ASSERT(vcpu); - kvm_mmu_unload(vcpu); init_kvm_mmu(vcpu); } @@ -4271,8 +4265,6 @@ static int alloc_mmu_pages(struct kvm_vcpu *vcpu) struct page *page; int i; - ASSERT(vcpu); - /* * When emulating 32-bit mode, cr3 is only 32 bits even on x86_64. * Therefore we need to allocate shadow page tables in the first @@ -4291,8 +4283,6 @@ static int alloc_mmu_pages(struct kvm_vcpu *vcpu) int kvm_mmu_create(struct kvm_vcpu *vcpu) { - ASSERT(vcpu); - vcpu->arch.walk_mmu = &vcpu->arch.mmu; vcpu->arch.mmu.root_hpa = INVALID_PAGE; vcpu->arch.mmu.translate_gpa = translate_gpa; @@ -4303,7 +4293,6 @@ int kvm_mmu_create(struct kvm_vcpu *vcpu) void kvm_mmu_setup(struct kvm_vcpu *vcpu) { - ASSERT(vcpu); ASSERT(!VALID_PAGE(vcpu->arch.mmu.root_hpa)); init_kvm_mmu(vcpu); @@ -4611,8 +4600,6 @@ EXPORT_SYMBOL_GPL(kvm_mmu_get_spte_hierarchy); void kvm_mmu_destroy(struct kvm_vcpu *vcpu) { - ASSERT(vcpu); - kvm_mmu_unload(vcpu); free_mmu_pages(vcpu); mmu_free_memory_caches(vcpu); -- cgit v1.2.3 From fa4a2c080e37d362ae603f4ea157fe779bd85cb5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 2 Oct 2013 16:56:16 +0200 Subject: KVM: x86: mmu: replace assertions with MMU_WARN_ON, a conditional WARN_ON This makes the direction of the conditions consistent with code that is already using WARN_ON. Signed-off-by: Paolo Bonzini --- arch/x86/kvm/mmu.c | 42 ++++++++++++++---------------------------- 1 file changed, 14 insertions(+), 28 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index b31eff8fa43d..a0985ebb5512 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -63,30 +63,16 @@ enum { #undef MMU_DEBUG #ifdef MMU_DEBUG +static bool dbg = 0; +module_param(dbg, bool, 0644); #define pgprintk(x...) do { if (dbg) printk(x); } while (0) #define rmap_printk(x...) do { if (dbg) printk(x); } while (0) - +#define MMU_WARN_ON(x) WARN_ON(x) #else - #define pgprintk(x...) do { } while (0) #define rmap_printk(x...) do { } while (0) - -#endif - -#ifdef MMU_DEBUG -static bool dbg = 0; -module_param(dbg, bool, 0644); -#endif - -#ifndef MMU_DEBUG -#define ASSERT(x) do { } while (0) -#else -#define ASSERT(x) \ - if (!(x)) { \ - printk(KERN_WARNING "assertion failed %s:%d: %s\n", \ - __FILE__, __LINE__, #x); \ - } +#define MMU_WARN_ON(x) do { } while (0) #endif #define PTE_PREFETCH_NUM 8 @@ -1536,7 +1522,7 @@ static inline void kvm_mod_used_mmu_pages(struct kvm *kvm, int nr) static void kvm_mmu_free_page(struct kvm_mmu_page *sp) { - ASSERT(is_empty_shadow_page(sp->spt)); + MMU_WARN_ON(!is_empty_shadow_page(sp->spt)); hlist_del(&sp->hash_link); list_del(&sp->link); free_page((unsigned long)sp->spt); @@ -3041,7 +3027,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu) for (i = 0; i < 4; ++i) { hpa_t root = vcpu->arch.mmu.pae_root[i]; - ASSERT(!VALID_PAGE(root)); + MMU_WARN_ON(VALID_PAGE(root)); spin_lock(&vcpu->kvm->mmu_lock); make_mmu_pages_available(vcpu); sp = kvm_mmu_get_page(vcpu, i << (30 - PAGE_SHIFT), @@ -3079,7 +3065,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu) if (vcpu->arch.mmu.root_level == PT64_ROOT_LEVEL) { hpa_t root = vcpu->arch.mmu.root_hpa; - ASSERT(!VALID_PAGE(root)); + MMU_WARN_ON(VALID_PAGE(root)); spin_lock(&vcpu->kvm->mmu_lock); make_mmu_pages_available(vcpu); @@ -3104,7 +3090,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu) for (i = 0; i < 4; ++i) { hpa_t root = vcpu->arch.mmu.pae_root[i]; - ASSERT(!VALID_PAGE(root)); + MMU_WARN_ON(VALID_PAGE(root)); if (vcpu->arch.mmu.root_level == PT32E_ROOT_LEVEL) { pdptr = vcpu->arch.mmu.get_pdptr(vcpu, i); if (!is_present_gpte(pdptr)) { @@ -3329,7 +3315,7 @@ static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva, if (r) return r; - ASSERT(VALID_PAGE(vcpu->arch.mmu.root_hpa)); + MMU_WARN_ON(!VALID_PAGE(vcpu->arch.mmu.root_hpa)); gfn = gva >> PAGE_SHIFT; @@ -3395,7 +3381,7 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code, int write = error_code & PFERR_WRITE_MASK; bool map_writable; - ASSERT(VALID_PAGE(vcpu->arch.mmu.root_hpa)); + MMU_WARN_ON(!VALID_PAGE(vcpu->arch.mmu.root_hpa)); if (unlikely(error_code & PFERR_RSVD_MASK)) { r = handle_mmio_page_fault(vcpu, gpa, error_code, true); @@ -3716,7 +3702,7 @@ static void paging64_init_context_common(struct kvm_vcpu *vcpu, update_permission_bitmask(vcpu, context, false); update_last_pte_bitmap(vcpu, context); - ASSERT(is_pae(vcpu)); + MMU_WARN_ON(!is_pae(vcpu)); context->page_fault = paging64_page_fault; context->gva_to_gpa = paging64_gva_to_gpa; context->sync_page = paging64_sync_page; @@ -3806,7 +3792,7 @@ void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu) bool smep = kvm_read_cr4_bits(vcpu, X86_CR4_SMEP); struct kvm_mmu *context = &vcpu->arch.mmu; - ASSERT(!VALID_PAGE(context->root_hpa)); + MMU_WARN_ON(VALID_PAGE(context->root_hpa)); if (!is_paging(vcpu)) nonpaging_init_context(vcpu, context); @@ -3829,7 +3815,7 @@ void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly) { struct kvm_mmu *context = &vcpu->arch.mmu; - ASSERT(!VALID_PAGE(context->root_hpa)); + MMU_WARN_ON(VALID_PAGE(context->root_hpa)); context->shadow_root_level = kvm_x86_ops->get_tdp_level(); @@ -4293,7 +4279,7 @@ int kvm_mmu_create(struct kvm_vcpu *vcpu) void kvm_mmu_setup(struct kvm_vcpu *vcpu) { - ASSERT(!VALID_PAGE(vcpu->arch.mmu.root_hpa)); + MMU_WARN_ON(VALID_PAGE(vcpu->arch.mmu.root_hpa)); init_kvm_mmu(vcpu); } -- cgit v1.2.3 From 3313bc4ee83c4e2870d8e83800c6064b0d215679 Mon Sep 17 00:00:00 2001 From: Nadav Amit Date: Thu, 25 Dec 2014 02:52:17 +0200 Subject: KVM: x86: pop sreg accesses only 2 bytes Although pop sreg updates RSP according to the operand size, only 2 bytes are read. The current behavior may result in incorrect #GP or #PF exceptions. Signed-off-by: Nadav Amit Signed-off-by: Paolo Bonzini --- arch/x86/kvm/emulate.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index feaba468cce6..abe95d2e6848 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -1828,12 +1828,14 @@ static int em_pop_sreg(struct x86_emulate_ctxt *ctxt) unsigned long selector; int rc; - rc = emulate_pop(ctxt, &selector, ctxt->op_bytes); + rc = emulate_pop(ctxt, &selector, 2); if (rc != X86EMUL_CONTINUE) return rc; if (ctxt->modrm_reg == VCPU_SREG_SS) ctxt->interruptibility = KVM_X86_SHADOW_INT_MOV_SS; + if (ctxt->op_bytes > 2) + rsp_increment(ctxt, ctxt->op_bytes - 2); rc = load_segment_descriptor(ctxt, (u16)selector, seg); return rc; -- cgit v1.2.3 From 16bebefe29d8495c89961a9d57ea1947547a5211 Mon Sep 17 00:00:00 2001 From: Nadav Amit Date: Thu, 25 Dec 2014 02:52:18 +0200 Subject: KVM: x86: fnstcw and fnstsw may cause spurious exception Since the operand size of fnstcw and fnstsw is updated during the execution, the emulation may cause spurious exceptions as it reads the memory beforehand. Marking these instructions as Mov (since the previous value is ignored) and DstMem16 to simplify the setting of operand size. Signed-off-by: Nadav Amit Signed-off-by: Paolo Bonzini --- arch/x86/kvm/emulate.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index abe95d2e6848..fff11885a3a0 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -86,6 +86,7 @@ #define DstAcc (OpAcc << DstShift) #define DstDI (OpDI << DstShift) #define DstMem64 (OpMem64 << DstShift) +#define DstMem16 (OpMem16 << DstShift) #define DstImmUByte (OpImmUByte << DstShift) #define DstDX (OpDX << DstShift) #define DstAccLo (OpAccLo << DstShift) @@ -1057,8 +1058,6 @@ static int em_fnstcw(struct x86_emulate_ctxt *ctxt) asm volatile("fnstcw %0": "+m"(fcw)); ctxt->ops->put_fpu(ctxt); - /* force 2 byte destination */ - ctxt->dst.bytes = 2; ctxt->dst.val = fcw; return X86EMUL_CONTINUE; @@ -1075,8 +1074,6 @@ static int em_fnstsw(struct x86_emulate_ctxt *ctxt) asm volatile("fnstsw %0": "+m"(fsw)); ctxt->ops->put_fpu(ctxt); - /* force 2 byte destination */ - ctxt->dst.bytes = 2; ctxt->dst.val = fsw; return X86EMUL_CONTINUE; @@ -3863,7 +3860,7 @@ static const struct gprefix pfx_0f_e7 = { }; static const struct escape escape_d9 = { { - N, N, N, N, N, N, N, I(DstMem, em_fnstcw), + N, N, N, N, N, N, N, I(DstMem16 | Mov, em_fnstcw), }, { /* 0xC0 - 0xC7 */ N, N, N, N, N, N, N, N, @@ -3905,7 +3902,7 @@ static const struct escape escape_db = { { } }; static const struct escape escape_dd = { { - N, N, N, N, N, N, N, I(DstMem, em_fnstsw), + N, N, N, N, N, N, N, I(DstMem16 | Mov, em_fnstsw), }, { /* 0xC0 - 0xC7 */ N, N, N, N, N, N, N, N, -- cgit v1.2.3 From 3dc4bc4f6b9265bd05dda007b07eac5a17da0562 Mon Sep 17 00:00:00 2001 From: Nadav Amit Date: Thu, 25 Dec 2014 02:52:19 +0200 Subject: KVM: x86: JMP/CALL using call- or task-gate causes exception The KVM emulator does not emulate JMP and CALL that target a call gate or a task gate. This patch does not try to implement these scenario as they are presumably rare; yet it returns X86EMUL_UNHANDLEABLE error in such cases instead of generating an exception. Signed-off-by: Nadav Amit Signed-off-by: Paolo Bonzini --- arch/x86/kvm/emulate.c | 54 +++++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index fff11885a3a0..1fec3ed86cbf 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -263,6 +263,13 @@ struct instr_dual { #define EFLG_RESERVED_ZEROS_MASK 0xffc0802a #define EFLG_RESERVED_ONE_MASK 2 +enum x86_transfer_type { + X86_TRANSFER_NONE, + X86_TRANSFER_CALL_JMP, + X86_TRANSFER_RET, + X86_TRANSFER_TASK_SWITCH, +}; + static ulong reg_read(struct x86_emulate_ctxt *ctxt, unsigned nr) { if (!(ctxt->regs_valid & (1 << nr))) { @@ -1472,7 +1479,7 @@ static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt, /* Does not support long mode */ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt, u16 selector, int seg, u8 cpl, - bool in_task_switch, + enum x86_transfer_type transfer, struct desc_struct *desc) { struct desc_struct seg_desc, old_desc; @@ -1526,11 +1533,15 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt, return ret; err_code = selector & 0xfffc; - err_vec = in_task_switch ? TS_VECTOR : GP_VECTOR; + err_vec = (transfer == X86_TRANSFER_TASK_SWITCH) ? TS_VECTOR : + GP_VECTOR; /* can't load system descriptor into segment selector */ - if (seg <= VCPU_SREG_GS && !seg_desc.s) + if (seg <= VCPU_SREG_GS && !seg_desc.s) { + if (transfer == X86_TRANSFER_CALL_JMP) + return X86EMUL_UNHANDLEABLE; goto exception; + } if (!seg_desc.p) { err_vec = (seg == VCPU_SREG_SS) ? SS_VECTOR : NP_VECTOR; @@ -1628,7 +1639,8 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt, u16 selector, int seg) { u8 cpl = ctxt->ops->cpl(ctxt); - return __load_segment_descriptor(ctxt, selector, seg, cpl, false, NULL); + return __load_segment_descriptor(ctxt, selector, seg, cpl, + X86_TRANSFER_NONE, NULL); } static void write_register_operand(struct operand *op) @@ -2040,7 +2052,8 @@ static int em_jmp_far(struct x86_emulate_ctxt *ctxt) memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2); - rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl, false, + rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl, + X86_TRANSFER_CALL_JMP, &new_desc); if (rc != X86EMUL_CONTINUE) return rc; @@ -2129,7 +2142,8 @@ static int em_ret_far(struct x86_emulate_ctxt *ctxt) /* Outer-privilege level return is not implemented */ if (ctxt->mode >= X86EMUL_MODE_PROT16 && (cs & 3) > cpl) return X86EMUL_UNHANDLEABLE; - rc = __load_segment_descriptor(ctxt, (u16)cs, VCPU_SREG_CS, cpl, false, + rc = __load_segment_descriptor(ctxt, (u16)cs, VCPU_SREG_CS, cpl, + X86_TRANSFER_RET, &new_desc); if (rc != X86EMUL_CONTINUE) return rc; @@ -2566,23 +2580,23 @@ static int load_state_from_tss16(struct x86_emulate_ctxt *ctxt, * it is handled in a context of new task */ ret = __load_segment_descriptor(ctxt, tss->ldt, VCPU_SREG_LDTR, cpl, - true, NULL); + X86_TRANSFER_TASK_SWITCH, NULL); if (ret != X86EMUL_CONTINUE) return ret; ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl, - true, NULL); + X86_TRANSFER_TASK_SWITCH, NULL); if (ret != X86EMUL_CONTINUE) return ret; ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl, - true, NULL); + X86_TRANSFER_TASK_SWITCH, NULL); if (ret != X86EMUL_CONTINUE) return ret; ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl, - true, NULL); + X86_TRANSFER_TASK_SWITCH, NULL); if (ret != X86EMUL_CONTINUE) return ret; ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl, - true, NULL); + X86_TRANSFER_TASK_SWITCH, NULL); if (ret != X86EMUL_CONTINUE) return ret; @@ -2704,31 +2718,31 @@ static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt, * it is handled in a context of new task */ ret = __load_segment_descriptor(ctxt, tss->ldt_selector, VCPU_SREG_LDTR, - cpl, true, NULL); + cpl, X86_TRANSFER_TASK_SWITCH, NULL); if (ret != X86EMUL_CONTINUE) return ret; ret = __load_segment_descriptor(ctxt, tss->es, VCPU_SREG_ES, cpl, - true, NULL); + X86_TRANSFER_TASK_SWITCH, NULL); if (ret != X86EMUL_CONTINUE) return ret; ret = __load_segment_descriptor(ctxt, tss->cs, VCPU_SREG_CS, cpl, - true, NULL); + X86_TRANSFER_TASK_SWITCH, NULL); if (ret != X86EMUL_CONTINUE) return ret; ret = __load_segment_descriptor(ctxt, tss->ss, VCPU_SREG_SS, cpl, - true, NULL); + X86_TRANSFER_TASK_SWITCH, NULL); if (ret != X86EMUL_CONTINUE) return ret; ret = __load_segment_descriptor(ctxt, tss->ds, VCPU_SREG_DS, cpl, - true, NULL); + X86_TRANSFER_TASK_SWITCH, NULL); if (ret != X86EMUL_CONTINUE) return ret; ret = __load_segment_descriptor(ctxt, tss->fs, VCPU_SREG_FS, cpl, - true, NULL); + X86_TRANSFER_TASK_SWITCH, NULL); if (ret != X86EMUL_CONTINUE) return ret; ret = __load_segment_descriptor(ctxt, tss->gs, VCPU_SREG_GS, cpl, - true, NULL); + X86_TRANSFER_TASK_SWITCH, NULL); if (ret != X86EMUL_CONTINUE) return ret; @@ -3010,8 +3024,8 @@ static int em_call_far(struct x86_emulate_ctxt *ctxt) ops->get_segment(ctxt, &old_cs, &old_desc, NULL, VCPU_SREG_CS); memcpy(&sel, ctxt->src.valptr + ctxt->op_bytes, 2); - rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl, false, - &new_desc); + rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl, + X86_TRANSFER_CALL_JMP, &new_desc); if (rc != X86EMUL_CONTINUE) return X86EMUL_CONTINUE; -- cgit v1.2.3 From 80976dbb5cb2b64480d7d38981b3220887575728 Mon Sep 17 00:00:00 2001 From: Nadav Amit Date: Thu, 25 Dec 2014 02:52:20 +0200 Subject: KVM: x86: em_call_far should return failure result Currently, if em_call_far fails it returns success instead of the resulting error-code. Fix it. Signed-off-by: Nadav Amit Signed-off-by: Paolo Bonzini --- arch/x86/kvm/emulate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 1fec3ed86cbf..8f32c03515ad 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -3027,7 +3027,7 @@ static int em_call_far(struct x86_emulate_ctxt *ctxt) rc = __load_segment_descriptor(ctxt, sel, VCPU_SREG_CS, cpl, X86_TRANSFER_CALL_JMP, &new_desc); if (rc != X86EMUL_CONTINUE) - return X86EMUL_CONTINUE; + return rc; rc = assign_eip_far(ctxt, ctxt->src.val, &new_desc); if (rc != X86EMUL_CONTINUE) -- cgit v1.2.3 From ab708099a0617e2c37b26d9ecbb373456057ba9b Mon Sep 17 00:00:00 2001 From: Nadav Amit Date: Thu, 25 Dec 2014 02:52:21 +0200 Subject: KVM: x86: POP [ESP] is not emulated correctly According to Intel SDM: "If the ESP register is used as a base register for addressing a destination operand in memory, the POP instruction computes the effective address of the operand after it increments the ESP register." The current emulation does not behave so. The fix required to waste another of the precious instruction flags and to check the flag in decode_modrm. Signed-off-by: Nadav Amit Signed-off-by: Paolo Bonzini --- arch/x86/kvm/emulate.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 8f32c03515ad..cc24b74b7454 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -170,6 +170,7 @@ #define PrivUD ((u64)1 << 51) /* #UD instead of #GP on CPL > 0 */ #define NearBranch ((u64)1 << 52) /* Near branches */ #define No16 ((u64)1 << 53) /* No 16 bit operand */ +#define IncSP ((u64)1 << 54) /* SP is incremented before ModRM calc */ #define DstXacc (DstAccLo | SrcAccHi | SrcWrite) @@ -1227,6 +1228,10 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt, else { modrm_ea += reg_read(ctxt, base_reg); adjust_modrm_seg(ctxt, base_reg); + /* Increment ESP on POP [ESP] */ + if ((ctxt->d & IncSP) && + base_reg == VCPU_REGS_RSP) + modrm_ea += ctxt->op_bytes; } if (index_reg != 4) modrm_ea += reg_read(ctxt, index_reg) << scale; @@ -3758,7 +3763,7 @@ static const struct opcode group1[] = { }; static const struct opcode group1A[] = { - I(DstMem | SrcNone | Mov | Stack, em_pop), N, N, N, N, N, N, N, + I(DstMem | SrcNone | Mov | Stack | IncSP, em_pop), N, N, N, N, N, N, N, }; static const struct opcode group2[] = { -- cgit v1.2.3 From e2cefa746e7e2a1104931d411b6f5de159d98ec6 Mon Sep 17 00:00:00 2001 From: Nadav Amit Date: Thu, 25 Dec 2014 02:52:22 +0200 Subject: KVM: x86: Do not set access bit on accessed segments When segment is loaded, the segment access bit is set unconditionally. In fact, it should be set conditionally, based on whether the segment had the accessed bit set before. In addition, it can improve performance. Signed-off-by: Nadav Amit Signed-off-by: Paolo Bonzini --- arch/x86/kvm/emulate.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index cc24b74b7454..e36e1fc5bf85 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -1618,10 +1618,13 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt, if (seg_desc.s) { /* mark segment as accessed */ - seg_desc.type |= 1; - ret = write_segment_descriptor(ctxt, selector, &seg_desc); - if (ret != X86EMUL_CONTINUE) - return ret; + if (!(seg_desc.type & 1)) { + seg_desc.type |= 1; + ret = write_segment_descriptor(ctxt, selector, + &seg_desc); + if (ret != X86EMUL_CONTINUE) + return ret; + } } else if (ctxt->mode == X86EMUL_MODE_PROT64) { ret = ctxt->ops->read_std(ctxt, desc_addr+8, &base3, sizeof(base3), &ctxt->exception); -- cgit v1.2.3 From edccda7ca7e56b335c70ae512f89d0fdf7fb8c69 Mon Sep 17 00:00:00 2001 From: Nadav Amit Date: Thu, 25 Dec 2014 02:52:23 +0200 Subject: KVM: x86: Access to LDT/GDT that wraparound is incorrect When access to descriptor in LDT/GDT wraparound outside long-mode, the address of the descriptor should be truncated to 32-bit. Citing Intel SDM 2.1.1.1 "Global and Local Descriptor Tables in IA-32e Mode": "GDTR and LDTR registers are expanded to 64-bits wide in both IA-32e sub-modes (64-bit mode and compatibility mode)." So in other cases, we need to truncate. Creating new function to return a pointer to descriptor table to avoid too much code duplication. Signed-off-by: Nadav Amit [Wrap 64-bit check with #ifdef CONFIG_X86_64, to avoid a "right shift count >= width of type" warning and consequent undefined behavior. - Paolo] Signed-off-by: Paolo Bonzini --- arch/x86/kvm/emulate.c | 47 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index e36e1fc5bf85..d949287ed010 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -1444,10 +1444,8 @@ static void get_descriptor_table_ptr(struct x86_emulate_ctxt *ctxt, ops->get_gdt(ctxt, dt); } -/* allowed just for 8 bytes segments */ -static int read_segment_descriptor(struct x86_emulate_ctxt *ctxt, - u16 selector, struct desc_struct *desc, - ulong *desc_addr_p) +static int get_descriptor_ptr(struct x86_emulate_ctxt *ctxt, + u16 selector, ulong *desc_addr_p) { struct desc_ptr dt; u16 index = selector >> 3; @@ -1458,8 +1456,34 @@ static int read_segment_descriptor(struct x86_emulate_ctxt *ctxt, if (dt.size < index * 8 + 7) return emulate_gp(ctxt, selector & 0xfffc); - *desc_addr_p = addr = dt.address + index * 8; - return ctxt->ops->read_std(ctxt, addr, desc, sizeof *desc, + addr = dt.address + index * 8; + +#ifdef CONFIG_X86_64 + if (addr >> 32 != 0) { + u64 efer = 0; + + ctxt->ops->get_msr(ctxt, MSR_EFER, &efer); + if (!(efer & EFER_LMA)) + addr &= (u32)-1; + } +#endif + + *desc_addr_p = addr; + return X86EMUL_CONTINUE; +} + +/* allowed just for 8 bytes segments */ +static int read_segment_descriptor(struct x86_emulate_ctxt *ctxt, + u16 selector, struct desc_struct *desc, + ulong *desc_addr_p) +{ + int rc; + + rc = get_descriptor_ptr(ctxt, selector, desc_addr_p); + if (rc != X86EMUL_CONTINUE) + return rc; + + return ctxt->ops->read_std(ctxt, *desc_addr_p, desc, sizeof(*desc), &ctxt->exception); } @@ -1467,16 +1491,13 @@ static int read_segment_descriptor(struct x86_emulate_ctxt *ctxt, static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt, u16 selector, struct desc_struct *desc) { - struct desc_ptr dt; - u16 index = selector >> 3; + int rc; ulong addr; - get_descriptor_table_ptr(ctxt, selector, &dt); - - if (dt.size < index * 8 + 7) - return emulate_gp(ctxt, selector & 0xfffc); + rc = get_descriptor_ptr(ctxt, selector, &addr); + if (rc != X86EMUL_CONTINUE) + return rc; - addr = dt.address + index * 8; return ctxt->ops->write_std(ctxt, addr, desc, sizeof *desc, &ctxt->exception); } -- cgit v1.2.3 From bab5bb398273bb37547a185f7b344b37c700d0b9 Mon Sep 17 00:00:00 2001 From: Nicholas Krause Date: Thu, 1 Jan 2015 22:05:18 -0500 Subject: kvm: x86: Remove kvm_make_request from lapic.c Adds a function kvm_vcpu_set_pending_timer instead of calling kvm_make_request in lapic.c. Signed-off-by: Nicholas Krause Signed-off-by: Paolo Bonzini --- arch/x86/kvm/lapic.c | 7 +------ arch/x86/kvm/x86.c | 9 +++++++++ arch/x86/kvm/x86.h | 1 + 3 files changed, 11 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 3eb7f8d9992c..a688fbffb34e 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1076,16 +1076,11 @@ static void apic_timer_expired(struct kvm_lapic *apic) wait_queue_head_t *q = &vcpu->wq; struct kvm_timer *ktimer = &apic->lapic_timer; - /* - * Note: KVM_REQ_PENDING_TIMER is implicitly checked in - * vcpu_enter_guest. - */ if (atomic_read(&apic->lapic_timer.pending)) return; atomic_inc(&apic->lapic_timer.pending); - /* FIXME: this code should not know anything about vcpus */ - kvm_make_request(KVM_REQ_PENDING_TIMER, vcpu); + kvm_set_pending_timer(vcpu); if (waitqueue_active(q)) wake_up_interruptible(q); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 559e3fd6c897..49ecda7ca958 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1087,6 +1087,15 @@ static void update_pvclock_gtod(struct timekeeper *tk) } #endif +void kvm_set_pending_timer(struct kvm_vcpu *vcpu) +{ + /* + * Note: KVM_REQ_PENDING_TIMER is implicitly checked in + * vcpu_enter_guest. This function is only called from + * the physical CPU that is running vcpu. + */ + kvm_make_request(KVM_REQ_PENDING_TIMER, vcpu); +} static void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock) { diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 07994f38dacf..f5fef1868096 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -147,6 +147,7 @@ static inline void kvm_register_writel(struct kvm_vcpu *vcpu, void kvm_before_handle_nmi(struct kvm_vcpu *vcpu); void kvm_after_handle_nmi(struct kvm_vcpu *vcpu); +void kvm_set_pending_timer(struct kvm_vcpu *vcpu); int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip); void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr); -- cgit v1.2.3 From 99b164a66b7c80be69097d19e55dd1f6a5284fd6 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 7 Jan 2015 10:39:52 -0200 Subject: Revert "ARM: imx: add FEC sleep mode callback function" i.MX platform maintainer Shawn Guo is not happy with the such commit as explained below [1]: "The GPR difference between SoCs can be encoded in device tree as well. It's pointless to repeat the same code pattern for every single platform, that need to set up GPR bits for enabling magic packet wake up, while the only difference is the register and bit offset. The platform code will become quite messy and unmaintainable if every device driver dump their GPR register setup code into platform. Sorry, but it's NACK from me." This reverts commit 456062b3ec6f5b9 ("ARM: imx: add FEC sleep mode callback function"). [1] http://www.spinics.net/lists/netdev/msg310922.html Signed-off-by: Fabio Estevam Acked-by: Shawn Guo Signed-off-by: David S. Miller --- arch/arm/mach-imx/mach-imx6q.c | 41 +-------------------------------- arch/arm/mach-imx/mach-imx6sx.c | 50 ----------------------------------------- 2 files changed, 1 insertion(+), 90 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index 2f7616889c3f..5057d61298b7 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -31,8 +31,6 @@ #include #include #include -#include -#include #include #include #include @@ -41,35 +39,6 @@ #include "cpuidle.h" #include "hardware.h" -static struct fec_platform_data fec_pdata; - -static void imx6q_fec_sleep_enable(int enabled) -{ - struct regmap *gpr; - - gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); - if (!IS_ERR(gpr)) { - if (enabled) - regmap_update_bits(gpr, IOMUXC_GPR13, - IMX6Q_GPR13_ENET_STOP_REQ, - IMX6Q_GPR13_ENET_STOP_REQ); - - else - regmap_update_bits(gpr, IOMUXC_GPR13, - IMX6Q_GPR13_ENET_STOP_REQ, 0); - } else - pr_err("failed to find fsl,imx6q-iomux-gpr regmap\n"); -} - -static void __init imx6q_enet_plt_init(void) -{ - struct device_node *np; - - np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@02188000"); - if (np && of_get_property(np, "fsl,magic-packet", NULL)) - fec_pdata.sleep_mode_enable = imx6q_fec_sleep_enable; -} - /* For imx6q sabrelite board: set KSZ9021RN RGMII pad skew */ static int ksz9021rn_phy_fixup(struct phy_device *phydev) { @@ -292,12 +261,6 @@ static void __init imx6q_axi_init(void) } } -/* Add auxdata to pass platform data */ -static const struct of_dev_auxdata imx6q_auxdata_lookup[] __initconst = { - OF_DEV_AUXDATA("fsl,imx6q-fec", 0x02188000, NULL, &fec_pdata), - { /* sentinel */ } -}; - static void __init imx6q_init_machine(void) { struct device *parent; @@ -311,13 +274,11 @@ static void __init imx6q_init_machine(void) imx6q_enet_phy_init(); - of_platform_populate(NULL, of_default_bus_match_table, - imx6q_auxdata_lookup, parent); + of_platform_populate(NULL, of_default_bus_match_table, NULL, parent); imx_anatop_init(); cpu_is_imx6q() ? imx6q_pm_init() : imx6dl_pm_init(); imx6q_1588_init(); - imx6q_enet_plt_init(); imx6q_axi_init(); } diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c index 747b012665f5..7a96c6577234 100644 --- a/arch/arm/mach-imx/mach-imx6sx.c +++ b/arch/arm/mach-imx/mach-imx6sx.c @@ -12,62 +12,12 @@ #include #include #include -#include -#include #include #include #include "common.h" #include "cpuidle.h" -static struct fec_platform_data fec_pdata[2]; - -static void imx6sx_fec1_sleep_enable(int enabled) -{ - struct regmap *gpr; - - gpr = syscon_regmap_lookup_by_compatible("fsl,imx6sx-iomuxc-gpr"); - if (!IS_ERR(gpr)) { - if (enabled) - regmap_update_bits(gpr, IOMUXC_GPR4, - IMX6SX_GPR4_FEC_ENET1_STOP_REQ, - IMX6SX_GPR4_FEC_ENET1_STOP_REQ); - else - regmap_update_bits(gpr, IOMUXC_GPR4, - IMX6SX_GPR4_FEC_ENET1_STOP_REQ, 0); - } else - pr_err("failed to find fsl,imx6sx-iomux-gpr regmap\n"); -} - -static void imx6sx_fec2_sleep_enable(int enabled) -{ - struct regmap *gpr; - - gpr = syscon_regmap_lookup_by_compatible("fsl,imx6sx-iomuxc-gpr"); - if (!IS_ERR(gpr)) { - if (enabled) - regmap_update_bits(gpr, IOMUXC_GPR4, - IMX6SX_GPR4_FEC_ENET2_STOP_REQ, - IMX6SX_GPR4_FEC_ENET2_STOP_REQ); - else - regmap_update_bits(gpr, IOMUXC_GPR4, - IMX6SX_GPR4_FEC_ENET2_STOP_REQ, 0); - } else - pr_err("failed to find fsl,imx6sx-iomux-gpr regmap\n"); -} - -static void __init imx6sx_enet_plt_init(void) -{ - struct device_node *np; - - np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@02188000"); - if (np && of_get_property(np, "fsl,magic-packet", NULL)) - fec_pdata[0].sleep_mode_enable = imx6sx_fec1_sleep_enable; - np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@021b4000"); - if (np && of_get_property(np, "fsl,magic-packet", NULL)) - fec_pdata[1].sleep_mode_enable = imx6sx_fec2_sleep_enable; -} - static int ar8031_phy_fixup(struct phy_device *dev) { u16 val; -- cgit v1.2.3 From 3552c319493c5a4ccfd6b767a3878e472aa27984 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 7 Jan 2015 10:39:53 -0200 Subject: Revert "ARM: dts: imx6qdl: enable FEC magic-packet feature" As 456062b3ec6f ("ARM: imx: add FEC sleep mode callback function") has been reverted, also revert the dts part. This reverts commit 07b4d2dda0c00f56248 ("ARM: dts: imx6qdl: enable FEC magic-packet feature"). Signed-off-by: Fabio Estevam Signed-off-by: David S. Miller --- arch/arm/boot/dts/imx6qdl-sabreauto.dtsi | 1 - arch/arm/boot/dts/imx6qdl-sabresd.dtsi | 1 - 2 files changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi index 327d362fe275..009abd69385d 100644 --- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi +++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi @@ -67,7 +67,6 @@ phy-mode = "rgmii"; interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>, <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; - fsl,magic-packet; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi index 6bfd0bc6e658..f1cd2147421d 100644 --- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi +++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi @@ -160,7 +160,6 @@ pinctrl-0 = <&pinctrl_enet>; phy-mode = "rgmii"; phy-reset-gpios = <&gpio1 25 0>; - fsl,magic-packet; status = "okay"; }; -- cgit v1.2.3 From defcf51fa93929bd5d3ce5b91f8e6a106dae5e46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= Date: Thu, 8 Jan 2015 15:59:30 +0100 Subject: KVM: x86: allow TSC deadline timer on all hosts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Emulation does not utilize the feature. Signed-off-by: Radim Krčmář Signed-off-by: Paolo Bonzini --- arch/x86/kvm/x86.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 49ecda7ca958..98930c64b06e 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2752,6 +2752,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_READONLY_MEM: case KVM_CAP_HYPERV_TIME: case KVM_CAP_IOAPIC_POLARITY_IGNORED: + case KVM_CAP_TSC_DEADLINE_TIMER: #ifdef CONFIG_KVM_DEVICE_ASSIGNMENT case KVM_CAP_ASSIGN_DEV_IRQ: case KVM_CAP_PCI_2_3: @@ -2790,9 +2791,6 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_TSC_CONTROL: r = kvm_has_tsc_control; break; - case KVM_CAP_TSC_DEADLINE_TIMER: - r = boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER); - break; default: r = 0; break; -- cgit v1.2.3 From 7e71a59b250330fd52ee7293eb9d31952f16682e Mon Sep 17 00:00:00 2001 From: Kai Huang Date: Fri, 9 Jan 2015 16:44:30 +0800 Subject: KVM: x86: flush TLB when D bit is manually changed. When software changes D bit (either from 1 to 0, or 0 to 1), the corresponding TLB entity in the hardware won't be updated immediately. We should flush it to guarantee the consistence of D bit between TLB and MMU page table in memory. This is especially important when clearing the D bit, since it may cause false negatives in reporting dirtiness. Sanity test was done on my machine with Intel processor. Signed-off-by: Kai Huang [Check A bit too. - Paolo] Signed-off-by: Paolo Bonzini --- arch/x86/kvm/mmu.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'arch') diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index a0985ebb5512..0d0fdd6f002c 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -532,6 +532,11 @@ static bool spte_is_bit_cleared(u64 old_spte, u64 new_spte, u64 bit_mask) return (old_spte & bit_mask) && !(new_spte & bit_mask); } +static bool spte_is_bit_changed(u64 old_spte, u64 new_spte, u64 bit_mask) +{ + return (old_spte & bit_mask) != (new_spte & bit_mask); +} + /* Rules for using mmu_spte_set: * Set the sptep from nonpresent to present. * Note: the sptep being assigned *must* be either not present @@ -582,6 +587,14 @@ static bool mmu_spte_update(u64 *sptep, u64 new_spte) if (!shadow_accessed_mask) return ret; + /* + * Flush TLB when accessed/dirty bits are changed in the page tables, + * to guarantee consistency between TLB and page tables. + */ + if (spte_is_bit_changed(old_spte, new_spte, + shadow_accessed_mask | shadow_dirty_mask)) + ret = true; + if (spte_is_bit_cleared(old_spte, new_spte, shadow_accessed_mask)) kvm_set_pfn_accessed(spte_to_pfn(old_spte)); if (spte_is_bit_cleared(old_spte, new_spte, shadow_dirty_mask)) -- cgit v1.2.3 From c205fb7d7d4f81e46fc577b707ceb9e356af1456 Mon Sep 17 00:00:00 2001 From: Nadav Amit Date: Thu, 25 Dec 2014 02:52:16 +0200 Subject: KVM: x86: #PF error-code on R/W operations is wrong When emulating an instruction that reads the destination memory operand (i.e., instructions without the Mov flag in the emulator), the operand is first read. If a page-fault is detected in this phase, the error-code which would be delivered to the VM does not indicate that the access that caused the exception is a write one. This does not conform with real hardware, and may cause the VM to enter the page-fault handler twice for no reason (once for read, once for write). Signed-off-by: Nadav Amit Signed-off-by: Paolo Bonzini --- arch/x86/include/asm/kvm_host.h | 12 ++++++++++++ arch/x86/kvm/emulate.c | 6 +++++- arch/x86/kvm/mmu.h | 12 ------------ 3 files changed, 17 insertions(+), 13 deletions(-) (limited to 'arch') diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index cb19d05af3cd..97a5dd0222c8 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -160,6 +160,18 @@ enum { #define DR7_FIXED_1 0x00000400 #define DR7_VOLATILE 0xffff2bff +#define PFERR_PRESENT_BIT 0 +#define PFERR_WRITE_BIT 1 +#define PFERR_USER_BIT 2 +#define PFERR_RSVD_BIT 3 +#define PFERR_FETCH_BIT 4 + +#define PFERR_PRESENT_MASK (1U << PFERR_PRESENT_BIT) +#define PFERR_WRITE_MASK (1U << PFERR_WRITE_BIT) +#define PFERR_USER_MASK (1U << PFERR_USER_BIT) +#define PFERR_RSVD_MASK (1U << PFERR_RSVD_BIT) +#define PFERR_FETCH_MASK (1U << PFERR_FETCH_BIT) + /* apic attention bits */ #define KVM_APIC_CHECK_VAPIC 0 /* diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index d949287ed010..ef23c1e5fa9f 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -4909,8 +4909,12 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) /* optimisation - avoid slow emulated read if Mov */ rc = segmented_read(ctxt, ctxt->dst.addr.mem, &ctxt->dst.val, ctxt->dst.bytes); - if (rc != X86EMUL_CONTINUE) + if (rc != X86EMUL_CONTINUE) { + if (rc == X86EMUL_PROPAGATE_FAULT && + ctxt->exception.vector == PF_VECTOR) + ctxt->exception.error_code |= PFERR_WRITE_MASK; goto done; + } } ctxt->dst.orig_val = ctxt->dst.val; diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h index a7f9a121690d..c7d65637c851 100644 --- a/arch/x86/kvm/mmu.h +++ b/arch/x86/kvm/mmu.h @@ -44,18 +44,6 @@ #define PT_DIRECTORY_LEVEL 2 #define PT_PAGE_TABLE_LEVEL 1 -#define PFERR_PRESENT_BIT 0 -#define PFERR_WRITE_BIT 1 -#define PFERR_USER_BIT 2 -#define PFERR_RSVD_BIT 3 -#define PFERR_FETCH_BIT 4 - -#define PFERR_PRESENT_MASK (1U << PFERR_PRESENT_BIT) -#define PFERR_WRITE_MASK (1U << PFERR_WRITE_BIT) -#define PFERR_USER_MASK (1U << PFERR_USER_BIT) -#define PFERR_RSVD_MASK (1U << PFERR_RSVD_BIT) -#define PFERR_FETCH_MASK (1U << PFERR_FETCH_BIT) - static inline u64 rsvd_bits(int s, int e) { return ((1ULL << (e - s + 1)) - 1) << s; -- cgit v1.2.3 From fca08f326ae0423f03b097ff54de432fe77b95d0 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Fri, 9 Jan 2015 10:19:49 +0800 Subject: ARM: probes: move all probe code to dedicate directory In discussion on LKML (https://lkml.org/lkml/2014/11/28/158), Russell King suggests to move all probe related code to arch/arm/probes. This patch does the work. Due to dependency on 'arch/arm/kernel/patch.h', this patch also moves patch.h to 'arch/arm/include/asm/patch.h', and related '#include' directives are also midified to '#include '. Following is an overview of this patch: ./arch/arm/kernel/ ./arch/arm/probes/ |-- Makefile |-- Makefile |-- probes-arm.c ==> |-- decode-arm.c |-- probes-arm.h ==> |-- decode-arm.h |-- probes-thumb.c ==> |-- decode-thumb.c |-- probes-thumb.h ==> |-- decode-thumb.h |-- probes.c ==> |-- decode.c |-- probes.h ==> |-- decode.h | |-- kprobes | | |-- Makefile |-- kprobes-arm.c ==> | |-- actions-arm.c |-- kprobes-common.c ==> | |-- actions-common.c |-- kprobes-thumb.c ==> | |-- actions-thumb.c |-- kprobes.c ==> | |-- core.c |-- kprobes.h ==> | |-- core.h |-- kprobes-test-arm.c ==> | |-- test-arm.c |-- kprobes-test.c ==> | |-- test-core.c |-- kprobes-test.h ==> | |-- test-core.h |-- kprobes-test-thumb.c ==> | `-- test-thumb.c | `-- uprobes | |-- Makefile |-- uprobes-arm.c ==> |-- actions-arm.c |-- uprobes.c ==> |-- core.c |-- uprobes.h ==> `-- core.h | `-- patch.h ==> arch/arm/include/asm/patch.h Signed-off-by: Wang Nan Acked-by: Masami Hiramatsu Signed-off-by: Jon Medhurst --- arch/arm/Makefile | 1 + arch/arm/include/asm/patch.h | 17 + arch/arm/kernel/Makefile | 16 +- arch/arm/kernel/jump_label.c | 2 +- arch/arm/kernel/kgdb.c | 3 +- arch/arm/kernel/kprobes-arm.c | 343 ------ arch/arm/kernel/kprobes-common.c | 171 --- arch/arm/kernel/kprobes-test-arm.c | 1346 ----------------------- arch/arm/kernel/kprobes-test-thumb.c | 1188 --------------------- arch/arm/kernel/kprobes-test.c | 1713 ------------------------------ arch/arm/kernel/kprobes-test.h | 435 -------- arch/arm/kernel/kprobes-thumb.c | 666 ------------ arch/arm/kernel/kprobes.c | 628 ----------- arch/arm/kernel/kprobes.h | 52 - arch/arm/kernel/patch.c | 3 +- arch/arm/kernel/patch.h | 17 - arch/arm/kernel/probes-arm.c | 734 ------------- arch/arm/kernel/probes-arm.h | 73 -- arch/arm/kernel/probes-thumb.c | 882 --------------- arch/arm/kernel/probes-thumb.h | 97 -- arch/arm/kernel/probes.c | 456 -------- arch/arm/kernel/probes.h | 407 ------- arch/arm/kernel/uprobes-arm.c | 234 ---- arch/arm/kernel/uprobes.c | 230 ---- arch/arm/kernel/uprobes.h | 35 - arch/arm/probes/Makefile | 7 + arch/arm/probes/decode-arm.c | 735 +++++++++++++ arch/arm/probes/decode-arm.h | 75 ++ arch/arm/probes/decode-thumb.c | 882 +++++++++++++++ arch/arm/probes/decode-thumb.h | 99 ++ arch/arm/probes/decode.c | 456 ++++++++ arch/arm/probes/decode.h | 407 +++++++ arch/arm/probes/kprobes/Makefile | 11 + arch/arm/probes/kprobes/actions-arm.c | 343 ++++++ arch/arm/probes/kprobes/actions-common.c | 171 +++ arch/arm/probes/kprobes/actions-thumb.c | 666 ++++++++++++ arch/arm/probes/kprobes/core.c | 628 +++++++++++ arch/arm/probes/kprobes/core.h | 53 + arch/arm/probes/kprobes/test-arm.c | 1346 +++++++++++++++++++++++ arch/arm/probes/kprobes/test-core.c | 1713 ++++++++++++++++++++++++++++++ arch/arm/probes/kprobes/test-core.h | 435 ++++++++ arch/arm/probes/kprobes/test-thumb.c | 1188 +++++++++++++++++++++ arch/arm/probes/uprobes/Makefile | 1 + arch/arm/probes/uprobes/actions-arm.c | 234 ++++ arch/arm/probes/uprobes/core.c | 230 ++++ arch/arm/probes/uprobes/core.h | 35 + 46 files changed, 9738 insertions(+), 9726 deletions(-) create mode 100644 arch/arm/include/asm/patch.h delete mode 100644 arch/arm/kernel/kprobes-arm.c delete mode 100644 arch/arm/kernel/kprobes-common.c delete mode 100644 arch/arm/kernel/kprobes-test-arm.c delete mode 100644 arch/arm/kernel/kprobes-test-thumb.c delete mode 100644 arch/arm/kernel/kprobes-test.c delete mode 100644 arch/arm/kernel/kprobes-test.h delete mode 100644 arch/arm/kernel/kprobes-thumb.c delete mode 100644 arch/arm/kernel/kprobes.c delete mode 100644 arch/arm/kernel/kprobes.h delete mode 100644 arch/arm/kernel/patch.h delete mode 100644 arch/arm/kernel/probes-arm.c delete mode 100644 arch/arm/kernel/probes-arm.h delete mode 100644 arch/arm/kernel/probes-thumb.c delete mode 100644 arch/arm/kernel/probes-thumb.h delete mode 100644 arch/arm/kernel/probes.c delete mode 100644 arch/arm/kernel/probes.h delete mode 100644 arch/arm/kernel/uprobes-arm.c delete mode 100644 arch/arm/kernel/uprobes.c delete mode 100644 arch/arm/kernel/uprobes.h create mode 100644 arch/arm/probes/Makefile create mode 100644 arch/arm/probes/decode-arm.c create mode 100644 arch/arm/probes/decode-arm.h create mode 100644 arch/arm/probes/decode-thumb.c create mode 100644 arch/arm/probes/decode-thumb.h create mode 100644 arch/arm/probes/decode.c create mode 100644 arch/arm/probes/decode.h create mode 100644 arch/arm/probes/kprobes/Makefile create mode 100644 arch/arm/probes/kprobes/actions-arm.c create mode 100644 arch/arm/probes/kprobes/actions-common.c create mode 100644 arch/arm/probes/kprobes/actions-thumb.c create mode 100644 arch/arm/probes/kprobes/core.c create mode 100644 arch/arm/probes/kprobes/core.h create mode 100644 arch/arm/probes/kprobes/test-arm.c create mode 100644 arch/arm/probes/kprobes/test-core.c create mode 100644 arch/arm/probes/kprobes/test-core.h create mode 100644 arch/arm/probes/kprobes/test-thumb.c create mode 100644 arch/arm/probes/uprobes/Makefile create mode 100644 arch/arm/probes/uprobes/actions-arm.c create mode 100644 arch/arm/probes/uprobes/core.c create mode 100644 arch/arm/probes/uprobes/core.h (limited to 'arch') diff --git a/arch/arm/Makefile b/arch/arm/Makefile index c1785eec2cf7..7f99cd652203 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -266,6 +266,7 @@ core-$(CONFIG_KVM_ARM_HOST) += arch/arm/kvm/ # If we have a machine-specific directory, then include it in the build. core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ +core-y += arch/arm/probes/ core-y += arch/arm/net/ core-y += arch/arm/crypto/ core-y += arch/arm/firmware/ diff --git a/arch/arm/include/asm/patch.h b/arch/arm/include/asm/patch.h new file mode 100644 index 000000000000..77e054c2f6cd --- /dev/null +++ b/arch/arm/include/asm/patch.h @@ -0,0 +1,17 @@ +#ifndef _ARM_KERNEL_PATCH_H +#define _ARM_KERNEL_PATCH_H + +void patch_text(void *addr, unsigned int insn); +void __patch_text_real(void *addr, unsigned int insn, bool remap); + +static inline void __patch_text(void *addr, unsigned int insn) +{ + __patch_text_real(addr, insn, true); +} + +static inline void __patch_text_early(void *addr, unsigned int insn) +{ + __patch_text_real(addr, insn, false); +} + +#endif diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index fb2b71ebe3f2..9c51a433e025 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -51,20 +51,8 @@ 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_UPROBES) += probes.o probes-arm.o uprobes.o uprobes-arm.o -obj-$(CONFIG_KPROBES) += probes.o kprobes.o kprobes-common.o patch.o -ifdef CONFIG_THUMB2_KERNEL -obj-$(CONFIG_KPROBES) += kprobes-thumb.o probes-thumb.o -else -obj-$(CONFIG_KPROBES) += kprobes-arm.o probes-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 +# Main staffs in KPROBES are in arch/arm/probes/ . +obj-$(CONFIG_KPROBES) += patch.o obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o obj-$(CONFIG_ARM_THUMBEE) += thumbee.o obj-$(CONFIG_KGDB) += kgdb.o patch.o diff --git a/arch/arm/kernel/jump_label.c b/arch/arm/kernel/jump_label.c index afeeb9ea6f43..d8da075959bf 100644 --- a/arch/arm/kernel/jump_label.c +++ b/arch/arm/kernel/jump_label.c @@ -1,8 +1,8 @@ #include #include +#include #include "insn.h" -#include "patch.h" #ifdef HAVE_JUMP_LABEL diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c index 07db2f8a1b45..a6ad93c9bce3 100644 --- a/arch/arm/kernel/kgdb.c +++ b/arch/arm/kernel/kgdb.c @@ -14,10 +14,9 @@ #include #include +#include #include -#include "patch.h" - struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = { { "r0", 4, offsetof(struct pt_regs, ARM_r0)}, diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c deleted file mode 100644 index ac300c60d656..000000000000 --- a/arch/arm/kernel/kprobes-arm.c +++ /dev/null @@ -1,343 +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 -#include -#include - -#include "kprobes.h" -#include "probes-arm.h" - -#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 - -static void __kprobes -emulate_ldrdstrd(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - unsigned long pc = regs->ARM_pc + 4; - 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" (asi->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(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - unsigned long pc = regs->ARM_pc + 4; - 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" (asi->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(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - unsigned long rtpc = regs->ARM_pc - 4 + str_pc_offset; - unsigned long rnpc = regs->ARM_pc + 4; - 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" (asi->insn_fn) - : "lr", "memory", "cc" - ); - - if (is_writeback(insn)) - regs->uregs[rn] = rnv; -} - -static void __kprobes -emulate_rd12rn16rm0rs8_rwflags(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - unsigned long pc = regs->ARM_pc + 4; - 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" (asi->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(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - 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" (asi->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(probes_opcode_t insn, - struct arch_probes_insn *asi, - struct pt_regs *regs) -{ - 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" (asi->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(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - 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" (asi->insn_fn) - : "lr", "memory", "cc" - ); - - regs->uregs[rd] = rdv; -} - -static void __kprobes -emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(probes_opcode_t insn, - struct arch_probes_insn *asi, - struct pt_regs *regs) -{ - 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" (asi->insn_fn) - : "lr", "memory", "cc" - ); - - regs->uregs[rdlo] = rdlov; - regs->uregs[rdhi] = rdhiv; - regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); -} - -const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = { - [PROBES_EMULATE_NONE] = {.handler = probes_emulate_none}, - [PROBES_SIMULATE_NOP] = {.handler = probes_simulate_nop}, - [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop}, - [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop}, - [PROBES_BRANCH_IMM] = {.handler = simulate_blx1}, - [PROBES_MRS] = {.handler = simulate_mrs}, - [PROBES_BRANCH_REG] = {.handler = simulate_blx2bx}, - [PROBES_CLZ] = {.handler = emulate_rd12rm0_noflags_nopc}, - [PROBES_SATURATING_ARITHMETIC] = { - .handler = emulate_rd12rn16rm0_rwflags_nopc}, - [PROBES_MUL1] = {.handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc}, - [PROBES_MUL2] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc}, - [PROBES_SWP] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, - [PROBES_LDRSTRD] = {.handler = emulate_ldrdstrd}, - [PROBES_LOAD_EXTRA] = {.handler = emulate_ldr}, - [PROBES_LOAD] = {.handler = emulate_ldr}, - [PROBES_STORE_EXTRA] = {.handler = emulate_str}, - [PROBES_STORE] = {.handler = emulate_str}, - [PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp}, - [PROBES_DATA_PROCESSING_REG] = { - .handler = emulate_rd12rn16rm0rs8_rwflags}, - [PROBES_DATA_PROCESSING_IMM] = { - .handler = emulate_rd12rn16rm0rs8_rwflags}, - [PROBES_MOV_HALFWORD] = {.handler = emulate_rd12rm0_noflags_nopc}, - [PROBES_SEV] = {.handler = probes_emulate_none}, - [PROBES_WFE] = {.handler = probes_simulate_nop}, - [PROBES_SATURATE] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, - [PROBES_REV] = {.handler = emulate_rd12rm0_noflags_nopc}, - [PROBES_MMI] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, - [PROBES_PACK] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, - [PROBES_EXTEND] = {.handler = emulate_rd12rm0_noflags_nopc}, - [PROBES_EXTEND_ADD] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, - [PROBES_MUL_ADD_LONG] = { - .handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc}, - [PROBES_MUL_ADD] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc}, - [PROBES_BITFIELD] = {.handler = emulate_rd12rm0_noflags_nopc}, - [PROBES_BRANCH] = {.handler = simulate_bbl}, - [PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm} -}; diff --git a/arch/arm/kernel/kprobes-common.c b/arch/arm/kernel/kprobes-common.c deleted file mode 100644 index 0bf5d64eba1d..000000000000 --- a/arch/arm/kernel/kprobes-common.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * arch/arm/kernel/kprobes-common.c - * - * Copyright (C) 2011 Jon Medhurst . - * - * 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 -#include -#include - -#include "kprobes.h" - - -static void __kprobes simulate_ldm1stm1(probes_opcode_t insn, - struct arch_probes_insn *asi, - struct pt_regs *regs) -{ - 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(probes_opcode_t insn, - struct arch_probes_insn *asi, - struct pt_regs *regs) -{ - unsigned long addr = regs->ARM_pc - 4; - - regs->ARM_pc = (long)addr + str_pc_offset; - simulate_ldm1stm1(insn, asi, regs); - regs->ARM_pc = (long)addr + 4; -} - -static void __kprobes simulate_ldm1_pc(probes_opcode_t insn, - struct arch_probes_insn *asi, - struct pt_regs *regs) -{ - simulate_ldm1stm1(insn, asi, regs); - load_write_pc(regs->ARM_pc, regs); -} - -static void __kprobes -emulate_generic_r0_12_noflags(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - register void *rregs asm("r1") = regs; - register void *rfn asm("lr") = asi->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(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - emulate_generic_r0_12_noflags(insn, asi, - (struct pt_regs *)(regs->uregs+2)); -} - -static void __kprobes -emulate_ldm_r3_15(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - emulate_generic_r0_12_noflags(insn, asi, - (struct pt_regs *)(regs->uregs+3)); - load_write_pc(regs->ARM_pc, regs); -} - -enum probes_insn __kprobes -kprobe_decode_ldmstm(probes_opcode_t insn, struct arch_probes_insn *asi, - const struct decode_header *h) -{ - probes_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] = __opcode_to_mem_arm((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; -} - diff --git a/arch/arm/kernel/kprobes-test-arm.c b/arch/arm/kernel/kprobes-test-arm.c deleted file mode 100644 index cb1424240ff6..000000000000 --- a/arch/arm/kernel/kprobes-test-arm.c +++ /dev/null @@ -1,1346 +0,0 @@ -/* - * arch/arm/kernel/kprobes-test-arm.c - * - * Copyright (C) 2011 Jon Medhurst . - * - * 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 -#include -#include -#include - -#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_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_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( 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 and a shift count in a register */ - TEST_UNSUPPORTED(__inst_arm(0xe15c0f1e) " @ cmp r12, r14, asl pc") - TEST_UNSUPPORTED(__inst_arm(0xe1a0cf1e) " @ mov r12, r14, asl pc") - TEST_UNSUPPORTED(__inst_arm(0xe08caf1e) " @ add r10, r12, r14, asl pc") - TEST_UNSUPPORTED(__inst_arm(0xe151021f) " @ cmp r1, pc, lsl r2") - TEST_UNSUPPORTED(__inst_arm(0xe17f0211) " @ cmn pc, r1, lsl r2") - TEST_UNSUPPORTED(__inst_arm(0xe1a0121f) " @ mov r1, pc, lsl r2") - TEST_UNSUPPORTED(__inst_arm(0xe1a0f211) " @ mov pc, r1, lsl r2") - TEST_UNSUPPORTED(__inst_arm(0xe042131f) " @ sub r1, r2, pc, lsl r3") - TEST_UNSUPPORTED(__inst_arm(0xe1cf1312) " @ bic r1, pc, r2, lsl r3") - TEST_UNSUPPORTED(__inst_arm(0xe081f312) " @ add pc, r1, r2, lsl r3") - - /* Data-processing with PC as a target and status registers updated */ - 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_R ("add pc, pc, r",14,(2f-1f-8)*2,", asr #1") - TEST_BB( "sub pc, pc, #1b-2b+8") -#if __LINUX_ARM_ARCH__ == 6 && !defined(CONFIG_CPU_V7) - TEST_BB( "sub pc, pc, #1b-2b+8-2") /* UNPREDICTABLE before and after 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_R( "add pc, pc, r",10,-2,", asl #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(__inst_arm(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,"") - -#if __LINUX_ARM_ARCH__ >= 5 - 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(__inst_arm(0x016fff10) " @ clz pc, r0") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(0xe101f050) " @ qadd pc, r0, r1") - TEST_UNSUPPORTED(__inst_arm(0xe121f050) " @ qsub pc, r0, r1") - TEST_UNSUPPORTED(__inst_arm(0xe141f050) " @ qdadd pc, r0, r1") - TEST_UNSUPPORTED(__inst_arm(0xe161f050) " @ qdsub pc, r0, r1") - TEST_UNSUPPORTED(__inst_arm(0xe16f2050) " @ qdsub r2, r0, pc") - TEST_UNSUPPORTED(__inst_arm(0xe161205f) " @ qdsub r2, pc, r1") - - TEST_UNSUPPORTED("bkpt 0xffff") - TEST_UNSUPPORTED("bkpt 0x0000") - - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe12f32c1) " @ smlawt pc, r1, r2, r3") - TEST_UNSUPPORTED(__inst_arm(0xe12032cf) " @ smlawt r0, pc, r2, r3") - TEST_UNSUPPORTED(__inst_arm(0xe1203fc1) " @ smlawt r0, r1, pc, r3") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe14f1382) " @ smlalbb pc, r1, r2, r3") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe14f13a2) " @ smlaltb pc, r1, r2, r3") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe14f13c2) " @ smlalbt pc, r1, r2, r3") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe14f13e2) " @ smlalbb pc, r1, r2, r3") - TEST_UNSUPPORTED(__inst_arm(0xe140f3e2) " @ smlalbb r0, pc, r2, r3") - TEST_UNSUPPORTED(__inst_arm(0xe14013ef) " @ smlalbb r0, r1, pc, r3") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe16f02e1) " @ smultt pc, r1, r2") - TEST_UNSUPPORTED(__inst_arm(0xe16002ef) " @ smultt r0, pc, r2") - TEST_UNSUPPORTED(__inst_arm(0xe1600fe1) " @ smultt r0, r1, pc") -#endif - - 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(__inst_arm(0xe00f0291) " @ mul pc, r1, r2") - TEST_UNSUPPORTED(__inst_arm(0xe000029f) " @ mul r0, pc, r2") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe041f392) " @ umaal pc, r1, r2, r3") - TEST_UNSUPPORTED(__inst_arm(0xe04f0392) " @ umaal r0, pc, r2, r3") - TEST_UNSUPPORTED(__inst_arm(0xe0500090) " @ undef") - TEST_UNSUPPORTED(__inst_arm(0xe05fff9f) " @ undef") -#endif - -#if __LINUX_ARM_ARCH__ >= 7 - 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(__inst_arm(0xe06f3291) " @ mls pc, r1, r2, r3") - TEST_UNSUPPORTED(__inst_arm(0xe060329f) " @ mls r0, pc, r2, r3") - TEST_UNSUPPORTED(__inst_arm(0xe0603f91) " @ mls r0, r1, pc, r3") - TEST_UNSUPPORTED(__inst_arm(0xe060f291) " @ mls r0, r1, r2, pc") -#endif - - TEST_UNSUPPORTED(__inst_arm(0xe0700090) " @ undef") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe081f392) " @ umull pc, r1, r2, r3") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe091f392) " @ umulls pc, r1, r2, r3") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe0af1392) " @ umlal pc, r1, r2, r3") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe0bf1392) " @ umlals pc, r1, r2, r3") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe0c1f392) " @ smull pc, r1, r2, r3") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe0d1f392) " @ smulls pc, r1, r2, r3") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe0ef1392) " @ smlal pc, r1, r2, r3") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe0ff1392) " @ smlals pc, r1, r2, r3") - TEST_UNSUPPORTED(__inst_arm(0xe0f0f392) " @ smlals r0, pc, r2, r3") - TEST_UNSUPPORTED(__inst_arm(0xe0f0139f) " @ smlals r0, r1, pc, r3") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe108e097) " @ swp lr, r7, [r8]") - TEST_UNSUPPORTED(__inst_arm(0x610d0091) " @ swpvs r0, r1, [sp]") - TEST_UNSUPPORTED(__inst_arm(0xe10cd09e) " @ swp sp, r14 [r12]") -#endif - TEST_UNSUPPORTED(__inst_arm(0xe102f091) " @ swp pc, r1, [r2]") - TEST_UNSUPPORTED(__inst_arm(0xe102009f) " @ swp r0, pc, [r2]") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe148e097) " @ swpb lr, r7, [r8]") - TEST_UNSUPPORTED(__inst_arm(0x614d0091) " @ swpvsb r0, r1, [sp]") -#endif - TEST_UNSUPPORTED(__inst_arm(0xe142f091) " @ swpb pc, r1, [r2]") - - TEST_UNSUPPORTED(__inst_arm(0xe1100090)) /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(0xe1200090)) /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(0xe1300090)) /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(0xe1500090)) /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(0xe1600090)) /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(0xe1700090)) /* Unallocated space */ -#if __LINUX_ARM_ARCH__ >= 6 - TEST_UNSUPPORTED("ldrex r2, [sp]") -#endif -#if (__LINUX_ARM_ARCH__ >= 7) || defined(CONFIG_CPU_32v6K) - 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(__inst_arm(0xe1afc0ba) " @ strh r12, [pc, r10]!") - TEST_UNSUPPORTED(__inst_arm(0xe089f0bb) " @ strh pc, [r9], r11") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe1bfc0ba) " @ ldrh r12, [pc, r10]!") - TEST_UNSUPPORTED(__inst_arm(0xe099f0bb) " @ ldrh pc, [r9], r11") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe1efc3b0) " @ strh r12, [pc, #48]!") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe1ffc3b0) " @ ldrh r12, [pc, #48]!") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe1bfc0da) " @ ldrsb r12, [pc, r10]!") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe1ffc3d0) " @ ldrsb r12, [pc, #48]!") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe1bfc0fa) " @ ldrsh r12, [pc, r10]!") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe1ffc3f0) " @ ldrsh r12, [pc, #48]!") - TEST_UNSUPPORTED(__inst_arm(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 - -#if __LINUX_ARM_ARCH__ >= 5 - 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(__inst_arm(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(__inst_arm(0xe1afc0da) " @ ldrd r12, [pc, r10]!") - TEST_UNSUPPORTED(__inst_arm(0xe089f0db) " @ ldrd pc, [r9], r11") - TEST_UNSUPPORTED(__inst_arm(0xe089e0db) " @ ldrd lr, [r9], r11") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(0xe1efc3d0) " @ ldrd r12, [pc, #48]!") - TEST_UNSUPPORTED(__inst_arm(0xe0c9f3d0) " @ ldrd pc, [r9], #48") - TEST_UNSUPPORTED(__inst_arm(0xe0c9e3d0) " @ ldrd lr, [r9], #48") -#endif - - TEST_GROUP("Miscellaneous") - -#if __LINUX_ARM_ARCH__ >= 7 - TEST("movw r0, #0") - TEST("movw r0, #0xffff") - TEST("movw lr, #0xffff") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(0xe5af6008) " @ str r6, [pc, #8]!") - TEST_UNSUPPORTED(__inst_arm(0xe7af6008) " @ str r6, [pc, r8]!") - TEST_UNSUPPORTED(__inst_arm(0xe5bf6008) " @ ldr r6, [pc, #8]!") - TEST_UNSUPPORTED(__inst_arm(0xe7bf6008) " @ ldr r6, [pc, r8]!") - TEST_UNSUPPORTED(__inst_arm(0xe788600f) " @ str r6, [r8, pc]") - TEST_UNSUPPORTED(__inst_arm(0xe798600f) " @ ldr r6, [r8, pc]") - - LOAD_STORE("b") - TEST_UNSUPPORTED(__inst_arm(0xe5f7f008) " @ ldrb pc, [r7, #8]!") - TEST_UNSUPPORTED(__inst_arm(0xe7f7f008) " @ ldrb pc, [r7, r8]!") - TEST_UNSUPPORTED(__inst_arm(0xe5ef6008) " @ strb r6, [pc, #8]!") - TEST_UNSUPPORTED(__inst_arm(0xe7ef6008) " @ strb r6, [pc, r3]!") - TEST_UNSUPPORTED(__inst_arm(0xe5ff6008) " @ ldrb r6, [pc, #8]!") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe6000010) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe61cff9a) " @ sadd8 pc, r12, r10") - TEST_UNSUPPORTED(__inst_arm(0xe61000b0) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(0xe61fffbf) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(0xe61000d0) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe62cff9a) " @ qadd8 pc, r12, r10") - TEST_UNSUPPORTED(__inst_arm(0xe62000b0) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(0xe62fffbf) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(0xe62000d0) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe63cff9a) " @ shadd8 pc, r12, r10") - TEST_UNSUPPORTED(__inst_arm(0xe63000b0) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(0xe63fffbf) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(0xe63000d0) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe63cfffa) " @ shsub8 pc, r12, r10") - - TEST_GROUP("Parallel addition and subtraction, unsigned") - - TEST_UNSUPPORTED(__inst_arm(0xe6400010) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe65cff9a) " @ uadd8 pc, r12, r10") - TEST_UNSUPPORTED(__inst_arm(0xe65000b0) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(0xe65fffbf) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(0xe65000d0) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe66cff9a) " @ uqadd8 pc, r12, r10") - TEST_UNSUPPORTED(__inst_arm(0xe66000b0) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(0xe66fffbf) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(0xe66000d0) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe67cff9a) " @ uhadd8 pc, r12, r10") - TEST_UNSUPPORTED(__inst_arm(0xe67000b0) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(0xe67fffbf) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(0xe67000d0) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe67cfffa) " @ uhsub8 pc, r12, r10") - TEST_UNSUPPORTED(__inst_arm(0xe67feffa) " @ uhsub8 r14, pc, r10") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(0xe68cf15a) " @ pkhtb pc, r12, r10, asr #2") - TEST_UNSUPPORTED(__inst_arm(0xe68fe15a) " @ pkhtb r14, pc, r10, asr #2") - TEST_UNSUPPORTED(__inst_arm(0xe68ce15f) " @ pkhtb r14, r12, pc, asr #2") - TEST_UNSUPPORTED(__inst_arm(0xe6900010) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe68cffba) " @ sel pc, r12, r10") - TEST_UNSUPPORTED(__inst_arm(0xe68fefba) " @ sel r14, pc, r10") - TEST_UNSUPPORTED(__inst_arm(0xe68cefbf) " @ sel r14, r12, pc") - - TEST_R( "ssat16 r0, #12, r",0, HH1,"") - TEST_R( "ssat16 r14, #12, r",12, HH2,"") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe6acf47a) " @ sxtab pc,r12, r10, ror #8") - - TEST_R( "rev r0, r",0, VAL1,"") - TEST_R( "rev r14, r",12, VAL2,"") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe6bcf47a) " @ sxtah pc,r12, r10, ror #8") - - TEST_R( "rev16 r0, r",0, VAL1,"") - TEST_R( "rev16 r14, r",12, VAL2,"") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(0xe6ecff3c) " @ usat16 pc, #12, r12") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe6fff077) " @ uxth pc, r7") - TEST_UNSUPPORTED(__inst_arm(0xe6ff807f) " @ uxth r8, pc") - TEST_UNSUPPORTED(__inst_arm(0xe6fcf47a) " @ uxtah pc, r12, r10, ror #8") - TEST_UNSUPPORTED(__inst_arm(0xe6fce47f) " @ uxtah r14, r12, pc, ror #8") - - TEST_R( "revsh r0, r",0, VAL1,"") - TEST_R( "revsh r14, r",12, VAL2,"") - TEST_UNSUPPORTED(__inst_arm(0xe6ffff3c) " @ revsh pc, r12") - TEST_UNSUPPORTED(__inst_arm(0xe6ffef3f) " @ revsh r14, pc") - - TEST_UNSUPPORTED(__inst_arm(0xe6900070) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(0xe69fff7f) "") /* Unallocated space */ - - TEST_UNSUPPORTED(__inst_arm(0xe6d00070) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe74af819) " @ smlald pc, r10, r9, r8") - TEST_UNSUPPORTED(__inst_arm(0xe74fb819) " @ smlald r11, pc, r9, r8") - TEST_UNSUPPORTED(__inst_arm(0xe74ab81f) " @ smlald r11, r10, pc, r8") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe74af839) " @ smlaldx pc, r10, r9, r8") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe75f8afc) " @ smmlsr pc, r12, r10, r8") - TEST_UNSUPPORTED(__inst_arm(0xe75e8aff) " @ smmlsr r14, pc, r10, r8") - TEST_UNSUPPORTED(__inst_arm(0xe75e8ffc) " @ smmlsr r14, r12, pc, r8") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe75ffa1c) " @ usad8 pc, r12, r10") - TEST_UNSUPPORTED(__inst_arm(0xe75efa1f) " @ usad8 r14, pc, r10") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe78f8a1c) " @ usada8 pc, r12, r10, r8") - TEST_UNSUPPORTED(__inst_arm(0xe78e8a1f) " @ usada8 r14, pc, r10, r8") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(0xe7eff45c) " @ ubfx pc, r12, #8, #16") - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(0xe7d7f21e) " @ bfi pc, r14, #4, #20") - - TEST_UNSUPPORTED(__inst_arm(0x07f000f0) "") /* Permanently UNDEFINED */ - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0x##cc##daf0001) " @ stc"two" 0, cr0, [r15, #4]!") \ - TEST_UNSUPPORTED(__inst_arm(0x##cc##d2f0001) " @ stc"two" 0, cr0, [r15, #-4]!") \ - TEST_UNSUPPORTED(__inst_arm(0x##cc##caf0001) " @ stc"two" 0, cr0, [r15], #4") \ - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0x##cc##def0001) " @ stc"two"l 0, cr0, [r15, #4]!") \ - TEST_UNSUPPORTED(__inst_arm(0x##cc##d6f0001) " @ stc"two"l 0, cr0, [r15, #-4]!") \ - TEST_UNSUPPORTED(__inst_arm(0x##cc##cef0001) " @ stc"two"l 0, cr0, [r15], #4") \ - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0x##cc##dbf0001) " @ ldc"two" 0, cr0, [r15, #4]!") \ - TEST_UNSUPPORTED(__inst_arm(0x##cc##d3f0001) " @ ldc"two" 0, cr0, [r15, #-4]!") \ - TEST_UNSUPPORTED(__inst_arm(0x##cc##cbf0001) " @ ldc"two" 0, cr0, [r15], #4") \ - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0x##cc##dff0001) " @ ldc"two"l 0, cr0, [r15, #4]!") \ - TEST_UNSUPPORTED(__inst_arm(0x##cc##d7f0001) " @ ldc"two"l 0, cr0, [r15, #-4]!") \ - TEST_UNSUPPORTED(__inst_arm(0x##cc##cff0001) " @ ldc"two"l 0, cr0, [r15], #4") \ - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0x##cc##c4f00f0) " @ mcrr"two" 0, 15, r0, r15, cr0") \ - TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0x##cc##c5f00f0) " @ mrrc"two" 0, 15, r0, r15, cr0") \ - TEST_UNSUPPORTED(__inst_arm(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) -#if __LINUX_ARM_ARCH__ >= 5 - COPROCESSOR_INSTRUCTIONS_MC_MR("",e) -#endif - 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(__inst_arm(0xf81d0a00) " @ rfeda pc") - TEST_UNSUPPORTED(__inst_arm(0xf91d0a00) " @ rfedb pc") - TEST_UNSUPPORTED(__inst_arm(0xf89d0a00) " @ rfeia pc") - TEST_UNSUPPORTED(__inst_arm(0xf99d0a00) " @ rfeib pc") - TEST_UNSUPPORTED(__inst_arm(0xf83d0a00) " @ rfeda pc!") - TEST_UNSUPPORTED(__inst_arm(0xf93d0a00) " @ rfedb pc!") - TEST_UNSUPPORTED(__inst_arm(0xf8bd0a00) " @ rfeia pc!") - TEST_UNSUPPORTED(__inst_arm(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 */ - -#if __LINUX_ARM_ARCH__ >= 5 - COPROCESSOR_INSTRUCTIONS_ST_LD("2",f) -#endif -#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( __inst_arm(0xf590f000) " @ pldw [r0, #0]") - TEST_SUPPORTED( __inst_arm(0xf797f000) " @ pldw [r7, r0]") - TEST_SUPPORTED( __inst_arm(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/arch/arm/kernel/kprobes-test-thumb.c b/arch/arm/kernel/kprobes-test-thumb.c deleted file mode 100644 index 844dd10d8593..000000000000 --- a/arch/arm/kernel/kprobes-test-thumb.c +++ /dev/null @@ -1,1188 +0,0 @@ -/* - * arch/arm/kernel/kprobes-test-thumb.c - * - * Copyright (C) 2011 Jon Medhurst . - * - * 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 -#include -#include - -#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(__inst_thumb16(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(__inst_thumb16(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(__inst_thumb16(0xba80) "") - TEST_UNSUPPORTED(__inst_thumb16(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(__inst_thumb16(0xbf50) "") /* Unassigned hints */ - TEST_UNSUPPORTED(__inst_thumb16(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(__inst_thumb16(0xde00) "") - TEST_UNSUPPORTED(__inst_thumb16(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(__inst_thumb32(0xe88f0101) " @ stmia pc, {r0,r8}") - TEST_UNSUPPORTED(__inst_thumb32(0xe92f5f00) " @ stmdb pc!, {r8-r12,r14}") - TEST_UNSUPPORTED(__inst_thumb32(0xe8bdc000) " @ ldmia r13!, {r14,pc}") - TEST_UNSUPPORTED(__inst_thumb32(0xe93ec000) " @ ldmdb r14!, {r14,pc}") - TEST_UNSUPPORTED(__inst_thumb32(0xe8a73f00) " @ stmia r7!, {r8-r12,sp}") - TEST_UNSUPPORTED(__inst_thumb32(0xe8a79f00) " @ stmia r7!, {r8-r12,pc}") - TEST_UNSUPPORTED(__inst_thumb32(0xe93e2010) " @ 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(__inst_thumb32(0xe9ffec04) " @ ldrd r14, r12, [pc, #16]!") - TEST_UNSUPPORTED(__inst_thumb32(0xe8ffec04) " @ ldrd r14, r12, [pc], #16") - TEST_UNSUPPORTED(__inst_thumb32(0xe9d4d800) " @ ldrd sp, r8, [r4]") - TEST_UNSUPPORTED(__inst_thumb32(0xe9d4f800) " @ ldrd pc, r8, [r4]") - TEST_UNSUPPORTED(__inst_thumb32(0xe9d47d00) " @ ldrd r7, sp, [r4]") - TEST_UNSUPPORTED(__inst_thumb32(0xe9d47f00) " @ 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(__inst_thumb32(0xe9efec04) " @ strd r14, r12, [pc, #16]!") - TEST_UNSUPPORTED(__inst_thumb32(0xe8efec04) " @ 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(__inst_thumb32(0xe8d1f01f) " @ tbh [r1, pc]") - TEST_UNSUPPORTED(__inst_thumb32(0xe8d1f01d) " @ tbh [r1, sp]") - TEST_UNSUPPORTED(__inst_thumb32(0xe8ddf012) " @ 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(__inst_thumb32(0xea170f0d) " @ tst.w r7, sp") - TEST_UNSUPPORTED(__inst_thumb32(0xea170f0f) " @ tst.w r7, pc") - TEST_UNSUPPORTED(__inst_thumb32(0xea1d0f07) " @ tst.w sp, r7") - TEST_UNSUPPORTED(__inst_thumb32(0xea1f0f07) " @ tst.w pc, r7") - TEST_UNSUPPORTED(__inst_thumb32(0xf01d1f08) " @ tst sp, #0x00080008") - TEST_UNSUPPORTED(__inst_thumb32(0xf01f1f08) " @ tst pc, #0x00080008") - - TEST_UNSUPPORTED(__inst_thumb32(0xea970f0d) " @ teq.w r7, sp") - TEST_UNSUPPORTED(__inst_thumb32(0xea970f0f) " @ teq.w r7, pc") - TEST_UNSUPPORTED(__inst_thumb32(0xea9d0f07) " @ teq.w sp, r7") - TEST_UNSUPPORTED(__inst_thumb32(0xea9f0f07) " @ teq.w pc, r7") - TEST_UNSUPPORTED(__inst_thumb32(0xf09d1f08) " @ tst sp, #0x00080008") - TEST_UNSUPPORTED(__inst_thumb32(0xf09f1f08) " @ tst pc, #0x00080008") - - TEST_UNSUPPORTED(__inst_thumb32(0xeb170f0d) " @ cmn.w r7, sp") - TEST_UNSUPPORTED(__inst_thumb32(0xeb170f0f) " @ cmn.w r7, pc") - TEST_P("cmn.w sp, r",7,0,"") - TEST_UNSUPPORTED(__inst_thumb32(0xeb1f0f07) " @ cmn.w pc, r7") - TEST( "cmn sp, #0x00080008") - TEST_UNSUPPORTED(__inst_thumb32(0xf11f1f08) " @ cmn pc, #0x00080008") - - TEST_UNSUPPORTED(__inst_thumb32(0xebb70f0d) " @ cmp.w r7, sp") - TEST_UNSUPPORTED(__inst_thumb32(0xebb70f0f) " @ cmp.w r7, pc") - TEST_P("cmp.w sp, r",7,0,"") - TEST_UNSUPPORTED(__inst_thumb32(0xebbf0f07) " @ cmp.w pc, r7") - TEST( "cmp sp, #0x00080008") - TEST_UNSUPPORTED(__inst_thumb32(0xf1bf1f08) " @ cmp pc, #0x00080008") - - TEST_UNSUPPORTED(__inst_thumb32(0xea5f070d) " @ movs.w r7, sp") - TEST_UNSUPPORTED(__inst_thumb32(0xea5f070f) " @ movs.w r7, pc") - TEST_UNSUPPORTED(__inst_thumb32(0xea5f0d07) " @ movs.w sp, r7") - TEST_UNSUPPORTED(__inst_thumb32(0xea4f0f07) " @ mov.w pc, r7") - TEST_UNSUPPORTED(__inst_thumb32(0xf04f1d08) " @ mov sp, #0x00080008") - TEST_UNSUPPORTED(__inst_thumb32(0xf04f1f08) " @ 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(__inst_thumb32(0xeb0d1d01) " @ add sp, sp, r1, asl #4") - TEST_UNSUPPORTED(__inst_thumb32(0xeb0d0d71) " @ add sp, sp, r1, ror #1") - TEST( "add.w r0, sp, #24") - TEST( "add.w sp, sp, #24") - TEST_UNSUPPORTED(__inst_thumb32(0xeb0d0f01) " @ add pc, sp, r1") - TEST_UNSUPPORTED(__inst_thumb32(0xeb0d000f) " @ add r0, sp, pc") - TEST_UNSUPPORTED(__inst_thumb32(0xeb0d000d) " @ add r0, sp, sp") - TEST_UNSUPPORTED(__inst_thumb32(0xeb0d0d0f) " @ add sp, sp, pc") - TEST_UNSUPPORTED(__inst_thumb32(0xeb0d0d0d) " @ 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(__inst_thumb32(0xebad1d01) " @ sub sp, sp, r1, asl #4") - TEST_UNSUPPORTED(__inst_thumb32(0xebad0d71) " @ sub sp, sp, r1, ror #1") - TEST_UNSUPPORTED(__inst_thumb32(0xebad0f01) " @ sub pc, sp, r1") - TEST( "sub.w r0, sp, #24") - TEST( "sub.w sp, sp, #24") - - TEST_UNSUPPORTED(__inst_thumb32(0xea02010f) " @ and r1, r2, pc") - TEST_UNSUPPORTED(__inst_thumb32(0xea0f0103) " @ and r1, pc, r3") - TEST_UNSUPPORTED(__inst_thumb32(0xea020f03) " @ and pc, r2, r3") - TEST_UNSUPPORTED(__inst_thumb32(0xea02010d) " @ and r1, r2, sp") - TEST_UNSUPPORTED(__inst_thumb32(0xea0d0103) " @ and r1, sp, r3") - TEST_UNSUPPORTED(__inst_thumb32(0xea020d03) " @ and sp, r2, r3") - TEST_UNSUPPORTED(__inst_thumb32(0xf00d1108) " @ and r1, sp, #0x00080008") - TEST_UNSUPPORTED(__inst_thumb32(0xf00f1108) " @ and r1, pc, #0x00080008") - TEST_UNSUPPORTED(__inst_thumb32(0xf0021d08) " @ and sp, r8, #0x00080008") - TEST_UNSUPPORTED(__inst_thumb32(0xf0021f08) " @ and pc, r8, #0x00080008") - - TEST_UNSUPPORTED(__inst_thumb32(0xeb02010f) " @ add r1, r2, pc") - TEST_UNSUPPORTED(__inst_thumb32(0xeb0f0103) " @ add r1, pc, r3") - TEST_UNSUPPORTED(__inst_thumb32(0xeb020f03) " @ add pc, r2, r3") - TEST_UNSUPPORTED(__inst_thumb32(0xeb02010d) " @ add r1, r2, sp") - TEST_SUPPORTED( __inst_thumb32(0xeb0d0103) " @ add r1, sp, r3") - TEST_UNSUPPORTED(__inst_thumb32(0xeb020d03) " @ add sp, r2, r3") - TEST_SUPPORTED( __inst_thumb32(0xf10d1108) " @ add r1, sp, #0x00080008") - TEST_UNSUPPORTED(__inst_thumb32(0xf10d1f08) " @ add pc, sp, #0x00080008") - TEST_UNSUPPORTED(__inst_thumb32(0xf10f1108) " @ add r1, pc, #0x00080008") - TEST_UNSUPPORTED(__inst_thumb32(0xf1021d08) " @ add sp, r8, #0x00080008") - TEST_UNSUPPORTED(__inst_thumb32(0xf1021f08) " @ add pc, r8, #0x00080008") - - TEST_UNSUPPORTED(__inst_thumb32(0xeaa00000) "") - TEST_UNSUPPORTED(__inst_thumb32(0xeaf00000) "") - TEST_UNSUPPORTED(__inst_thumb32(0xeb200000) "") - TEST_UNSUPPORTED(__inst_thumb32(0xeb800000) "") - TEST_UNSUPPORTED(__inst_thumb32(0xebe00000) "") - - TEST_UNSUPPORTED(__inst_thumb32(0xf0a00000) "") - TEST_UNSUPPORTED(__inst_thumb32(0xf0c00000) "") - TEST_UNSUPPORTED(__inst_thumb32(0xf0f00000) "") - TEST_UNSUPPORTED(__inst_thumb32(0xf1200000) "") - TEST_UNSUPPORTED(__inst_thumb32(0xf1800000) "") - TEST_UNSUPPORTED(__inst_thumb32(0xf1e00000) "") - - TEST_GROUP("Coprocessor instructions") - - TEST_UNSUPPORTED(__inst_thumb32(0xec000000) "") - TEST_UNSUPPORTED(__inst_thumb32(0xeff00000) "") - TEST_UNSUPPORTED(__inst_thumb32(0xfc000000) "") - TEST_UNSUPPORTED(__inst_thumb32(0xfff00000) "") - - 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(__inst_thumb32(0xf20f1f20) " @ addw pc, pc, #0x120") - TEST_UNSUPPORTED(__inst_thumb32(0xf20d1f20) " @ addw pc, sp, #0x120") - TEST_UNSUPPORTED(__inst_thumb32(0xf20f1d20) " @ addw sp, pc, #0x120") - TEST_UNSUPPORTED(__inst_thumb32(0xf2001d20) " @ 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(__inst_thumb32(0xf2af1f20) " @ subw pc, pc, #0x120") - TEST_UNSUPPORTED(__inst_thumb32(0xf2ad1f20) " @ subw pc, sp, #0x120") - TEST_UNSUPPORTED(__inst_thumb32(0xf2af1d20) " @ subw sp, pc, #0x120") - TEST_UNSUPPORTED(__inst_thumb32(0xf2a01d20) " @ subw sp, r0, #0x120") - - TEST("movw r0, #0") - TEST("movw r0, #0xffff") - TEST("movw lr, #0xffff") - TEST_UNSUPPORTED(__inst_thumb32(0xf2400d00) " @ movw sp, #0") - TEST_UNSUPPORTED(__inst_thumb32(0xf2400f00) " @ 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(__inst_thumb32(0xf2c00d00) " @ movt sp, #0") - TEST_UNSUPPORTED(__inst_thumb32(0xf2c00f00) " @ 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(__inst_thumb32(0xf30c0d17) " @ ssat sp, #24, r12") - TEST_UNSUPPORTED(__inst_thumb32(0xf30c0f17) " @ ssat pc, #24, r12") - TEST_UNSUPPORTED(__inst_thumb32(0xf30d0c17) " @ ssat r12, #24, sp") - TEST_UNSUPPORTED(__inst_thumb32(0xf30f0c17) " @ 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(__inst_thumb32(0xf38c0d17) " @ usat sp, #24, r12") - TEST_UNSUPPORTED(__inst_thumb32(0xf38c0f17) " @ usat pc, #24, r12") - TEST_UNSUPPORTED(__inst_thumb32(0xf38d0c17) " @ usat r12, #24, sp") - TEST_UNSUPPORTED(__inst_thumb32(0xf38f0c17) " @ usat r12, #24, pc") - - TEST_R( "ssat16 r0, #12, r",0, HH1,"") - TEST_R( "ssat16 r14, #12, r",12, HH2,"") - TEST_UNSUPPORTED(__inst_thumb32(0xf32c0d0b) " @ ssat16 sp, #12, r12") - TEST_UNSUPPORTED(__inst_thumb32(0xf32c0f0b) " @ ssat16 pc, #12, r12") - TEST_UNSUPPORTED(__inst_thumb32(0xf32d0c0b) " @ ssat16 r12, #12, sp") - TEST_UNSUPPORTED(__inst_thumb32(0xf32f0c0b) " @ ssat16 r12, #12, pc") - - TEST_R( "usat16 r0, #12, r",0, HH1,"") - TEST_R( "usat16 r14, #12, r",12, HH2,"") - TEST_UNSUPPORTED(__inst_thumb32(0xf3ac0d0b) " @ usat16 sp, #12, r12") - TEST_UNSUPPORTED(__inst_thumb32(0xf3ac0f0b) " @ usat16 pc, #12, r12") - TEST_UNSUPPORTED(__inst_thumb32(0xf3ad0c0b) " @ usat16 r12, #12, sp") - TEST_UNSUPPORTED(__inst_thumb32(0xf3af0c0b) " @ 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(__inst_thumb32(0xf34c2d0f) " @ sbfx sp, r12, #8, #16") - TEST_UNSUPPORTED(__inst_thumb32(0xf34c2f0f) " @ sbfx pc, r12, #8, #16") - TEST_UNSUPPORTED(__inst_thumb32(0xf34d2c0f) " @ sbfx r12, sp, #8, #16") - TEST_UNSUPPORTED(__inst_thumb32(0xf34f2c0f) " @ 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(__inst_thumb32(0xf3cc2d0f) " @ ubfx sp, r12, #8, #16") - TEST_UNSUPPORTED(__inst_thumb32(0xf3cc2f0f) " @ ubfx pc, r12, #8, #16") - TEST_UNSUPPORTED(__inst_thumb32(0xf3cd2c0f) " @ ubfx r12, sp, #8, #16") - TEST_UNSUPPORTED(__inst_thumb32(0xf3cf2c0f) " @ 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(__inst_thumb32(0xf36f0d1e) " @ bfc sp, #0, #31") - TEST_UNSUPPORTED(__inst_thumb32(0xf36f0f1e) " @ 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(__inst_thumb32(0xf36e1d17) " @ bfi sp, r14, #4, #20") - TEST_UNSUPPORTED(__inst_thumb32(0xf36e1f17) " @ bfi pc, r14, #4, #20") - TEST_UNSUPPORTED(__inst_thumb32(0xf36d1e17) " @ 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(__inst_thumb32(0xf3ef8d00) " @ mrs sp, spsr") - TEST_UNSUPPORTED(__inst_thumb32(0xf3ef8f00) " @ mrs pc, spsr") - TEST_UNSUPPORTED("mrs r0, spsr") - TEST_UNSUPPORTED("mrs lr, spsr") - - TEST_UNSUPPORTED(__inst_thumb32(0xf7f08000) " @ smc #0") - - TEST_UNSUPPORTED(__inst_thumb32(0xf7f0a000) " @ 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(__inst_thumb32(0xf8cfe000) " @ str r14, [pc]") - TEST_UNSUPPORTED(__inst_thumb32(0xf8cef000) " @ str pc, [r14]") - - TEST_GROUP("Advanced SIMD element or structure load/store instructions") - - TEST_UNSUPPORTED(__inst_thumb32(0xf9000000) "") - TEST_UNSUPPORTED(__inst_thumb32(0xf92fffff) "") - TEST_UNSUPPORTED(__inst_thumb32(0xf9800000) "") - TEST_UNSUPPORTED(__inst_thumb32(0xf9efffff) "") - - 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(__inst_thumb32(0xf854700d) " @ ldr r7, [r4, sp]") - TEST_UNSUPPORTED(__inst_thumb32(0xf854700f) " @ ldr r7, [r4, pc]") - TEST_UNSUPPORTED(__inst_thumb32(0xf814700d) " @ ldrb r7, [r4, sp]") - TEST_UNSUPPORTED(__inst_thumb32(0xf814700f) " @ ldrb r7, [r4, pc]") - TEST_UNSUPPORTED(__inst_thumb32(0xf89fd004) " @ ldrb sp, 99f") - TEST_UNSUPPORTED(__inst_thumb32(0xf814d008) " @ ldrb sp, [r4, r8]") - TEST_UNSUPPORTED(__inst_thumb32(0xf894d000) " @ ldrb sp, [r4]") - - TEST_UNSUPPORTED(__inst_thumb32(0xf8600000) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_thumb32(0xf9ffffff) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_thumb32(0xf9500000) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_thumb32(0xf95fffff) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_thumb32(0xf8000800) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_thumb32(0xf97ffaff) "") /* 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( __inst_thumb32(0xf8b0f400) " @ pldw [r0, #1024]") - TEST_P( "pli [r",4, 0b,", #1024]") - TEST_P( "pld [r",7, 120,", #-120]") - TEST( __inst_thumb32(0xf837fc78) " @ 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(__inst_thumb32(0xf837f000) " @ pldw [r7, r0]") - TEST_SUPPORTED(__inst_thumb32(0xf838f03c) " @ 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(__inst_thumb32(0xf817f00d) " @pld [r7, sp]") - TEST_UNSUPPORTED(__inst_thumb32(0xf817f00f) " @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(__inst_thumb32(0xfa01ff02) " @ lsl pc, r1, r2") - TEST_UNSUPPORTED(__inst_thumb32(0xfa01fd02) " @ lsl sp, r1, r2") - TEST_UNSUPPORTED(__inst_thumb32(0xfa0ff002) " @ lsl r0, pc, r2") - TEST_UNSUPPORTED(__inst_thumb32(0xfa0df002) " @ lsl r0, sp, r2") - TEST_UNSUPPORTED(__inst_thumb32(0xfa01f00f) " @ lsl r0, r1, pc") - TEST_UNSUPPORTED(__inst_thumb32(0xfa01f00d) " @ 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(__inst_thumb32(0xfa0fff87) " @ sxth pc, r7"); - TEST_UNSUPPORTED(__inst_thumb32(0xfa0ffd87) " @ sxth sp, r7"); - TEST_UNSUPPORTED(__inst_thumb32(0xfa0ff88f) " @ sxth r8, pc"); - TEST_UNSUPPORTED(__inst_thumb32(0xfa0ff88d) " @ 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(__inst_thumb32(0xfa6000f0) "") - TEST_UNSUPPORTED(__inst_thumb32(0xfa7fffff) "") - -#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(__inst_thumb32(0xfa9cff8c) " @ rev pc, r12"); - TEST_UNSUPPORTED(__inst_thumb32(0xfa9cfd8c) " @ rev sp, r12"); - TEST_UNSUPPORTED(__inst_thumb32(0xfa9ffe8f) " @ rev r14, pc"); - TEST_UNSUPPORTED(__inst_thumb32(0xfa9dfe8d) " @ 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(__inst_thumb32(0xfa80f030) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_thumb32(0xfaffff7f) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_thumb32(0xfab0f000) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_thumb32(0xfaffff7f) "") /* 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(__inst_thumb32(0xfb08ff09) " @ mul pc, r8, r9") - TEST_UNSUPPORTED(__inst_thumb32(0xfb08fd09) " @ mul sp, r8, r9") - TEST_UNSUPPORTED(__inst_thumb32(0xfb0ff709) " @ mul r7, pc, r9") - TEST_UNSUPPORTED(__inst_thumb32(0xfb0df709) " @ mul r7, sp, r9") - TEST_UNSUPPORTED(__inst_thumb32(0xfb08f70f) " @ mul r7, r8, pc") - TEST_UNSUPPORTED(__inst_thumb32(0xfb08f70d) " @ 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(__inst_thumb32(0xfb08af09) " @ mla pc, r8, r9, r10"); - TEST_UNSUPPORTED(__inst_thumb32(0xfb08ad09) " @ mla sp, r8, r9, r10"); - TEST_UNSUPPORTED(__inst_thumb32(0xfb0fa709) " @ mla r7, pc, r9, r10"); - TEST_UNSUPPORTED(__inst_thumb32(0xfb0da709) " @ mla r7, sp, r9, r10"); - TEST_UNSUPPORTED(__inst_thumb32(0xfb08a70f) " @ mla r7, r8, pc, r10"); - TEST_UNSUPPORTED(__inst_thumb32(0xfb08a70d) " @ mla r7, r8, sp, r10"); - TEST_UNSUPPORTED(__inst_thumb32(0xfb08d709) " @ 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(__inst_thumb32(0xfb00f010) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_thumb32(0xfb0fff1f) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_thumb32(0xfb70f010) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_thumb32(0xfb7fff1f) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_thumb32(0xfb700010) "") /* Unallocated space */ - TEST_UNSUPPORTED(__inst_thumb32(0xfb7fff1f) "") /* 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(__inst_thumb32(0xfb89f80a) " @ smull pc, r8, r9, r10"); - TEST_UNSUPPORTED(__inst_thumb32(0xfb89d80a) " @ smull sp, r8, r9, r10"); - TEST_UNSUPPORTED(__inst_thumb32(0xfb897f0a) " @ smull r7, pc, r9, r10"); - TEST_UNSUPPORTED(__inst_thumb32(0xfb897d0a) " @ smull r7, sp, r9, r10"); - TEST_UNSUPPORTED(__inst_thumb32(0xfb8f780a) " @ smull r7, r8, pc, r10"); - TEST_UNSUPPORTED(__inst_thumb32(0xfb8d780a) " @ smull r7, r8, sp, r10"); - TEST_UNSUPPORTED(__inst_thumb32(0xfb89780f) " @ smull r7, r8, r9, pc"); - TEST_UNSUPPORTED(__inst_thumb32(0xfb89780d) " @ 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(__inst_thumb32(0xfc000000) "") - TEST_UNSUPPORTED(__inst_thumb32(0xffffffff) "") - - TEST_GROUP("Testing instructions in IT blocks") - - TEST_ITBLOCK("sub.w r0, r0") - - verbose("\n"); -} - diff --git a/arch/arm/kernel/kprobes-test.c b/arch/arm/kernel/kprobes-test.c deleted file mode 100644 index b206d7790c77..000000000000 --- a/arch/arm/kernel/kprobes-test.c +++ /dev/null @@ -1,1713 +0,0 @@ -/* - * arch/arm/kernel/kprobes-test.c - * - * Copyright (C) 2011 Jon Medhurst . - * - * 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 - * .pushsection .rodata - * "10: - * .ascii "mov r0, r7" @ text title for test case - * .byte 0 - * .popsection - * @ start of inline data... - * .word 10b @ pointer to title in .rodata section - * - * @ 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 -#include -#include -#include -#include -#include -#include -#include - -#include "kprobes.h" -#include "probes-arm.h" -#include "probes-thumb.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; -static int tests_failed; - -#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 defined(CONFIG_THUMB2_KERNEL) && !defined(MODULE) - if (ret == -EINVAL) { - pr_err("FAIL: Known longtime bug with jprobe on Thumb kernels\n"); - tests_failed = ret; - ret = 0; - } -#endif - 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 data \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(__mem_to_opcode_thumb16(*(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; - - current_title = *title++; - args = (struct test_arg *)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 = __mem_to_opcode_thumb16(p[0]); - if (is_wide_instruction(current_instruction)) { - u16 instr2 = __mem_to_opcode_thumb16(p[1]); - current_instruction = __opcode_thumb32_compose(current_instruction, instr2); - } - } else { - current_instruction = __mem_to_opcode_arm(*(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("Beginning 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, probes_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, - probes_decode_thumb16_table); - if (ret) - goto out; - - pr_info("32-bit Thumb instruction simulation\n"); - ret = run_test_cases(kprobe_thumb32_test_cases, - probes_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) - ret = tests_failed; - 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/arch/arm/kernel/kprobes-test.h b/arch/arm/kernel/kprobes-test.h deleted file mode 100644 index 4430990e90e7..000000000000 --- a/arch/arm/kernel/kprobes-test.h +++ /dev/null @@ -1,435 +0,0 @@ -/* - * arch/arm/kernel/kprobes-test.h - * - * Copyright (C) 2011 Jon Medhurst . - * - * 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" \ - ".pushsection .rodata \n\t" \ - "10: \n\t" \ - /* don't use .asciz here as 'title' may be */ \ - /* multiple strings to be concatenated. */ \ - ".ascii "#title" \n\t" \ - ".byte 0 \n\t" \ - ".popsection \n\t" \ - ".word 10b \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/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c deleted file mode 100644 index 9495d7f3516f..000000000000 --- a/arch/arm/kernel/kprobes-thumb.c +++ /dev/null @@ -1,666 +0,0 @@ -/* - * arch/arm/kernel/kprobes-thumb.c - * - * Copyright (C) 2011 Jon Medhurst . - * - * 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 -#include -#include -#include - -#include "kprobes.h" -#include "probes-thumb.h" - -/* These emulation encodings are functionally equivalent... */ -#define t32_emulate_rd8rn16rm0ra12_noflags \ - t32_emulate_rdlo12rdhi8rn16rm0_noflags - -/* t32 thumb actions */ - -static void __kprobes -t32_simulate_table_branch(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - unsigned long pc = regs->ARM_pc; - 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(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - 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(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - unsigned long pc = regs->ARM_pc; - - 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 probes_insn __kprobes -t32_decode_cond_branch(probes_opcode_t insn, struct arch_probes_insn *asi, - const struct decode_header *d) -{ - int cc = (insn >> 22) & 0xf; - asi->insn_check_cc = probes_condition_checks[cc]; - asi->insn_handler = t32_simulate_cond_branch; - return INSN_GOOD_NO_SLOT; -} - -static void __kprobes -t32_simulate_branch(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - unsigned long pc = regs->ARM_pc; - - 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 = regs->ARM_pc | 1; - 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(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - unsigned long addr = regs->ARM_pc & ~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 probes_insn __kprobes -t32_decode_ldmstm(probes_opcode_t insn, struct arch_probes_insn *asi, - const struct decode_header *d) -{ - enum probes_insn ret = kprobe_decode_ldmstm(insn, asi, d); - - /* Fixup modified instruction to have halfwords in correct order...*/ - insn = __mem_to_opcode_arm(asi->insn[0]); - ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(insn >> 16); - ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0xffff); - - return ret; -} - -static void __kprobes -t32_emulate_ldrdstrd(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - unsigned long pc = regs->ARM_pc & ~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" (asi->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(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - 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" (asi->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(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - 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" (asi->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(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - unsigned long pc = regs->ARM_pc; - 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" (asi->insn_fn) - : "lr", "memory", "cc" - ); - - regs->uregs[rd] = rdv; -} - -static void __kprobes -t32_emulate_rd8rn16_noflags(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - 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" (asi->insn_fn) - : "lr", "memory", "cc" - ); - - regs->uregs[rd] = rdv; -} - -static void __kprobes -t32_emulate_rdlo12rdhi8rn16rm0_noflags(probes_opcode_t insn, - struct arch_probes_insn *asi, - struct pt_regs *regs) -{ - 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" (asi->insn_fn) - : "lr", "memory", "cc" - ); - - regs->uregs[rdlo] = rdlov; - regs->uregs[rdhi] = rdhiv; -} -/* t16 thumb actions */ - -static void __kprobes -t16_simulate_bxblx(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - unsigned long pc = regs->ARM_pc + 2; - int rm = (insn >> 3) & 0xf; - unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm]; - - if (insn & (1 << 7)) /* BLX ? */ - regs->ARM_lr = regs->ARM_pc | 1; - - bx_write_pc(rmv, regs); -} - -static void __kprobes -t16_simulate_ldr_literal(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - unsigned long *base = (unsigned long *)((regs->ARM_pc + 2) & ~3); - long index = insn & 0xff; - int rt = (insn >> 8) & 0x7; - regs->uregs[rt] = base[index]; -} - -static void __kprobes -t16_simulate_ldrstr_sp_relative(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - 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(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - unsigned long base = (insn & 0x800) ? regs->ARM_sp - : ((regs->ARM_pc + 2) & ~3); - long offset = insn & 0xff; - int rt = (insn >> 8) & 0x7; - regs->uregs[rt] = base + offset * 4; -} - -static void __kprobes -t16_simulate_add_sp_imm(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - 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(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - int rn = insn & 0x7; - probes_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn; - if (nonzero & 0x800) { - long i = insn & 0x200; - long imm5 = insn & 0xf8; - unsigned long pc = regs->ARM_pc + 2; - regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2); - } -} - -static void __kprobes -t16_simulate_it(probes_opcode_t insn, - struct arch_probes_insn *asi, 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. - */ - 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(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - regs->ARM_pc += 2; - t16_simulate_it(insn, asi, regs); -} - -static enum probes_insn __kprobes -t16_decode_it(probes_opcode_t insn, struct arch_probes_insn *asi, - const struct decode_header *d) -{ - asi->insn_singlestep = t16_singlestep_it; - return INSN_GOOD_NO_SLOT; -} - -static void __kprobes -t16_simulate_cond_branch(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - unsigned long pc = regs->ARM_pc + 2; - long offset = insn & 0x7f; - offset -= insn & 0x80; /* Apply sign bit */ - regs->ARM_pc = pc + (offset * 2); -} - -static enum probes_insn __kprobes -t16_decode_cond_branch(probes_opcode_t insn, struct arch_probes_insn *asi, - const struct decode_header *d) -{ - int cc = (insn >> 8) & 0xf; - asi->insn_check_cc = probes_condition_checks[cc]; - asi->insn_handler = t16_simulate_cond_branch; - return INSN_GOOD_NO_SLOT; -} - -static void __kprobes -t16_simulate_branch(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - unsigned long pc = regs->ARM_pc + 2; - long offset = insn & 0x3ff; - offset -= insn & 0x400; /* Apply sign bit */ - regs->ARM_pc = pc + (offset * 2); -} - -static unsigned long __kprobes -t16_emulate_loregs(probes_opcode_t insn, - struct arch_probes_insn *asi, 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" (asi->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(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - regs->ARM_cpsr = t16_emulate_loregs(insn, asi, regs); -} - -static void __kprobes -t16_emulate_loregs_noitrwflags(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - unsigned long cpsr = t16_emulate_loregs(insn, asi, regs); - if (!in_it_block(cpsr)) - regs->ARM_cpsr = cpsr; -} - -static void __kprobes -t16_emulate_hiregs(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - unsigned long pc = regs->ARM_pc + 2; - 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" (asi->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 probes_insn __kprobes -t16_decode_hiregs(probes_opcode_t insn, struct arch_probes_insn *asi, - const struct decode_header *d) -{ - insn &= ~0x00ff; - insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */ - ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(insn); - asi->insn_handler = t16_emulate_hiregs; - return INSN_GOOD; -} - -static void __kprobes -t16_emulate_push(probes_opcode_t insn, - struct arch_probes_insn *asi, 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" (asi->insn_fn) - : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", - "lr", "memory", "cc" - ); -} - -static enum probes_insn __kprobes -t16_decode_push(probes_opcode_t insn, struct arch_probes_insn *asi, - const struct decode_header *d) -{ - /* - * 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. - */ - /* 1st half STMDB R9!,{} */ - ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(0xe929); - /* 2nd half (register list) */ - ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0x1ff); - asi->insn_handler = t16_emulate_push; - return INSN_GOOD; -} - -static void __kprobes -t16_emulate_pop_nopc(probes_opcode_t insn, - struct arch_probes_insn *asi, 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" (asi->insn_fn) - : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", - "lr", "memory", "cc" - ); -} - -static void __kprobes -t16_emulate_pop_pc(probes_opcode_t insn, - struct arch_probes_insn *asi, 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" (asi->insn_fn) - : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", - "lr", "memory", "cc" - ); - - bx_write_pc(pc, regs); -} - -static enum probes_insn __kprobes -t16_decode_pop(probes_opcode_t insn, struct arch_probes_insn *asi, - const struct decode_header *d) -{ - /* - * 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. - */ - /* 1st half LDMIA R9!,{} */ - ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(0xe8b9); - /* 2nd half (register list) */ - ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0x1ff); - asi->insn_handler = insn & 0x100 ? t16_emulate_pop_pc - : t16_emulate_pop_nopc; - return INSN_GOOD; -} - -const union decode_action kprobes_t16_actions[NUM_PROBES_T16_ACTIONS] = { - [PROBES_T16_ADD_SP] = {.handler = t16_simulate_add_sp_imm}, - [PROBES_T16_CBZ] = {.handler = t16_simulate_cbz}, - [PROBES_T16_SIGN_EXTEND] = {.handler = t16_emulate_loregs_rwflags}, - [PROBES_T16_PUSH] = {.decoder = t16_decode_push}, - [PROBES_T16_POP] = {.decoder = t16_decode_pop}, - [PROBES_T16_SEV] = {.handler = probes_emulate_none}, - [PROBES_T16_WFE] = {.handler = probes_simulate_nop}, - [PROBES_T16_IT] = {.decoder = t16_decode_it}, - [PROBES_T16_CMP] = {.handler = t16_emulate_loregs_rwflags}, - [PROBES_T16_ADDSUB] = {.handler = t16_emulate_loregs_noitrwflags}, - [PROBES_T16_LOGICAL] = {.handler = t16_emulate_loregs_noitrwflags}, - [PROBES_T16_LDR_LIT] = {.handler = t16_simulate_ldr_literal}, - [PROBES_T16_BLX] = {.handler = t16_simulate_bxblx}, - [PROBES_T16_HIREGOPS] = {.decoder = t16_decode_hiregs}, - [PROBES_T16_LDRHSTRH] = {.handler = t16_emulate_loregs_rwflags}, - [PROBES_T16_LDRSTR] = {.handler = t16_simulate_ldrstr_sp_relative}, - [PROBES_T16_ADR] = {.handler = t16_simulate_reladr}, - [PROBES_T16_LDMSTM] = {.handler = t16_emulate_loregs_rwflags}, - [PROBES_T16_BRANCH_COND] = {.decoder = t16_decode_cond_branch}, - [PROBES_T16_BRANCH] = {.handler = t16_simulate_branch}, -}; - -const union decode_action kprobes_t32_actions[NUM_PROBES_T32_ACTIONS] = { - [PROBES_T32_LDMSTM] = {.decoder = t32_decode_ldmstm}, - [PROBES_T32_LDRDSTRD] = {.handler = t32_emulate_ldrdstrd}, - [PROBES_T32_TABLE_BRANCH] = {.handler = t32_simulate_table_branch}, - [PROBES_T32_TST] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, - [PROBES_T32_MOV] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, - [PROBES_T32_ADDSUB] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, - [PROBES_T32_LOGICAL] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, - [PROBES_T32_CMP] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, - [PROBES_T32_ADDWSUBW_PC] = {.handler = t32_emulate_rd8pc16_noflags,}, - [PROBES_T32_ADDWSUBW] = {.handler = t32_emulate_rd8rn16_noflags}, - [PROBES_T32_MOVW] = {.handler = t32_emulate_rd8rn16_noflags}, - [PROBES_T32_SAT] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, - [PROBES_T32_BITFIELD] = {.handler = t32_emulate_rd8rn16_noflags}, - [PROBES_T32_SEV] = {.handler = probes_emulate_none}, - [PROBES_T32_WFE] = {.handler = probes_simulate_nop}, - [PROBES_T32_MRS] = {.handler = t32_simulate_mrs}, - [PROBES_T32_BRANCH_COND] = {.decoder = t32_decode_cond_branch}, - [PROBES_T32_BRANCH] = {.handler = t32_simulate_branch}, - [PROBES_T32_PLDI] = {.handler = probes_simulate_nop}, - [PROBES_T32_LDR_LIT] = {.handler = t32_simulate_ldr_literal}, - [PROBES_T32_LDRSTR] = {.handler = t32_emulate_ldrstr}, - [PROBES_T32_SIGN_EXTEND] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, - [PROBES_T32_MEDIA] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, - [PROBES_T32_REVERSE] = {.handler = t32_emulate_rd8rn16_noflags}, - [PROBES_T32_MUL_ADD] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, - [PROBES_T32_MUL_ADD2] = {.handler = t32_emulate_rd8rn16rm0ra12_noflags}, - [PROBES_T32_MUL_ADD_LONG] = { - .handler = t32_emulate_rdlo12rdhi8rn16rm0_noflags}, -}; diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c deleted file mode 100644 index 6d644202c8dc..000000000000 --- a/arch/arm/kernel/kprobes.c +++ /dev/null @@ -1,628 +0,0 @@ -/* - * arch/arm/kernel/kprobes.c - * - * Kprobes on ARM - * - * Abhishek Sagar - * Copyright (C) 2006, 2007 Motorola Inc. - * - * Nicolas Pitre - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "kprobes.h" -#include "probes-arm.h" -#include "probes-thumb.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; - const union decode_action *actions; - 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 = __mem_to_opcode_thumb16(((u16 *)addr)[0]); - if (is_wide_instruction(insn)) { - u16 inst2 = __mem_to_opcode_thumb16(((u16 *)addr)[1]); - insn = __opcode_thumb32_compose(insn, inst2); - decode_insn = thumb32_probes_decode_insn; - actions = kprobes_t32_actions; - } else { - decode_insn = thumb16_probes_decode_insn; - actions = kprobes_t16_actions; - } -#else /* !CONFIG_THUMB2_KERNEL */ - thumb = false; - if (addr & 0x3) - return -EINVAL; - insn = __mem_to_opcode_arm(*p->addr); - decode_insn = arm_probes_decode_insn; - actions = kprobes_arm_actions; -#endif - - p->opcode = insn; - p->ainsn.insn = tmp_insn; - - switch ((*decode_insn)(insn, &p->ainsn, true, actions)) { - 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 = (probes_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) -{ - __this_cpu_write(current_kprobe, kcb->prev_kprobe.kp); - kcb->kprobe_status = kcb->prev_kprobe.status; -} - -static void __kprobes set_current_kprobe(struct kprobe *p) -{ - __this_cpu_write(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->opcode, &p->ainsn, 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 *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, tmp, head, hlist) { - if (ri->task != current) - /* another task is sharing our hash bucket */ - continue; - - if (ri->rp && ri->rp->handler) { - __this_cpu_write(current_kprobe, &ri->rp->kp); - get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE; - ri->rp->handler(ri, regs); - __this_cpu_write(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, 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_probes_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/arch/arm/kernel/kprobes.h b/arch/arm/kernel/kprobes.h deleted file mode 100644 index 9a2712ecefc3..000000000000 --- a/arch/arm/kernel/kprobes.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * arch/arm/kernel/kprobes.h - * - * Copyright (C) 2011 Jon Medhurst . - * - * 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 - -#include "probes.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 probes_insn __kprobes -kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_probes_insn *asi, - const struct decode_header *h); - -typedef enum probes_insn (kprobe_decode_insn_t)(probes_opcode_t, - struct arch_probes_insn *, - bool, - const union decode_action *); - -#ifdef CONFIG_THUMB2_KERNEL - -extern const union decode_action kprobes_t32_actions[]; -extern const union decode_action kprobes_t16_actions[]; - -#else /* !CONFIG_THUMB2_KERNEL */ - -extern const union decode_action kprobes_arm_actions[]; - -#endif - -#endif /* _ARM_KERNEL_KPROBES_H */ diff --git a/arch/arm/kernel/patch.c b/arch/arm/kernel/patch.c index 5038960e3c55..69bda1a5707e 100644 --- a/arch/arm/kernel/patch.c +++ b/arch/arm/kernel/patch.c @@ -8,8 +8,7 @@ #include #include #include - -#include "patch.h" +#include struct patch { void *addr; diff --git a/arch/arm/kernel/patch.h b/arch/arm/kernel/patch.h deleted file mode 100644 index 77e054c2f6cd..000000000000 --- a/arch/arm/kernel/patch.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _ARM_KERNEL_PATCH_H -#define _ARM_KERNEL_PATCH_H - -void patch_text(void *addr, unsigned int insn); -void __patch_text_real(void *addr, unsigned int insn, bool remap); - -static inline void __patch_text(void *addr, unsigned int insn) -{ - __patch_text_real(addr, insn, true); -} - -static inline void __patch_text_early(void *addr, unsigned int insn) -{ - __patch_text_real(addr, insn, false); -} - -#endif diff --git a/arch/arm/kernel/probes-arm.c b/arch/arm/kernel/probes-arm.c deleted file mode 100644 index 8eaef81d8344..000000000000 --- a/arch/arm/kernel/probes-arm.c +++ /dev/null @@ -1,734 +0,0 @@ -/* - * arch/arm/kernel/probes-arm.c - * - * Some code moved here from arch/arm/kernel/kprobes-arm.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. - */ - -#include -#include -#include -#include - -#include "probes.h" -#include "probes-arm.h" - -#define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit))))) - -#define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25) - -/* - * 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. - */ - -void __kprobes simulate_bbl(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - long iaddr = (long) regs->ARM_pc - 4; - int disp = branch_displacement(insn); - - if (insn & (1 << 24)) - regs->ARM_lr = iaddr + 4; - - regs->ARM_pc = iaddr + 8 + disp; -} - -void __kprobes simulate_blx1(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - long iaddr = (long) regs->ARM_pc - 4; - 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; -} - -void __kprobes simulate_blx2bx(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - int rm = insn & 0xf; - long rmv = regs->uregs[rm]; - - if (insn & (1 << 5)) - regs->ARM_lr = (long) regs->ARM_pc; - - regs->ARM_pc = rmv & ~0x1; - regs->ARM_cpsr &= ~PSR_T_BIT; - if (rmv & 0x1) - regs->ARM_cpsr |= PSR_T_BIT; -} - -void __kprobes simulate_mrs(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - int rd = (insn >> 12) & 0xf; - unsigned long mask = 0xf8ff03df; /* Mask out execution state */ - regs->uregs[rd] = regs->ARM_cpsr & mask; -} - -void __kprobes simulate_mov_ipsp(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - regs->uregs[12] = regs->uregs[13]; -} - -/* - * 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, PROBES_PRELOAD_IMM), - - /* 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, PROBES_PRELOAD_REG), - - /* BLX (immediate) 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx */ - DECODE_SIMULATE (0xfe000000, 0xfa000000, PROBES_BRANCH_IMM), - - /* 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, PROBES_MRS, - REGS(0, NOPC, 0, 0, 0)), - - /* BX cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */ - DECODE_SIMULATE (0x0ff000f0, 0x01200010, PROBES_BRANCH_REG), - - /* BLX (register) cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */ - DECODE_SIMULATEX(0x0ff000f0, 0x01200030, PROBES_BRANCH_REG, - REGS(0, 0, 0, 0, NOPC)), - - /* CLZ cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */ - DECODE_EMULATEX (0x0ff000f0, 0x01600010, PROBES_CLZ, - 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, PROBES_SATURATING_ARITHMETIC, - 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, PROBES_MUL1, - 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, PROBES_MUL2, - 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, PROBES_MUL2, - 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, PROBES_MUL2, - 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, PROBES_MUL2, - 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, PROBES_MUL1, - 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, PROBES_SWP, - 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, PROBES_LDRSTRD, - 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, PROBES_LDRSTRD, - REGS(NOPCWB, NOPCX, 0, 0, 0)), - - /* STRH (register) cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx */ - DECODE_EMULATEX (0x0e5000f0, 0x000000b0, PROBES_STORE_EXTRA, - 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, PROBES_LOAD_EXTRA, - REGS(NOPCWB, NOPC, 0, 0, NOPC)), - - /* STRH (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1011 xxxx */ - DECODE_EMULATEX (0x0e5000f0, 0x004000b0, PROBES_STORE_EXTRA, - 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, PROBES_LOAD_EXTRA, - REGS(NOPCWB, NOPC, 0, 0, 0)), - - DECODE_END -}; - -static const union decode_item arm_cccc_000x_table[] = { - /* Data-processing (register) */ - - /* 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, PROBES_MOV_IP_SP), - - /* 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, PROBES_DATA_PROCESSING_REG, - 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, PROBES_DATA_PROCESSING_REG, - 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, PROBES_DATA_PROCESSING_REG, - 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, PROBES_DATA_PROCESSING_REG, - REGS(NOPC, 0, NOPC, 0, NOPC)), - - /* 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, PROBES_DATA_PROCESSING_REG, - REGS(0, NOPC, NOPC, 0, NOPC)), - - /* 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, PROBES_DATA_PROCESSING_REG, - REGS(NOPC, NOPC, NOPC, 0, NOPC)), - - 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, PROBES_DATA_PROCESSING_IMM, - 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, PROBES_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, PROBES_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), - - /* 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, PROBES_DATA_PROCESSING_IMM, - 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, PROBES_DATA_PROCESSING_IMM, - 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, PROBES_DATA_PROCESSING_IMM, - 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, PROBES_SATURATE, - 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, PROBES_SATURATE, - 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, PROBES_REV, - 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, PROBES_MMI, - 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, PROBES_PACK, - 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, PROBES_EXTEND, - 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, PROBES_EXTEND_ADD, - 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, PROBES_MUL_ADD_LONG, - 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, PROBES_MUL_ADD, - 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, PROBES_MUL_ADD, - REGS(NOPC, NOPCX, NOPC, 0, NOPC)), - - /* SMMLS cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx */ - DECODE_EMULATEX (0x0ff000d0, 0x075000d0, PROBES_MUL_ADD, - 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, PROBES_BITFIELD, - REGS(0, NOPC, 0, 0, NOPC)), - - /* BFC cccc 0111 110x xxxx xxxx xxxx x001 1111 */ - DECODE_EMULATEX (0x0fe0007f, 0x07c0001f, PROBES_BITFIELD, - REGS(0, NOPC, 0, 0, 0)), - - /* BFI cccc 0111 110x xxxx xxxx xxxx x001 xxxx */ - DECODE_EMULATEX (0x0fe00070, 0x07c00010, PROBES_BITFIELD, - 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, PROBES_STORE, - 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, PROBES_LOAD, - 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, PROBES_STORE, - 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, PROBES_LOAD, - 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, PROBES_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 probes_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, PROBES_BRANCH), - - /* - * 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(probes_decode_arm_table); -#endif - -static void __kprobes arm_singlestep(probes_opcode_t insn, - struct arch_probes_insn *asi, struct pt_regs *regs) -{ - regs->ARM_pc += 4; - asi->insn_handler(insn, asi, 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 probes_insn __kprobes -arm_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, - bool emulate, const union decode_action *actions) -{ - asi->insn_singlestep = arm_singlestep; - asi->insn_check_cc = probes_condition_checks[insn>>28]; - return probes_decode_insn(insn, asi, probes_decode_arm_table, false, - emulate, actions); -} diff --git a/arch/arm/kernel/probes-arm.h b/arch/arm/kernel/probes-arm.h deleted file mode 100644 index ace6572f6e26..000000000000 --- a/arch/arm/kernel/probes-arm.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * arch/arm/kernel/probes-arm.h - * - * Copyright 2013 Linaro Ltd. - * Written by: David A. Long - * - * 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 - */ - -#ifndef _ARM_KERNEL_PROBES_ARM_H -#define _ARM_KERNEL_PROBES_ARM_H - -enum probes_arm_action { - PROBES_EMULATE_NONE, - PROBES_SIMULATE_NOP, - PROBES_PRELOAD_IMM, - PROBES_PRELOAD_REG, - PROBES_BRANCH_IMM, - PROBES_BRANCH_REG, - PROBES_MRS, - PROBES_CLZ, - PROBES_SATURATING_ARITHMETIC, - PROBES_MUL1, - PROBES_MUL2, - PROBES_SWP, - PROBES_LDRSTRD, - PROBES_LOAD, - PROBES_STORE, - PROBES_LOAD_EXTRA, - PROBES_STORE_EXTRA, - PROBES_MOV_IP_SP, - PROBES_DATA_PROCESSING_REG, - PROBES_DATA_PROCESSING_IMM, - PROBES_MOV_HALFWORD, - PROBES_SEV, - PROBES_WFE, - PROBES_SATURATE, - PROBES_REV, - PROBES_MMI, - PROBES_PACK, - PROBES_EXTEND, - PROBES_EXTEND_ADD, - PROBES_MUL_ADD_LONG, - PROBES_MUL_ADD, - PROBES_BITFIELD, - PROBES_BRANCH, - PROBES_LDMSTM, - NUM_PROBES_ARM_ACTIONS -}; - -void __kprobes simulate_bbl(probes_opcode_t opcode, - struct arch_probes_insn *asi, struct pt_regs *regs); -void __kprobes simulate_blx1(probes_opcode_t opcode, - struct arch_probes_insn *asi, struct pt_regs *regs); -void __kprobes simulate_blx2bx(probes_opcode_t opcode, - struct arch_probes_insn *asi, struct pt_regs *regs); -void __kprobes simulate_mrs(probes_opcode_t opcode, - struct arch_probes_insn *asi, struct pt_regs *regs); -void __kprobes simulate_mov_ipsp(probes_opcode_t opcode, - struct arch_probes_insn *asi, struct pt_regs *regs); - -extern const union decode_item probes_decode_arm_table[]; - -enum probes_insn arm_probes_decode_insn(probes_opcode_t, - struct arch_probes_insn *, bool emulate, - const union decode_action *actions); - -#endif diff --git a/arch/arm/kernel/probes-thumb.c b/arch/arm/kernel/probes-thumb.c deleted file mode 100644 index 4131351e812f..000000000000 --- a/arch/arm/kernel/probes-thumb.c +++ /dev/null @@ -1,882 +0,0 @@ -/* - * arch/arm/kernel/probes-thumb.c - * - * Copyright (C) 2011 Jon Medhurst . - * - * 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 -#include -#include - -#include "probes.h" -#include "probes-thumb.h" - - -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, PROBES_T32_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, PROBES_T32_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, PROBES_T32_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, PROBES_T32_TST, - 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, PROBES_T32_TST, - 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, PROBES_T32_MOV, - 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, PROBES_T32_ADDSUB, - 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, PROBES_T32_ADDSUB, - 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, PROBES_T32_LOGICAL, - 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, PROBES_T32_TST, - 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, PROBES_T32_CMP, - 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, PROBES_T32_MOV, - 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, PROBES_T32_ADDSUB, - 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, PROBES_T32_LOGICAL, - 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, PROBES_T32_ADDWSUBW_PC, - 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, PROBES_T32_ADDWSUBW, - 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, PROBES_T32_ADDWSUBW, - 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, PROBES_T32_MOVW, - 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, PROBES_T32_SAT, - 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, PROBES_T32_BITFIELD, - REGS(NOSPPC, 0, NOSPPC, 0, 0)), - - /* BFC 1111 0x11 0110 1111 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfbff8000, 0xf36f0000, PROBES_T32_BITFIELD, - REGS(0, 0, NOSPPC, 0, 0)), - - /* BFI 1111 0x11 0110 xxxx 0xxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0xfbf08000, 0xf3600000, PROBES_T32_BITFIELD, - 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, PROBES_T32_SEV), - /* 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, PROBES_T32_WFE), - - /* MRS Rd, CPSR 1111 0011 1110 xxxx 10x0 xxxx xxxx xxxx */ - DECODE_SIMULATEX(0xfff0d000, 0xf3e08000, PROBES_T32_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,# 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, PROBES_T32_BRANCH_COND), - - /* 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, PROBES_T32_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, PROBES_T32_PLDI), - - /* 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, PROBES_T32_PLDI, - 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, PROBES_T32_PLDI, - 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, PROBES_T32_LDR_LIT, - 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, PROBES_T32_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, PROBES_T32_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_SIMULATEX(0xfe5f0000, 0xf81f0000, PROBES_T32_LDR_LIT, - 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, PROBES_T32_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, PROBES_T32_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, PROBES_T32_SIGN_EXTEND, - 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, PROBES_T32_MEDIA, - 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, PROBES_T32_REVERSE, - 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, PROBES_T32_MUL_ADD, - 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, PROBES_T32_MUL_ADD2, - 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, PROBES_T32_MUL_ADD_LONG, - 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 probes_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(probes_decode_thumb32_table); -#endif - -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, PROBES_T16_ADD_SP), - - /* CBZ 1011 00x1 xxxx xxxx */ - /* CBNZ 1011 10x1 xxxx xxxx */ - DECODE_SIMULATE (0xf500, 0xb100, PROBES_T16_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, PROBES_T16_SIGN_EXTEND), - - /* PUSH 1011 010x xxxx xxxx */ - DECODE_CUSTOM (0xfe00, 0xb400, PROBES_T16_PUSH), - /* POP 1011 110x xxxx xxxx */ - DECODE_CUSTOM (0xfe00, 0xbc00, PROBES_T16_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, PROBES_T16_SEV), - /* NOP 1011 1111 0000 0000 */ - /* WFE 1011 1111 0010 0000 */ - /* WFI 1011 1111 0011 0000 */ - DECODE_SIMULATE (0xffcf, 0xbf00, PROBES_T16_WFE), - /* Unassigned hints 1011 1111 xxxx 0000 */ - DECODE_REJECT (0xff0f, 0xbf00), - /* IT 1011 1111 xxxx xxxx */ - DECODE_CUSTOM (0xff00, 0xbf00, PROBES_T16_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 probes_decode_thumb16_table[] = { - - /* - * Shift (immediate), add, subtract, move, and compare - * 00xx xxxx xxxx xxxx - */ - - /* CMP (immediate) 0010 1xxx xxxx xxxx */ - DECODE_EMULATE (0xf800, 0x2800, PROBES_T16_CMP), - - /* 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, PROBES_T16_ADDSUB), - - /* - * 16-bit Thumb data-processing instructions - * 0100 00xx xxxx xxxx - */ - - /* TST (register) 0100 0010 00xx xxxx */ - DECODE_EMULATE (0xffc0, 0x4200, PROBES_T16_CMP), - /* CMP (register) 0100 0010 10xx xxxx */ - /* CMN (register) 0100 0010 11xx xxxx */ - DECODE_EMULATE (0xff80, 0x4280, PROBES_T16_CMP), - /* 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, PROBES_T16_LOGICAL), - - /* - * 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, PROBES_T16_BLX), - - /* 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, PROBES_T16_HIREGOPS), - - /* - * Load from Literal Pool - * LDR (literal) 0100 1xxx xxxx xxxx - */ - DECODE_SIMULATE (0xf800, 0x4800, PROBES_T16_LDR_LIT), - - /* - * 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, PROBES_T16_LDRHSTRH), - /* STRH (immediate, Thumb) 1000 0xxx xxxx xxxx */ - /* LDRH (immediate, Thumb) 1000 1xxx xxxx xxxx */ - DECODE_EMULATE (0xf000, 0x8000, PROBES_T16_LDRHSTRH), - /* STR (immediate, Thumb) 1001 0xxx xxxx xxxx */ - /* LDR (immediate, Thumb) 1001 1xxx xxxx xxxx */ - DECODE_SIMULATE (0xf000, 0x9000, PROBES_T16_LDRSTR), - - /* - * Generate PC-/SP-relative address - * ADR (literal) 1010 0xxx xxxx xxxx - * ADD (SP plus immediate) 1010 1xxx xxxx xxxx - */ - DECODE_SIMULATE (0xf000, 0xa000, PROBES_T16_ADR), - - /* - * 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, PROBES_T16_LDMSTM), - - /* - * 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, PROBES_T16_BRANCH_COND), - - /* - * Unconditional branch - * B 1110 0xxx xxxx xxxx - */ - DECODE_SIMULATE (0xf800, 0xe000, PROBES_T16_BRANCH), - - DECODE_END -}; -#ifdef CONFIG_ARM_KPROBES_TEST_MODULE -EXPORT_SYMBOL_GPL(probes_decode_thumb16_table); -#endif - -static unsigned long __kprobes thumb_check_cc(unsigned long cpsr) -{ - if (unlikely(in_it_block(cpsr))) - return probes_condition_checks[current_cond(cpsr)](cpsr); - return true; -} - -static void __kprobes thumb16_singlestep(probes_opcode_t opcode, - struct arch_probes_insn *asi, - struct pt_regs *regs) -{ - regs->ARM_pc += 2; - asi->insn_handler(opcode, asi, regs); - regs->ARM_cpsr = it_advance(regs->ARM_cpsr); -} - -static void __kprobes thumb32_singlestep(probes_opcode_t opcode, - struct arch_probes_insn *asi, - struct pt_regs *regs) -{ - regs->ARM_pc += 4; - asi->insn_handler(opcode, asi, regs); - regs->ARM_cpsr = it_advance(regs->ARM_cpsr); -} - -enum probes_insn __kprobes -thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, - bool emulate, const union decode_action *actions) -{ - asi->insn_singlestep = thumb16_singlestep; - asi->insn_check_cc = thumb_check_cc; - return probes_decode_insn(insn, asi, probes_decode_thumb16_table, true, - emulate, actions); -} - -enum probes_insn __kprobes -thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, - bool emulate, const union decode_action *actions) -{ - asi->insn_singlestep = thumb32_singlestep; - asi->insn_check_cc = thumb_check_cc; - return probes_decode_insn(insn, asi, probes_decode_thumb32_table, true, - emulate, actions); -} diff --git a/arch/arm/kernel/probes-thumb.h b/arch/arm/kernel/probes-thumb.h deleted file mode 100644 index 7c6f6ebe514f..000000000000 --- a/arch/arm/kernel/probes-thumb.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * arch/arm/kernel/probes-thumb.h - * - * Copyright 2013 Linaro Ltd. - * Written by: David A. Long - * - * 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 - */ - -#ifndef _ARM_KERNEL_PROBES_THUMB_H -#define _ARM_KERNEL_PROBES_THUMB_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) - -enum probes_t32_action { - PROBES_T32_EMULATE_NONE, - PROBES_T32_SIMULATE_NOP, - PROBES_T32_LDMSTM, - PROBES_T32_LDRDSTRD, - PROBES_T32_TABLE_BRANCH, - PROBES_T32_TST, - PROBES_T32_CMP, - PROBES_T32_MOV, - PROBES_T32_ADDSUB, - PROBES_T32_LOGICAL, - PROBES_T32_ADDWSUBW_PC, - PROBES_T32_ADDWSUBW, - PROBES_T32_MOVW, - PROBES_T32_SAT, - PROBES_T32_BITFIELD, - PROBES_T32_SEV, - PROBES_T32_WFE, - PROBES_T32_MRS, - PROBES_T32_BRANCH_COND, - PROBES_T32_BRANCH, - PROBES_T32_PLDI, - PROBES_T32_LDR_LIT, - PROBES_T32_LDRSTR, - PROBES_T32_SIGN_EXTEND, - PROBES_T32_MEDIA, - PROBES_T32_REVERSE, - PROBES_T32_MUL_ADD, - PROBES_T32_MUL_ADD2, - PROBES_T32_MUL_ADD_LONG, - NUM_PROBES_T32_ACTIONS -}; - -enum probes_t16_action { - PROBES_T16_ADD_SP, - PROBES_T16_CBZ, - PROBES_T16_SIGN_EXTEND, - PROBES_T16_PUSH, - PROBES_T16_POP, - PROBES_T16_SEV, - PROBES_T16_WFE, - PROBES_T16_IT, - PROBES_T16_CMP, - PROBES_T16_ADDSUB, - PROBES_T16_LOGICAL, - PROBES_T16_BLX, - PROBES_T16_HIREGOPS, - PROBES_T16_LDR_LIT, - PROBES_T16_LDRHSTRH, - PROBES_T16_LDRSTR, - PROBES_T16_ADR, - PROBES_T16_LDMSTM, - PROBES_T16_BRANCH_COND, - PROBES_T16_BRANCH, - NUM_PROBES_T16_ACTIONS -}; - -extern const union decode_item probes_decode_thumb32_table[]; -extern const union decode_item probes_decode_thumb16_table[]; - -enum probes_insn __kprobes -thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, - bool emulate, const union decode_action *actions); -enum probes_insn __kprobes -thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, - bool emulate, const union decode_action *actions); - -#endif diff --git a/arch/arm/kernel/probes.c b/arch/arm/kernel/probes.c deleted file mode 100644 index a8ab540d7e73..000000000000 --- a/arch/arm/kernel/probes.c +++ /dev/null @@ -1,456 +0,0 @@ -/* - * arch/arm/kernel/probes.c - * - * Copyright (C) 2011 Jon Medhurst . - * - * 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 -#include -#include -#include -#include - -#include "probes.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_probes_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; -} - -probes_check_cc * const probes_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 probes_simulate_nop(probes_opcode_t opcode, - struct arch_probes_insn *asi, - struct pt_regs *regs) -{ -} - -void __kprobes probes_emulate_none(probes_opcode_t opcode, - struct arch_probes_insn *asi, - struct pt_regs *regs) -{ - asi->insn_fn(); -} - -/* - * 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 probes_opcode_t __kprobes -prepare_emulated_insn(probes_opcode_t insn, struct arch_probes_insn *asi, - bool thumb) -{ -#ifdef CONFIG_THUMB2_KERNEL - if (thumb) { - u16 *thumb_insn = (u16 *)asi->insn; - /* Thumb bx lr */ - thumb_insn[1] = __opcode_to_mem_thumb16(0x4770); - thumb_insn[2] = __opcode_to_mem_thumb16(0x4770); - return insn; - } - asi->insn[1] = __opcode_to_mem_arm(0xe12fff1e); /* ARM bx lr */ -#else - asi->insn[1] = __opcode_to_mem_arm(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(probes_opcode_t insn, struct arch_probes_insn *asi, - bool thumb) -{ -#ifdef CONFIG_THUMB2_KERNEL - if (thumb) { - u16 *ip = (u16 *)asi->insn; - if (is_wide_instruction(insn)) - *ip++ = __opcode_to_mem_thumb16(insn >> 16); - *ip++ = __opcode_to_mem_thumb16(insn); - return; - } -#endif - asi->insn[0] = __opcode_to_mem_arm(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(probes_opcode_t *pinsn, u32 regs, bool modify) -{ - probes_opcode_t insn = *pinsn; - probes_opcode_t mask = 0xf; /* Start at least significant nibble */ - - for (; regs != 0; regs >>= 4, mask <<= 4) { - - probes_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; - } - - if (modify) - *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) -}; - -/* - * probes_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 -probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, - const union decode_item *table, bool thumb, - bool emulate, const union decode_action *actions) -{ - const struct decode_header *h = (struct decode_header *)table; - const struct decode_header *next; - bool matched = false; - - if (emulate) - 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, emulate)) - 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 actions[d->decoder.action].decoder(insn, asi, h); - } - - case DECODE_TYPE_SIMULATE: { - struct decode_simulate *d = (struct decode_simulate *)h; - asi->insn_handler = actions[d->handler.action].handler; - return INSN_GOOD_NO_SLOT; - } - - case DECODE_TYPE_EMULATE: { - struct decode_emulate *d = (struct decode_emulate *)h; - - if (!emulate) - return actions[d->handler.action].decoder(insn, - asi, h); - - asi->insn_handler = actions[d->handler.action].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/arch/arm/kernel/probes.h b/arch/arm/kernel/probes.h deleted file mode 100644 index dba9f2466a93..000000000000 --- a/arch/arm/kernel/probes.h +++ /dev/null @@ -1,407 +0,0 @@ -/* - * arch/arm/kernel/probes.h - * - * Copyright (C) 2011 Jon Medhurst . - * - * 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_PROBES_H -#define _ARM_KERNEL_PROBES_H - -#include -#include -#include - -void __init arm_probes_decode_init(void); - -extern probes_check_cc * const probes_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; -} - - -/* - * 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 probes_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}, - * {.action = _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 value of 'decoder' is used as an index into the array of - * action functions, and the retrieved decoder function is invoked - * to complete decoding of the instruction. - * - * DECODE_SIMULATE(mask, value, handler) - * The probes instruction handler is set to the value found by - * indexing into the action array using the value of '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) - * The probes instruction handler is set to the value found by - * indexing into the action array using the value of '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 ,,, " - * - * DECODE_EMULATEX (0x0e000090, 0x00000010, PROBES_DATA_PROCESSING_REG, - * 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 (a pointer to which is retrieved from - * the indicated slot in the action array), 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; - int action; -}; - -struct decode_header; -typedef enum probes_insn (probes_custom_decode_t)(probes_opcode_t, - struct arch_probes_insn *, - const struct decode_header *); - -union decode_action { - probes_insn_handler_t *handler; - probes_custom_decode_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), \ - {.action = (_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), \ - {.action = (_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), \ - {.action = (_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) - -enum probes_insn { - INSN_REJECTED, - INSN_GOOD, - INSN_GOOD_NO_SLOT -}; - -struct decode_reject { - struct decode_header header; -}; - -#define DECODE_REJECT(_mask, _value) \ - DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0) - -probes_insn_handler_t probes_simulate_nop; -probes_insn_handler_t probes_emulate_none; - -int __kprobes -probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, - const union decode_item *table, bool thumb, bool emulate, - const union decode_action *actions); - -#endif diff --git a/arch/arm/kernel/uprobes-arm.c b/arch/arm/kernel/uprobes-arm.c deleted file mode 100644 index d3b655ff17da..000000000000 --- a/arch/arm/kernel/uprobes-arm.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (C) 2012 Rabin Vincent - * - * 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 -#include -#include -#include -#include -#include - -#include "probes.h" -#include "probes-arm.h" -#include "uprobes.h" - -static int uprobes_substitute_pc(unsigned long *pinsn, u32 oregs) -{ - probes_opcode_t insn = __mem_to_opcode_arm(*pinsn); - probes_opcode_t temp; - probes_opcode_t mask; - int freereg; - u32 free = 0xffff; - u32 regs; - - for (regs = oregs; regs; regs >>= 4, insn >>= 4) { - if ((regs & 0xf) == REG_TYPE_NONE) - continue; - - free &= ~(1 << (insn & 0xf)); - } - - /* No PC, no problem */ - if (free & (1 << 15)) - return 15; - - if (!free) - return -1; - - /* - * fls instead of ffs ensures that for "ldrd r0, r1, [pc]" we would - * pick LR instead of R1. - */ - freereg = free = fls(free) - 1; - - temp = __mem_to_opcode_arm(*pinsn); - insn = temp; - regs = oregs; - mask = 0xf; - - for (; regs; regs >>= 4, mask <<= 4, free <<= 4, temp >>= 4) { - if ((regs & 0xf) == REG_TYPE_NONE) - continue; - - if ((temp & 0xf) != 15) - continue; - - insn &= ~mask; - insn |= free & mask; - } - - *pinsn = __opcode_to_mem_arm(insn); - return freereg; -} - -static void uprobe_set_pc(struct arch_uprobe *auprobe, - struct arch_uprobe_task *autask, - struct pt_regs *regs) -{ - u32 pcreg = auprobe->pcreg; - - autask->backup = regs->uregs[pcreg]; - regs->uregs[pcreg] = regs->ARM_pc + 8; -} - -static void uprobe_unset_pc(struct arch_uprobe *auprobe, - struct arch_uprobe_task *autask, - struct pt_regs *regs) -{ - /* PC will be taken care of by common code */ - regs->uregs[auprobe->pcreg] = autask->backup; -} - -static void uprobe_aluwrite_pc(struct arch_uprobe *auprobe, - struct arch_uprobe_task *autask, - struct pt_regs *regs) -{ - u32 pcreg = auprobe->pcreg; - - alu_write_pc(regs->uregs[pcreg], regs); - regs->uregs[pcreg] = autask->backup; -} - -static void uprobe_write_pc(struct arch_uprobe *auprobe, - struct arch_uprobe_task *autask, - struct pt_regs *regs) -{ - u32 pcreg = auprobe->pcreg; - - load_write_pc(regs->uregs[pcreg], regs); - regs->uregs[pcreg] = autask->backup; -} - -enum probes_insn -decode_pc_ro(probes_opcode_t insn, struct arch_probes_insn *asi, - const struct decode_header *d) -{ - struct arch_uprobe *auprobe = container_of(asi, struct arch_uprobe, - asi); - struct decode_emulate *decode = (struct decode_emulate *) d; - u32 regs = decode->header.type_regs.bits >> DECODE_TYPE_BITS; - int reg; - - reg = uprobes_substitute_pc(&auprobe->ixol[0], regs); - if (reg == 15) - return INSN_GOOD; - - if (reg == -1) - return INSN_REJECTED; - - auprobe->pcreg = reg; - auprobe->prehandler = uprobe_set_pc; - auprobe->posthandler = uprobe_unset_pc; - - return INSN_GOOD; -} - -enum probes_insn -decode_wb_pc(probes_opcode_t insn, struct arch_probes_insn *asi, - const struct decode_header *d, bool alu) -{ - struct arch_uprobe *auprobe = container_of(asi, struct arch_uprobe, - asi); - enum probes_insn ret = decode_pc_ro(insn, asi, d); - - if (((insn >> 12) & 0xf) == 15) - auprobe->posthandler = alu ? uprobe_aluwrite_pc - : uprobe_write_pc; - - return ret; -} - -enum probes_insn -decode_rd12rn16rm0rs8_rwflags(probes_opcode_t insn, - struct arch_probes_insn *asi, - const struct decode_header *d) -{ - return decode_wb_pc(insn, asi, d, true); -} - -enum probes_insn -decode_ldr(probes_opcode_t insn, struct arch_probes_insn *asi, - const struct decode_header *d) -{ - return decode_wb_pc(insn, asi, d, false); -} - -enum probes_insn -uprobe_decode_ldmstm(probes_opcode_t insn, - struct arch_probes_insn *asi, - const struct decode_header *d) -{ - struct arch_uprobe *auprobe = container_of(asi, struct arch_uprobe, - asi); - unsigned reglist = insn & 0xffff; - int rn = (insn >> 16) & 0xf; - int lbit = insn & (1 << 20); - unsigned used = reglist | (1 << rn); - - if (rn == 15) - return INSN_REJECTED; - - if (!(used & (1 << 15))) - return INSN_GOOD; - - if (used & (1 << 14)) - return INSN_REJECTED; - - /* Use LR instead of PC */ - insn ^= 0xc000; - - auprobe->pcreg = 14; - auprobe->ixol[0] = __opcode_to_mem_arm(insn); - - auprobe->prehandler = uprobe_set_pc; - if (lbit) - auprobe->posthandler = uprobe_write_pc; - else - auprobe->posthandler = uprobe_unset_pc; - - return INSN_GOOD; -} - -const union decode_action uprobes_probes_actions[] = { - [PROBES_EMULATE_NONE] = {.handler = probes_simulate_nop}, - [PROBES_SIMULATE_NOP] = {.handler = probes_simulate_nop}, - [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop}, - [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop}, - [PROBES_BRANCH_IMM] = {.handler = simulate_blx1}, - [PROBES_MRS] = {.handler = simulate_mrs}, - [PROBES_BRANCH_REG] = {.handler = simulate_blx2bx}, - [PROBES_CLZ] = {.handler = probes_simulate_nop}, - [PROBES_SATURATING_ARITHMETIC] = {.handler = probes_simulate_nop}, - [PROBES_MUL1] = {.handler = probes_simulate_nop}, - [PROBES_MUL2] = {.handler = probes_simulate_nop}, - [PROBES_SWP] = {.handler = probes_simulate_nop}, - [PROBES_LDRSTRD] = {.decoder = decode_pc_ro}, - [PROBES_LOAD_EXTRA] = {.decoder = decode_pc_ro}, - [PROBES_LOAD] = {.decoder = decode_ldr}, - [PROBES_STORE_EXTRA] = {.decoder = decode_pc_ro}, - [PROBES_STORE] = {.decoder = decode_pc_ro}, - [PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp}, - [PROBES_DATA_PROCESSING_REG] = { - .decoder = decode_rd12rn16rm0rs8_rwflags}, - [PROBES_DATA_PROCESSING_IMM] = { - .decoder = decode_rd12rn16rm0rs8_rwflags}, - [PROBES_MOV_HALFWORD] = {.handler = probes_simulate_nop}, - [PROBES_SEV] = {.handler = probes_simulate_nop}, - [PROBES_WFE] = {.handler = probes_simulate_nop}, - [PROBES_SATURATE] = {.handler = probes_simulate_nop}, - [PROBES_REV] = {.handler = probes_simulate_nop}, - [PROBES_MMI] = {.handler = probes_simulate_nop}, - [PROBES_PACK] = {.handler = probes_simulate_nop}, - [PROBES_EXTEND] = {.handler = probes_simulate_nop}, - [PROBES_EXTEND_ADD] = {.handler = probes_simulate_nop}, - [PROBES_MUL_ADD_LONG] = {.handler = probes_simulate_nop}, - [PROBES_MUL_ADD] = {.handler = probes_simulate_nop}, - [PROBES_BITFIELD] = {.handler = probes_simulate_nop}, - [PROBES_BRANCH] = {.handler = simulate_bbl}, - [PROBES_LDMSTM] = {.decoder = uprobe_decode_ldmstm} -}; diff --git a/arch/arm/kernel/uprobes.c b/arch/arm/kernel/uprobes.c deleted file mode 100644 index 56adf9c1fde0..000000000000 --- a/arch/arm/kernel/uprobes.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (C) 2012 Rabin Vincent - * - * 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 -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "probes.h" -#include "probes-arm.h" -#include "uprobes.h" - -#define UPROBE_TRAP_NR UINT_MAX - -bool is_swbp_insn(uprobe_opcode_t *insn) -{ - return (__mem_to_opcode_arm(*insn) & 0x0fffffff) == - (UPROBE_SWBP_ARM_INSN & 0x0fffffff); -} - -int set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, - unsigned long vaddr) -{ - return uprobe_write_opcode(mm, vaddr, - __opcode_to_mem_arm(auprobe->bpinsn)); -} - -bool arch_uprobe_ignore(struct arch_uprobe *auprobe, struct pt_regs *regs) -{ - if (!auprobe->asi.insn_check_cc(regs->ARM_cpsr)) { - regs->ARM_pc += 4; - return true; - } - - return false; -} - -bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) -{ - probes_opcode_t opcode; - - if (!auprobe->simulate) - return false; - - opcode = __mem_to_opcode_arm(*(unsigned int *) auprobe->insn); - - auprobe->asi.insn_singlestep(opcode, &auprobe->asi, regs); - - return true; -} - -unsigned long -arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, - struct pt_regs *regs) -{ - unsigned long orig_ret_vaddr; - - orig_ret_vaddr = regs->ARM_lr; - /* Replace the return addr with trampoline addr */ - regs->ARM_lr = trampoline_vaddr; - return orig_ret_vaddr; -} - -int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, - unsigned long addr) -{ - unsigned int insn; - unsigned int bpinsn; - enum probes_insn ret; - - /* Thumb not yet support */ - if (addr & 0x3) - return -EINVAL; - - insn = __mem_to_opcode_arm(*(unsigned int *)auprobe->insn); - auprobe->ixol[0] = __opcode_to_mem_arm(insn); - auprobe->ixol[1] = __opcode_to_mem_arm(UPROBE_SS_ARM_INSN); - - ret = arm_probes_decode_insn(insn, &auprobe->asi, false, - uprobes_probes_actions); - switch (ret) { - case INSN_REJECTED: - return -EINVAL; - - case INSN_GOOD_NO_SLOT: - auprobe->simulate = true; - break; - - case INSN_GOOD: - default: - break; - } - - bpinsn = UPROBE_SWBP_ARM_INSN & 0x0fffffff; - if (insn >= 0xe0000000) - bpinsn |= 0xe0000000; /* Unconditional instruction */ - else - bpinsn |= insn & 0xf0000000; /* Copy condition from insn */ - - auprobe->bpinsn = bpinsn; - - return 0; -} - -void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr, - void *src, unsigned long len) -{ - void *xol_page_kaddr = kmap_atomic(page); - void *dst = xol_page_kaddr + (vaddr & ~PAGE_MASK); - - preempt_disable(); - - /* Initialize the slot */ - memcpy(dst, src, len); - - /* flush caches (dcache/icache) */ - flush_uprobe_xol_access(page, vaddr, dst, len); - - preempt_enable(); - - kunmap_atomic(xol_page_kaddr); -} - - -int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) -{ - struct uprobe_task *utask = current->utask; - - if (auprobe->prehandler) - auprobe->prehandler(auprobe, &utask->autask, regs); - - utask->autask.saved_trap_no = current->thread.trap_no; - current->thread.trap_no = UPROBE_TRAP_NR; - regs->ARM_pc = utask->xol_vaddr; - - return 0; -} - -int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) -{ - struct uprobe_task *utask = current->utask; - - WARN_ON_ONCE(current->thread.trap_no != UPROBE_TRAP_NR); - - current->thread.trap_no = utask->autask.saved_trap_no; - regs->ARM_pc = utask->vaddr + 4; - - if (auprobe->posthandler) - auprobe->posthandler(auprobe, &utask->autask, regs); - - return 0; -} - -bool arch_uprobe_xol_was_trapped(struct task_struct *t) -{ - if (t->thread.trap_no != UPROBE_TRAP_NR) - return true; - - return false; -} - -void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) -{ - struct uprobe_task *utask = current->utask; - - current->thread.trap_no = utask->autask.saved_trap_no; - instruction_pointer_set(regs, utask->vaddr); -} - -int arch_uprobe_exception_notify(struct notifier_block *self, - unsigned long val, void *data) -{ - return NOTIFY_DONE; -} - -static int uprobe_trap_handler(struct pt_regs *regs, unsigned int instr) -{ - unsigned long flags; - - local_irq_save(flags); - instr &= 0x0fffffff; - if (instr == (UPROBE_SWBP_ARM_INSN & 0x0fffffff)) - uprobe_pre_sstep_notifier(regs); - else if (instr == (UPROBE_SS_ARM_INSN & 0x0fffffff)) - uprobe_post_sstep_notifier(regs); - local_irq_restore(flags); - - return 0; -} - -unsigned long uprobe_get_swbp_addr(struct pt_regs *regs) -{ - return instruction_pointer(regs); -} - -static struct undef_hook uprobes_arm_break_hook = { - .instr_mask = 0x0fffffff, - .instr_val = (UPROBE_SWBP_ARM_INSN & 0x0fffffff), - .cpsr_mask = MODE_MASK, - .cpsr_val = USR_MODE, - .fn = uprobe_trap_handler, -}; - -static struct undef_hook uprobes_arm_ss_hook = { - .instr_mask = 0x0fffffff, - .instr_val = (UPROBE_SS_ARM_INSN & 0x0fffffff), - .cpsr_mask = MODE_MASK, - .cpsr_val = USR_MODE, - .fn = uprobe_trap_handler, -}; - -static int arch_uprobes_init(void) -{ - register_undef_hook(&uprobes_arm_break_hook); - register_undef_hook(&uprobes_arm_ss_hook); - - return 0; -} -device_initcall(arch_uprobes_init); diff --git a/arch/arm/kernel/uprobes.h b/arch/arm/kernel/uprobes.h deleted file mode 100644 index 1d0c12dfbd03..000000000000 --- a/arch/arm/kernel/uprobes.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2012 Rabin Vincent - * - * 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. - */ - -#ifndef __ARM_KERNEL_UPROBES_H -#define __ARM_KERNEL_UPROBES_H - -enum probes_insn uprobe_decode_ldmstm(probes_opcode_t insn, - struct arch_probes_insn *asi, - const struct decode_header *d); - -enum probes_insn decode_ldr(probes_opcode_t insn, - struct arch_probes_insn *asi, - const struct decode_header *d); - -enum probes_insn -decode_rd12rn16rm0rs8_rwflags(probes_opcode_t insn, - struct arch_probes_insn *asi, - const struct decode_header *d); - -enum probes_insn -decode_wb_pc(probes_opcode_t insn, struct arch_probes_insn *asi, - const struct decode_header *d, bool alu); - -enum probes_insn -decode_pc_ro(probes_opcode_t insn, struct arch_probes_insn *asi, - const struct decode_header *d); - -extern const union decode_action uprobes_probes_actions[]; - -#endif diff --git a/arch/arm/probes/Makefile b/arch/arm/probes/Makefile new file mode 100644 index 000000000000..aa1f8590dcdd --- /dev/null +++ b/arch/arm/probes/Makefile @@ -0,0 +1,7 @@ +obj-$(CONFIG_UPROBES) += decode.o decode-arm.o uprobes/ +obj-$(CONFIG_KPROBES) += decode.o kprobes/ +ifdef CONFIG_THUMB2_KERNEL +obj-$(CONFIG_KPROBES) += decode-thumb.o +else +obj-$(CONFIG_KPROBES) += decode-arm.o +endif diff --git a/arch/arm/probes/decode-arm.c b/arch/arm/probes/decode-arm.c new file mode 100644 index 000000000000..e39cc75952f2 --- /dev/null +++ b/arch/arm/probes/decode-arm.c @@ -0,0 +1,735 @@ +/* + * + * arch/arm/probes/decode-arm.c + * + * Some code moved here from arch/arm/kernel/kprobes-arm.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. + */ + +#include +#include +#include +#include + +#include "decode.h" +#include "decode-arm.h" + +#define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit))))) + +#define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25) + +/* + * 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. + */ + +void __kprobes simulate_bbl(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + long iaddr = (long) regs->ARM_pc - 4; + int disp = branch_displacement(insn); + + if (insn & (1 << 24)) + regs->ARM_lr = iaddr + 4; + + regs->ARM_pc = iaddr + 8 + disp; +} + +void __kprobes simulate_blx1(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + long iaddr = (long) regs->ARM_pc - 4; + 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; +} + +void __kprobes simulate_blx2bx(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + int rm = insn & 0xf; + long rmv = regs->uregs[rm]; + + if (insn & (1 << 5)) + regs->ARM_lr = (long) regs->ARM_pc; + + regs->ARM_pc = rmv & ~0x1; + regs->ARM_cpsr &= ~PSR_T_BIT; + if (rmv & 0x1) + regs->ARM_cpsr |= PSR_T_BIT; +} + +void __kprobes simulate_mrs(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + int rd = (insn >> 12) & 0xf; + unsigned long mask = 0xf8ff03df; /* Mask out execution state */ + regs->uregs[rd] = regs->ARM_cpsr & mask; +} + +void __kprobes simulate_mov_ipsp(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + regs->uregs[12] = regs->uregs[13]; +} + +/* + * 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, PROBES_PRELOAD_IMM), + + /* 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, PROBES_PRELOAD_REG), + + /* BLX (immediate) 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx */ + DECODE_SIMULATE (0xfe000000, 0xfa000000, PROBES_BRANCH_IMM), + + /* 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, PROBES_MRS, + REGS(0, NOPC, 0, 0, 0)), + + /* BX cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */ + DECODE_SIMULATE (0x0ff000f0, 0x01200010, PROBES_BRANCH_REG), + + /* BLX (register) cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */ + DECODE_SIMULATEX(0x0ff000f0, 0x01200030, PROBES_BRANCH_REG, + REGS(0, 0, 0, 0, NOPC)), + + /* CLZ cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */ + DECODE_EMULATEX (0x0ff000f0, 0x01600010, PROBES_CLZ, + 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, PROBES_SATURATING_ARITHMETIC, + 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, PROBES_MUL1, + 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, PROBES_MUL2, + 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, PROBES_MUL2, + 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, PROBES_MUL2, + 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, PROBES_MUL2, + 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, PROBES_MUL1, + 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, PROBES_SWP, + 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, PROBES_LDRSTRD, + 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, PROBES_LDRSTRD, + REGS(NOPCWB, NOPCX, 0, 0, 0)), + + /* STRH (register) cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx */ + DECODE_EMULATEX (0x0e5000f0, 0x000000b0, PROBES_STORE_EXTRA, + 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, PROBES_LOAD_EXTRA, + REGS(NOPCWB, NOPC, 0, 0, NOPC)), + + /* STRH (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1011 xxxx */ + DECODE_EMULATEX (0x0e5000f0, 0x004000b0, PROBES_STORE_EXTRA, + 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, PROBES_LOAD_EXTRA, + REGS(NOPCWB, NOPC, 0, 0, 0)), + + DECODE_END +}; + +static const union decode_item arm_cccc_000x_table[] = { + /* Data-processing (register) */ + + /* 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, PROBES_MOV_IP_SP), + + /* 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, PROBES_DATA_PROCESSING_REG, + 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, PROBES_DATA_PROCESSING_REG, + 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, PROBES_DATA_PROCESSING_REG, + 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, PROBES_DATA_PROCESSING_REG, + REGS(NOPC, 0, NOPC, 0, NOPC)), + + /* 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, PROBES_DATA_PROCESSING_REG, + REGS(0, NOPC, NOPC, 0, NOPC)), + + /* 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, PROBES_DATA_PROCESSING_REG, + REGS(NOPC, NOPC, NOPC, 0, NOPC)), + + 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, PROBES_DATA_PROCESSING_IMM, + 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, PROBES_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, PROBES_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), + + /* 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, PROBES_DATA_PROCESSING_IMM, + 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, PROBES_DATA_PROCESSING_IMM, + 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, PROBES_DATA_PROCESSING_IMM, + 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, PROBES_SATURATE, + 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, PROBES_SATURATE, + 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, PROBES_REV, + 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, PROBES_MMI, + 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, PROBES_PACK, + 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, PROBES_EXTEND, + 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, PROBES_EXTEND_ADD, + 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, PROBES_MUL_ADD_LONG, + 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, PROBES_MUL_ADD, + 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, PROBES_MUL_ADD, + REGS(NOPC, NOPCX, NOPC, 0, NOPC)), + + /* SMMLS cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx */ + DECODE_EMULATEX (0x0ff000d0, 0x075000d0, PROBES_MUL_ADD, + 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, PROBES_BITFIELD, + REGS(0, NOPC, 0, 0, NOPC)), + + /* BFC cccc 0111 110x xxxx xxxx xxxx x001 1111 */ + DECODE_EMULATEX (0x0fe0007f, 0x07c0001f, PROBES_BITFIELD, + REGS(0, NOPC, 0, 0, 0)), + + /* BFI cccc 0111 110x xxxx xxxx xxxx x001 xxxx */ + DECODE_EMULATEX (0x0fe00070, 0x07c00010, PROBES_BITFIELD, + 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, PROBES_STORE, + 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, PROBES_LOAD, + 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, PROBES_STORE, + 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, PROBES_LOAD, + 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, PROBES_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 probes_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, PROBES_BRANCH), + + /* + * 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(probes_decode_arm_table); +#endif + +static void __kprobes arm_singlestep(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + regs->ARM_pc += 4; + asi->insn_handler(insn, asi, 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 probes_insn __kprobes +arm_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, + bool emulate, const union decode_action *actions) +{ + asi->insn_singlestep = arm_singlestep; + asi->insn_check_cc = probes_condition_checks[insn>>28]; + return probes_decode_insn(insn, asi, probes_decode_arm_table, false, + emulate, actions); +} diff --git a/arch/arm/probes/decode-arm.h b/arch/arm/probes/decode-arm.h new file mode 100644 index 000000000000..9c56b40d6a57 --- /dev/null +++ b/arch/arm/probes/decode-arm.h @@ -0,0 +1,75 @@ +/* + * arch/arm/probes/decode-arm.h + * + * Copyright 2013 Linaro Ltd. + * Written by: David A. Long + * + * 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 + */ + +#ifndef _ARM_KERNEL_PROBES_ARM_H +#define _ARM_KERNEL_PROBES_ARM_H + +#include "decode.h" + +enum probes_arm_action { + PROBES_EMULATE_NONE, + PROBES_SIMULATE_NOP, + PROBES_PRELOAD_IMM, + PROBES_PRELOAD_REG, + PROBES_BRANCH_IMM, + PROBES_BRANCH_REG, + PROBES_MRS, + PROBES_CLZ, + PROBES_SATURATING_ARITHMETIC, + PROBES_MUL1, + PROBES_MUL2, + PROBES_SWP, + PROBES_LDRSTRD, + PROBES_LOAD, + PROBES_STORE, + PROBES_LOAD_EXTRA, + PROBES_STORE_EXTRA, + PROBES_MOV_IP_SP, + PROBES_DATA_PROCESSING_REG, + PROBES_DATA_PROCESSING_IMM, + PROBES_MOV_HALFWORD, + PROBES_SEV, + PROBES_WFE, + PROBES_SATURATE, + PROBES_REV, + PROBES_MMI, + PROBES_PACK, + PROBES_EXTEND, + PROBES_EXTEND_ADD, + PROBES_MUL_ADD_LONG, + PROBES_MUL_ADD, + PROBES_BITFIELD, + PROBES_BRANCH, + PROBES_LDMSTM, + NUM_PROBES_ARM_ACTIONS +}; + +void __kprobes simulate_bbl(probes_opcode_t opcode, + struct arch_probes_insn *asi, struct pt_regs *regs); +void __kprobes simulate_blx1(probes_opcode_t opcode, + struct arch_probes_insn *asi, struct pt_regs *regs); +void __kprobes simulate_blx2bx(probes_opcode_t opcode, + struct arch_probes_insn *asi, struct pt_regs *regs); +void __kprobes simulate_mrs(probes_opcode_t opcode, + struct arch_probes_insn *asi, struct pt_regs *regs); +void __kprobes simulate_mov_ipsp(probes_opcode_t opcode, + struct arch_probes_insn *asi, struct pt_regs *regs); + +extern const union decode_item probes_decode_arm_table[]; + +enum probes_insn arm_probes_decode_insn(probes_opcode_t, + struct arch_probes_insn *, bool emulate, + const union decode_action *actions); + +#endif diff --git a/arch/arm/probes/decode-thumb.c b/arch/arm/probes/decode-thumb.c new file mode 100644 index 000000000000..2f0453a895dc --- /dev/null +++ b/arch/arm/probes/decode-thumb.c @@ -0,0 +1,882 @@ +/* + * arch/arm/probes/decode-thumb.c + * + * Copyright (C) 2011 Jon Medhurst . + * + * 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 +#include +#include + +#include "decode.h" +#include "decode-thumb.h" + + +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, PROBES_T32_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, PROBES_T32_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, PROBES_T32_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, PROBES_T32_TST, + 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, PROBES_T32_TST, + 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, PROBES_T32_MOV, + 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, PROBES_T32_ADDSUB, + 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, PROBES_T32_ADDSUB, + 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, PROBES_T32_LOGICAL, + 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, PROBES_T32_TST, + 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, PROBES_T32_CMP, + 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, PROBES_T32_MOV, + 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, PROBES_T32_ADDSUB, + 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, PROBES_T32_LOGICAL, + 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, PROBES_T32_ADDWSUBW_PC, + 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, PROBES_T32_ADDWSUBW, + 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, PROBES_T32_ADDWSUBW, + 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, PROBES_T32_MOVW, + 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, PROBES_T32_SAT, + 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, PROBES_T32_BITFIELD, + REGS(NOSPPC, 0, NOSPPC, 0, 0)), + + /* BFC 1111 0x11 0110 1111 0xxx xxxx xxxx xxxx */ + DECODE_EMULATEX (0xfbff8000, 0xf36f0000, PROBES_T32_BITFIELD, + REGS(0, 0, NOSPPC, 0, 0)), + + /* BFI 1111 0x11 0110 xxxx 0xxx xxxx xxxx xxxx */ + DECODE_EMULATEX (0xfbf08000, 0xf3600000, PROBES_T32_BITFIELD, + 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, PROBES_T32_SEV), + /* 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, PROBES_T32_WFE), + + /* MRS Rd, CPSR 1111 0011 1110 xxxx 10x0 xxxx xxxx xxxx */ + DECODE_SIMULATEX(0xfff0d000, 0xf3e08000, PROBES_T32_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,# 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, PROBES_T32_BRANCH_COND), + + /* 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, PROBES_T32_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, PROBES_T32_PLDI), + + /* 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, PROBES_T32_PLDI, + 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, PROBES_T32_PLDI, + 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, PROBES_T32_LDR_LIT, + 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, PROBES_T32_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, PROBES_T32_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_SIMULATEX(0xfe5f0000, 0xf81f0000, PROBES_T32_LDR_LIT, + 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, PROBES_T32_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, PROBES_T32_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, PROBES_T32_SIGN_EXTEND, + 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, PROBES_T32_MEDIA, + 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, PROBES_T32_REVERSE, + 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, PROBES_T32_MUL_ADD, + 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, PROBES_T32_MUL_ADD2, + 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, PROBES_T32_MUL_ADD_LONG, + 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 probes_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(probes_decode_thumb32_table); +#endif + +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, PROBES_T16_ADD_SP), + + /* CBZ 1011 00x1 xxxx xxxx */ + /* CBNZ 1011 10x1 xxxx xxxx */ + DECODE_SIMULATE (0xf500, 0xb100, PROBES_T16_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, PROBES_T16_SIGN_EXTEND), + + /* PUSH 1011 010x xxxx xxxx */ + DECODE_CUSTOM (0xfe00, 0xb400, PROBES_T16_PUSH), + /* POP 1011 110x xxxx xxxx */ + DECODE_CUSTOM (0xfe00, 0xbc00, PROBES_T16_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, PROBES_T16_SEV), + /* NOP 1011 1111 0000 0000 */ + /* WFE 1011 1111 0010 0000 */ + /* WFI 1011 1111 0011 0000 */ + DECODE_SIMULATE (0xffcf, 0xbf00, PROBES_T16_WFE), + /* Unassigned hints 1011 1111 xxxx 0000 */ + DECODE_REJECT (0xff0f, 0xbf00), + /* IT 1011 1111 xxxx xxxx */ + DECODE_CUSTOM (0xff00, 0xbf00, PROBES_T16_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 probes_decode_thumb16_table[] = { + + /* + * Shift (immediate), add, subtract, move, and compare + * 00xx xxxx xxxx xxxx + */ + + /* CMP (immediate) 0010 1xxx xxxx xxxx */ + DECODE_EMULATE (0xf800, 0x2800, PROBES_T16_CMP), + + /* 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, PROBES_T16_ADDSUB), + + /* + * 16-bit Thumb data-processing instructions + * 0100 00xx xxxx xxxx + */ + + /* TST (register) 0100 0010 00xx xxxx */ + DECODE_EMULATE (0xffc0, 0x4200, PROBES_T16_CMP), + /* CMP (register) 0100 0010 10xx xxxx */ + /* CMN (register) 0100 0010 11xx xxxx */ + DECODE_EMULATE (0xff80, 0x4280, PROBES_T16_CMP), + /* 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, PROBES_T16_LOGICAL), + + /* + * 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, PROBES_T16_BLX), + + /* 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, PROBES_T16_HIREGOPS), + + /* + * Load from Literal Pool + * LDR (literal) 0100 1xxx xxxx xxxx + */ + DECODE_SIMULATE (0xf800, 0x4800, PROBES_T16_LDR_LIT), + + /* + * 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, PROBES_T16_LDRHSTRH), + /* STRH (immediate, Thumb) 1000 0xxx xxxx xxxx */ + /* LDRH (immediate, Thumb) 1000 1xxx xxxx xxxx */ + DECODE_EMULATE (0xf000, 0x8000, PROBES_T16_LDRHSTRH), + /* STR (immediate, Thumb) 1001 0xxx xxxx xxxx */ + /* LDR (immediate, Thumb) 1001 1xxx xxxx xxxx */ + DECODE_SIMULATE (0xf000, 0x9000, PROBES_T16_LDRSTR), + + /* + * Generate PC-/SP-relative address + * ADR (literal) 1010 0xxx xxxx xxxx + * ADD (SP plus immediate) 1010 1xxx xxxx xxxx + */ + DECODE_SIMULATE (0xf000, 0xa000, PROBES_T16_ADR), + + /* + * 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, PROBES_T16_LDMSTM), + + /* + * 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, PROBES_T16_BRANCH_COND), + + /* + * Unconditional branch + * B 1110 0xxx xxxx xxxx + */ + DECODE_SIMULATE (0xf800, 0xe000, PROBES_T16_BRANCH), + + DECODE_END +}; +#ifdef CONFIG_ARM_KPROBES_TEST_MODULE +EXPORT_SYMBOL_GPL(probes_decode_thumb16_table); +#endif + +static unsigned long __kprobes thumb_check_cc(unsigned long cpsr) +{ + if (unlikely(in_it_block(cpsr))) + return probes_condition_checks[current_cond(cpsr)](cpsr); + return true; +} + +static void __kprobes thumb16_singlestep(probes_opcode_t opcode, + struct arch_probes_insn *asi, + struct pt_regs *regs) +{ + regs->ARM_pc += 2; + asi->insn_handler(opcode, asi, regs); + regs->ARM_cpsr = it_advance(regs->ARM_cpsr); +} + +static void __kprobes thumb32_singlestep(probes_opcode_t opcode, + struct arch_probes_insn *asi, + struct pt_regs *regs) +{ + regs->ARM_pc += 4; + asi->insn_handler(opcode, asi, regs); + regs->ARM_cpsr = it_advance(regs->ARM_cpsr); +} + +enum probes_insn __kprobes +thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, + bool emulate, const union decode_action *actions) +{ + asi->insn_singlestep = thumb16_singlestep; + asi->insn_check_cc = thumb_check_cc; + return probes_decode_insn(insn, asi, probes_decode_thumb16_table, true, + emulate, actions); +} + +enum probes_insn __kprobes +thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, + bool emulate, const union decode_action *actions) +{ + asi->insn_singlestep = thumb32_singlestep; + asi->insn_check_cc = thumb_check_cc; + return probes_decode_insn(insn, asi, probes_decode_thumb32_table, true, + emulate, actions); +} diff --git a/arch/arm/probes/decode-thumb.h b/arch/arm/probes/decode-thumb.h new file mode 100644 index 000000000000..039013c7131d --- /dev/null +++ b/arch/arm/probes/decode-thumb.h @@ -0,0 +1,99 @@ +/* + * arch/arm/probes/decode-thumb.h + * + * Copyright 2013 Linaro Ltd. + * Written by: David A. Long + * + * 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 + */ + +#ifndef _ARM_KERNEL_PROBES_THUMB_H +#define _ARM_KERNEL_PROBES_THUMB_H + +#include "decode.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) + +enum probes_t32_action { + PROBES_T32_EMULATE_NONE, + PROBES_T32_SIMULATE_NOP, + PROBES_T32_LDMSTM, + PROBES_T32_LDRDSTRD, + PROBES_T32_TABLE_BRANCH, + PROBES_T32_TST, + PROBES_T32_CMP, + PROBES_T32_MOV, + PROBES_T32_ADDSUB, + PROBES_T32_LOGICAL, + PROBES_T32_ADDWSUBW_PC, + PROBES_T32_ADDWSUBW, + PROBES_T32_MOVW, + PROBES_T32_SAT, + PROBES_T32_BITFIELD, + PROBES_T32_SEV, + PROBES_T32_WFE, + PROBES_T32_MRS, + PROBES_T32_BRANCH_COND, + PROBES_T32_BRANCH, + PROBES_T32_PLDI, + PROBES_T32_LDR_LIT, + PROBES_T32_LDRSTR, + PROBES_T32_SIGN_EXTEND, + PROBES_T32_MEDIA, + PROBES_T32_REVERSE, + PROBES_T32_MUL_ADD, + PROBES_T32_MUL_ADD2, + PROBES_T32_MUL_ADD_LONG, + NUM_PROBES_T32_ACTIONS +}; + +enum probes_t16_action { + PROBES_T16_ADD_SP, + PROBES_T16_CBZ, + PROBES_T16_SIGN_EXTEND, + PROBES_T16_PUSH, + PROBES_T16_POP, + PROBES_T16_SEV, + PROBES_T16_WFE, + PROBES_T16_IT, + PROBES_T16_CMP, + PROBES_T16_ADDSUB, + PROBES_T16_LOGICAL, + PROBES_T16_BLX, + PROBES_T16_HIREGOPS, + PROBES_T16_LDR_LIT, + PROBES_T16_LDRHSTRH, + PROBES_T16_LDRSTR, + PROBES_T16_ADR, + PROBES_T16_LDMSTM, + PROBES_T16_BRANCH_COND, + PROBES_T16_BRANCH, + NUM_PROBES_T16_ACTIONS +}; + +extern const union decode_item probes_decode_thumb32_table[]; +extern const union decode_item probes_decode_thumb16_table[]; + +enum probes_insn __kprobes +thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, + bool emulate, const union decode_action *actions); +enum probes_insn __kprobes +thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, + bool emulate, const union decode_action *actions); + +#endif diff --git a/arch/arm/probes/decode.c b/arch/arm/probes/decode.c new file mode 100644 index 000000000000..3b05d5742359 --- /dev/null +++ b/arch/arm/probes/decode.c @@ -0,0 +1,456 @@ +/* + * arch/arm/probes/decode.c + * + * Copyright (C) 2011 Jon Medhurst . + * + * 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 +#include +#include +#include +#include + +#include "decode.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_probes_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; +} + +probes_check_cc * const probes_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 probes_simulate_nop(probes_opcode_t opcode, + struct arch_probes_insn *asi, + struct pt_regs *regs) +{ +} + +void __kprobes probes_emulate_none(probes_opcode_t opcode, + struct arch_probes_insn *asi, + struct pt_regs *regs) +{ + asi->insn_fn(); +} + +/* + * 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 probes_opcode_t __kprobes +prepare_emulated_insn(probes_opcode_t insn, struct arch_probes_insn *asi, + bool thumb) +{ +#ifdef CONFIG_THUMB2_KERNEL + if (thumb) { + u16 *thumb_insn = (u16 *)asi->insn; + /* Thumb bx lr */ + thumb_insn[1] = __opcode_to_mem_thumb16(0x4770); + thumb_insn[2] = __opcode_to_mem_thumb16(0x4770); + return insn; + } + asi->insn[1] = __opcode_to_mem_arm(0xe12fff1e); /* ARM bx lr */ +#else + asi->insn[1] = __opcode_to_mem_arm(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(probes_opcode_t insn, struct arch_probes_insn *asi, + bool thumb) +{ +#ifdef CONFIG_THUMB2_KERNEL + if (thumb) { + u16 *ip = (u16 *)asi->insn; + if (is_wide_instruction(insn)) + *ip++ = __opcode_to_mem_thumb16(insn >> 16); + *ip++ = __opcode_to_mem_thumb16(insn); + return; + } +#endif + asi->insn[0] = __opcode_to_mem_arm(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(probes_opcode_t *pinsn, u32 regs, bool modify) +{ + probes_opcode_t insn = *pinsn; + probes_opcode_t mask = 0xf; /* Start at least significant nibble */ + + for (; regs != 0; regs >>= 4, mask <<= 4) { + + probes_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; + } + + if (modify) + *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) +}; + +/* + * probes_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 +probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, + const union decode_item *table, bool thumb, + bool emulate, const union decode_action *actions) +{ + const struct decode_header *h = (struct decode_header *)table; + const struct decode_header *next; + bool matched = false; + + if (emulate) + 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, emulate)) + 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 actions[d->decoder.action].decoder(insn, asi, h); + } + + case DECODE_TYPE_SIMULATE: { + struct decode_simulate *d = (struct decode_simulate *)h; + asi->insn_handler = actions[d->handler.action].handler; + return INSN_GOOD_NO_SLOT; + } + + case DECODE_TYPE_EMULATE: { + struct decode_emulate *d = (struct decode_emulate *)h; + + if (!emulate) + return actions[d->handler.action].decoder(insn, + asi, h); + + asi->insn_handler = actions[d->handler.action].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/arch/arm/probes/decode.h b/arch/arm/probes/decode.h new file mode 100644 index 000000000000..1d0b53169080 --- /dev/null +++ b/arch/arm/probes/decode.h @@ -0,0 +1,407 @@ +/* + * arch/arm/probes/decode.h + * + * Copyright (C) 2011 Jon Medhurst . + * + * 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_PROBES_H +#define _ARM_KERNEL_PROBES_H + +#include +#include +#include + +void __init arm_probes_decode_init(void); + +extern probes_check_cc * const probes_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; +} + + +/* + * 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 probes_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}, + * {.action = _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 value of 'decoder' is used as an index into the array of + * action functions, and the retrieved decoder function is invoked + * to complete decoding of the instruction. + * + * DECODE_SIMULATE(mask, value, handler) + * The probes instruction handler is set to the value found by + * indexing into the action array using the value of '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) + * The probes instruction handler is set to the value found by + * indexing into the action array using the value of '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 ,,, " + * + * DECODE_EMULATEX (0x0e000090, 0x00000010, PROBES_DATA_PROCESSING_REG, + * 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 (a pointer to which is retrieved from + * the indicated slot in the action array), 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; + int action; +}; + +struct decode_header; +typedef enum probes_insn (probes_custom_decode_t)(probes_opcode_t, + struct arch_probes_insn *, + const struct decode_header *); + +union decode_action { + probes_insn_handler_t *handler; + probes_custom_decode_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), \ + {.action = (_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), \ + {.action = (_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), \ + {.action = (_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) + +enum probes_insn { + INSN_REJECTED, + INSN_GOOD, + INSN_GOOD_NO_SLOT +}; + +struct decode_reject { + struct decode_header header; +}; + +#define DECODE_REJECT(_mask, _value) \ + DECODE_HEADER(DECODE_TYPE_REJECT, _mask, _value, 0) + +probes_insn_handler_t probes_simulate_nop; +probes_insn_handler_t probes_emulate_none; + +int __kprobes +probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, + const union decode_item *table, bool thumb, bool emulate, + const union decode_action *actions); + +#endif diff --git a/arch/arm/probes/kprobes/Makefile b/arch/arm/probes/kprobes/Makefile new file mode 100644 index 000000000000..eb38a428ecd6 --- /dev/null +++ b/arch/arm/probes/kprobes/Makefile @@ -0,0 +1,11 @@ +obj-$(CONFIG_KPROBES) += core.o actions-common.o +obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o +test-kprobes-objs := test-core.o + +ifdef CONFIG_THUMB2_KERNEL +obj-$(CONFIG_KPROBES) += actions-thumb.o +test-kprobes-objs += test-thumb.o +else +obj-$(CONFIG_KPROBES) += actions-arm.o +test-kprobes-objs += test-arm.o +endif diff --git a/arch/arm/probes/kprobes/actions-arm.c b/arch/arm/probes/kprobes/actions-arm.c new file mode 100644 index 000000000000..8797879f7b3a --- /dev/null +++ b/arch/arm/probes/kprobes/actions-arm.c @@ -0,0 +1,343 @@ +/* + * arch/arm/probes/kprobes/actions-arm.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 +#include +#include + +#include "../decode-arm.h" +#include "core.h" + +#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 + +static void __kprobes +emulate_ldrdstrd(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + unsigned long pc = regs->ARM_pc + 4; + 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" (asi->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(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + unsigned long pc = regs->ARM_pc + 4; + 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" (asi->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(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + unsigned long rtpc = regs->ARM_pc - 4 + str_pc_offset; + unsigned long rnpc = regs->ARM_pc + 4; + 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" (asi->insn_fn) + : "lr", "memory", "cc" + ); + + if (is_writeback(insn)) + regs->uregs[rn] = rnv; +} + +static void __kprobes +emulate_rd12rn16rm0rs8_rwflags(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + unsigned long pc = regs->ARM_pc + 4; + 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" (asi->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(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + 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" (asi->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(probes_opcode_t insn, + struct arch_probes_insn *asi, + struct pt_regs *regs) +{ + 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" (asi->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(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + 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" (asi->insn_fn) + : "lr", "memory", "cc" + ); + + regs->uregs[rd] = rdv; +} + +static void __kprobes +emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(probes_opcode_t insn, + struct arch_probes_insn *asi, + struct pt_regs *regs) +{ + 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" (asi->insn_fn) + : "lr", "memory", "cc" + ); + + regs->uregs[rdlo] = rdlov; + regs->uregs[rdhi] = rdhiv; + regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK); +} + +const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = { + [PROBES_EMULATE_NONE] = {.handler = probes_emulate_none}, + [PROBES_SIMULATE_NOP] = {.handler = probes_simulate_nop}, + [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop}, + [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop}, + [PROBES_BRANCH_IMM] = {.handler = simulate_blx1}, + [PROBES_MRS] = {.handler = simulate_mrs}, + [PROBES_BRANCH_REG] = {.handler = simulate_blx2bx}, + [PROBES_CLZ] = {.handler = emulate_rd12rm0_noflags_nopc}, + [PROBES_SATURATING_ARITHMETIC] = { + .handler = emulate_rd12rn16rm0_rwflags_nopc}, + [PROBES_MUL1] = {.handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc}, + [PROBES_MUL2] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc}, + [PROBES_SWP] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, + [PROBES_LDRSTRD] = {.handler = emulate_ldrdstrd}, + [PROBES_LOAD_EXTRA] = {.handler = emulate_ldr}, + [PROBES_LOAD] = {.handler = emulate_ldr}, + [PROBES_STORE_EXTRA] = {.handler = emulate_str}, + [PROBES_STORE] = {.handler = emulate_str}, + [PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp}, + [PROBES_DATA_PROCESSING_REG] = { + .handler = emulate_rd12rn16rm0rs8_rwflags}, + [PROBES_DATA_PROCESSING_IMM] = { + .handler = emulate_rd12rn16rm0rs8_rwflags}, + [PROBES_MOV_HALFWORD] = {.handler = emulate_rd12rm0_noflags_nopc}, + [PROBES_SEV] = {.handler = probes_emulate_none}, + [PROBES_WFE] = {.handler = probes_simulate_nop}, + [PROBES_SATURATE] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, + [PROBES_REV] = {.handler = emulate_rd12rm0_noflags_nopc}, + [PROBES_MMI] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, + [PROBES_PACK] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, + [PROBES_EXTEND] = {.handler = emulate_rd12rm0_noflags_nopc}, + [PROBES_EXTEND_ADD] = {.handler = emulate_rd12rn16rm0_rwflags_nopc}, + [PROBES_MUL_ADD_LONG] = { + .handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc}, + [PROBES_MUL_ADD] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc}, + [PROBES_BITFIELD] = {.handler = emulate_rd12rm0_noflags_nopc}, + [PROBES_BRANCH] = {.handler = simulate_bbl}, + [PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm} +}; diff --git a/arch/arm/probes/kprobes/actions-common.c b/arch/arm/probes/kprobes/actions-common.c new file mode 100644 index 000000000000..bd20a71cd34a --- /dev/null +++ b/arch/arm/probes/kprobes/actions-common.c @@ -0,0 +1,171 @@ +/* + * arch/arm/probes/kprobes/actions-common.c + * + * Copyright (C) 2011 Jon Medhurst . + * + * 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 +#include +#include + +#include "core.h" + + +static void __kprobes simulate_ldm1stm1(probes_opcode_t insn, + struct arch_probes_insn *asi, + struct pt_regs *regs) +{ + 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(probes_opcode_t insn, + struct arch_probes_insn *asi, + struct pt_regs *regs) +{ + unsigned long addr = regs->ARM_pc - 4; + + regs->ARM_pc = (long)addr + str_pc_offset; + simulate_ldm1stm1(insn, asi, regs); + regs->ARM_pc = (long)addr + 4; +} + +static void __kprobes simulate_ldm1_pc(probes_opcode_t insn, + struct arch_probes_insn *asi, + struct pt_regs *regs) +{ + simulate_ldm1stm1(insn, asi, regs); + load_write_pc(regs->ARM_pc, regs); +} + +static void __kprobes +emulate_generic_r0_12_noflags(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + register void *rregs asm("r1") = regs; + register void *rfn asm("lr") = asi->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(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + emulate_generic_r0_12_noflags(insn, asi, + (struct pt_regs *)(regs->uregs+2)); +} + +static void __kprobes +emulate_ldm_r3_15(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + emulate_generic_r0_12_noflags(insn, asi, + (struct pt_regs *)(regs->uregs+3)); + load_write_pc(regs->ARM_pc, regs); +} + +enum probes_insn __kprobes +kprobe_decode_ldmstm(probes_opcode_t insn, struct arch_probes_insn *asi, + const struct decode_header *h) +{ + probes_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] = __opcode_to_mem_arm((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; +} + diff --git a/arch/arm/probes/kprobes/actions-thumb.c b/arch/arm/probes/kprobes/actions-thumb.c new file mode 100644 index 000000000000..6c4e60b62826 --- /dev/null +++ b/arch/arm/probes/kprobes/actions-thumb.c @@ -0,0 +1,666 @@ +/* + * arch/arm/probes/kprobes/actions-thumb.c + * + * Copyright (C) 2011 Jon Medhurst . + * + * 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 +#include +#include +#include + +#include "../decode-thumb.h" +#include "core.h" + +/* These emulation encodings are functionally equivalent... */ +#define t32_emulate_rd8rn16rm0ra12_noflags \ + t32_emulate_rdlo12rdhi8rn16rm0_noflags + +/* t32 thumb actions */ + +static void __kprobes +t32_simulate_table_branch(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + unsigned long pc = regs->ARM_pc; + 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(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + 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(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + unsigned long pc = regs->ARM_pc; + + 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 probes_insn __kprobes +t32_decode_cond_branch(probes_opcode_t insn, struct arch_probes_insn *asi, + const struct decode_header *d) +{ + int cc = (insn >> 22) & 0xf; + asi->insn_check_cc = probes_condition_checks[cc]; + asi->insn_handler = t32_simulate_cond_branch; + return INSN_GOOD_NO_SLOT; +} + +static void __kprobes +t32_simulate_branch(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + unsigned long pc = regs->ARM_pc; + + 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 = regs->ARM_pc | 1; + 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(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + unsigned long addr = regs->ARM_pc & ~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 probes_insn __kprobes +t32_decode_ldmstm(probes_opcode_t insn, struct arch_probes_insn *asi, + const struct decode_header *d) +{ + enum probes_insn ret = kprobe_decode_ldmstm(insn, asi, d); + + /* Fixup modified instruction to have halfwords in correct order...*/ + insn = __mem_to_opcode_arm(asi->insn[0]); + ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(insn >> 16); + ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0xffff); + + return ret; +} + +static void __kprobes +t32_emulate_ldrdstrd(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + unsigned long pc = regs->ARM_pc & ~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" (asi->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(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + 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" (asi->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(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + 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" (asi->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(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + unsigned long pc = regs->ARM_pc; + 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" (asi->insn_fn) + : "lr", "memory", "cc" + ); + + regs->uregs[rd] = rdv; +} + +static void __kprobes +t32_emulate_rd8rn16_noflags(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + 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" (asi->insn_fn) + : "lr", "memory", "cc" + ); + + regs->uregs[rd] = rdv; +} + +static void __kprobes +t32_emulate_rdlo12rdhi8rn16rm0_noflags(probes_opcode_t insn, + struct arch_probes_insn *asi, + struct pt_regs *regs) +{ + 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" (asi->insn_fn) + : "lr", "memory", "cc" + ); + + regs->uregs[rdlo] = rdlov; + regs->uregs[rdhi] = rdhiv; +} +/* t16 thumb actions */ + +static void __kprobes +t16_simulate_bxblx(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + unsigned long pc = regs->ARM_pc + 2; + int rm = (insn >> 3) & 0xf; + unsigned long rmv = (rm == 15) ? pc : regs->uregs[rm]; + + if (insn & (1 << 7)) /* BLX ? */ + regs->ARM_lr = regs->ARM_pc | 1; + + bx_write_pc(rmv, regs); +} + +static void __kprobes +t16_simulate_ldr_literal(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + unsigned long *base = (unsigned long *)((regs->ARM_pc + 2) & ~3); + long index = insn & 0xff; + int rt = (insn >> 8) & 0x7; + regs->uregs[rt] = base[index]; +} + +static void __kprobes +t16_simulate_ldrstr_sp_relative(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + 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(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + unsigned long base = (insn & 0x800) ? regs->ARM_sp + : ((regs->ARM_pc + 2) & ~3); + long offset = insn & 0xff; + int rt = (insn >> 8) & 0x7; + regs->uregs[rt] = base + offset * 4; +} + +static void __kprobes +t16_simulate_add_sp_imm(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + 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(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + int rn = insn & 0x7; + probes_opcode_t nonzero = regs->uregs[rn] ? insn : ~insn; + if (nonzero & 0x800) { + long i = insn & 0x200; + long imm5 = insn & 0xf8; + unsigned long pc = regs->ARM_pc + 2; + regs->ARM_pc = pc + (i >> 3) + (imm5 >> 2); + } +} + +static void __kprobes +t16_simulate_it(probes_opcode_t insn, + struct arch_probes_insn *asi, 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. + */ + 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(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + regs->ARM_pc += 2; + t16_simulate_it(insn, asi, regs); +} + +static enum probes_insn __kprobes +t16_decode_it(probes_opcode_t insn, struct arch_probes_insn *asi, + const struct decode_header *d) +{ + asi->insn_singlestep = t16_singlestep_it; + return INSN_GOOD_NO_SLOT; +} + +static void __kprobes +t16_simulate_cond_branch(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + unsigned long pc = regs->ARM_pc + 2; + long offset = insn & 0x7f; + offset -= insn & 0x80; /* Apply sign bit */ + regs->ARM_pc = pc + (offset * 2); +} + +static enum probes_insn __kprobes +t16_decode_cond_branch(probes_opcode_t insn, struct arch_probes_insn *asi, + const struct decode_header *d) +{ + int cc = (insn >> 8) & 0xf; + asi->insn_check_cc = probes_condition_checks[cc]; + asi->insn_handler = t16_simulate_cond_branch; + return INSN_GOOD_NO_SLOT; +} + +static void __kprobes +t16_simulate_branch(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + unsigned long pc = regs->ARM_pc + 2; + long offset = insn & 0x3ff; + offset -= insn & 0x400; /* Apply sign bit */ + regs->ARM_pc = pc + (offset * 2); +} + +static unsigned long __kprobes +t16_emulate_loregs(probes_opcode_t insn, + struct arch_probes_insn *asi, 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" (asi->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(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + regs->ARM_cpsr = t16_emulate_loregs(insn, asi, regs); +} + +static void __kprobes +t16_emulate_loregs_noitrwflags(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + unsigned long cpsr = t16_emulate_loregs(insn, asi, regs); + if (!in_it_block(cpsr)) + regs->ARM_cpsr = cpsr; +} + +static void __kprobes +t16_emulate_hiregs(probes_opcode_t insn, + struct arch_probes_insn *asi, struct pt_regs *regs) +{ + unsigned long pc = regs->ARM_pc + 2; + 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" (asi->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 probes_insn __kprobes +t16_decode_hiregs(probes_opcode_t insn, struct arch_probes_insn *asi, + const struct decode_header *d) +{ + insn &= ~0x00ff; + insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */ + ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(insn); + asi->insn_handler = t16_emulate_hiregs; + return INSN_GOOD; +} + +static void __kprobes +t16_emulate_push(probes_opcode_t insn, + struct arch_probes_insn *asi, 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" (asi->insn_fn) + : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", + "lr", "memory", "cc" + ); +} + +static enum probes_insn __kprobes +t16_decode_push(probes_opcode_t insn, struct arch_probes_insn *asi, + const struct decode_header *d) +{ + /* + * 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. + */ + /* 1st half STMDB R9!,{} */ + ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(0xe929); + /* 2nd half (register list) */ + ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0x1ff); + asi->insn_handler = t16_emulate_push; + return INSN_GOOD; +} + +static void __kprobes +t16_emulate_pop_nopc(probes_opcode_t insn, + struct arch_probes_insn *asi, 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" (asi->insn_fn) + : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", + "lr", "memory", "cc" + ); +} + +static void __kprobes +t16_emulate_pop_pc(probes_opcode_t insn, + struct arch_probes_insn *asi, 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" (asi->insn_fn) + : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r9", + "lr", "memory", "cc" + ); + + bx_write_pc(pc, regs); +} + +static enum probes_insn __kprobes +t16_decode_pop(probes_opcode_t insn, struct arch_probes_insn *asi, + const struct decode_header *d) +{ + /* + * 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. + */ + /* 1st half LDMIA R9!,{} */ + ((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(0xe8b9); + /* 2nd half (register list) */ + ((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0x1ff); + asi->insn_handler = insn & 0x100 ? t16_emulate_pop_pc + : t16_emulate_pop_nopc; + return INSN_GOOD; +} + +const union decode_action kprobes_t16_actions[NUM_PROBES_T16_ACTIONS] = { + [PROBES_T16_ADD_SP] = {.handler = t16_simulate_add_sp_imm}, + [PROBES_T16_CBZ] = {.handler = t16_simulate_cbz}, + [PROBES_T16_SIGN_EXTEND] = {.handler = t16_emulate_loregs_rwflags}, + [PROBES_T16_PUSH] = {.decoder = t16_decode_push}, + [PROBES_T16_POP] = {.decoder = t16_decode_pop}, + [PROBES_T16_SEV] = {.handler = probes_emulate_none}, + [PROBES_T16_WFE] = {.handler = probes_simulate_nop}, + [PROBES_T16_IT] = {.decoder = t16_decode_it}, + [PROBES_T16_CMP] = {.handler = t16_emulate_loregs_rwflags}, + [PROBES_T16_ADDSUB] = {.handler = t16_emulate_loregs_noitrwflags}, + [PROBES_T16_LOGICAL] = {.handler = t16_emulate_loregs_noitrwflags}, + [PROBES_T16_LDR_LIT] = {.handler = t16_simulate_ldr_literal}, + [PROBES_T16_BLX] = {.handler = t16_simulate_bxblx}, + [PROBES_T16_HIREGOPS] = {.decoder = t16_decode_hiregs}, + [PROBES_T16_LDRHSTRH] = {.handler = t16_emulate_loregs_rwflags}, + [PROBES_T16_LDRSTR] = {.handler = t16_simulate_ldrstr_sp_relative}, + [PROBES_T16_ADR] = {.handler = t16_simulate_reladr}, + [PROBES_T16_LDMSTM] = {.handler = t16_emulate_loregs_rwflags}, + [PROBES_T16_BRANCH_COND] = {.decoder = t16_decode_cond_branch}, + [PROBES_T16_BRANCH] = {.handler = t16_simulate_branch}, +}; + +const union decode_action kprobes_t32_actions[NUM_PROBES_T32_ACTIONS] = { + [PROBES_T32_LDMSTM] = {.decoder = t32_decode_ldmstm}, + [PROBES_T32_LDRDSTRD] = {.handler = t32_emulate_ldrdstrd}, + [PROBES_T32_TABLE_BRANCH] = {.handler = t32_simulate_table_branch}, + [PROBES_T32_TST] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, + [PROBES_T32_MOV] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, + [PROBES_T32_ADDSUB] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, + [PROBES_T32_LOGICAL] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, + [PROBES_T32_CMP] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, + [PROBES_T32_ADDWSUBW_PC] = {.handler = t32_emulate_rd8pc16_noflags,}, + [PROBES_T32_ADDWSUBW] = {.handler = t32_emulate_rd8rn16_noflags}, + [PROBES_T32_MOVW] = {.handler = t32_emulate_rd8rn16_noflags}, + [PROBES_T32_SAT] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, + [PROBES_T32_BITFIELD] = {.handler = t32_emulate_rd8rn16_noflags}, + [PROBES_T32_SEV] = {.handler = probes_emulate_none}, + [PROBES_T32_WFE] = {.handler = probes_simulate_nop}, + [PROBES_T32_MRS] = {.handler = t32_simulate_mrs}, + [PROBES_T32_BRANCH_COND] = {.decoder = t32_decode_cond_branch}, + [PROBES_T32_BRANCH] = {.handler = t32_simulate_branch}, + [PROBES_T32_PLDI] = {.handler = probes_simulate_nop}, + [PROBES_T32_LDR_LIT] = {.handler = t32_simulate_ldr_literal}, + [PROBES_T32_LDRSTR] = {.handler = t32_emulate_ldrstr}, + [PROBES_T32_SIGN_EXTEND] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, + [PROBES_T32_MEDIA] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, + [PROBES_T32_REVERSE] = {.handler = t32_emulate_rd8rn16_noflags}, + [PROBES_T32_MUL_ADD] = {.handler = t32_emulate_rd8rn16rm0_rwflags}, + [PROBES_T32_MUL_ADD2] = {.handler = t32_emulate_rd8rn16rm0ra12_noflags}, + [PROBES_T32_MUL_ADD_LONG] = { + .handler = t32_emulate_rdlo12rdhi8rn16rm0_noflags}, +}; diff --git a/arch/arm/probes/kprobes/core.c b/arch/arm/probes/kprobes/core.c new file mode 100644 index 000000000000..701f49d74c35 --- /dev/null +++ b/arch/arm/probes/kprobes/core.c @@ -0,0 +1,628 @@ +/* + * arch/arm/kernel/kprobes.c + * + * Kprobes on ARM + * + * Abhishek Sagar + * Copyright (C) 2006, 2007 Motorola Inc. + * + * Nicolas Pitre + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../decode-arm.h" +#include "../decode-thumb.h" +#include "core.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; + const union decode_action *actions; + 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 = __mem_to_opcode_thumb16(((u16 *)addr)[0]); + if (is_wide_instruction(insn)) { + u16 inst2 = __mem_to_opcode_thumb16(((u16 *)addr)[1]); + insn = __opcode_thumb32_compose(insn, inst2); + decode_insn = thumb32_probes_decode_insn; + actions = kprobes_t32_actions; + } else { + decode_insn = thumb16_probes_decode_insn; + actions = kprobes_t16_actions; + } +#else /* !CONFIG_THUMB2_KERNEL */ + thumb = false; + if (addr & 0x3) + return -EINVAL; + insn = __mem_to_opcode_arm(*p->addr); + decode_insn = arm_probes_decode_insn; + actions = kprobes_arm_actions; +#endif + + p->opcode = insn; + p->ainsn.insn = tmp_insn; + + switch ((*decode_insn)(insn, &p->ainsn, true, actions)) { + 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 = (probes_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) +{ + __this_cpu_write(current_kprobe, kcb->prev_kprobe.kp); + kcb->kprobe_status = kcb->prev_kprobe.status; +} + +static void __kprobes set_current_kprobe(struct kprobe *p) +{ + __this_cpu_write(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->opcode, &p->ainsn, 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 *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, tmp, head, hlist) { + if (ri->task != current) + /* another task is sharing our hash bucket */ + continue; + + if (ri->rp && ri->rp->handler) { + __this_cpu_write(current_kprobe, &ri->rp->kp); + get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE; + ri->rp->handler(ri, regs); + __this_cpu_write(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, 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_probes_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/arch/arm/probes/kprobes/core.h b/arch/arm/probes/kprobes/core.h new file mode 100644 index 000000000000..2e1e5a3d9155 --- /dev/null +++ b/arch/arm/probes/kprobes/core.h @@ -0,0 +1,53 @@ +/* + * arch/arm/kernel/kprobes.h + * + * Copyright (C) 2011 Jon Medhurst . + * + * 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 + +#include +#include "../decode.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 probes_insn __kprobes +kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_probes_insn *asi, + const struct decode_header *h); + +typedef enum probes_insn (kprobe_decode_insn_t)(probes_opcode_t, + struct arch_probes_insn *, + bool, + const union decode_action *); + +#ifdef CONFIG_THUMB2_KERNEL + +extern const union decode_action kprobes_t32_actions[]; +extern const union decode_action kprobes_t16_actions[]; + +#else /* !CONFIG_THUMB2_KERNEL */ + +extern const union decode_action kprobes_arm_actions[]; + +#endif + +#endif /* _ARM_KERNEL_KPROBES_H */ diff --git a/arch/arm/probes/kprobes/test-arm.c b/arch/arm/probes/kprobes/test-arm.c new file mode 100644 index 000000000000..d9a1255f3043 --- /dev/null +++ b/arch/arm/probes/kprobes/test-arm.c @@ -0,0 +1,1346 @@ +/* + * arch/arm/kernel/kprobes-test-arm.c + * + * Copyright (C) 2011 Jon Medhurst . + * + * 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 +#include +#include +#include + +#include "test-core.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_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_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( 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 and a shift count in a register */ + TEST_UNSUPPORTED(__inst_arm(0xe15c0f1e) " @ cmp r12, r14, asl pc") + TEST_UNSUPPORTED(__inst_arm(0xe1a0cf1e) " @ mov r12, r14, asl pc") + TEST_UNSUPPORTED(__inst_arm(0xe08caf1e) " @ add r10, r12, r14, asl pc") + TEST_UNSUPPORTED(__inst_arm(0xe151021f) " @ cmp r1, pc, lsl r2") + TEST_UNSUPPORTED(__inst_arm(0xe17f0211) " @ cmn pc, r1, lsl r2") + TEST_UNSUPPORTED(__inst_arm(0xe1a0121f) " @ mov r1, pc, lsl r2") + TEST_UNSUPPORTED(__inst_arm(0xe1a0f211) " @ mov pc, r1, lsl r2") + TEST_UNSUPPORTED(__inst_arm(0xe042131f) " @ sub r1, r2, pc, lsl r3") + TEST_UNSUPPORTED(__inst_arm(0xe1cf1312) " @ bic r1, pc, r2, lsl r3") + TEST_UNSUPPORTED(__inst_arm(0xe081f312) " @ add pc, r1, r2, lsl r3") + + /* Data-processing with PC as a target and status registers updated */ + 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_R ("add pc, pc, r",14,(2f-1f-8)*2,", asr #1") + TEST_BB( "sub pc, pc, #1b-2b+8") +#if __LINUX_ARM_ARCH__ == 6 && !defined(CONFIG_CPU_V7) + TEST_BB( "sub pc, pc, #1b-2b+8-2") /* UNPREDICTABLE before and after 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_R( "add pc, pc, r",10,-2,", asl #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(__inst_arm(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,"") + +#if __LINUX_ARM_ARCH__ >= 5 + 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(__inst_arm(0x016fff10) " @ clz pc, r0") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(0xe101f050) " @ qadd pc, r0, r1") + TEST_UNSUPPORTED(__inst_arm(0xe121f050) " @ qsub pc, r0, r1") + TEST_UNSUPPORTED(__inst_arm(0xe141f050) " @ qdadd pc, r0, r1") + TEST_UNSUPPORTED(__inst_arm(0xe161f050) " @ qdsub pc, r0, r1") + TEST_UNSUPPORTED(__inst_arm(0xe16f2050) " @ qdsub r2, r0, pc") + TEST_UNSUPPORTED(__inst_arm(0xe161205f) " @ qdsub r2, pc, r1") + + TEST_UNSUPPORTED("bkpt 0xffff") + TEST_UNSUPPORTED("bkpt 0x0000") + + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe12f32c1) " @ smlawt pc, r1, r2, r3") + TEST_UNSUPPORTED(__inst_arm(0xe12032cf) " @ smlawt r0, pc, r2, r3") + TEST_UNSUPPORTED(__inst_arm(0xe1203fc1) " @ smlawt r0, r1, pc, r3") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe14f1382) " @ smlalbb pc, r1, r2, r3") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe14f13a2) " @ smlaltb pc, r1, r2, r3") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe14f13c2) " @ smlalbt pc, r1, r2, r3") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe14f13e2) " @ smlalbb pc, r1, r2, r3") + TEST_UNSUPPORTED(__inst_arm(0xe140f3e2) " @ smlalbb r0, pc, r2, r3") + TEST_UNSUPPORTED(__inst_arm(0xe14013ef) " @ smlalbb r0, r1, pc, r3") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe16f02e1) " @ smultt pc, r1, r2") + TEST_UNSUPPORTED(__inst_arm(0xe16002ef) " @ smultt r0, pc, r2") + TEST_UNSUPPORTED(__inst_arm(0xe1600fe1) " @ smultt r0, r1, pc") +#endif + + 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(__inst_arm(0xe00f0291) " @ mul pc, r1, r2") + TEST_UNSUPPORTED(__inst_arm(0xe000029f) " @ mul r0, pc, r2") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe041f392) " @ umaal pc, r1, r2, r3") + TEST_UNSUPPORTED(__inst_arm(0xe04f0392) " @ umaal r0, pc, r2, r3") + TEST_UNSUPPORTED(__inst_arm(0xe0500090) " @ undef") + TEST_UNSUPPORTED(__inst_arm(0xe05fff9f) " @ undef") +#endif + +#if __LINUX_ARM_ARCH__ >= 7 + 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(__inst_arm(0xe06f3291) " @ mls pc, r1, r2, r3") + TEST_UNSUPPORTED(__inst_arm(0xe060329f) " @ mls r0, pc, r2, r3") + TEST_UNSUPPORTED(__inst_arm(0xe0603f91) " @ mls r0, r1, pc, r3") + TEST_UNSUPPORTED(__inst_arm(0xe060f291) " @ mls r0, r1, r2, pc") +#endif + + TEST_UNSUPPORTED(__inst_arm(0xe0700090) " @ undef") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe081f392) " @ umull pc, r1, r2, r3") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe091f392) " @ umulls pc, r1, r2, r3") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe0af1392) " @ umlal pc, r1, r2, r3") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe0bf1392) " @ umlals pc, r1, r2, r3") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe0c1f392) " @ smull pc, r1, r2, r3") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe0d1f392) " @ smulls pc, r1, r2, r3") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe0ef1392) " @ smlal pc, r1, r2, r3") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe0ff1392) " @ smlals pc, r1, r2, r3") + TEST_UNSUPPORTED(__inst_arm(0xe0f0f392) " @ smlals r0, pc, r2, r3") + TEST_UNSUPPORTED(__inst_arm(0xe0f0139f) " @ smlals r0, r1, pc, r3") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe108e097) " @ swp lr, r7, [r8]") + TEST_UNSUPPORTED(__inst_arm(0x610d0091) " @ swpvs r0, r1, [sp]") + TEST_UNSUPPORTED(__inst_arm(0xe10cd09e) " @ swp sp, r14 [r12]") +#endif + TEST_UNSUPPORTED(__inst_arm(0xe102f091) " @ swp pc, r1, [r2]") + TEST_UNSUPPORTED(__inst_arm(0xe102009f) " @ swp r0, pc, [r2]") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe148e097) " @ swpb lr, r7, [r8]") + TEST_UNSUPPORTED(__inst_arm(0x614d0091) " @ swpvsb r0, r1, [sp]") +#endif + TEST_UNSUPPORTED(__inst_arm(0xe142f091) " @ swpb pc, r1, [r2]") + + TEST_UNSUPPORTED(__inst_arm(0xe1100090)) /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(0xe1200090)) /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(0xe1300090)) /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(0xe1500090)) /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(0xe1600090)) /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(0xe1700090)) /* Unallocated space */ +#if __LINUX_ARM_ARCH__ >= 6 + TEST_UNSUPPORTED("ldrex r2, [sp]") +#endif +#if (__LINUX_ARM_ARCH__ >= 7) || defined(CONFIG_CPU_32v6K) + 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(__inst_arm(0xe1afc0ba) " @ strh r12, [pc, r10]!") + TEST_UNSUPPORTED(__inst_arm(0xe089f0bb) " @ strh pc, [r9], r11") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe1bfc0ba) " @ ldrh r12, [pc, r10]!") + TEST_UNSUPPORTED(__inst_arm(0xe099f0bb) " @ ldrh pc, [r9], r11") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe1efc3b0) " @ strh r12, [pc, #48]!") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe1ffc3b0) " @ ldrh r12, [pc, #48]!") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe1bfc0da) " @ ldrsb r12, [pc, r10]!") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe1ffc3d0) " @ ldrsb r12, [pc, #48]!") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe1bfc0fa) " @ ldrsh r12, [pc, r10]!") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe1ffc3f0) " @ ldrsh r12, [pc, #48]!") + TEST_UNSUPPORTED(__inst_arm(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 + +#if __LINUX_ARM_ARCH__ >= 5 + 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(__inst_arm(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(__inst_arm(0xe1afc0da) " @ ldrd r12, [pc, r10]!") + TEST_UNSUPPORTED(__inst_arm(0xe089f0db) " @ ldrd pc, [r9], r11") + TEST_UNSUPPORTED(__inst_arm(0xe089e0db) " @ ldrd lr, [r9], r11") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(0xe1efc3d0) " @ ldrd r12, [pc, #48]!") + TEST_UNSUPPORTED(__inst_arm(0xe0c9f3d0) " @ ldrd pc, [r9], #48") + TEST_UNSUPPORTED(__inst_arm(0xe0c9e3d0) " @ ldrd lr, [r9], #48") +#endif + + TEST_GROUP("Miscellaneous") + +#if __LINUX_ARM_ARCH__ >= 7 + TEST("movw r0, #0") + TEST("movw r0, #0xffff") + TEST("movw lr, #0xffff") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(0xe5af6008) " @ str r6, [pc, #8]!") + TEST_UNSUPPORTED(__inst_arm(0xe7af6008) " @ str r6, [pc, r8]!") + TEST_UNSUPPORTED(__inst_arm(0xe5bf6008) " @ ldr r6, [pc, #8]!") + TEST_UNSUPPORTED(__inst_arm(0xe7bf6008) " @ ldr r6, [pc, r8]!") + TEST_UNSUPPORTED(__inst_arm(0xe788600f) " @ str r6, [r8, pc]") + TEST_UNSUPPORTED(__inst_arm(0xe798600f) " @ ldr r6, [r8, pc]") + + LOAD_STORE("b") + TEST_UNSUPPORTED(__inst_arm(0xe5f7f008) " @ ldrb pc, [r7, #8]!") + TEST_UNSUPPORTED(__inst_arm(0xe7f7f008) " @ ldrb pc, [r7, r8]!") + TEST_UNSUPPORTED(__inst_arm(0xe5ef6008) " @ strb r6, [pc, #8]!") + TEST_UNSUPPORTED(__inst_arm(0xe7ef6008) " @ strb r6, [pc, r3]!") + TEST_UNSUPPORTED(__inst_arm(0xe5ff6008) " @ ldrb r6, [pc, #8]!") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe6000010) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe61cff9a) " @ sadd8 pc, r12, r10") + TEST_UNSUPPORTED(__inst_arm(0xe61000b0) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(0xe61fffbf) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(0xe61000d0) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe62cff9a) " @ qadd8 pc, r12, r10") + TEST_UNSUPPORTED(__inst_arm(0xe62000b0) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(0xe62fffbf) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(0xe62000d0) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe63cff9a) " @ shadd8 pc, r12, r10") + TEST_UNSUPPORTED(__inst_arm(0xe63000b0) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(0xe63fffbf) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(0xe63000d0) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe63cfffa) " @ shsub8 pc, r12, r10") + + TEST_GROUP("Parallel addition and subtraction, unsigned") + + TEST_UNSUPPORTED(__inst_arm(0xe6400010) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe65cff9a) " @ uadd8 pc, r12, r10") + TEST_UNSUPPORTED(__inst_arm(0xe65000b0) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(0xe65fffbf) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(0xe65000d0) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe66cff9a) " @ uqadd8 pc, r12, r10") + TEST_UNSUPPORTED(__inst_arm(0xe66000b0) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(0xe66fffbf) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(0xe66000d0) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe67cff9a) " @ uhadd8 pc, r12, r10") + TEST_UNSUPPORTED(__inst_arm(0xe67000b0) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(0xe67fffbf) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(0xe67000d0) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe67cfffa) " @ uhsub8 pc, r12, r10") + TEST_UNSUPPORTED(__inst_arm(0xe67feffa) " @ uhsub8 r14, pc, r10") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(0xe68cf15a) " @ pkhtb pc, r12, r10, asr #2") + TEST_UNSUPPORTED(__inst_arm(0xe68fe15a) " @ pkhtb r14, pc, r10, asr #2") + TEST_UNSUPPORTED(__inst_arm(0xe68ce15f) " @ pkhtb r14, r12, pc, asr #2") + TEST_UNSUPPORTED(__inst_arm(0xe6900010) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe68cffba) " @ sel pc, r12, r10") + TEST_UNSUPPORTED(__inst_arm(0xe68fefba) " @ sel r14, pc, r10") + TEST_UNSUPPORTED(__inst_arm(0xe68cefbf) " @ sel r14, r12, pc") + + TEST_R( "ssat16 r0, #12, r",0, HH1,"") + TEST_R( "ssat16 r14, #12, r",12, HH2,"") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe6acf47a) " @ sxtab pc,r12, r10, ror #8") + + TEST_R( "rev r0, r",0, VAL1,"") + TEST_R( "rev r14, r",12, VAL2,"") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe6bcf47a) " @ sxtah pc,r12, r10, ror #8") + + TEST_R( "rev16 r0, r",0, VAL1,"") + TEST_R( "rev16 r14, r",12, VAL2,"") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(0xe6ecff3c) " @ usat16 pc, #12, r12") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe6fff077) " @ uxth pc, r7") + TEST_UNSUPPORTED(__inst_arm(0xe6ff807f) " @ uxth r8, pc") + TEST_UNSUPPORTED(__inst_arm(0xe6fcf47a) " @ uxtah pc, r12, r10, ror #8") + TEST_UNSUPPORTED(__inst_arm(0xe6fce47f) " @ uxtah r14, r12, pc, ror #8") + + TEST_R( "revsh r0, r",0, VAL1,"") + TEST_R( "revsh r14, r",12, VAL2,"") + TEST_UNSUPPORTED(__inst_arm(0xe6ffff3c) " @ revsh pc, r12") + TEST_UNSUPPORTED(__inst_arm(0xe6ffef3f) " @ revsh r14, pc") + + TEST_UNSUPPORTED(__inst_arm(0xe6900070) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(0xe69fff7f) "") /* Unallocated space */ + + TEST_UNSUPPORTED(__inst_arm(0xe6d00070) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe74af819) " @ smlald pc, r10, r9, r8") + TEST_UNSUPPORTED(__inst_arm(0xe74fb819) " @ smlald r11, pc, r9, r8") + TEST_UNSUPPORTED(__inst_arm(0xe74ab81f) " @ smlald r11, r10, pc, r8") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe74af839) " @ smlaldx pc, r10, r9, r8") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(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(__inst_arm(0xe75f8afc) " @ smmlsr pc, r12, r10, r8") + TEST_UNSUPPORTED(__inst_arm(0xe75e8aff) " @ smmlsr r14, pc, r10, r8") + TEST_UNSUPPORTED(__inst_arm(0xe75e8ffc) " @ smmlsr r14, r12, pc, r8") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe75ffa1c) " @ usad8 pc, r12, r10") + TEST_UNSUPPORTED(__inst_arm(0xe75efa1f) " @ usad8 r14, pc, r10") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0xe78f8a1c) " @ usada8 pc, r12, r10, r8") + TEST_UNSUPPORTED(__inst_arm(0xe78e8a1f) " @ usada8 r14, pc, r10, r8") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(0xe7eff45c) " @ ubfx pc, r12, #8, #16") + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(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(__inst_arm(0xe7d7f21e) " @ bfi pc, r14, #4, #20") + + TEST_UNSUPPORTED(__inst_arm(0x07f000f0) "") /* Permanently UNDEFINED */ + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0x##cc##daf0001) " @ stc"two" 0, cr0, [r15, #4]!") \ + TEST_UNSUPPORTED(__inst_arm(0x##cc##d2f0001) " @ stc"two" 0, cr0, [r15, #-4]!") \ + TEST_UNSUPPORTED(__inst_arm(0x##cc##caf0001) " @ stc"two" 0, cr0, [r15], #4") \ + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0x##cc##def0001) " @ stc"two"l 0, cr0, [r15, #4]!") \ + TEST_UNSUPPORTED(__inst_arm(0x##cc##d6f0001) " @ stc"two"l 0, cr0, [r15, #-4]!") \ + TEST_UNSUPPORTED(__inst_arm(0x##cc##cef0001) " @ stc"two"l 0, cr0, [r15], #4") \ + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0x##cc##dbf0001) " @ ldc"two" 0, cr0, [r15, #4]!") \ + TEST_UNSUPPORTED(__inst_arm(0x##cc##d3f0001) " @ ldc"two" 0, cr0, [r15, #-4]!") \ + TEST_UNSUPPORTED(__inst_arm(0x##cc##cbf0001) " @ ldc"two" 0, cr0, [r15], #4") \ + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0x##cc##dff0001) " @ ldc"two"l 0, cr0, [r15, #4]!") \ + TEST_UNSUPPORTED(__inst_arm(0x##cc##d7f0001) " @ ldc"two"l 0, cr0, [r15, #-4]!") \ + TEST_UNSUPPORTED(__inst_arm(0x##cc##cff0001) " @ ldc"two"l 0, cr0, [r15], #4") \ + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0x##cc##c4f00f0) " @ mcrr"two" 0, 15, r0, r15, cr0") \ + TEST_UNSUPPORTED(__inst_arm(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(__inst_arm(0x##cc##c5f00f0) " @ mrrc"two" 0, 15, r0, r15, cr0") \ + TEST_UNSUPPORTED(__inst_arm(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) +#if __LINUX_ARM_ARCH__ >= 5 + COPROCESSOR_INSTRUCTIONS_MC_MR("",e) +#endif + 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(__inst_arm(0xf81d0a00) " @ rfeda pc") + TEST_UNSUPPORTED(__inst_arm(0xf91d0a00) " @ rfedb pc") + TEST_UNSUPPORTED(__inst_arm(0xf89d0a00) " @ rfeia pc") + TEST_UNSUPPORTED(__inst_arm(0xf99d0a00) " @ rfeib pc") + TEST_UNSUPPORTED(__inst_arm(0xf83d0a00) " @ rfeda pc!") + TEST_UNSUPPORTED(__inst_arm(0xf93d0a00) " @ rfedb pc!") + TEST_UNSUPPORTED(__inst_arm(0xf8bd0a00) " @ rfeia pc!") + TEST_UNSUPPORTED(__inst_arm(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 */ + +#if __LINUX_ARM_ARCH__ >= 5 + COPROCESSOR_INSTRUCTIONS_ST_LD("2",f) +#endif +#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( __inst_arm(0xf590f000) " @ pldw [r0, #0]") + TEST_SUPPORTED( __inst_arm(0xf797f000) " @ pldw [r7, r0]") + TEST_SUPPORTED( __inst_arm(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/arch/arm/probes/kprobes/test-core.c b/arch/arm/probes/kprobes/test-core.c new file mode 100644 index 000000000000..7ab633d51954 --- /dev/null +++ b/arch/arm/probes/kprobes/test-core.c @@ -0,0 +1,1713 @@ +/* + * arch/arm/kernel/kprobes-test.c + * + * Copyright (C) 2011 Jon Medhurst . + * + * 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 + * .pushsection .rodata + * "10: + * .ascii "mov r0, r7" @ text title for test case + * .byte 0 + * .popsection + * @ start of inline data... + * .word 10b @ pointer to title in .rodata section + * + * @ 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 +#include +#include +#include +#include +#include +#include +#include + +#include "core.h" +#include "test-core.h" +#include "../decode-arm.h" +#include "../decode-thumb.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; +static int tests_failed; + +#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 defined(CONFIG_THUMB2_KERNEL) && !defined(MODULE) + if (ret == -EINVAL) { + pr_err("FAIL: Known longtime bug with jprobe on Thumb kernels\n"); + tests_failed = ret; + ret = 0; + } +#endif + 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 data \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(__mem_to_opcode_thumb16(*(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; + + current_title = *title++; + args = (struct test_arg *)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 = __mem_to_opcode_thumb16(p[0]); + if (is_wide_instruction(current_instruction)) { + u16 instr2 = __mem_to_opcode_thumb16(p[1]); + current_instruction = __opcode_thumb32_compose(current_instruction, instr2); + } + } else { + current_instruction = __mem_to_opcode_arm(*(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("Beginning 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, probes_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, + probes_decode_thumb16_table); + if (ret) + goto out; + + pr_info("32-bit Thumb instruction simulation\n"); + ret = run_test_cases(kprobe_thumb32_test_cases, + probes_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) + ret = tests_failed; + 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/arch/arm/probes/kprobes/test-core.h b/arch/arm/probes/kprobes/test-core.h new file mode 100644 index 000000000000..9991754947bc --- /dev/null +++ b/arch/arm/probes/kprobes/test-core.h @@ -0,0 +1,435 @@ +/* + * arch/arm/probes/kprobes/test-core.h + * + * Copyright (C) 2011 Jon Medhurst . + * + * 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" \ + ".pushsection .rodata \n\t" \ + "10: \n\t" \ + /* don't use .asciz here as 'title' may be */ \ + /* multiple strings to be concatenated. */ \ + ".ascii "#title" \n\t" \ + ".byte 0 \n\t" \ + ".popsection \n\t" \ + ".word 10b \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/arch/arm/probes/kprobes/test-thumb.c b/arch/arm/probes/kprobes/test-thumb.c new file mode 100644 index 000000000000..6c6e9a9bb675 --- /dev/null +++ b/arch/arm/probes/kprobes/test-thumb.c @@ -0,0 +1,1188 @@ +/* + * arch/arm/probes/kprobes/test-thumb.c + * + * Copyright (C) 2011 Jon Medhurst . + * + * 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 +#include +#include + +#include "test-core.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(__inst_thumb16(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(__inst_thumb16(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(__inst_thumb16(0xba80) "") + TEST_UNSUPPORTED(__inst_thumb16(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(__inst_thumb16(0xbf50) "") /* Unassigned hints */ + TEST_UNSUPPORTED(__inst_thumb16(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(__inst_thumb16(0xde00) "") + TEST_UNSUPPORTED(__inst_thumb16(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(__inst_thumb32(0xe88f0101) " @ stmia pc, {r0,r8}") + TEST_UNSUPPORTED(__inst_thumb32(0xe92f5f00) " @ stmdb pc!, {r8-r12,r14}") + TEST_UNSUPPORTED(__inst_thumb32(0xe8bdc000) " @ ldmia r13!, {r14,pc}") + TEST_UNSUPPORTED(__inst_thumb32(0xe93ec000) " @ ldmdb r14!, {r14,pc}") + TEST_UNSUPPORTED(__inst_thumb32(0xe8a73f00) " @ stmia r7!, {r8-r12,sp}") + TEST_UNSUPPORTED(__inst_thumb32(0xe8a79f00) " @ stmia r7!, {r8-r12,pc}") + TEST_UNSUPPORTED(__inst_thumb32(0xe93e2010) " @ 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(__inst_thumb32(0xe9ffec04) " @ ldrd r14, r12, [pc, #16]!") + TEST_UNSUPPORTED(__inst_thumb32(0xe8ffec04) " @ ldrd r14, r12, [pc], #16") + TEST_UNSUPPORTED(__inst_thumb32(0xe9d4d800) " @ ldrd sp, r8, [r4]") + TEST_UNSUPPORTED(__inst_thumb32(0xe9d4f800) " @ ldrd pc, r8, [r4]") + TEST_UNSUPPORTED(__inst_thumb32(0xe9d47d00) " @ ldrd r7, sp, [r4]") + TEST_UNSUPPORTED(__inst_thumb32(0xe9d47f00) " @ 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(__inst_thumb32(0xe9efec04) " @ strd r14, r12, [pc, #16]!") + TEST_UNSUPPORTED(__inst_thumb32(0xe8efec04) " @ 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(__inst_thumb32(0xe8d1f01f) " @ tbh [r1, pc]") + TEST_UNSUPPORTED(__inst_thumb32(0xe8d1f01d) " @ tbh [r1, sp]") + TEST_UNSUPPORTED(__inst_thumb32(0xe8ddf012) " @ 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(__inst_thumb32(0xea170f0d) " @ tst.w r7, sp") + TEST_UNSUPPORTED(__inst_thumb32(0xea170f0f) " @ tst.w r7, pc") + TEST_UNSUPPORTED(__inst_thumb32(0xea1d0f07) " @ tst.w sp, r7") + TEST_UNSUPPORTED(__inst_thumb32(0xea1f0f07) " @ tst.w pc, r7") + TEST_UNSUPPORTED(__inst_thumb32(0xf01d1f08) " @ tst sp, #0x00080008") + TEST_UNSUPPORTED(__inst_thumb32(0xf01f1f08) " @ tst pc, #0x00080008") + + TEST_UNSUPPORTED(__inst_thumb32(0xea970f0d) " @ teq.w r7, sp") + TEST_UNSUPPORTED(__inst_thumb32(0xea970f0f) " @ teq.w r7, pc") + TEST_UNSUPPORTED(__inst_thumb32(0xea9d0f07) " @ teq.w sp, r7") + TEST_UNSUPPORTED(__inst_thumb32(0xea9f0f07) " @ teq.w pc, r7") + TEST_UNSUPPORTED(__inst_thumb32(0xf09d1f08) " @ tst sp, #0x00080008") + TEST_UNSUPPORTED(__inst_thumb32(0xf09f1f08) " @ tst pc, #0x00080008") + + TEST_UNSUPPORTED(__inst_thumb32(0xeb170f0d) " @ cmn.w r7, sp") + TEST_UNSUPPORTED(__inst_thumb32(0xeb170f0f) " @ cmn.w r7, pc") + TEST_P("cmn.w sp, r",7,0,"") + TEST_UNSUPPORTED(__inst_thumb32(0xeb1f0f07) " @ cmn.w pc, r7") + TEST( "cmn sp, #0x00080008") + TEST_UNSUPPORTED(__inst_thumb32(0xf11f1f08) " @ cmn pc, #0x00080008") + + TEST_UNSUPPORTED(__inst_thumb32(0xebb70f0d) " @ cmp.w r7, sp") + TEST_UNSUPPORTED(__inst_thumb32(0xebb70f0f) " @ cmp.w r7, pc") + TEST_P("cmp.w sp, r",7,0,"") + TEST_UNSUPPORTED(__inst_thumb32(0xebbf0f07) " @ cmp.w pc, r7") + TEST( "cmp sp, #0x00080008") + TEST_UNSUPPORTED(__inst_thumb32(0xf1bf1f08) " @ cmp pc, #0x00080008") + + TEST_UNSUPPORTED(__inst_thumb32(0xea5f070d) " @ movs.w r7, sp") + TEST_UNSUPPORTED(__inst_thumb32(0xea5f070f) " @ movs.w r7, pc") + TEST_UNSUPPORTED(__inst_thumb32(0xea5f0d07) " @ movs.w sp, r7") + TEST_UNSUPPORTED(__inst_thumb32(0xea4f0f07) " @ mov.w pc, r7") + TEST_UNSUPPORTED(__inst_thumb32(0xf04f1d08) " @ mov sp, #0x00080008") + TEST_UNSUPPORTED(__inst_thumb32(0xf04f1f08) " @ 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(__inst_thumb32(0xeb0d1d01) " @ add sp, sp, r1, asl #4") + TEST_UNSUPPORTED(__inst_thumb32(0xeb0d0d71) " @ add sp, sp, r1, ror #1") + TEST( "add.w r0, sp, #24") + TEST( "add.w sp, sp, #24") + TEST_UNSUPPORTED(__inst_thumb32(0xeb0d0f01) " @ add pc, sp, r1") + TEST_UNSUPPORTED(__inst_thumb32(0xeb0d000f) " @ add r0, sp, pc") + TEST_UNSUPPORTED(__inst_thumb32(0xeb0d000d) " @ add r0, sp, sp") + TEST_UNSUPPORTED(__inst_thumb32(0xeb0d0d0f) " @ add sp, sp, pc") + TEST_UNSUPPORTED(__inst_thumb32(0xeb0d0d0d) " @ 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(__inst_thumb32(0xebad1d01) " @ sub sp, sp, r1, asl #4") + TEST_UNSUPPORTED(__inst_thumb32(0xebad0d71) " @ sub sp, sp, r1, ror #1") + TEST_UNSUPPORTED(__inst_thumb32(0xebad0f01) " @ sub pc, sp, r1") + TEST( "sub.w r0, sp, #24") + TEST( "sub.w sp, sp, #24") + + TEST_UNSUPPORTED(__inst_thumb32(0xea02010f) " @ and r1, r2, pc") + TEST_UNSUPPORTED(__inst_thumb32(0xea0f0103) " @ and r1, pc, r3") + TEST_UNSUPPORTED(__inst_thumb32(0xea020f03) " @ and pc, r2, r3") + TEST_UNSUPPORTED(__inst_thumb32(0xea02010d) " @ and r1, r2, sp") + TEST_UNSUPPORTED(__inst_thumb32(0xea0d0103) " @ and r1, sp, r3") + TEST_UNSUPPORTED(__inst_thumb32(0xea020d03) " @ and sp, r2, r3") + TEST_UNSUPPORTED(__inst_thumb32(0xf00d1108) " @ and r1, sp, #0x00080008") + TEST_UNSUPPORTED(__inst_thumb32(0xf00f1108) " @ and r1, pc, #0x00080008") + TEST_UNSUPPORTED(__inst_thumb32(0xf0021d08) " @ and sp, r8, #0x00080008") + TEST_UNSUPPORTED(__inst_thumb32(0xf0021f08) " @ and pc, r8, #0x00080008") + + TEST_UNSUPPORTED(__inst_thumb32(0xeb02010f) " @ add r1, r2, pc") + TEST_UNSUPPORTED(__inst_thumb32(0xeb0f0103) " @ add r1, pc, r3") + TEST_UNSUPPORTED(__inst_thumb32(0xeb020f03) " @ add pc, r2, r3") + TEST_UNSUPPORTED(__inst_thumb32(0xeb02010d) " @ add r1, r2, sp") + TEST_SUPPORTED( __inst_thumb32(0xeb0d0103) " @ add r1, sp, r3") + TEST_UNSUPPORTED(__inst_thumb32(0xeb020d03) " @ add sp, r2, r3") + TEST_SUPPORTED( __inst_thumb32(0xf10d1108) " @ add r1, sp, #0x00080008") + TEST_UNSUPPORTED(__inst_thumb32(0xf10d1f08) " @ add pc, sp, #0x00080008") + TEST_UNSUPPORTED(__inst_thumb32(0xf10f1108) " @ add r1, pc, #0x00080008") + TEST_UNSUPPORTED(__inst_thumb32(0xf1021d08) " @ add sp, r8, #0x00080008") + TEST_UNSUPPORTED(__inst_thumb32(0xf1021f08) " @ add pc, r8, #0x00080008") + + TEST_UNSUPPORTED(__inst_thumb32(0xeaa00000) "") + TEST_UNSUPPORTED(__inst_thumb32(0xeaf00000) "") + TEST_UNSUPPORTED(__inst_thumb32(0xeb200000) "") + TEST_UNSUPPORTED(__inst_thumb32(0xeb800000) "") + TEST_UNSUPPORTED(__inst_thumb32(0xebe00000) "") + + TEST_UNSUPPORTED(__inst_thumb32(0xf0a00000) "") + TEST_UNSUPPORTED(__inst_thumb32(0xf0c00000) "") + TEST_UNSUPPORTED(__inst_thumb32(0xf0f00000) "") + TEST_UNSUPPORTED(__inst_thumb32(0xf1200000) "") + TEST_UNSUPPORTED(__inst_thumb32(0xf1800000) "") + TEST_UNSUPPORTED(__inst_thumb32(0xf1e00000) "") + + TEST_GROUP("Coprocessor instructions") + + TEST_UNSUPPORTED(__inst_thumb32(0xec000000) "") + TEST_UNSUPPORTED(__inst_thumb32(0xeff00000) "") + TEST_UNSUPPORTED(__inst_thumb32(0xfc000000) "") + TEST_UNSUPPORTED(__inst_thumb32(0xfff00000) "") + + 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(__inst_thumb32(0xf20f1f20) " @ addw pc, pc, #0x120") + TEST_UNSUPPORTED(__inst_thumb32(0xf20d1f20) " @ addw pc, sp, #0x120") + TEST_UNSUPPORTED(__inst_thumb32(0xf20f1d20) " @ addw sp, pc, #0x120") + TEST_UNSUPPORTED(__inst_thumb32(0xf2001d20) " @ 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(__inst_thumb32(0xf2af1f20) " @ subw pc, pc, #0x120") + TEST_UNSUPPORTED(__inst_thumb32(0xf2ad1f20) " @ subw pc, sp, #0x120") + TEST_UNSUPPORTED(__inst_thumb32(0xf2af1d20) " @ subw sp, pc, #0x120") + TEST_UNSUPPORTED(__inst_thumb32(0xf2a01d20) " @ subw sp, r0, #0x120") + + TEST("movw r0, #0") + TEST("movw r0, #0xffff") + TEST("movw lr, #0xffff") + TEST_UNSUPPORTED(__inst_thumb32(0xf2400d00) " @ movw sp, #0") + TEST_UNSUPPORTED(__inst_thumb32(0xf2400f00) " @ 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(__inst_thumb32(0xf2c00d00) " @ movt sp, #0") + TEST_UNSUPPORTED(__inst_thumb32(0xf2c00f00) " @ 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(__inst_thumb32(0xf30c0d17) " @ ssat sp, #24, r12") + TEST_UNSUPPORTED(__inst_thumb32(0xf30c0f17) " @ ssat pc, #24, r12") + TEST_UNSUPPORTED(__inst_thumb32(0xf30d0c17) " @ ssat r12, #24, sp") + TEST_UNSUPPORTED(__inst_thumb32(0xf30f0c17) " @ 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(__inst_thumb32(0xf38c0d17) " @ usat sp, #24, r12") + TEST_UNSUPPORTED(__inst_thumb32(0xf38c0f17) " @ usat pc, #24, r12") + TEST_UNSUPPORTED(__inst_thumb32(0xf38d0c17) " @ usat r12, #24, sp") + TEST_UNSUPPORTED(__inst_thumb32(0xf38f0c17) " @ usat r12, #24, pc") + + TEST_R( "ssat16 r0, #12, r",0, HH1,"") + TEST_R( "ssat16 r14, #12, r",12, HH2,"") + TEST_UNSUPPORTED(__inst_thumb32(0xf32c0d0b) " @ ssat16 sp, #12, r12") + TEST_UNSUPPORTED(__inst_thumb32(0xf32c0f0b) " @ ssat16 pc, #12, r12") + TEST_UNSUPPORTED(__inst_thumb32(0xf32d0c0b) " @ ssat16 r12, #12, sp") + TEST_UNSUPPORTED(__inst_thumb32(0xf32f0c0b) " @ ssat16 r12, #12, pc") + + TEST_R( "usat16 r0, #12, r",0, HH1,"") + TEST_R( "usat16 r14, #12, r",12, HH2,"") + TEST_UNSUPPORTED(__inst_thumb32(0xf3ac0d0b) " @ usat16 sp, #12, r12") + TEST_UNSUPPORTED(__inst_thumb32(0xf3ac0f0b) " @ usat16 pc, #12, r12") + TEST_UNSUPPORTED(__inst_thumb32(0xf3ad0c0b) " @ usat16 r12, #12, sp") + TEST_UNSUPPORTED(__inst_thumb32(0xf3af0c0b) " @ 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(__inst_thumb32(0xf34c2d0f) " @ sbfx sp, r12, #8, #16") + TEST_UNSUPPORTED(__inst_thumb32(0xf34c2f0f) " @ sbfx pc, r12, #8, #16") + TEST_UNSUPPORTED(__inst_thumb32(0xf34d2c0f) " @ sbfx r12, sp, #8, #16") + TEST_UNSUPPORTED(__inst_thumb32(0xf34f2c0f) " @ 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(__inst_thumb32(0xf3cc2d0f) " @ ubfx sp, r12, #8, #16") + TEST_UNSUPPORTED(__inst_thumb32(0xf3cc2f0f) " @ ubfx pc, r12, #8, #16") + TEST_UNSUPPORTED(__inst_thumb32(0xf3cd2c0f) " @ ubfx r12, sp, #8, #16") + TEST_UNSUPPORTED(__inst_thumb32(0xf3cf2c0f) " @ 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(__inst_thumb32(0xf36f0d1e) " @ bfc sp, #0, #31") + TEST_UNSUPPORTED(__inst_thumb32(0xf36f0f1e) " @ 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(__inst_thumb32(0xf36e1d17) " @ bfi sp, r14, #4, #20") + TEST_UNSUPPORTED(__inst_thumb32(0xf36e1f17) " @ bfi pc, r14, #4, #20") + TEST_UNSUPPORTED(__inst_thumb32(0xf36d1e17) " @ 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(__inst_thumb32(0xf3ef8d00) " @ mrs sp, spsr") + TEST_UNSUPPORTED(__inst_thumb32(0xf3ef8f00) " @ mrs pc, spsr") + TEST_UNSUPPORTED("mrs r0, spsr") + TEST_UNSUPPORTED("mrs lr, spsr") + + TEST_UNSUPPORTED(__inst_thumb32(0xf7f08000) " @ smc #0") + + TEST_UNSUPPORTED(__inst_thumb32(0xf7f0a000) " @ 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(__inst_thumb32(0xf8cfe000) " @ str r14, [pc]") + TEST_UNSUPPORTED(__inst_thumb32(0xf8cef000) " @ str pc, [r14]") + + TEST_GROUP("Advanced SIMD element or structure load/store instructions") + + TEST_UNSUPPORTED(__inst_thumb32(0xf9000000) "") + TEST_UNSUPPORTED(__inst_thumb32(0xf92fffff) "") + TEST_UNSUPPORTED(__inst_thumb32(0xf9800000) "") + TEST_UNSUPPORTED(__inst_thumb32(0xf9efffff) "") + + 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(__inst_thumb32(0xf854700d) " @ ldr r7, [r4, sp]") + TEST_UNSUPPORTED(__inst_thumb32(0xf854700f) " @ ldr r7, [r4, pc]") + TEST_UNSUPPORTED(__inst_thumb32(0xf814700d) " @ ldrb r7, [r4, sp]") + TEST_UNSUPPORTED(__inst_thumb32(0xf814700f) " @ ldrb r7, [r4, pc]") + TEST_UNSUPPORTED(__inst_thumb32(0xf89fd004) " @ ldrb sp, 99f") + TEST_UNSUPPORTED(__inst_thumb32(0xf814d008) " @ ldrb sp, [r4, r8]") + TEST_UNSUPPORTED(__inst_thumb32(0xf894d000) " @ ldrb sp, [r4]") + + TEST_UNSUPPORTED(__inst_thumb32(0xf8600000) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_thumb32(0xf9ffffff) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_thumb32(0xf9500000) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_thumb32(0xf95fffff) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_thumb32(0xf8000800) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_thumb32(0xf97ffaff) "") /* 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( __inst_thumb32(0xf8b0f400) " @ pldw [r0, #1024]") + TEST_P( "pli [r",4, 0b,", #1024]") + TEST_P( "pld [r",7, 120,", #-120]") + TEST( __inst_thumb32(0xf837fc78) " @ 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(__inst_thumb32(0xf837f000) " @ pldw [r7, r0]") + TEST_SUPPORTED(__inst_thumb32(0xf838f03c) " @ 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(__inst_thumb32(0xf817f00d) " @pld [r7, sp]") + TEST_UNSUPPORTED(__inst_thumb32(0xf817f00f) " @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(__inst_thumb32(0xfa01ff02) " @ lsl pc, r1, r2") + TEST_UNSUPPORTED(__inst_thumb32(0xfa01fd02) " @ lsl sp, r1, r2") + TEST_UNSUPPORTED(__inst_thumb32(0xfa0ff002) " @ lsl r0, pc, r2") + TEST_UNSUPPORTED(__inst_thumb32(0xfa0df002) " @ lsl r0, sp, r2") + TEST_UNSUPPORTED(__inst_thumb32(0xfa01f00f) " @ lsl r0, r1, pc") + TEST_UNSUPPORTED(__inst_thumb32(0xfa01f00d) " @ 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(__inst_thumb32(0xfa0fff87) " @ sxth pc, r7"); + TEST_UNSUPPORTED(__inst_thumb32(0xfa0ffd87) " @ sxth sp, r7"); + TEST_UNSUPPORTED(__inst_thumb32(0xfa0ff88f) " @ sxth r8, pc"); + TEST_UNSUPPORTED(__inst_thumb32(0xfa0ff88d) " @ 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(__inst_thumb32(0xfa6000f0) "") + TEST_UNSUPPORTED(__inst_thumb32(0xfa7fffff) "") + +#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(__inst_thumb32(0xfa9cff8c) " @ rev pc, r12"); + TEST_UNSUPPORTED(__inst_thumb32(0xfa9cfd8c) " @ rev sp, r12"); + TEST_UNSUPPORTED(__inst_thumb32(0xfa9ffe8f) " @ rev r14, pc"); + TEST_UNSUPPORTED(__inst_thumb32(0xfa9dfe8d) " @ 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(__inst_thumb32(0xfa80f030) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_thumb32(0xfaffff7f) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_thumb32(0xfab0f000) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_thumb32(0xfaffff7f) "") /* 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(__inst_thumb32(0xfb08ff09) " @ mul pc, r8, r9") + TEST_UNSUPPORTED(__inst_thumb32(0xfb08fd09) " @ mul sp, r8, r9") + TEST_UNSUPPORTED(__inst_thumb32(0xfb0ff709) " @ mul r7, pc, r9") + TEST_UNSUPPORTED(__inst_thumb32(0xfb0df709) " @ mul r7, sp, r9") + TEST_UNSUPPORTED(__inst_thumb32(0xfb08f70f) " @ mul r7, r8, pc") + TEST_UNSUPPORTED(__inst_thumb32(0xfb08f70d) " @ 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(__inst_thumb32(0xfb08af09) " @ mla pc, r8, r9, r10"); + TEST_UNSUPPORTED(__inst_thumb32(0xfb08ad09) " @ mla sp, r8, r9, r10"); + TEST_UNSUPPORTED(__inst_thumb32(0xfb0fa709) " @ mla r7, pc, r9, r10"); + TEST_UNSUPPORTED(__inst_thumb32(0xfb0da709) " @ mla r7, sp, r9, r10"); + TEST_UNSUPPORTED(__inst_thumb32(0xfb08a70f) " @ mla r7, r8, pc, r10"); + TEST_UNSUPPORTED(__inst_thumb32(0xfb08a70d) " @ mla r7, r8, sp, r10"); + TEST_UNSUPPORTED(__inst_thumb32(0xfb08d709) " @ 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(__inst_thumb32(0xfb00f010) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_thumb32(0xfb0fff1f) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_thumb32(0xfb70f010) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_thumb32(0xfb7fff1f) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_thumb32(0xfb700010) "") /* Unallocated space */ + TEST_UNSUPPORTED(__inst_thumb32(0xfb7fff1f) "") /* 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(__inst_thumb32(0xfb89f80a) " @ smull pc, r8, r9, r10"); + TEST_UNSUPPORTED(__inst_thumb32(0xfb89d80a) " @ smull sp, r8, r9, r10"); + TEST_UNSUPPORTED(__inst_thumb32(0xfb897f0a) " @ smull r7, pc, r9, r10"); + TEST_UNSUPPORTED(__inst_thumb32(0xfb897d0a) " @ smull r7, sp, r9, r10"); + TEST_UNSUPPORTED(__inst_thumb32(0xfb8f780a) " @ smull r7, r8, pc, r10"); + TEST_UNSUPPORTED(__inst_thumb32(0xfb8d780a) " @ smull r7, r8, sp, r10"); + TEST_UNSUPPORTED(__inst_thumb32(0xfb89780f) " @ smull r7, r8, r9, pc"); + TEST_UNSUPPORTED(__inst_thumb32(0xfb89780d) " @ 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(__inst_thumb32(0xfc000000) "") + TEST_UNSUPPORTED(__inst_thumb32(0xffffffff) "") + + TEST_GROUP("Testing instructions in IT blocks") + + TEST_ITBLOCK("sub.w r0, r0") + + verbose("\n"); +} + diff --git a/arch/arm/probes/uprobes/Makefile b/arch/arm/probes/uprobes/Makefile new file mode 100644 index 000000000000..e1dc3d0f6d5a --- /dev/null +++ b/arch/arm/probes/uprobes/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_UPROBES) += core.o actions-arm.o diff --git a/arch/arm/probes/uprobes/actions-arm.c b/arch/arm/probes/uprobes/actions-arm.c new file mode 100644 index 000000000000..1dd4916ba8aa --- /dev/null +++ b/arch/arm/probes/uprobes/actions-arm.c @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2012 Rabin Vincent + * + * 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 +#include +#include +#include +#include +#include + +#include "../decode.h" +#include "../decode-arm.h" +#include "core.h" + +static int uprobes_substitute_pc(unsigned long *pinsn, u32 oregs) +{ + probes_opcode_t insn = __mem_to_opcode_arm(*pinsn); + probes_opcode_t temp; + probes_opcode_t mask; + int freereg; + u32 free = 0xffff; + u32 regs; + + for (regs = oregs; regs; regs >>= 4, insn >>= 4) { + if ((regs & 0xf) == REG_TYPE_NONE) + continue; + + free &= ~(1 << (insn & 0xf)); + } + + /* No PC, no problem */ + if (free & (1 << 15)) + return 15; + + if (!free) + return -1; + + /* + * fls instead of ffs ensures that for "ldrd r0, r1, [pc]" we would + * pick LR instead of R1. + */ + freereg = free = fls(free) - 1; + + temp = __mem_to_opcode_arm(*pinsn); + insn = temp; + regs = oregs; + mask = 0xf; + + for (; regs; regs >>= 4, mask <<= 4, free <<= 4, temp >>= 4) { + if ((regs & 0xf) == REG_TYPE_NONE) + continue; + + if ((temp & 0xf) != 15) + continue; + + insn &= ~mask; + insn |= free & mask; + } + + *pinsn = __opcode_to_mem_arm(insn); + return freereg; +} + +static void uprobe_set_pc(struct arch_uprobe *auprobe, + struct arch_uprobe_task *autask, + struct pt_regs *regs) +{ + u32 pcreg = auprobe->pcreg; + + autask->backup = regs->uregs[pcreg]; + regs->uregs[pcreg] = regs->ARM_pc + 8; +} + +static void uprobe_unset_pc(struct arch_uprobe *auprobe, + struct arch_uprobe_task *autask, + struct pt_regs *regs) +{ + /* PC will be taken care of by common code */ + regs->uregs[auprobe->pcreg] = autask->backup; +} + +static void uprobe_aluwrite_pc(struct arch_uprobe *auprobe, + struct arch_uprobe_task *autask, + struct pt_regs *regs) +{ + u32 pcreg = auprobe->pcreg; + + alu_write_pc(regs->uregs[pcreg], regs); + regs->uregs[pcreg] = autask->backup; +} + +static void uprobe_write_pc(struct arch_uprobe *auprobe, + struct arch_uprobe_task *autask, + struct pt_regs *regs) +{ + u32 pcreg = auprobe->pcreg; + + load_write_pc(regs->uregs[pcreg], regs); + regs->uregs[pcreg] = autask->backup; +} + +enum probes_insn +decode_pc_ro(probes_opcode_t insn, struct arch_probes_insn *asi, + const struct decode_header *d) +{ + struct arch_uprobe *auprobe = container_of(asi, struct arch_uprobe, + asi); + struct decode_emulate *decode = (struct decode_emulate *) d; + u32 regs = decode->header.type_regs.bits >> DECODE_TYPE_BITS; + int reg; + + reg = uprobes_substitute_pc(&auprobe->ixol[0], regs); + if (reg == 15) + return INSN_GOOD; + + if (reg == -1) + return INSN_REJECTED; + + auprobe->pcreg = reg; + auprobe->prehandler = uprobe_set_pc; + auprobe->posthandler = uprobe_unset_pc; + + return INSN_GOOD; +} + +enum probes_insn +decode_wb_pc(probes_opcode_t insn, struct arch_probes_insn *asi, + const struct decode_header *d, bool alu) +{ + struct arch_uprobe *auprobe = container_of(asi, struct arch_uprobe, + asi); + enum probes_insn ret = decode_pc_ro(insn, asi, d); + + if (((insn >> 12) & 0xf) == 15) + auprobe->posthandler = alu ? uprobe_aluwrite_pc + : uprobe_write_pc; + + return ret; +} + +enum probes_insn +decode_rd12rn16rm0rs8_rwflags(probes_opcode_t insn, + struct arch_probes_insn *asi, + const struct decode_header *d) +{ + return decode_wb_pc(insn, asi, d, true); +} + +enum probes_insn +decode_ldr(probes_opcode_t insn, struct arch_probes_insn *asi, + const struct decode_header *d) +{ + return decode_wb_pc(insn, asi, d, false); +} + +enum probes_insn +uprobe_decode_ldmstm(probes_opcode_t insn, + struct arch_probes_insn *asi, + const struct decode_header *d) +{ + struct arch_uprobe *auprobe = container_of(asi, struct arch_uprobe, + asi); + unsigned reglist = insn & 0xffff; + int rn = (insn >> 16) & 0xf; + int lbit = insn & (1 << 20); + unsigned used = reglist | (1 << rn); + + if (rn == 15) + return INSN_REJECTED; + + if (!(used & (1 << 15))) + return INSN_GOOD; + + if (used & (1 << 14)) + return INSN_REJECTED; + + /* Use LR instead of PC */ + insn ^= 0xc000; + + auprobe->pcreg = 14; + auprobe->ixol[0] = __opcode_to_mem_arm(insn); + + auprobe->prehandler = uprobe_set_pc; + if (lbit) + auprobe->posthandler = uprobe_write_pc; + else + auprobe->posthandler = uprobe_unset_pc; + + return INSN_GOOD; +} + +const union decode_action uprobes_probes_actions[] = { + [PROBES_EMULATE_NONE] = {.handler = probes_simulate_nop}, + [PROBES_SIMULATE_NOP] = {.handler = probes_simulate_nop}, + [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop}, + [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop}, + [PROBES_BRANCH_IMM] = {.handler = simulate_blx1}, + [PROBES_MRS] = {.handler = simulate_mrs}, + [PROBES_BRANCH_REG] = {.handler = simulate_blx2bx}, + [PROBES_CLZ] = {.handler = probes_simulate_nop}, + [PROBES_SATURATING_ARITHMETIC] = {.handler = probes_simulate_nop}, + [PROBES_MUL1] = {.handler = probes_simulate_nop}, + [PROBES_MUL2] = {.handler = probes_simulate_nop}, + [PROBES_SWP] = {.handler = probes_simulate_nop}, + [PROBES_LDRSTRD] = {.decoder = decode_pc_ro}, + [PROBES_LOAD_EXTRA] = {.decoder = decode_pc_ro}, + [PROBES_LOAD] = {.decoder = decode_ldr}, + [PROBES_STORE_EXTRA] = {.decoder = decode_pc_ro}, + [PROBES_STORE] = {.decoder = decode_pc_ro}, + [PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp}, + [PROBES_DATA_PROCESSING_REG] = { + .decoder = decode_rd12rn16rm0rs8_rwflags}, + [PROBES_DATA_PROCESSING_IMM] = { + .decoder = decode_rd12rn16rm0rs8_rwflags}, + [PROBES_MOV_HALFWORD] = {.handler = probes_simulate_nop}, + [PROBES_SEV] = {.handler = probes_simulate_nop}, + [PROBES_WFE] = {.handler = probes_simulate_nop}, + [PROBES_SATURATE] = {.handler = probes_simulate_nop}, + [PROBES_REV] = {.handler = probes_simulate_nop}, + [PROBES_MMI] = {.handler = probes_simulate_nop}, + [PROBES_PACK] = {.handler = probes_simulate_nop}, + [PROBES_EXTEND] = {.handler = probes_simulate_nop}, + [PROBES_EXTEND_ADD] = {.handler = probes_simulate_nop}, + [PROBES_MUL_ADD_LONG] = {.handler = probes_simulate_nop}, + [PROBES_MUL_ADD] = {.handler = probes_simulate_nop}, + [PROBES_BITFIELD] = {.handler = probes_simulate_nop}, + [PROBES_BRANCH] = {.handler = simulate_bbl}, + [PROBES_LDMSTM] = {.decoder = uprobe_decode_ldmstm} +}; diff --git a/arch/arm/probes/uprobes/core.c b/arch/arm/probes/uprobes/core.c new file mode 100644 index 000000000000..b2954f6d3abe --- /dev/null +++ b/arch/arm/probes/uprobes/core.c @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2012 Rabin Vincent + * + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "../decode.h" +#include "../decode-arm.h" +#include "core.h" + +#define UPROBE_TRAP_NR UINT_MAX + +bool is_swbp_insn(uprobe_opcode_t *insn) +{ + return (__mem_to_opcode_arm(*insn) & 0x0fffffff) == + (UPROBE_SWBP_ARM_INSN & 0x0fffffff); +} + +int set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, + unsigned long vaddr) +{ + return uprobe_write_opcode(mm, vaddr, + __opcode_to_mem_arm(auprobe->bpinsn)); +} + +bool arch_uprobe_ignore(struct arch_uprobe *auprobe, struct pt_regs *regs) +{ + if (!auprobe->asi.insn_check_cc(regs->ARM_cpsr)) { + regs->ARM_pc += 4; + return true; + } + + return false; +} + +bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) +{ + probes_opcode_t opcode; + + if (!auprobe->simulate) + return false; + + opcode = __mem_to_opcode_arm(*(unsigned int *) auprobe->insn); + + auprobe->asi.insn_singlestep(opcode, &auprobe->asi, regs); + + return true; +} + +unsigned long +arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, + struct pt_regs *regs) +{ + unsigned long orig_ret_vaddr; + + orig_ret_vaddr = regs->ARM_lr; + /* Replace the return addr with trampoline addr */ + regs->ARM_lr = trampoline_vaddr; + return orig_ret_vaddr; +} + +int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, + unsigned long addr) +{ + unsigned int insn; + unsigned int bpinsn; + enum probes_insn ret; + + /* Thumb not yet support */ + if (addr & 0x3) + return -EINVAL; + + insn = __mem_to_opcode_arm(*(unsigned int *)auprobe->insn); + auprobe->ixol[0] = __opcode_to_mem_arm(insn); + auprobe->ixol[1] = __opcode_to_mem_arm(UPROBE_SS_ARM_INSN); + + ret = arm_probes_decode_insn(insn, &auprobe->asi, false, + uprobes_probes_actions); + switch (ret) { + case INSN_REJECTED: + return -EINVAL; + + case INSN_GOOD_NO_SLOT: + auprobe->simulate = true; + break; + + case INSN_GOOD: + default: + break; + } + + bpinsn = UPROBE_SWBP_ARM_INSN & 0x0fffffff; + if (insn >= 0xe0000000) + bpinsn |= 0xe0000000; /* Unconditional instruction */ + else + bpinsn |= insn & 0xf0000000; /* Copy condition from insn */ + + auprobe->bpinsn = bpinsn; + + return 0; +} + +void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr, + void *src, unsigned long len) +{ + void *xol_page_kaddr = kmap_atomic(page); + void *dst = xol_page_kaddr + (vaddr & ~PAGE_MASK); + + preempt_disable(); + + /* Initialize the slot */ + memcpy(dst, src, len); + + /* flush caches (dcache/icache) */ + flush_uprobe_xol_access(page, vaddr, dst, len); + + preempt_enable(); + + kunmap_atomic(xol_page_kaddr); +} + + +int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) +{ + struct uprobe_task *utask = current->utask; + + if (auprobe->prehandler) + auprobe->prehandler(auprobe, &utask->autask, regs); + + utask->autask.saved_trap_no = current->thread.trap_no; + current->thread.trap_no = UPROBE_TRAP_NR; + regs->ARM_pc = utask->xol_vaddr; + + return 0; +} + +int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) +{ + struct uprobe_task *utask = current->utask; + + WARN_ON_ONCE(current->thread.trap_no != UPROBE_TRAP_NR); + + current->thread.trap_no = utask->autask.saved_trap_no; + regs->ARM_pc = utask->vaddr + 4; + + if (auprobe->posthandler) + auprobe->posthandler(auprobe, &utask->autask, regs); + + return 0; +} + +bool arch_uprobe_xol_was_trapped(struct task_struct *t) +{ + if (t->thread.trap_no != UPROBE_TRAP_NR) + return true; + + return false; +} + +void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) +{ + struct uprobe_task *utask = current->utask; + + current->thread.trap_no = utask->autask.saved_trap_no; + instruction_pointer_set(regs, utask->vaddr); +} + +int arch_uprobe_exception_notify(struct notifier_block *self, + unsigned long val, void *data) +{ + return NOTIFY_DONE; +} + +static int uprobe_trap_handler(struct pt_regs *regs, unsigned int instr) +{ + unsigned long flags; + + local_irq_save(flags); + instr &= 0x0fffffff; + if (instr == (UPROBE_SWBP_ARM_INSN & 0x0fffffff)) + uprobe_pre_sstep_notifier(regs); + else if (instr == (UPROBE_SS_ARM_INSN & 0x0fffffff)) + uprobe_post_sstep_notifier(regs); + local_irq_restore(flags); + + return 0; +} + +unsigned long uprobe_get_swbp_addr(struct pt_regs *regs) +{ + return instruction_pointer(regs); +} + +static struct undef_hook uprobes_arm_break_hook = { + .instr_mask = 0x0fffffff, + .instr_val = (UPROBE_SWBP_ARM_INSN & 0x0fffffff), + .cpsr_mask = MODE_MASK, + .cpsr_val = USR_MODE, + .fn = uprobe_trap_handler, +}; + +static struct undef_hook uprobes_arm_ss_hook = { + .instr_mask = 0x0fffffff, + .instr_val = (UPROBE_SS_ARM_INSN & 0x0fffffff), + .cpsr_mask = MODE_MASK, + .cpsr_val = USR_MODE, + .fn = uprobe_trap_handler, +}; + +static int arch_uprobes_init(void) +{ + register_undef_hook(&uprobes_arm_break_hook); + register_undef_hook(&uprobes_arm_ss_hook); + + return 0; +} +device_initcall(arch_uprobes_init); diff --git a/arch/arm/probes/uprobes/core.h b/arch/arm/probes/uprobes/core.h new file mode 100644 index 000000000000..1d0c12dfbd03 --- /dev/null +++ b/arch/arm/probes/uprobes/core.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2012 Rabin Vincent + * + * 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. + */ + +#ifndef __ARM_KERNEL_UPROBES_H +#define __ARM_KERNEL_UPROBES_H + +enum probes_insn uprobe_decode_ldmstm(probes_opcode_t insn, + struct arch_probes_insn *asi, + const struct decode_header *d); + +enum probes_insn decode_ldr(probes_opcode_t insn, + struct arch_probes_insn *asi, + const struct decode_header *d); + +enum probes_insn +decode_rd12rn16rm0rs8_rwflags(probes_opcode_t insn, + struct arch_probes_insn *asi, + const struct decode_header *d); + +enum probes_insn +decode_wb_pc(probes_opcode_t insn, struct arch_probes_insn *asi, + const struct decode_header *d, bool alu); + +enum probes_insn +decode_pc_ro(probes_opcode_t insn, struct arch_probes_insn *asi, + const struct decode_header *d); + +extern const union decode_action uprobes_probes_actions[]; + +#endif -- cgit v1.2.3 From 832607e79d7423c67ef8a3de8dfa3d25b5b0bf86 Mon Sep 17 00:00:00 2001 From: Jon Medhurst Date: Wed, 7 Jan 2015 11:42:30 +0000 Subject: ARM: probes: Use correct action types for MOVW, SEV and WFI This doesn't correct any bugs when probing these instructions but makes MOVW slightly faster and makes everything more symmetric with the Thumb instruction cases. We can also remove the now redundant PROBES_EMULATE_NONE and PROBES_SIMULATE_NOP actions. Signed-off-by: Jon Medhurst --- arch/arm/probes/decode-arm.c | 6 +++--- arch/arm/probes/decode-arm.h | 2 -- arch/arm/probes/kprobes/actions-arm.c | 2 -- arch/arm/probes/uprobes/actions-arm.c | 2 -- 4 files changed, 3 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/arm/probes/decode-arm.c b/arch/arm/probes/decode-arm.c index e39cc75952f2..04114f74a2d2 100644 --- a/arch/arm/probes/decode-arm.c +++ b/arch/arm/probes/decode-arm.c @@ -370,17 +370,17 @@ static const union decode_item arm_cccc_001x_table[] = { /* MOVW cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */ /* MOVT cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */ - DECODE_EMULATEX (0x0fb00000, 0x03000000, PROBES_DATA_PROCESSING_IMM, + DECODE_EMULATEX (0x0fb00000, 0x03000000, PROBES_MOV_HALFWORD, 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, PROBES_EMULATE_NONE), + DECODE_EMULATE (0x0fff00ff, 0x03200004, PROBES_SEV), /* 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, PROBES_SIMULATE_NOP), + DECODE_SIMULATE (0x0fff00fc, 0x03200000, PROBES_WFE), /* 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 */ diff --git a/arch/arm/probes/decode-arm.h b/arch/arm/probes/decode-arm.h index 9c56b40d6a57..cb0b26331930 100644 --- a/arch/arm/probes/decode-arm.h +++ b/arch/arm/probes/decode-arm.h @@ -18,8 +18,6 @@ #include "decode.h" enum probes_arm_action { - PROBES_EMULATE_NONE, - PROBES_SIMULATE_NOP, PROBES_PRELOAD_IMM, PROBES_PRELOAD_REG, PROBES_BRANCH_IMM, diff --git a/arch/arm/probes/kprobes/actions-arm.c b/arch/arm/probes/kprobes/actions-arm.c index 8797879f7b3a..2206f2d80c76 100644 --- a/arch/arm/probes/kprobes/actions-arm.c +++ b/arch/arm/probes/kprobes/actions-arm.c @@ -302,8 +302,6 @@ emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(probes_opcode_t insn, } const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = { - [PROBES_EMULATE_NONE] = {.handler = probes_emulate_none}, - [PROBES_SIMULATE_NOP] = {.handler = probes_simulate_nop}, [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop}, [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop}, [PROBES_BRANCH_IMM] = {.handler = simulate_blx1}, diff --git a/arch/arm/probes/uprobes/actions-arm.c b/arch/arm/probes/uprobes/actions-arm.c index 1dd4916ba8aa..76eb44972ebe 100644 --- a/arch/arm/probes/uprobes/actions-arm.c +++ b/arch/arm/probes/uprobes/actions-arm.c @@ -195,8 +195,6 @@ uprobe_decode_ldmstm(probes_opcode_t insn, } const union decode_action uprobes_probes_actions[] = { - [PROBES_EMULATE_NONE] = {.handler = probes_simulate_nop}, - [PROBES_SIMULATE_NOP] = {.handler = probes_simulate_nop}, [PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop}, [PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop}, [PROBES_BRANCH_IMM] = {.handler = simulate_blx1}, -- cgit v1.2.3 From 83803d97dae1eaf6850a45ef8ee179cc66e147dc Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Mon, 5 Jan 2015 19:29:18 +0800 Subject: ARM: kprobes: introduces checker This patch introdces 'checker' to decoding phase, and calls checkers when instruction decoding. This allows further decoding for specific instructions. This patch introduces a stub call of checkers in kprobe arch_prepare_kprobe() as an example and for further expansion. Signed-off-by: Wang Nan Reviewed-by: Jon Medhurst Reviewed-by: Masami Hiramatsu Signed-off-by: Jon Medhurst --- arch/arm/probes/decode-arm.c | 5 +-- arch/arm/probes/decode-arm.h | 3 +- arch/arm/probes/decode-thumb.c | 10 +++--- arch/arm/probes/decode-thumb.h | 6 ++-- arch/arm/probes/decode.c | 60 +++++++++++++++++++++++++++++---- arch/arm/probes/decode.h | 11 +++++- arch/arm/probes/kprobes/actions-arm.c | 2 ++ arch/arm/probes/kprobes/actions-thumb.c | 3 ++ arch/arm/probes/kprobes/core.c | 6 +++- arch/arm/probes/kprobes/core.h | 7 ++-- arch/arm/probes/uprobes/core.c | 2 +- 11 files changed, 95 insertions(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/arm/probes/decode-arm.c b/arch/arm/probes/decode-arm.c index 04114f74a2d2..f72c33a2dcfb 100644 --- a/arch/arm/probes/decode-arm.c +++ b/arch/arm/probes/decode-arm.c @@ -726,10 +726,11 @@ static void __kprobes arm_singlestep(probes_opcode_t insn, */ enum probes_insn __kprobes arm_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, - bool emulate, const union decode_action *actions) + bool emulate, const union decode_action *actions, + const struct decode_checker *checkers[]) { asi->insn_singlestep = arm_singlestep; asi->insn_check_cc = probes_condition_checks[insn>>28]; return probes_decode_insn(insn, asi, probes_decode_arm_table, false, - emulate, actions); + emulate, actions, checkers); } diff --git a/arch/arm/probes/decode-arm.h b/arch/arm/probes/decode-arm.h index cb0b26331930..b3b80f6d414b 100644 --- a/arch/arm/probes/decode-arm.h +++ b/arch/arm/probes/decode-arm.h @@ -68,6 +68,7 @@ extern const union decode_item probes_decode_arm_table[]; enum probes_insn arm_probes_decode_insn(probes_opcode_t, struct arch_probes_insn *, bool emulate, - const union decode_action *actions); + const union decode_action *actions, + const struct decode_checker *checkers[]); #endif diff --git a/arch/arm/probes/decode-thumb.c b/arch/arm/probes/decode-thumb.c index 2f0453a895dc..985e7dd4cac6 100644 --- a/arch/arm/probes/decode-thumb.c +++ b/arch/arm/probes/decode-thumb.c @@ -863,20 +863,22 @@ static void __kprobes thumb32_singlestep(probes_opcode_t opcode, enum probes_insn __kprobes thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, - bool emulate, const union decode_action *actions) + bool emulate, const union decode_action *actions, + const struct decode_checker *checkers[]) { asi->insn_singlestep = thumb16_singlestep; asi->insn_check_cc = thumb_check_cc; return probes_decode_insn(insn, asi, probes_decode_thumb16_table, true, - emulate, actions); + emulate, actions, checkers); } enum probes_insn __kprobes thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, - bool emulate, const union decode_action *actions) + bool emulate, const union decode_action *actions, + const struct decode_checker *checkers[]) { asi->insn_singlestep = thumb32_singlestep; asi->insn_check_cc = thumb_check_cc; return probes_decode_insn(insn, asi, probes_decode_thumb32_table, true, - emulate, actions); + emulate, actions, checkers); } diff --git a/arch/arm/probes/decode-thumb.h b/arch/arm/probes/decode-thumb.h index 039013c7131d..8457add0a2d8 100644 --- a/arch/arm/probes/decode-thumb.h +++ b/arch/arm/probes/decode-thumb.h @@ -91,9 +91,11 @@ extern const union decode_item probes_decode_thumb16_table[]; enum probes_insn __kprobes thumb16_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, - bool emulate, const union decode_action *actions); + bool emulate, const union decode_action *actions, + const struct decode_checker *checkers[]); enum probes_insn __kprobes thumb32_probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, - bool emulate, const union decode_action *actions); + bool emulate, const union decode_action *actions, + const struct decode_checker *checkers[]); #endif diff --git a/arch/arm/probes/decode.c b/arch/arm/probes/decode.c index 3b05d5742359..c7d442018902 100644 --- a/arch/arm/probes/decode.c +++ b/arch/arm/probes/decode.c @@ -342,6 +342,31 @@ static const int decode_struct_sizes[NUM_DECODE_TYPES] = { [DECODE_TYPE_REJECT] = sizeof(struct decode_reject) }; +static int run_checkers(const struct decode_checker *checkers[], + int action, probes_opcode_t insn, + struct arch_probes_insn *asi, + const struct decode_header *h) +{ + const struct decode_checker **p; + + if (!checkers) + return INSN_GOOD; + + p = checkers; + while (*p != NULL) { + int retval; + probes_check_t *checker_func = (*p)[action].checker; + + retval = INSN_GOOD; + if (checker_func) + retval = checker_func(insn, asi, h); + if (retval == INSN_REJECTED) + return retval; + p++; + } + return INSN_GOOD; +} + /* * probes_decode_insn operates on data tables in order to decode an ARM * architecture instruction onto which a kprobe has been placed. @@ -388,11 +413,17 @@ static const int decode_struct_sizes[NUM_DECODE_TYPES] = { int __kprobes probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, const union decode_item *table, bool thumb, - bool emulate, const union decode_action *actions) + bool emulate, const union decode_action *actions, + const struct decode_checker *checkers[]) { const struct decode_header *h = (struct decode_header *)table; const struct decode_header *next; bool matched = false; + /* + * @insn can be modified by decode_regs. Save its original + * value for checkers. + */ + probes_opcode_t origin_insn = insn; if (emulate) insn = prepare_emulated_insn(insn, asi, thumb); @@ -422,24 +453,41 @@ probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, } case DECODE_TYPE_CUSTOM: { + int err; struct decode_custom *d = (struct decode_custom *)h; - return actions[d->decoder.action].decoder(insn, asi, h); + int action = d->decoder.action; + + err = run_checkers(checkers, action, origin_insn, asi, h); + if (err == INSN_REJECTED) + return INSN_REJECTED; + return actions[action].decoder(insn, asi, h); } case DECODE_TYPE_SIMULATE: { + int err; struct decode_simulate *d = (struct decode_simulate *)h; - asi->insn_handler = actions[d->handler.action].handler; + int action = d->handler.action; + + err = run_checkers(checkers, action, origin_insn, asi, h); + if (err == INSN_REJECTED) + return INSN_REJECTED; + asi->insn_handler = actions[action].handler; return INSN_GOOD_NO_SLOT; } case DECODE_TYPE_EMULATE: { + int err; struct decode_emulate *d = (struct decode_emulate *)h; + int action = d->handler.action; + + err = run_checkers(checkers, action, origin_insn, asi, h); + if (err == INSN_REJECTED) + return INSN_REJECTED; if (!emulate) - return actions[d->handler.action].decoder(insn, - asi, h); + return actions[action].decoder(insn, asi, h); - asi->insn_handler = actions[d->handler.action].handler; + asi->insn_handler = actions[action].handler; set_emulated_insn(insn, asi, thumb); return INSN_GOOD; } diff --git a/arch/arm/probes/decode.h b/arch/arm/probes/decode.h index 1d0b53169080..f9b08ba7fe73 100644 --- a/arch/arm/probes/decode.h +++ b/arch/arm/probes/decode.h @@ -314,6 +314,14 @@ union decode_action { probes_custom_decode_t *decoder; }; +typedef enum probes_insn (probes_check_t)(probes_opcode_t, + struct arch_probes_insn *, + const struct decode_header *); + +struct decode_checker { + probes_check_t *checker; +}; + #define DECODE_END \ {.bits = DECODE_TYPE_END} @@ -402,6 +410,7 @@ probes_insn_handler_t probes_emulate_none; int __kprobes probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, const union decode_item *table, bool thumb, bool emulate, - const union decode_action *actions); + const union decode_action *actions, + const struct decode_checker **checkers); #endif diff --git a/arch/arm/probes/kprobes/actions-arm.c b/arch/arm/probes/kprobes/actions-arm.c index 2206f2d80c76..fbd93a9ada75 100644 --- a/arch/arm/probes/kprobes/actions-arm.c +++ b/arch/arm/probes/kprobes/actions-arm.c @@ -339,3 +339,5 @@ const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = { [PROBES_BRANCH] = {.handler = simulate_bbl}, [PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm} }; + +const struct decode_checker *kprobes_arm_checkers[] = {NULL}; diff --git a/arch/arm/probes/kprobes/actions-thumb.c b/arch/arm/probes/kprobes/actions-thumb.c index 6c4e60b62826..2796121fe90e 100644 --- a/arch/arm/probes/kprobes/actions-thumb.c +++ b/arch/arm/probes/kprobes/actions-thumb.c @@ -664,3 +664,6 @@ const union decode_action kprobes_t32_actions[NUM_PROBES_T32_ACTIONS] = { [PROBES_T32_MUL_ADD_LONG] = { .handler = t32_emulate_rdlo12rdhi8rn16rm0_noflags}, }; + +const struct decode_checker *kprobes_t32_checkers[] = {NULL}; +const struct decode_checker *kprobes_t16_checkers[] = {NULL}; diff --git a/arch/arm/probes/kprobes/core.c b/arch/arm/probes/kprobes/core.c index 701f49d74c35..74f3dc3ac212 100644 --- a/arch/arm/probes/kprobes/core.c +++ b/arch/arm/probes/kprobes/core.c @@ -61,6 +61,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) kprobe_decode_insn_t *decode_insn; const union decode_action *actions; int is; + const struct decode_checker **checkers; if (in_exception_text(addr)) return -EINVAL; @@ -74,9 +75,11 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) insn = __opcode_thumb32_compose(insn, inst2); decode_insn = thumb32_probes_decode_insn; actions = kprobes_t32_actions; + checkers = kprobes_t32_checkers; } else { decode_insn = thumb16_probes_decode_insn; actions = kprobes_t16_actions; + checkers = kprobes_t16_checkers; } #else /* !CONFIG_THUMB2_KERNEL */ thumb = false; @@ -85,12 +88,13 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) insn = __mem_to_opcode_arm(*p->addr); decode_insn = arm_probes_decode_insn; actions = kprobes_arm_actions; + checkers = kprobes_arm_checkers; #endif p->opcode = insn; p->ainsn.insn = tmp_insn; - switch ((*decode_insn)(insn, &p->ainsn, true, actions)) { + switch ((*decode_insn)(insn, &p->ainsn, true, actions, checkers)) { case INSN_REJECTED: /* not supported */ return -EINVAL; diff --git a/arch/arm/probes/kprobes/core.h b/arch/arm/probes/kprobes/core.h index 2e1e5a3d9155..f88c79fe632a 100644 --- a/arch/arm/probes/kprobes/core.h +++ b/arch/arm/probes/kprobes/core.h @@ -37,16 +37,19 @@ kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_probes_insn *asi, typedef enum probes_insn (kprobe_decode_insn_t)(probes_opcode_t, struct arch_probes_insn *, bool, - const union decode_action *); + const union decode_action *, + const struct decode_checker *[*]); #ifdef CONFIG_THUMB2_KERNEL extern const union decode_action kprobes_t32_actions[]; extern const union decode_action kprobes_t16_actions[]; - +extern const struct decode_checker *kprobes_t32_checkers[]; +extern const struct decode_checker *kprobes_t16_checkers[]; #else /* !CONFIG_THUMB2_KERNEL */ extern const union decode_action kprobes_arm_actions[]; +extern const struct decode_checker *kprobes_arm_checkers[]; #endif diff --git a/arch/arm/probes/uprobes/core.c b/arch/arm/probes/uprobes/core.c index b2954f6d3abe..d1329f1ba4e4 100644 --- a/arch/arm/probes/uprobes/core.c +++ b/arch/arm/probes/uprobes/core.c @@ -88,7 +88,7 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, auprobe->ixol[1] = __opcode_to_mem_arm(UPROBE_SS_ARM_INSN); ret = arm_probes_decode_insn(insn, &auprobe->asi, false, - uprobes_probes_actions); + uprobes_probes_actions, NULL); switch (ret) { case INSN_REJECTED: return -EINVAL; -- cgit v1.2.3 From b9dfe0bed999d23ee8838d389637dd8aef83fafa Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Fri, 9 Jan 2015 10:53:21 +0100 Subject: livepatch: handle ancient compilers with more grace We are aborting a build in case when gcc doesn't support fentry on x86_64 (regs->ip modification can't really reliably work with mcount). This however breaks allmodconfig for people with older gccs that don't support -mfentry. Turn the build-time failure into runtime failure, resulting in the whole infrastructure not being initialized if CC_USING_FENTRY is unset. Reported-by: Andrew Morton Signed-off-by: Jiri Kosina Signed-off-by: Andrew Morton Acked-by: Josh Poimboeuf --- arch/x86/include/asm/livepatch.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/include/asm/livepatch.h b/arch/x86/include/asm/livepatch.h index b5608d7757fd..26e58134c8cb 100644 --- a/arch/x86/include/asm/livepatch.h +++ b/arch/x86/include/asm/livepatch.h @@ -25,9 +25,13 @@ #include #ifdef CONFIG_LIVE_PATCHING +static inline int klp_check_compiler_support(void) +{ #ifndef CC_USING_FENTRY -#error Your compiler must support -mfentry for live patching to work + return 1; #endif + return 0; +} extern int klp_write_module_reloc(struct module *mod, unsigned long type, unsigned long loc, unsigned long value); -- cgit v1.2.3 From 2cda1880f8c6b6a081ab78824d3742a229887b69 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 8 Jan 2015 13:24:33 +0100 Subject: ARM: tegra: Fix unit address for Cortex-A9 TWD timer The Cortex-A9 TWD timer has registers at address 0x50040600, but the unit address was 50004600, most likely a typo. Signed-off-by: Thierry Reding --- arch/arm/boot/dts/tegra20.dtsi | 2 +- arch/arm/boot/dts/tegra30.dtsi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index f76fe94267d6..e5527f742696 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi @@ -140,7 +140,7 @@ }; }; - timer@50004600 { + timer@50040600 { compatible = "arm,cortex-a9-twd-timer"; reg = <0x50040600 0x20>; interrupts = ; interrupts = Date: Wed, 7 Jan 2015 16:04:00 +0100 Subject: ARM: multi_v7_defconfig: Enable stih407 usb picophy This patch enables the picoPHY usb phy which is used by the usb2 and usb3 host controllers when controlling usb2/1.1 devices. It is found in stih407 family SoC's from STMicroelectronics. Signed-off-by: Peter Griffin Acked-by: Lee Jones Reviewed-by: Arnd Bergmann Signed-off-by: Maxime Coquelin --- arch/arm/configs/multi_v7_defconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index 2328fe752e9c..3e85a86c8d51 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -455,6 +455,7 @@ CONFIG_OMAP_USB2=y CONFIG_TI_PIPE3=y CONFIG_PHY_MIPHY365X=y CONFIG_PHY_STIH41X_USB=y +CONFIG_PHY_STIH407_USB=y CONFIG_PHY_SUN4I_USB=y CONFIG_EXT4_FS=y CONFIG_AUTOFS4_FS=y -- cgit v1.2.3 From 62981239a61bfd5306737effc015deba26c0d198 Mon Sep 17 00:00:00 2001 From: Arnaud Ebalard Date: Tue, 16 Dec 2014 22:21:16 +0100 Subject: ARM: tegra: Update isl29028 compatible string to use isil vendor prefix "isil" and "isl" prefixes are used at various locations inside the kernel to reference Intersil corporation. This patch is part of a series fixing those locations were "isl" is used in compatible strings to use the now expected "isil" prefix instead (NASDAQ symbol for Intersil and most used version). Note: isl29028 is an I2C device so the patch does not in fact currently depend on the introduction of "isil"-based compatible string in isl29028 driver because I2C core does not check the prefix yet. Signed-off-by: Arnaud Ebalard Signed-off-by: Thierry Reding --- arch/arm/boot/dts/tegra30-cardhu.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi index cbf5a1ae0ca7..a1b682ea01bd 100644 --- a/arch/arm/boot/dts/tegra30-cardhu.dtsi +++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi @@ -189,7 +189,7 @@ /* ALS and Proximity sensor */ isl29028@44 { - compatible = "isl,isl29028"; + compatible = "isil,isl29028"; reg = <0x44>; interrupt-parent = <&gpio>; interrupts = ; -- cgit v1.2.3 From 8facce138f0105727f3f6d4c4e1ce5570a54a556 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Wed, 7 Jan 2015 16:04:00 +0100 Subject: ARM: STi: DT: STiH407: Add usb2 picophy dt nodes This patch adds the dt nodes for the usb2 picophy found on the stih407 device family. It is used on stih407 by the dwc3 usb3 controller when controlling usb2/1.1 devices. Signed-off-by: Peter Griffin Reviewed-by: Arnd Bergmann Signed-off-by: Maxime Coquelin --- arch/arm/boot/dts/stih407-family.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi index 3e31d32133b8..d4a8f843cdc8 100644 --- a/arch/arm/boot/dts/stih407-family.dtsi +++ b/arch/arm/boot/dts/stih407-family.dtsi @@ -274,5 +274,14 @@ status = "disabled"; }; + + usb2_picophy0: phy1 { + compatible = "st,stih407-usb2-phy"; + #phy-cells = <0>; + st,syscfg = <&syscfg_core 0x100 0xf4>; + resets = <&softreset STIH407_PICOPHY_SOFTRESET>, + <&picophyreset STIH407_PICOPHY0_RESET>; + reset-names = "global", "port"; + }; }; }; -- cgit v1.2.3 From 9d9f65fcf5455fa2737486466498c7321372d966 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Wed, 7 Jan 2015 16:04:00 +0100 Subject: ARM: STi: DT: STiH410: Add usb2 picophy dt nodes This patch adds the dt nodes for the extra usb2 picophys found on the stih410. These two picophys are used in conjunction with the extra ehci/ohci usb controllers also found on the stih410 SoC. Signed-off-by: Peter Griffin Reviewed-by: Arnd Bergmann Signed-off-by: Maxime Coquelin --- arch/arm/boot/dts/stih410.dtsi | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/stih410.dtsi b/arch/arm/boot/dts/stih410.dtsi index c05627eb717d..2e5e9ed8b615 100644 --- a/arch/arm/boot/dts/stih410.dtsi +++ b/arch/arm/boot/dts/stih410.dtsi @@ -10,5 +10,23 @@ #include "stih407-family.dtsi" #include "stih410-pinctrl.dtsi" / { + soc { + usb2_picophy1: phy2 { + compatible = "st,stih407-usb2-phy"; + #phy-cells = <0>; + st,syscfg = <&syscfg_core 0xf8 0xf4>; + resets = <&softreset STIH407_PICOPHY_SOFTRESET>, + <&picophyreset STIH407_PICOPHY0_RESET>; + reset-names = "global", "port"; + }; + usb2_picophy2: phy3 { + compatible = "st,stih407-usb2-phy"; + #phy-cells = <0>; + st,syscfg = <&syscfg_core 0xfc 0xf4>; + resets = <&softreset STIH407_PICOPHY_SOFTRESET>, + <&picophyreset STIH407_PICOPHY1_RESET>; + reset-names = "global", "port"; + }; + }; }; -- cgit v1.2.3 From a59a4d969a7a74532cc0d4b3b44a962c3a199036 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Wed, 7 Jan 2015 16:04:00 +0100 Subject: ARM: STi: DT: STiH410: Add DT nodes for the ehci and ohci usb controllers. This patch adds the DT nodes for the extra ehci and ohci usb controllers on the stih410 SoC. Signed-off-by: Peter Griffin Reviewed-by: Arnd Bergmann Signed-off-by: Maxime Coquelin --- arch/arm/boot/dts/stih410.dtsi | 52 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/stih410.dtsi b/arch/arm/boot/dts/stih410.dtsi index 2e5e9ed8b615..37995f4739d2 100644 --- a/arch/arm/boot/dts/stih410.dtsi +++ b/arch/arm/boot/dts/stih410.dtsi @@ -28,5 +28,57 @@ <&picophyreset STIH407_PICOPHY1_RESET>; reset-names = "global", "port"; }; + + ohci0: usb@9a03c00 { + compatible = "st,st-ohci-300x"; + reg = <0x9a03c00 0x100>; + interrupts = ; + clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>; + resets = <&powerdown STIH407_USB2_PORT0_POWERDOWN>, + <&softreset STIH407_USB2_PORT0_SOFTRESET>; + reset-names = "power", "softreset"; + phys = <&usb2_picophy1>; + phy-names = "usb"; + }; + + ehci0: usb@9a03e00 { + compatible = "st,st-ehci-300x"; + reg = <0x9a03e00 0x100>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb0>; + clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>; + resets = <&powerdown STIH407_USB2_PORT0_POWERDOWN>, + <&softreset STIH407_USB2_PORT0_SOFTRESET>; + reset-names = "power", "softreset"; + phys = <&usb2_picophy1>; + phy-names = "usb"; + }; + + ohci1: usb@9a83c00 { + compatible = "st,st-ohci-300x"; + reg = <0x9a83c00 0x100>; + interrupts = ; + clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>; + resets = <&powerdown STIH407_USB2_PORT1_POWERDOWN>, + <&softreset STIH407_USB2_PORT1_SOFTRESET>; + reset-names = "power", "softreset"; + phys = <&usb2_picophy2>; + phy-names = "usb"; + }; + + ehci1: usb@9a83e00 { + compatible = "st,st-ehci-300x"; + reg = <0x9a83e00 0x100>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb1>; + clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>; + resets = <&powerdown STIH407_USB2_PORT1_POWERDOWN>, + <&softreset STIH407_USB2_PORT1_SOFTRESET>; + reset-names = "power", "softreset"; + phys = <&usb2_picophy2>; + phy-names = "usb"; + }; }; }; -- cgit v1.2.3 From 910978e753d0be0b429cf75b5adaed55b90c96b2 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 7 Jul 2014 15:26:30 +0200 Subject: clocksource: Build Tegra timer on 32-bit ARM only Instead of directly using the ARCH_TEGRA Kconfig symbol to enable this driver, add a new, non-user-visible Kconfig symbol (TEGRA_TIMER) which can be selected by the various SoCs. This is useful to disable building the driver on Tegra132 (64-bit ARM) where it doesn't currently compile but also isn't needed (yet). Acked-by: Daniel Lezcano Signed-off-by: Thierry Reding --- arch/arm/mach-tegra/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index d0be9a1ef6b8..5d1a318f1302 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -27,6 +27,7 @@ config ARCH_TEGRA_2x_SOC select PINCTRL_TEGRA20 select PL310_ERRATA_727915 if CACHE_L2X0 select PL310_ERRATA_769419 if CACHE_L2X0 + select TEGRA_TIMER help Support for NVIDIA Tegra AP20 and T20 processors, based on the ARM CortexA9MP CPU and the ARM PL310 L2 cache controller @@ -37,6 +38,7 @@ config ARCH_TEGRA_3x_SOC select ARM_ERRATA_764369 if SMP select PINCTRL_TEGRA30 select PL310_ERRATA_769419 if CACHE_L2X0 + select TEGRA_TIMER help Support for NVIDIA Tegra T30 processor family, based on the ARM CortexA9MP CPU and the ARM PL310 L2 cache controller @@ -47,6 +49,7 @@ config ARCH_TEGRA_114_SOC select ARM_L1_CACHE_SHIFT_6 select HAVE_ARM_ARCH_TIMER select PINCTRL_TEGRA114 + select TEGRA_TIMER help Support for NVIDIA Tegra T114 processor family, based on the ARM CortexA15MP CPU @@ -56,6 +59,7 @@ config ARCH_TEGRA_124_SOC select ARM_L1_CACHE_SHIFT_6 select HAVE_ARM_ARCH_TIMER select PINCTRL_TEGRA124 + select TEGRA_TIMER help Support for NVIDIA Tegra T124 processor family, based on the ARM CortexA15MP CPU -- cgit v1.2.3 From d91125ddf96237cee7b56448d7f318361c97c8b1 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 8 Jan 2015 18:38:03 +0100 Subject: ARM: mvebu: Rename DEBUG_LL to indicate UART index The mvebu SoCs actually have more UARTs than just the one exposed in DEBUG_LL yet. In order to differentiate them, Add the index in the configuration options and their help. Signed-off-by: Maxime Ripard Acked-by: Jason Cooper Acked-by: Gregory CLEMENT Signed-off-by: Gregory CLEMENT Signed-off-by: Andrew Lunn --- arch/arm/Kconfig.debug | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 5ddd4906f7a7..eb3991cf63ab 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -455,13 +455,13 @@ choice Please adjust DEBUG_UART_PHYS and DEBUG_UART_BASE configuration options based on your needs. - config DEBUG_MVEBU_UART - bool "Kernel low-level debugging messages via MVEBU UART (old bootloaders)" + config DEBUG_MVEBU_UART0 + bool "Kernel low-level debugging messages via MVEBU UART0 (old bootloaders)" depends on ARCH_MVEBU select DEBUG_UART_8250 help Say Y here if you want kernel low-level debugging support - on MVEBU based platforms. + on MVEBU based platforms on UART0. This option should be used with the old bootloaders that left the internal registers mapped at @@ -474,13 +474,13 @@ choice when u-boot hands over to the kernel, the system silently crashes, with no serial output at all. - config DEBUG_MVEBU_UART_ALTERNATE - bool "Kernel low-level debugging messages via MVEBU UART (new bootloaders)" + config DEBUG_MVEBU_UART0_ALTERNATE + bool "Kernel low-level debugging messages via MVEBU UART0 (new bootloaders)" depends on ARCH_MVEBU select DEBUG_UART_8250 help Say Y here if you want kernel low-level debugging support - on MVEBU based platforms. + on MVEBU based platforms on UART0. This option should be used with the new bootloaders that remap the internal registers at 0xf1000000. @@ -1282,7 +1282,7 @@ config DEBUG_UART_PHYS default 0xc8000000 if ARCH_IXP4XX && !CPU_BIG_ENDIAN default 0xc8000003 if ARCH_IXP4XX && CPU_BIG_ENDIAN default 0xd0000000 if ARCH_SPEAR3XX || ARCH_SPEAR6XX - default 0xd0012000 if DEBUG_MVEBU_UART + default 0xd0012000 if DEBUG_MVEBU_UART0 default 0xc81004c0 if DEBUG_MESON_UARTAO default 0xd4017000 if DEBUG_MMP_UART2 default 0xd4018000 if DEBUG_MMP_UART3 @@ -1296,7 +1296,7 @@ config DEBUG_UART_PHYS default 0xe8008000 if DEBUG_R7S72100_SCIF2 default 0xf0000be0 if ARCH_EBSA110 default 0xf040ab00 if DEBUG_BRCMSTB_UART - default 0xf1012000 if DEBUG_MVEBU_UART_ALTERNATE + default 0xf1012000 if DEBUG_MVEBU_UART0_ALTERNATE default 0xf1012000 if ARCH_DOVE || ARCH_MV78XX0 || \ ARCH_ORION5X default 0xf7fc9000 if DEBUG_BERLIN_UART @@ -1377,7 +1377,7 @@ config DEBUG_UART_VIRT default 0xfeb30c00 if DEBUG_KEYSTONE_UART0 default 0xfeb31000 if DEBUG_KEYSTONE_UART1 default 0xfec02000 if DEBUG_SOCFPGA_UART - default 0xfec12000 if DEBUG_MVEBU_UART || DEBUG_MVEBU_UART_ALTERNATE + default 0xfec12000 if DEBUG_MVEBU_UART0 || DEBUG_MVEBU_UART0_ALTERNATE default 0xfec20000 if DEBUG_DAVINCI_DMx_UART0 default 0xfec90000 if DEBUG_RK32_UART2 default 0xfed0c000 if DEBUG_DAVINCI_DA8XX_UART1 -- cgit v1.2.3 From bd920490047ae5fb0dbf1c2fdaabeaf664528966 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 8 Jan 2015 18:38:04 +0100 Subject: ARM: mvebu: Add UART1 as DEBUG_LL possible target Some mvebu boards have the UART1 more easily accessible than the other UARTs found on the system. Add a debug_ll option for this case. Signed-off-by: Maxime Ripard Acked-by: Jason Cooper Acked-by: Gregory CLEMENT Signed-off-by: Gregory CLEMENT Signed-off-by: Andrew Lunn --- arch/arm/Kconfig.debug | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'arch') diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index eb3991cf63ab..7bd1bbccc43c 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -489,6 +489,21 @@ choice when u-boot hands over to the kernel, the system silently crashes, with no serial output at all. + config DEBUG_MVEBU_UART1_ALTERNATE + bool "Kernel low-level debugging messages via MVEBU UART1 (new bootloaders)" + depends on ARCH_MVEBU + select DEBUG_UART_8250 + help + Say Y here if you want kernel low-level debugging support + on MVEBU based platforms on UART1. + + This option should be used with the new bootloaders + that remap the internal registers at 0xf1000000. + + If the wrong DEBUG_MVEBU_UART* option is selected, + when u-boot hands over to the kernel, the system + silently crashes, with no serial output at all. + config DEBUG_VF_UART bool "Vybrid UART" depends on SOC_VF610 @@ -1297,6 +1312,7 @@ config DEBUG_UART_PHYS default 0xf0000be0 if ARCH_EBSA110 default 0xf040ab00 if DEBUG_BRCMSTB_UART default 0xf1012000 if DEBUG_MVEBU_UART0_ALTERNATE + default 0xf1012100 if DEBUG_MVEBU_UART1_ALTERNATE default 0xf1012000 if ARCH_DOVE || ARCH_MV78XX0 || \ ARCH_ORION5X default 0xf7fc9000 if DEBUG_BERLIN_UART @@ -1378,6 +1394,7 @@ config DEBUG_UART_VIRT default 0xfeb31000 if DEBUG_KEYSTONE_UART1 default 0xfec02000 if DEBUG_SOCFPGA_UART default 0xfec12000 if DEBUG_MVEBU_UART0 || DEBUG_MVEBU_UART0_ALTERNATE + default 0xfec12100 if DEBUG_MVEBU_UART1_ALTERNATE default 0xfec20000 if DEBUG_DAVINCI_DMx_UART0 default 0xfec90000 if DEBUG_RK32_UART2 default 0xfed0c000 if DEBUG_DAVINCI_DA8XX_UART1 -- cgit v1.2.3 From 4a25432b13090b57d257fa0ffb6712d8acf94523 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 8 Jan 2015 18:38:05 +0100 Subject: ARM: mvebu: a38x: Fix node names Some nodes in the DTs have a reg property but no unit name in their node name. This contradicts the way the ePAPR defines the node names. Fix this. Signed-off-by: Maxime Ripard Acked-by: Gregory CLEMENT Signed-off-by: Gregory CLEMENT Signed-off-by: Andrew Lunn --- arch/arm/boot/dts/armada-380.dtsi | 2 +- arch/arm/boot/dts/armada-385-db.dts | 2 +- arch/arm/boot/dts/armada-385-rd.dts | 2 +- arch/arm/boot/dts/armada-385.dtsi | 2 +- arch/arm/boot/dts/armada-38x.dtsi | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/armada-380.dtsi b/arch/arm/boot/dts/armada-380.dtsi index 4173a8ab34e7..13400ce88c54 100644 --- a/arch/arm/boot/dts/armada-380.dtsi +++ b/arch/arm/boot/dts/armada-380.dtsi @@ -32,7 +32,7 @@ soc { internal-regs { - pinctrl { + pinctrl@18000 { compatible = "marvell,mv88f6810-pinctrl"; reg = <0x18000 0x20>; }; diff --git a/arch/arm/boot/dts/armada-385-db.dts b/arch/arm/boot/dts/armada-385-db.dts index 2aaa9d2ac284..212605ccc7b6 100644 --- a/arch/arm/boot/dts/armada-385-db.dts +++ b/arch/arm/boot/dts/armada-385-db.dts @@ -74,7 +74,7 @@ phy-mode = "rgmii-id"; }; - mdio { + mdio@72004 { phy0: ethernet-phy@0 { reg = <0>; }; diff --git a/arch/arm/boot/dts/armada-385-rd.dts b/arch/arm/boot/dts/armada-385-rd.dts index aaca2861dc87..74a3bfe6efd7 100644 --- a/arch/arm/boot/dts/armada-385-rd.dts +++ b/arch/arm/boot/dts/armada-385-rd.dts @@ -67,7 +67,7 @@ }; - mdio { + mdio@72004 { phy0: ethernet-phy@0 { reg = <0>; }; diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi index 6283d7912f71..5249a4d3c207 100644 --- a/arch/arm/boot/dts/armada-385.dtsi +++ b/arch/arm/boot/dts/armada-385.dtsi @@ -37,7 +37,7 @@ soc { internal-regs { - pinctrl { + pinctrl@18000 { compatible = "marvell,mv88f6820-pinctrl"; reg = <0x18000 0x20>; }; diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi index 74391dace9e7..ada1f206028b 100644 --- a/arch/arm/boot/dts/armada-38x.dtsi +++ b/arch/arm/boot/dts/armada-38x.dtsi @@ -193,7 +193,7 @@ status = "disabled"; }; - pinctrl { + pinctrl@18000 { compatible = "marvell,mv88f6820-pinctrl"; reg = <0x18000 0x20>; }; @@ -373,7 +373,7 @@ status = "disabled"; }; - mdio { + mdio@72004 { #address-cells = <1>; #size-cells = <0>; compatible = "marvell,orion-mdio"; -- cgit v1.2.3 From 684f216f9eee5b38432c398cbd045ee2f3f11ece Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 8 Jan 2015 18:38:07 +0100 Subject: ARM: mvebu: A38x: Remove redundant pinctrl informations The compatible set in the armada-38x DTSI is always overridden, and the reg defined in there is duplicated in the armada-380 and armada-385 DTSIs. Remove these useless items. Signed-off-by: Maxime Ripard Acked-by: Gregory CLEMENT Signed-off-by: Gregory CLEMENT Signed-off-by: Andrew Lunn --- arch/arm/boot/dts/armada-380.dtsi | 1 - arch/arm/boot/dts/armada-385.dtsi | 1 - arch/arm/boot/dts/armada-38x.dtsi | 1 - 3 files changed, 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/armada-380.dtsi b/arch/arm/boot/dts/armada-380.dtsi index 13400ce88c54..7e509d2d74d0 100644 --- a/arch/arm/boot/dts/armada-380.dtsi +++ b/arch/arm/boot/dts/armada-380.dtsi @@ -34,7 +34,6 @@ internal-regs { pinctrl@18000 { compatible = "marvell,mv88f6810-pinctrl"; - reg = <0x18000 0x20>; }; }; diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi index 5249a4d3c207..a54a252ddb4c 100644 --- a/arch/arm/boot/dts/armada-385.dtsi +++ b/arch/arm/boot/dts/armada-385.dtsi @@ -39,7 +39,6 @@ internal-regs { pinctrl@18000 { compatible = "marvell,mv88f6820-pinctrl"; - reg = <0x18000 0x20>; }; }; diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi index ada1f206028b..40200084c6c8 100644 --- a/arch/arm/boot/dts/armada-38x.dtsi +++ b/arch/arm/boot/dts/armada-38x.dtsi @@ -194,7 +194,6 @@ }; pinctrl@18000 { - compatible = "marvell,mv88f6820-pinctrl"; reg = <0x18000 0x20>; }; -- cgit v1.2.3 From 91b4c91f919abffa72cbf7545a944252f8e4f775 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 8 Jan 2015 18:38:08 +0100 Subject: ARM: mvebu: Add a number of pinctrl functions Some pinctrl functions can be shared with all DTS out there, since they are generic, SoC-wide muxing options. Add a number of these to the DTSI to avoid duplication. Signed-off-by: Maxime Ripard Acked-by: Gregory CLEMENT Signed-off-by: Gregory CLEMENT Signed-off-by: Andrew Lunn --- arch/arm/boot/dts/armada-38x.dtsi | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi index 40200084c6c8..98885c58be29 100644 --- a/arch/arm/boot/dts/armada-38x.dtsi +++ b/arch/arm/boot/dts/armada-38x.dtsi @@ -195,6 +195,45 @@ pinctrl@18000 { reg = <0x18000 0x20>; + + ge0_rgmii_pins: ge-rgmii-pins-0 { + marvell,pins = "mpp6", "mpp7", "mpp8", + "mpp9", "mpp10", "mpp11", + "mpp12", "mpp13", "mpp14", + "mpp15", "mpp16", "mpp17"; + marvell,function = "ge0"; + }; + + i2c0_pins: i2c-pins-0 { + marvell,pins = "mpp2", "mpp3"; + marvell,function = "i2c0"; + }; + + mdio_pins: mdio-pins { + marvell,pins = "mpp4", "mpp5"; + marvell,function = "ge"; + }; + + ref_clk0_pins: ref-clk-pins-0 { + marvell,pins = "mpp45"; + marvell,function = "ref"; + }; + + spi1_pins: spi-pins-1 { + marvell,pins = "mpp56", "mpp57", "mpp58", + "mpp59"; + marvell,function = "spi1"; + }; + + uart0_pins: uart-pins-0 { + marvell,pins = "mpp0", "mpp1"; + marvell,function = "ua0"; + }; + + uart1_pins: uart-pins-1 { + marvell,pins = "mpp19", "mpp20"; + marvell,function = "ua1"; + }; }; gpio0: gpio@18100 { -- cgit v1.2.3 From e5ee12817e9eac891c6b2a340f64d94d9abd355f Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 8 Jan 2015 18:38:09 +0100 Subject: ARM: mvebu: Add Armada 385 Access Point Development Board support The A385-AP is a board produced by Marvell that holds 3 mPCIe slot, a 16MB SPI-NOR, 3 Gigabit Ethernet ports, USB3 and NAND flash storage. [gregory.clement@free-electrons.com: switch the license to the dual X11/GPL with the agreement of the author] Signed-off-by: Maxime Ripard Signed-off-by: Gregory CLEMENT Signed-off-by: Andrew Lunn --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/armada-385-db-ap.dts | 178 +++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 arch/arm/boot/dts/armada-385-db-ap.dts (limited to 'arch') diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 6dc9c17f9ff5..d34837104949 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -536,6 +536,7 @@ dtb-$(CONFIG_MACH_ARMADA_375) += \ armada-375-db.dtb dtb-$(CONFIG_MACH_ARMADA_38X) += \ armada-385-db.dtb \ + armada-385-db-ap.dtb \ armada-385-rd.dtb dtb-$(CONFIG_MACH_ARMADA_XP) += \ armada-xp-axpwifiap.dtb \ diff --git a/arch/arm/boot/dts/armada-385-db-ap.dts b/arch/arm/boot/dts/armada-385-db-ap.dts new file mode 100644 index 000000000000..57b9119fb3e0 --- /dev/null +++ b/arch/arm/boot/dts/armada-385-db-ap.dts @@ -0,0 +1,178 @@ +/* + * Device Tree file for Marvell Armada 385 Access Point Development board + * (DB-88F6820-AP) + * + * Copyright (C) 2014 Marvell + * + * Nadav Haklai + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without + * any warranty of any kind, whether express or implied. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "armada-385.dtsi" + +#include + +/ { + model = "Marvell Armada 385 Access Point Development Board"; + compatible = "marvell,a385-db-ap", "marvell,armada385", "marvell,armada38x"; + + chosen { + bootargs = "console=ttyS0,115200"; + stdout-path = &uart1; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x80000000>; /* 2GB */ + }; + + soc { + ranges = ; + + internal-regs { + spi1: spi@10680 { + pinctrl-names = "default"; + pinctrl-0 = <&spi1_pins>; + status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,m25p128"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <54000000>; + }; + }; + + i2c0: i2c@11000 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + /* + * This bus is wired to two EEPROM + * sockets, one of which holding the + * board ID used by the bootloader. + * Erasing this EEPROM's content will + * brick the board. + * Use this bus with caution. + */ + }; + + mdio@72004 { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + + phy0: ethernet-phy@1 { + reg = <1>; + }; + + phy1: ethernet-phy@4 { + reg = <4>; + }; + + phy2: ethernet-phy@6 { + reg = <6>; + }; + }; + + /* UART0 is exposed through the JP8 connector */ + uart0: serial@12000 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; + }; + + /* + * UART1 is exposed through a FTDI chip + * wired to the mini-USB connector + */ + uart1: serial@12100 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + status = "okay"; + }; + + ethernet@30000 { + status = "okay"; + phy = <&phy2>; + phy-mode = "sgmii"; + }; + + ethernet@34000 { + status = "okay"; + phy = <&phy1>; + phy-mode = "sgmii"; + }; + + ethernet@70000 { + pinctrl-names = "default"; + + /* + * The Reference Clock 0 is used to + * provide a clock to the PHY + */ + pinctrl-0 = <&ge0_rgmii_pins>, <&ref_clk0_pins>; + status = "okay"; + phy = <&phy0>; + phy-mode = "rgmii-id"; + }; + }; + + pcie-controller { + status = "okay"; + + /* + * The three PCIe units are accessible through + * standard mini-PCIe slots on the board. + */ + pcie@1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + + pcie@2,0 { + /* Port 1, Lane 0 */ + status = "okay"; + }; + + pcie@3,0 { + /* Port 2, Lane 0 */ + status = "okay"; + }; + }; + }; +}; -- cgit v1.2.3 From 34598503049688741edc45e800627d945293e5f2 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Thu, 8 Jan 2015 18:38:10 +0100 Subject: ARM: mvebu: a38x: Add more pinctrl functions With the Armada 385 GP board more pinctrl functions depending of the SoC are needed. Add them to the DTSI to avoid duplication. Signed-off-by: Gregory CLEMENT Signed-off-by: Andrew Lunn --- arch/arm/boot/dts/armada-38x.dtsi | 47 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi index 98885c58be29..63fe15174fee 100644 --- a/arch/arm/boot/dts/armada-38x.dtsi +++ b/arch/arm/boot/dts/armada-38x.dtsi @@ -204,6 +204,14 @@ marvell,function = "ge0"; }; + ge1_rgmii_pins: ge-rgmii-pins-1 { + marvell,pins = "mpp21", "mpp27", "mpp28", + "mpp29", "mpp30", "mpp31", + "mpp32", "mpp37", "mpp38", + "mpp39", "mpp40", "mpp41"; + marvell,function = "ge1"; + }; + i2c0_pins: i2c-pins-0 { marvell,pins = "mpp2", "mpp3"; marvell,function = "i2c0"; @@ -219,6 +227,17 @@ marvell,function = "ref"; }; + ref_clk1_pins: ref-clk-pins-1 { + marvell,pins = "mpp46"; + marvell,function = "ref"; + }; + + spi0_pins: spi-pins-0 { + marvell,pins = "mpp22", "mpp23", "mpp24", + "mpp25"; + marvell,function = "spi0"; + }; + spi1_pins: spi-pins-1 { marvell,pins = "mpp56", "mpp57", "mpp58", "mpp59"; @@ -234,6 +253,34 @@ marvell,pins = "mpp19", "mpp20"; marvell,function = "ua1"; }; + + sdhci_pins: sdhci-pins { + marvell,pins = "mpp48", "mpp49", "mpp50", + "mpp52", "mpp53", "mpp54", + "mpp55", "mpp57", "mpp58", + "mpp59"; + marvell,function = "sd0"; + }; + + sata0_pins: sata-pins-0 { + marvell,pins = "mpp20"; + marvell,function = "sata0"; + }; + + sata1_pins: sata-pins-1 { + marvell,pins = "mpp19"; + marvell,function = "sata1"; + }; + + sata2_pins: sata-pins-2 { + marvell,pins = "mpp47"; + marvell,function = "sata2"; + }; + + sata3_pins: sata-pins-3 { + marvell,pins = "mpp44"; + marvell,function = "sata3"; + }; }; gpio0: gpio@18100 { -- cgit v1.2.3 From 10c5c472703714a933ac3761653dd3f248d35011 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Thu, 8 Jan 2015 18:38:11 +0100 Subject: ARM: mvebu: a38x: Add missing labels The pintcrl label was missing. Adding it allowed referring it from the root of the device tree. Also add the uart0 label used by the bootloader. Signed-off-by: Gregory CLEMENT Signed-off-by: Andrew Lunn --- arch/arm/boot/dts/armada-38x.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi index 63fe15174fee..04fe80d101f8 100644 --- a/arch/arm/boot/dts/armada-38x.dtsi +++ b/arch/arm/boot/dts/armada-38x.dtsi @@ -173,7 +173,7 @@ status = "disabled"; }; - serial@12000 { + uart0: serial@12000 { compatible = "snps,dw-apb-uart"; reg = <0x12000 0x100>; reg-shift = <2>; @@ -193,7 +193,7 @@ status = "disabled"; }; - pinctrl@18000 { + pinctrl: pinctrl@18000 { reg = <0x18000 0x20>; ge0_rgmii_pins: ge-rgmii-pins-0 { -- cgit v1.2.3 From 881a50e47f231fb0185396125234f3188e14c2f3 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Thu, 8 Jan 2015 18:38:13 +0100 Subject: ARM: mvebu: Add Device Tree description of the Armada 388 SoC This SoC belongs to the Armada 38x family. The main difference with the Armada 385 is that the 388 can handle two more SATA ports. Currently the consequence is the use of a different compatible string for the pinctrl node, in order to be able to use the pins associated to this 2 new SATA ports. The second SATA controller has also been moved from the armada38x.dtsi as it it specific to the Armada388 version. In the same time the Armada385 DB and Armada 385 RD board have been renamed in the 388 one and now include the armada-388.dtsi file. AS both of them have 4 SATA ports the SoC used on them were wrongly described. Signed-off-by: Gregory CLEMENT Signed-off-by: Andrew Lunn --- arch/arm/boot/dts/Makefile | 4 +- arch/arm/boot/dts/armada-385-db.dts | 151 ----------------------------------- arch/arm/boot/dts/armada-385-rd.dts | 97 ----------------------- arch/arm/boot/dts/armada-388-db.dts | 152 ++++++++++++++++++++++++++++++++++++ arch/arm/boot/dts/armada-388-rd.dts | 98 +++++++++++++++++++++++ arch/arm/boot/dts/armada-388.dtsi | 70 +++++++++++++++++ 6 files changed, 322 insertions(+), 250 deletions(-) delete mode 100644 arch/arm/boot/dts/armada-385-db.dts delete mode 100644 arch/arm/boot/dts/armada-385-rd.dts create mode 100644 arch/arm/boot/dts/armada-388-db.dts create mode 100644 arch/arm/boot/dts/armada-388-rd.dts create mode 100644 arch/arm/boot/dts/armada-388.dtsi (limited to 'arch') diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index d34837104949..3ed928e364de 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -535,9 +535,9 @@ dtb-$(CONFIG_MACH_ARMADA_370) += \ dtb-$(CONFIG_MACH_ARMADA_375) += \ armada-375-db.dtb dtb-$(CONFIG_MACH_ARMADA_38X) += \ - armada-385-db.dtb \ armada-385-db-ap.dtb \ - armada-385-rd.dtb + armada-388-db.dtb \ + armada-388-rd.dtb dtb-$(CONFIG_MACH_ARMADA_XP) += \ armada-xp-axpwifiap.dtb \ armada-xp-db.dtb \ diff --git a/arch/arm/boot/dts/armada-385-db.dts b/arch/arm/boot/dts/armada-385-db.dts deleted file mode 100644 index 212605ccc7b6..000000000000 --- a/arch/arm/boot/dts/armada-385-db.dts +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Device Tree file for Marvell Armada 385 evaluation board - * (DB-88F6820) - * - * Copyright (C) 2014 Marvell - * - * Thomas Petazzoni - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -/dts-v1/; -#include "armada-385.dtsi" - -/ { - model = "Marvell Armada 385 Development Board"; - compatible = "marvell,a385-db", "marvell,armada385", "marvell,armada380"; - - chosen { - bootargs = "console=ttyS0,115200 earlyprintk"; - }; - - memory { - device_type = "memory"; - reg = <0x00000000 0x10000000>; /* 256 MB */ - }; - - soc { - ranges = ; - - internal-regs { - spi@10600 { - status = "okay"; - - spi-flash@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "w25q32"; - reg = <0>; /* Chip select 0 */ - spi-max-frequency = <108000000>; - }; - }; - - i2c@11000 { - status = "okay"; - clock-frequency = <100000>; - }; - - i2c@11100 { - status = "okay"; - clock-frequency = <100000>; - }; - - serial@12000 { - status = "okay"; - }; - - ethernet@30000 { - status = "okay"; - phy = <&phy1>; - phy-mode = "rgmii-id"; - }; - - usb@50000 { - status = "ok"; - }; - - ethernet@70000 { - status = "okay"; - phy = <&phy0>; - phy-mode = "rgmii-id"; - }; - - mdio@72004 { - phy0: ethernet-phy@0 { - reg = <0>; - }; - - phy1: ethernet-phy@1 { - reg = <1>; - }; - }; - - sata@a8000 { - status = "okay"; - }; - - sata@e0000 { - status = "okay"; - }; - - flash@d0000 { - status = "okay"; - num-cs = <1>; - marvell,nand-keep-config; - marvell,nand-enable-arbiter; - nand-on-flash-bbt; - nand-ecc-strength = <4>; - nand-ecc-step-size = <512>; - - partition@0 { - label = "U-Boot"; - reg = <0 0x800000>; - }; - partition@800000 { - label = "Linux"; - reg = <0x800000 0x800000>; - }; - partition@1000000 { - label = "Filesystem"; - reg = <0x1000000 0x3f000000>; - }; - }; - - sdhci@d8000 { - broken-cd; - wp-inverted; - bus-width = <8>; - status = "okay"; - no-1-8-v; - }; - - usb3@f0000 { - status = "okay"; - }; - - usb3@f8000 { - status = "okay"; - }; - }; - - pcie-controller { - status = "okay"; - /* - * The two PCIe units are accessible through - * standard PCIe slots on the board. - */ - pcie@1,0 { - /* Port 0, Lane 0 */ - status = "okay"; - }; - pcie@2,0 { - /* Port 1, Lane 0 */ - status = "okay"; - }; - }; - }; -}; diff --git a/arch/arm/boot/dts/armada-385-rd.dts b/arch/arm/boot/dts/armada-385-rd.dts deleted file mode 100644 index 74a3bfe6efd7..000000000000 --- a/arch/arm/boot/dts/armada-385-rd.dts +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Device Tree file for Marvell Armada 385 Reference Design board - * (RD-88F6820-AP) - * - * Copyright (C) 2014 Marvell - * - * Gregory CLEMENT - * Thomas Petazzoni - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -/dts-v1/; -#include "armada-385.dtsi" - -/ { - model = "Marvell Armada 385 Reference Design"; - compatible = "marvell,a385-rd", "marvell,armada385", "marvell,armada380"; - - chosen { - bootargs = "console=ttyS0,115200 earlyprintk"; - }; - - memory { - device_type = "memory"; - reg = <0x00000000 0x10000000>; /* 256 MB */ - }; - - soc { - ranges = ; - - internal-regs { - spi@10600 { - status = "okay"; - - spi-flash@0 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "st,m25p128"; - reg = <0>; /* Chip select 0 */ - spi-max-frequency = <108000000>; - }; - }; - - i2c@11000 { - status = "okay"; - clock-frequency = <100000>; - }; - - serial@12000 { - status = "okay"; - }; - - ethernet@30000 { - status = "okay"; - phy = <&phy0>; - phy-mode = "rgmii-id"; - }; - - ethernet@70000 { - status = "okay"; - phy = <&phy1>; - phy-mode = "rgmii-id"; - }; - - - mdio@72004 { - phy0: ethernet-phy@0 { - reg = <0>; - }; - - phy1: ethernet-phy@1 { - reg = <1>; - }; - }; - - usb3@f0000 { - status = "okay"; - }; - }; - - pcie-controller { - status = "okay"; - /* - * One PCIe units is accessible through - * standard PCIe slot on the board. - */ - pcie@1,0 { - /* Port 0, Lane 0 */ - status = "okay"; - }; - }; - }; -}; diff --git a/arch/arm/boot/dts/armada-388-db.dts b/arch/arm/boot/dts/armada-388-db.dts new file mode 100644 index 000000000000..e200836c30be --- /dev/null +++ b/arch/arm/boot/dts/armada-388-db.dts @@ -0,0 +1,152 @@ +/* + * Device Tree file for Marvell Armada 388 evaluation board + * (DB-88F6820) + * + * Copyright (C) 2014 Marvell + * + * Thomas Petazzoni + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +/dts-v1/; +#include "armada-388.dtsi" + +/ { + model = "Marvell Armada 385 Development Board"; + compatible = "marvell,a385-db", "marvell,armada388", + "marvell,armada385", "marvell,armada380"; + + chosen { + bootargs = "console=ttyS0,115200 earlyprintk"; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x10000000>; /* 256 MB */ + }; + + soc { + ranges = ; + + internal-regs { + spi@10600 { + status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "w25q32"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <108000000>; + }; + }; + + i2c@11000 { + status = "okay"; + clock-frequency = <100000>; + }; + + i2c@11100 { + status = "okay"; + clock-frequency = <100000>; + }; + + serial@12000 { + status = "okay"; + }; + + ethernet@30000 { + status = "okay"; + phy = <&phy1>; + phy-mode = "rgmii-id"; + }; + + usb@50000 { + status = "ok"; + }; + + ethernet@70000 { + status = "okay"; + phy = <&phy0>; + phy-mode = "rgmii-id"; + }; + + mdio@72004 { + phy0: ethernet-phy@0 { + reg = <0>; + }; + + phy1: ethernet-phy@1 { + reg = <1>; + }; + }; + + sata@a8000 { + status = "okay"; + }; + + sata@e0000 { + status = "okay"; + }; + + flash@d0000 { + status = "okay"; + num-cs = <1>; + marvell,nand-keep-config; + marvell,nand-enable-arbiter; + nand-on-flash-bbt; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + + partition@0 { + label = "U-Boot"; + reg = <0 0x800000>; + }; + partition@800000 { + label = "Linux"; + reg = <0x800000 0x800000>; + }; + partition@1000000 { + label = "Filesystem"; + reg = <0x1000000 0x3f000000>; + }; + }; + + sdhci@d8000 { + broken-cd; + wp-inverted; + bus-width = <8>; + status = "okay"; + no-1-8-v; + }; + + usb3@f0000 { + status = "okay"; + }; + + usb3@f8000 { + status = "okay"; + }; + }; + + pcie-controller { + status = "okay"; + /* + * The two PCIe units are accessible through + * standard PCIe slots on the board. + */ + pcie@1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + pcie@2,0 { + /* Port 1, Lane 0 */ + status = "okay"; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/armada-388-rd.dts b/arch/arm/boot/dts/armada-388-rd.dts new file mode 100644 index 000000000000..c98a8f8d01a9 --- /dev/null +++ b/arch/arm/boot/dts/armada-388-rd.dts @@ -0,0 +1,98 @@ +/* + * Device Tree file for Marvell Armada 388 Reference Design board + * (RD-88F6820-AP) + * + * Copyright (C) 2014 Marvell + * + * Gregory CLEMENT + * Thomas Petazzoni + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +/dts-v1/; +#include "armada-388.dtsi" + +/ { + model = "Marvell Armada 385 Reference Design"; + compatible = "marvell,a385-rd", "marvell,armada388", + "marvell,armada385","marvell,armada380"; + + chosen { + bootargs = "console=ttyS0,115200 earlyprintk"; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x10000000>; /* 256 MB */ + }; + + soc { + ranges = ; + + internal-regs { + spi@10600 { + status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,m25p128"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <108000000>; + }; + }; + + i2c@11000 { + status = "okay"; + clock-frequency = <100000>; + }; + + serial@12000 { + status = "okay"; + }; + + ethernet@30000 { + status = "okay"; + phy = <&phy0>; + phy-mode = "rgmii-id"; + }; + + ethernet@70000 { + status = "okay"; + phy = <&phy1>; + phy-mode = "rgmii-id"; + }; + + + mdio@72004 { + phy0: ethernet-phy@0 { + reg = <0>; + }; + + phy1: ethernet-phy@1 { + reg = <1>; + }; + }; + + usb3@f0000 { + status = "okay"; + }; + }; + + pcie-controller { + status = "okay"; + /* + * One PCIe units is accessible through + * standard PCIe slot on the board. + */ + pcie@1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/armada-388.dtsi b/arch/arm/boot/dts/armada-388.dtsi new file mode 100644 index 000000000000..564fa5937e25 --- /dev/null +++ b/arch/arm/boot/dts/armada-388.dtsi @@ -0,0 +1,70 @@ +/* + * Device Tree Include file for Marvell Armada 388 SoC. + * + * Copyright (C) 2015 Marvell + * + * Gregory CLEMENT + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without + * any warranty of any kind, whether express or implied. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * + * The main difference with the Armada 385 is that the 388 can handle two more + * SATA ports. So we can reuse the dtsi of the Armada 385, override the pinctrl + * property and the name of the SoC, and add the second SATA host which control + * the 2 other ports. + */ + +#include "armada-385.dtsi" + +/ { + model = "Marvell Armada 388 family SoC"; + compatible = "marvell,armada388", "marvell,armada385", + "marvell,armada380"; + + soc { + internal-regs { + pinctrl@18000 { + compatible = "marvell,mv88f6828-pinctrl"; + }; + + sata@e0000 { + compatible = "marvell,armada-380-ahci"; + reg = <0xe0000 0x2000>; + interrupts = ; + clocks = <&gateclk 30>; + status = "disabled"; + }; + + }; + }; +}; -- cgit v1.2.3 From 928413bd859c0936f03f6a3504c4721e83a3d1d7 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Thu, 8 Jan 2015 19:11:33 +0100 Subject: ARM: mvebu: Add Armada 388 General Purpose Development Board support The A388-GP is a board produced by Marvell that holds - 1 PCIe slot - 2 mini PCIe slot (one of them is multiplexed with the PCIe slot, muxing is selected through the GPIO expander) - 1 16MB SPI-NOR - 2 Gigabit Ethernet ports - 4 SATA ports (2 of them are multiplexed with the mini PCIe slots, muxing is selected through the GPIO expander) - 1 SDIO slot - 1 USB3 port - 2 USB2 port - 2 GPIO/interrupts expander on I2C Signed-off-by: Gregory CLEMENT Signed-off-by: Andrew Lunn --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/armada-388-gp.dts | 288 ++++++++++++++++++++++++++++++++++++ 2 files changed, 289 insertions(+) create mode 100644 arch/arm/boot/dts/armada-388-gp.dts (limited to 'arch') diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 3ed928e364de..17ee1d6a0ac0 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -537,6 +537,7 @@ dtb-$(CONFIG_MACH_ARMADA_375) += \ dtb-$(CONFIG_MACH_ARMADA_38X) += \ armada-385-db-ap.dtb \ armada-388-db.dtb \ + armada-388-gp.dtb \ armada-388-rd.dtb dtb-$(CONFIG_MACH_ARMADA_XP) += \ armada-xp-axpwifiap.dtb \ diff --git a/arch/arm/boot/dts/armada-388-gp.dts b/arch/arm/boot/dts/armada-388-gp.dts new file mode 100644 index 000000000000..4df22bf91683 --- /dev/null +++ b/arch/arm/boot/dts/armada-388-gp.dts @@ -0,0 +1,288 @@ +/* + * Device Tree file for Marvell Armada 385 development board + * (RD-88F6820-GP) + * + * Copyright (C) 2014 Marvell + * + * Gregory CLEMENT + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without + * any warranty of any kind, whether express or implied. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include "armada-388.dtsi" +#include + +/ { + model = "Marvell Armada 385 GP"; + compatible = "marvell,a385-gp", "marvell,armada388", "marvell,armada380"; + + chosen { + bootargs = "console=ttyS0,115200"; + stdout-path = &uart0; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x80000000>; /* 2 GB */ + }; + + soc { + ranges = ; + + internal-regs { + spi@10600 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins>; + status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,m25p128"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <50000000>; + m25p,fast-read; + }; + }; + + i2c@11000 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + clock-frequency = <100000>; + /* + * The EEPROM located at adresse 54 is needed + * for the boot - DO NOT ERASE IT - + */ + + expander0: pca9555@20 { + compatible = "nxp,pca9555"; + pinctrl-names = "default"; + pinctrl-0 = <&pca0_pins>; + interrupt-parent = <&gpio0>; + interrupts = <18 IRQ_TYPE_EDGE_FALLING>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x20>; + }; + + expander1: pca9555@21 { + compatible = "nxp,pca9555"; + pinctrl-names = "default"; + interrupt-parent = <&gpio0>; + interrupts = <18 IRQ_TYPE_EDGE_FALLING>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x21>; + }; + + }; + + serial@12000 { + /* + * Exported on the micro USB connector CON16 + * through an FTDI + */ + + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; + }; + + /* GE1 CON15 */ + ethernet@30000 { + pinctrl-names = "default"; + pinctrl-0 = <&ge1_rgmii_pins>; + status = "okay"; + phy = <&phy1>; + phy-mode = "rgmii-id"; + }; + + /* CON4 */ + usb@50000 { + vcc-supply = <®_usb2_0_vbus>; + status = "okay"; + }; + + /* GE0 CON1 */ + ethernet@70000 { + pinctrl-names = "default"; + /* + * The Reference Clock 0 is used to provide a + * clock to the PHY + */ + pinctrl-0 = <&ge0_rgmii_pins>, <&ref_clk0_pins>; + status = "okay"; + phy = <&phy0>; + phy-mode = "rgmii-id"; + }; + + + mdio@72004 { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + + phy0: ethernet-phy@1 { + reg = <1>; + }; + + phy1: ethernet-phy@0 { + reg = <0>; + }; + }; + + sata@a8000 { + pinctrl-names = "default"; + pinctrl-0 = <&sata0_pins>, <&sata1_pins>; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + }; + + sata@e0000 { + pinctrl-names = "default"; + pinctrl-0 = <&sata2_pins>, <&sata3_pins>; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + }; + + sdhci@d8000 { + pinctrl-names = "default"; + pinctrl-0 = <&sdhci_pins>; + cd-gpios = <&expander0 5 GPIO_ACTIVE_LOW>; + no-1-8-v; + wp-inverted; + bus-width = <8>; + status = "okay"; + }; + + /* CON5 */ + usb3@f0000 { + vcc-supply = <®_usb2_1_vbus>; + status = "okay"; + }; + + /* CON7 */ + usb3@f8000 { + vcc-supply = <®_usb3_vbus>; + status = "okay"; + }; + }; + + pcie-controller { + status = "okay"; + /* + * One PCIe units is accessible through + * standard PCIe slot on the board. + */ + pcie@1,0 { + /* Port 0, Lane 0 */ + status = "okay"; + }; + + /* + * The two other PCIe units are accessible + * through mini PCIe slot on the board. + */ + pcie@2,0 { + /* Port 1, Lane 0 */ + status = "okay"; + }; + pcie@3,0 { + /* Port 2, Lane 0 */ + status = "okay"; + }; + }; + + gpio-fan { + compatible = "gpio-fan"; + gpios = <&expander1 3 GPIO_ACTIVE_HIGH>; + gpio-fan,speed-map = < 0 0 + 3000 1>; + }; + }; + + reg_usb3_vbus: usb3-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb3-vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + gpio = <&expander1 15 GPIO_ACTIVE_HIGH>; + }; + + reg_usb2_0_vbus: v5-vbus0 { + compatible = "regulator-fixed"; + regulator-name = "v5.0-vbus0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + gpio = <&expander1 14 GPIO_ACTIVE_HIGH>; + }; + + reg_usb2_1_vbus: v5-vbus1 { + compatible = "regulator-fixed"; + regulator-name = "v5.0-vbus1"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + gpio = <&expander0 4 GPIO_ACTIVE_HIGH>; + }; + + reg_usb2_1_vbus: v5-vbus1 { + compatible = "regulator-fixed"; + regulator-name = "v5.0-vbus1"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + gpio = <&expander0 4 GPIO_ACTIVE_HIGH>; + }; +}; + +&pinctrl { + pca0_pins: pca0_pins { + marvell,pins = "mpp18"; + marvell,function = "gpio"; + }; +}; -- cgit v1.2.3 From c6574542149dede8093e326d2c358ba447e30f33 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Thu, 8 Jan 2015 16:08:08 +0100 Subject: ARM: mvebu: Update the SoC ID and revision definitions Add the missing SoC and revision ID for the Armada 370 and 38x SoCs. Signed-off-by: Gregory CLEMENT Signed-off-by: Andrew Lunn --- arch/arm/mach-mvebu/mvebu-soc-id.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-mvebu/mvebu-soc-id.h b/arch/arm/mach-mvebu/mvebu-soc-id.h index c16bb68ca81f..e124a0b82a3e 100644 --- a/arch/arm/mach-mvebu/mvebu-soc-id.h +++ b/arch/arm/mach-mvebu/mvebu-soc-id.h @@ -20,10 +20,28 @@ #define MV78XX0_A0_REV 0x1 #define MV78XX0_B0_REV 0x2 +/* Amada 370 ID */ +#define ARMADA_370_DEV_ID 0x6710 + +/* Amada 370 Revision */ +#define ARMADA_370_A1_REV 0x1 + +/* Armada 375 ID */ +#define ARMADA_375_DEV_ID 0x6720 + /* Armada 375 */ #define ARMADA_375_Z1_REV 0x0 #define ARMADA_375_A0_REV 0x3 +/* Armada 38x ID */ +#define ARMADA_380_DEV_ID 0x6810 +#define ARMADA_385_DEV_ID 0x6820 +#define ARMADA_388_DEV_ID 0x6828 + +/* Armada 38x Revision */ +#define ARMADA_38x_Z1_REV 0x0 +#define ARMADA_38x_A0_REV 0x4 + #ifdef CONFIG_ARCH_MVEBU int mvebu_get_soc_id(u32 *dev, u32 *rev); #else -- cgit v1.2.3 From 665d92e38f65d70796aad2b8e49e42e80815d4a4 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 25 Dec 2014 14:31:24 +0900 Subject: kbuild: do not add $(call ...) to invoke cc-version or cc-fullversion The macros cc-version, cc-fullversion and ld-version take no argument. It is not necessary to add $(call ...) to invoke them. Signed-off-by: Masahiro Yamada Acked-by: Helge Deller [parisc] Signed-off-by: Michal Marek --- arch/parisc/Makefile | 2 +- arch/powerpc/Makefile | 6 +++--- arch/x86/Makefile.um | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile index 5db8882f732c..fc1aca379fe2 100644 --- a/arch/parisc/Makefile +++ b/arch/parisc/Makefile @@ -149,7 +149,7 @@ endef # we require gcc 3.3 or above to compile the kernel archprepare: checkbin checkbin: - @if test "$(call cc-version)" -lt "0303"; then \ + @if test "$(cc-version)" -lt "0303"; then \ echo -n "Sorry, GCC v3.3 or above is required to build " ; \ echo "the kernel." ; \ false ; \ diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 132d9c681d6a..fc502e042438 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -314,7 +314,7 @@ TOUT := .tmp_gas_check # - Require gcc 4.0 or above on 64-bit # - gcc-4.2.0 has issues compiling modules on 64-bit checkbin: - @if test "$(call cc-version)" = "0304" ; then \ + @if test "$(cc-version)" = "0304" ; then \ if ! /bin/echo mftb 5 | $(AS) -v -mppc -many -o $(TOUT) >/dev/null 2>&1 ; then \ echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build '; \ echo 'correctly with gcc-3.4 and your version of binutils.'; \ @@ -322,13 +322,13 @@ checkbin: false; \ fi ; \ fi - @if test "$(call cc-version)" -lt "0400" \ + @if test "$(cc-version)" -lt "0400" \ && test "x${CONFIG_PPC64}" = "xy" ; then \ echo -n "Sorry, GCC v4.0 or above is required to build " ; \ echo "the 64-bit powerpc kernel." ; \ false ; \ fi - @if test "$(call cc-fullversion)" = "040200" \ + @if test "$(cc-fullversion)" = "040200" \ && test "x${CONFIG_MODULES}${CONFIG_PPC64}" = "xyy" ; then \ echo -n '*** GCC-4.2.0 cannot compile the 64-bit powerpc ' ; \ echo 'kernel with modules enabled.' ; \ diff --git a/arch/x86/Makefile.um b/arch/x86/Makefile.um index 36b62bc52638..95eba554baf9 100644 --- a/arch/x86/Makefile.um +++ b/arch/x86/Makefile.um @@ -30,7 +30,7 @@ cflags-y += -ffreestanding # Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use # a lot more stack due to the lack of sharing of stacklots. Also, gcc # 4.3.0 needs -funit-at-a-time for extern inline functions. -KBUILD_CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then \ +KBUILD_CFLAGS += $(shell if [ $(cc-version) -lt 0400 ] ; then \ echo $(call cc-option,-fno-unit-at-a-time); \ else echo $(call cc-option,-funit-at-a-time); fi ;) -- cgit v1.2.3 From a95cfa6b86a19a822877e75d5a73b2a95d249e70 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Tue, 6 Jan 2015 13:48:56 +0100 Subject: USB: host: Remove hard-coded octeon platform information for ehci/ohci Instead rely on device tree information for ehci and ohci. This was suggested with http://www.linux-mips.org/cgi-bin/mesg.cgi?a=linux-mips&i=1401358203-60225-4-git-send-email-alex.smith%40imgtec.com "The device tree will *always* have correct ehci/ohci clock configuration, so use it. This allows us to remove a big chunk of platform configuration code from octeon-platform.c." More or less I rebased that patch on Alan's work to remove ehci-octeon and ohci-octeon drivers. Cc: David Daney Cc: Alex Smith Cc: Alan Stern Signed-off-by: Andreas Herrmann Acked-by: Ralf Baechle Tested-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- arch/mips/cavium-octeon/octeon-platform.c | 148 +++++++++++++----------------- 1 file changed, 62 insertions(+), 86 deletions(-) (limited to 'arch') diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c index b67ddf0f8bcd..eea60b6c927b 100644 --- a/arch/mips/cavium-octeon/octeon-platform.c +++ b/arch/mips/cavium-octeon/octeon-platform.c @@ -77,7 +77,7 @@ static DEFINE_MUTEX(octeon2_usb_clocks_mutex); static int octeon2_usb_clock_start_cnt; -static void octeon2_usb_clocks_start(void) +static void octeon2_usb_clocks_start(struct device *dev) { u64 div; union cvmx_uctlx_if_ena if_ena; @@ -86,6 +86,8 @@ static void octeon2_usb_clocks_start(void) union cvmx_uctlx_uphy_portx_ctl_status port_ctl_status; int i; unsigned long io_clk_64_to_ns; + u32 clock_rate = 12000000; + bool is_crystal_clock = false; mutex_lock(&octeon2_usb_clocks_mutex); @@ -96,6 +98,28 @@ static void octeon2_usb_clocks_start(void) io_clk_64_to_ns = 64000000000ull / octeon_get_io_clock_rate(); + if (dev->of_node) { + struct device_node *uctl_node; + const char *clock_type; + + uctl_node = of_get_parent(dev->of_node); + if (!uctl_node) { + dev_err(dev, "No UCTL device node\n"); + goto exit; + } + i = of_property_read_u32(uctl_node, + "refclk-frequency", &clock_rate); + if (i) { + dev_err(dev, "No UCTL \"refclk-frequency\"\n"); + goto exit; + } + i = of_property_read_string(uctl_node, + "refclk-type", &clock_type); + + if (!i && strcmp("crystal", clock_type) == 0) + is_crystal_clock = true; + } + /* * Step 1: Wait for voltages stable. That surely happened * before starting the kernel. @@ -126,9 +150,22 @@ static void octeon2_usb_clocks_start(void) cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); /* 3b */ - /* 12MHz crystal. */ - clk_rst_ctl.s.p_refclk_sel = 0; - clk_rst_ctl.s.p_refclk_div = 0; + clk_rst_ctl.s.p_refclk_sel = is_crystal_clock ? 0 : 1; + switch (clock_rate) { + default: + pr_err("Invalid UCTL clock rate of %u, using 12000000 instead\n", + clock_rate); + /* Fall through */ + case 12000000: + clk_rst_ctl.s.p_refclk_div = 0; + break; + case 24000000: + clk_rst_ctl.s.p_refclk_div = 1; + break; + case 48000000: + clk_rst_ctl.s.p_refclk_div = 2; + break; + } cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64); /* 3c */ @@ -259,7 +296,7 @@ static void octeon2_usb_clocks_stop(void) static int octeon_ehci_power_on(struct platform_device *pdev) { - octeon2_usb_clocks_start(); + octeon2_usb_clocks_start(&pdev->dev); return 0; } @@ -277,11 +314,11 @@ static struct usb_ehci_pdata octeon_ehci_pdata = { .power_off = octeon_ehci_power_off, }; -static void __init octeon_ehci_hw_start(void) +static void __init octeon_ehci_hw_start(struct device *dev) { union cvmx_uctlx_ehci_ctl ehci_ctl; - octeon2_usb_clocks_start(); + octeon2_usb_clocks_start(dev); ehci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_EHCI_CTL(0)); /* Use 64-bit addressing. */ @@ -299,59 +336,28 @@ static u64 octeon_ehci_dma_mask = DMA_BIT_MASK(64); static int __init octeon_ehci_device_init(void) { struct platform_device *pd; + struct device_node *ehci_node; int ret = 0; - struct resource usb_resources[] = { - { - .flags = IORESOURCE_MEM, - }, { - .flags = IORESOURCE_IRQ, - } - }; - - /* Only Octeon2 has ehci/ohci */ - if (!OCTEON_IS_MODEL(OCTEON_CN63XX)) + ehci_node = of_find_node_by_name(NULL, "ehci"); + if (!ehci_node) return 0; - if (octeon_is_simulation() || usb_disabled()) - return 0; /* No USB in the simulator. */ - - pd = platform_device_alloc("ehci-platform", 0); - if (!pd) { - ret = -ENOMEM; - goto out; - } - - usb_resources[0].start = 0x00016F0000000000ULL; - usb_resources[0].end = usb_resources[0].start + 0x100; - - usb_resources[1].start = OCTEON_IRQ_USB0; - usb_resources[1].end = OCTEON_IRQ_USB0; - - ret = platform_device_add_resources(pd, usb_resources, - ARRAY_SIZE(usb_resources)); - if (ret) - goto fail; + pd = of_find_device_by_node(ehci_node); + if (!pd) + return 0; pd->dev.dma_mask = &octeon_ehci_dma_mask; pd->dev.platform_data = &octeon_ehci_pdata; - octeon_ehci_hw_start(); - - ret = platform_device_add(pd); - if (ret) - goto fail; + octeon_ehci_hw_start(&pd->dev); - return ret; -fail: - platform_device_put(pd); -out: return ret; } device_initcall(octeon_ehci_device_init); static int octeon_ohci_power_on(struct platform_device *pdev) { - octeon2_usb_clocks_start(); + octeon2_usb_clocks_start(&pdev->dev); return 0; } @@ -369,11 +375,11 @@ static struct usb_ohci_pdata octeon_ohci_pdata = { .power_off = octeon_ohci_power_off, }; -static void __init octeon_ohci_hw_start(void) +static void __init octeon_ohci_hw_start(struct device *dev) { union cvmx_uctlx_ohci_ctl ohci_ctl; - octeon2_usb_clocks_start(); + octeon2_usb_clocks_start(dev); ohci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_OHCI_CTL(0)); ohci_ctl.s.l2c_addr_msb = 0; @@ -387,57 +393,27 @@ static void __init octeon_ohci_hw_start(void) static int __init octeon_ohci_device_init(void) { struct platform_device *pd; + struct device_node *ohci_node; int ret = 0; - struct resource usb_resources[] = { - { - .flags = IORESOURCE_MEM, - }, { - .flags = IORESOURCE_IRQ, - } - }; - - /* Only Octeon2 has ehci/ohci */ - if (!OCTEON_IS_MODEL(OCTEON_CN63XX)) + ohci_node = of_find_node_by_name(NULL, "ohci"); + if (!ohci_node) return 0; - if (octeon_is_simulation() || usb_disabled()) - return 0; /* No USB in the simulator. */ - - pd = platform_device_alloc("ohci-platform", 0); - if (!pd) { - ret = -ENOMEM; - goto out; - } - - usb_resources[0].start = 0x00016F0000000400ULL; - usb_resources[0].end = usb_resources[0].start + 0x100; - - usb_resources[1].start = OCTEON_IRQ_USB0; - usb_resources[1].end = OCTEON_IRQ_USB0; - - ret = platform_device_add_resources(pd, usb_resources, - ARRAY_SIZE(usb_resources)); - if (ret) - goto fail; + pd = of_find_device_by_node(ohci_node); + if (!pd) + return 0; pd->dev.platform_data = &octeon_ohci_pdata; - octeon_ohci_hw_start(); - - ret = platform_device_add(pd); - if (ret) - goto fail; + octeon_ohci_hw_start(&pd->dev); - return ret; -fail: - platform_device_put(pd); -out: return ret; } device_initcall(octeon_ohci_device_init); #endif /* CONFIG_USB */ + static struct of_device_id __initdata octeon_ids[] = { { .compatible = "simple-bus", }, { .compatible = "cavium,octeon-6335-uctl", }, -- cgit v1.2.3 From a9e274c42da9213c94e308fae9aa488d3698f86a Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 30 Dec 2014 13:43:44 +0100 Subject: ARM: mvebu: fix compatible strings of MBus on Armada 375 and Armada 38x Due to the special handling of window 13 on Armada 375 and Armada 38x (similar to Armada XP), the MBus hardware block is *not* compatible with the one used on Armada 370. Using the Armada 370 compatible string on Armada 375 and 38x will lead to a non-working device if window 13 ends up being used. Signed-off-by: Thomas Petazzoni Signed-off-by: Andrew Lunn --- arch/arm/boot/dts/armada-375.dtsi | 2 +- arch/arm/boot/dts/armada-38x.dtsi | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/armada-375.dtsi b/arch/arm/boot/dts/armada-375.dtsi index 50096d3427eb..126bf7e9e6b4 100644 --- a/arch/arm/boot/dts/armada-375.dtsi +++ b/arch/arm/boot/dts/armada-375.dtsi @@ -63,7 +63,7 @@ }; soc { - compatible = "marvell,armada375-mbus", "marvell,armada370-mbus", "simple-bus"; + compatible = "marvell,armada375-mbus", "simple-bus"; #address-cells = <2>; #size-cells = <1>; controller = <&mbusc>; diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi index 04fe80d101f8..33cad7f7a224 100644 --- a/arch/arm/boot/dts/armada-38x.dtsi +++ b/arch/arm/boot/dts/armada-38x.dtsi @@ -31,8 +31,7 @@ }; soc { - compatible = "marvell,armada380-mbus", "marvell,armada370-mbus", - "simple-bus"; + compatible = "marvell,armada380-mbus", "simple-bus"; #address-cells = <2>; #size-cells = <1>; controller = <&mbusc>; -- cgit v1.2.3 From f94fe119f2e53362a3038ee856fa58412f728bc9 Mon Sep 17 00:00:00 2001 From: Steven Honeyman Date: Wed, 5 Nov 2014 22:52:18 +0000 Subject: x86, CPU: Fix trivial printk formatting issues with dmesg dmesg (from util-linux) currently has two methods for reading the kernel message ring buffer: /dev/kmsg and syslog(2). Since kernel 3.5.0 kmsg has been the default, which escapes control characters (e.g. new lines) before they are shown. This change means that when dmesg is using /dev/kmsg, a 2 line printk makes the output messy, because the second line does not get a timestamp. For example: [ 0.012863] CPU0: Thermal monitoring enabled (TM1) [ 0.012869] Last level iTLB entries: 4KB 1024, 2MB 1024, 4MB 1024 Last level dTLB entries: 4KB 1024, 2MB 1024, 4MB 1024, 1GB 4 [ 0.012958] Freeing SMP alternatives memory: 28K (ffffffff81d86000 - ffffffff81d8d000) [ 0.014961] dmar: Host address width 39 Because printk.c intentionally escapes control characters, they should not be there in the first place. This patch fixes two occurrences of this. Signed-off-by: Steven Honeyman Link: https://lkml.kernel.org/r/1414856696-8094-1-git-send-email-stevenhoneyman@gmail.com [ Boris: make cpu_detect_tlb() static, while at it. ] Signed-off-by: Borislav Petkov --- arch/x86/kernel/cpu/common.c | 13 +++++++------ arch/x86/kernel/cpu/intel.c | 6 ++---- 2 files changed, 9 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index c6049650c093..4973d6308938 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -491,17 +491,18 @@ u16 __read_mostly tlb_lld_2m[NR_INFO]; u16 __read_mostly tlb_lld_4m[NR_INFO]; u16 __read_mostly tlb_lld_1g[NR_INFO]; -void cpu_detect_tlb(struct cpuinfo_x86 *c) +static void cpu_detect_tlb(struct cpuinfo_x86 *c) { if (this_cpu->c_detect_tlb) this_cpu->c_detect_tlb(c); - printk(KERN_INFO "Last level iTLB entries: 4KB %d, 2MB %d, 4MB %d\n" - "Last level dTLB entries: 4KB %d, 2MB %d, 4MB %d, 1GB %d\n", + pr_info("Last level iTLB entries: 4KB %d, 2MB %d, 4MB %d\n", tlb_lli_4k[ENTRIES], tlb_lli_2m[ENTRIES], - tlb_lli_4m[ENTRIES], tlb_lld_4k[ENTRIES], - tlb_lld_2m[ENTRIES], tlb_lld_4m[ENTRIES], - tlb_lld_1g[ENTRIES]); + tlb_lli_4m[ENTRIES]); + + pr_info("Last level dTLB entries: 4KB %d, 2MB %d, 4MB %d, 1GB %d\n", + tlb_lld_4k[ENTRIES], tlb_lld_2m[ENTRIES], + tlb_lld_4m[ENTRIES], tlb_lld_1g[ENTRIES]); } void detect_ht(struct cpuinfo_x86 *c) diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 9cc6b6f25f42..94d7dcb12145 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -487,10 +487,8 @@ static void init_intel(struct cpuinfo_x86 *c) rdmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb); if ((epb & 0xF) == ENERGY_PERF_BIAS_PERFORMANCE) { - printk_once(KERN_WARNING "ENERGY_PERF_BIAS:" - " Set to 'normal', was 'performance'\n" - "ENERGY_PERF_BIAS: View and update with" - " x86_energy_perf_policy(8)\n"); + pr_warn_once("ENERGY_PERF_BIAS: Set to 'normal', was 'performance'\n"); + pr_warn_once("ENERGY_PERF_BIAS: View and update with x86_energy_perf_policy(8)\n"); epb = (epb & ~0xF) | ENERGY_PERF_BIAS_NORMAL; wrmsrl(MSR_IA32_ENERGY_PERF_BIAS, epb); } -- cgit v1.2.3 From 51ad77ada1edc2c4096730820c45756cd8f112ad Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 16 Jan 2014 17:15:14 -0500 Subject: m68k/mvme16x: rtc - Don't use module_init in non-modular code The rtc.o is built for obj-y, i.e. always built in. It will never be modular, so using module_init as an alias for __initcall can be somewhat misleading. Fix this up now, so that we can relocate module_init from init.h into module.h in the future. If we don't do this, we'd have to add module.h to obviously non-modular code, and that would be a worse thing. Note that direct use of __initcall is discouraged, vs. one of the priority categorized subgroups. As __initcall gets mapped onto device_initcall, our use of device_initcall directly in this change means that the runtime impact is zero -- it will remain at level 6 in initcall ordering. Signed-off-by: Paul Gortmaker Signed-off-by: Geert Uytterhoeven --- arch/m68k/mvme16x/rtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c index 6ef7a81a3b12..1755e2f7137d 100644 --- a/arch/m68k/mvme16x/rtc.c +++ b/arch/m68k/mvme16x/rtc.c @@ -161,4 +161,4 @@ static int __init rtc_MK48T08_init(void) printk(KERN_INFO "MK48T08 Real Time Clock Driver v%s\n", RTC_VERSION); return misc_register(&rtc_dev); } -module_init(rtc_MK48T08_init); +device_initcall(rtc_MK48T08_init); -- cgit v1.2.3 From 23b94210267185db51f0be8d7115eb49b63b064b Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Thu, 1 Jan 2015 16:37:57 +0100 Subject: m68k/atari: atakeyb.c - Remove some unused functions Remove some functions that are not used anywhere: atari_kbd_leds() ikbd_exec() ikbd_mem_read() ikbd_mem_write() ikbd_clock_get() ikbd_clock_set() ikbd_pause() ikbd_resume() This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist Signed-off-by: Geert Uytterhoeven --- arch/m68k/atari/atakeyb.c | 66 ----------------------------------------------- 1 file changed, 66 deletions(-) (limited to 'arch') diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c index 95022b04b62d..ad919696ec88 100644 --- a/arch/m68k/atari/atakeyb.c +++ b/arch/m68k/atari/atakeyb.c @@ -430,14 +430,6 @@ void ikbd_mouse_y0_top(void) } EXPORT_SYMBOL(ikbd_mouse_y0_top); -/* Resume */ -void ikbd_resume(void) -{ - static const char cmd[1] = { 0x11 }; - - ikbd_write(cmd, 1); -} - /* Disable mouse */ void ikbd_mouse_disable(void) { @@ -447,14 +439,6 @@ void ikbd_mouse_disable(void) } EXPORT_SYMBOL(ikbd_mouse_disable); -/* Pause output */ -void ikbd_pause(void) -{ - static const char cmd[1] = { 0x13 }; - - ikbd_write(cmd, 1); -} - /* Set joystick event reporting */ void ikbd_joystick_event_on(void) { @@ -502,56 +486,6 @@ void ikbd_joystick_disable(void) ikbd_write(cmd, 1); } -/* Time-of-day clock set */ -void ikbd_clock_set(int year, int month, int day, int hour, int minute, int second) -{ - char cmd[7] = { 0x1B, year, month, day, hour, minute, second }; - - ikbd_write(cmd, 7); -} - -/* Interrogate time-of-day clock */ -void ikbd_clock_get(int *year, int *month, int *day, int *hour, int *minute, int second) -{ - static const char cmd[1] = { 0x1C }; - - ikbd_write(cmd, 1); -} - -/* Memory load */ -void ikbd_mem_write(int address, int size, char *data) -{ - panic("Attempt to write data into keyboard memory"); -} - -/* Memory read */ -void ikbd_mem_read(int address, char data[6]) -{ - char cmd[3] = { 0x21, address>>8, address&0xFF }; - - ikbd_write(cmd, 3); - - /* receive data and put it in data */ -} - -/* Controller execute */ -void ikbd_exec(int address) -{ - char cmd[3] = { 0x22, address>>8, address&0xFF }; - - ikbd_write(cmd, 3); -} - -/* Status inquiries (0x87-0x9A) not yet implemented */ - -/* Set the state of the caps lock led. */ -void atari_kbd_leds(unsigned int leds) -{ - char cmd[6] = {32, 0, 4, 1, 254 + ((leds & 4) != 0), 0}; - - ikbd_write(cmd, 6); -} - /* * The original code sometimes left the interrupt line of * the ACIAs low forever. I hope, it is fixed now. -- cgit v1.2.3 From a38eaa07a0ce4bdb5f79637fedefae276a567e72 Mon Sep 17 00:00:00 2001 From: Rickard Strandqvist Date: Thu, 1 Jan 2015 17:49:11 +0100 Subject: m68k/mvme147: config.c - Remove unused functions Remove the function mvme147_init_console_port() that is not used anywhere. This was partially found by using a static code analysis program called cppcheck. Signed-off-by: Rickard Strandqvist [geert: Also remove now unused m147_scc_write(), scc_write(), scc_delay()] Signed-off-by: Geert Uytterhoeven --- arch/m68k/mvme147/config.c | 46 ---------------------------------------------- 1 file changed, 46 deletions(-) (limited to 'arch') diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c index 1bb3ce6634d3..e6a3b56c6481 100644 --- a/arch/m68k/mvme147/config.c +++ b/arch/m68k/mvme147/config.c @@ -168,49 +168,3 @@ int mvme147_set_clock_mmss (unsigned long nowtime) { return 0; } - -/*------------------- Serial console stuff ------------------------*/ - -static void scc_delay (void) -{ - int n; - volatile int trash; - - for (n = 0; n < 20; n++) - trash = n; -} - -static void scc_write (char ch) -{ - volatile char *p = (volatile char *)M147_SCC_A_ADDR; - - do { - scc_delay(); - } - while (!(*p & 4)); - scc_delay(); - *p = 8; - scc_delay(); - *p = ch; -} - - -void m147_scc_write (struct console *co, const char *str, unsigned count) -{ - unsigned long flags; - - local_irq_save(flags); - - while (count--) - { - if (*str == '\n') - scc_write ('\r'); - scc_write (*str++); - } - local_irq_restore(flags); -} - -void mvme147_init_console_port (struct console *co, int cflag) -{ - co->write = m147_scc_write; -} -- cgit v1.2.3 From 8c0ce284b320d2e6ef1a7c9a590d4fa44299c695 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 6 Jan 2015 08:49:52 +0100 Subject: m68k: Switch to asm-generic/futex.h As of commit 00f634bc522dedc8 ("asm-generic: add generic futex for !CONFIG_SMP") asm-generic follows the m68k futex implementation. Signed-off-by: Geert Uytterhoeven --- arch/m68k/include/asm/Kbuild | 1 + arch/m68k/include/asm/futex.h | 94 ------------------------------------------- 2 files changed, 1 insertion(+), 94 deletions(-) delete mode 100644 arch/m68k/include/asm/futex.h (limited to 'arch') diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild index 9b6c691874bd..1517ed1c6471 100644 --- a/arch/m68k/include/asm/Kbuild +++ b/arch/m68k/include/asm/Kbuild @@ -6,6 +6,7 @@ generic-y += device.h generic-y += emergency-restart.h generic-y += errno.h generic-y += exec.h +generic-y += futex.h generic-y += hw_irq.h generic-y += ioctl.h generic-y += ipcbuf.h diff --git a/arch/m68k/include/asm/futex.h b/arch/m68k/include/asm/futex.h deleted file mode 100644 index bc868af10c96..000000000000 --- a/arch/m68k/include/asm/futex.h +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef _ASM_M68K_FUTEX_H -#define _ASM_M68K_FUTEX_H - -#ifdef __KERNEL__ -#if !defined(CONFIG_MMU) -#include -#else /* CONFIG_MMU */ - -#include -#include -#include - -static inline int -futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, - u32 oldval, u32 newval) -{ - u32 val; - - if (unlikely(get_user(val, uaddr) != 0)) - return -EFAULT; - - if (val == oldval && unlikely(put_user(newval, uaddr) != 0)) - return -EFAULT; - - *uval = val; - - return 0; -} - -static inline int -futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) -{ - int op = (encoded_op >> 28) & 7; - int cmp = (encoded_op >> 24) & 15; - int oparg = (encoded_op << 8) >> 20; - int cmparg = (encoded_op << 20) >> 20; - int oldval, ret; - u32 tmp; - - if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) - oparg = 1 << oparg; - - pagefault_disable(); /* implies preempt_disable() */ - - ret = -EFAULT; - if (unlikely(get_user(oldval, uaddr) != 0)) - goto out_pagefault_enable; - - ret = 0; - tmp = oldval; - - switch (op) { - case FUTEX_OP_SET: - tmp = oparg; - break; - case FUTEX_OP_ADD: - tmp += oparg; - break; - case FUTEX_OP_OR: - tmp |= oparg; - break; - case FUTEX_OP_ANDN: - tmp &= ~oparg; - break; - case FUTEX_OP_XOR: - tmp ^= oparg; - break; - default: - ret = -ENOSYS; - } - - if (ret == 0 && unlikely(put_user(tmp, uaddr) != 0)) - ret = -EFAULT; - -out_pagefault_enable: - pagefault_enable(); /* subsumes preempt_enable() */ - - if (ret == 0) { - switch (cmp) { - case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; - case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; - case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; - case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; - case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; - case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; - default: ret = -ENOSYS; - } - } - return ret; -} - -#endif /* CONFIG_MMU */ -#endif /* __KERNEL__ */ -#endif /* _ASM_M68K_FUTEX_H */ -- cgit v1.2.3 From 2e874d178c9e8cb048bfc1075ec0e93582c0e124 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Wed, 7 Jan 2015 11:17:35 +1100 Subject: m68k/mac: Fix scsi_type for Mac LC and similar models Designing Cards and Drivers for the Macintosh Family, 3rd ed. on page 310 says that the I/O address space for the Mac LC is $50F0 0000 - $50FF FFFF. The developer notes for the Classic II, LC III and IIvx/IIvi give the same I/O address space. That means I've assigned the wrong platform resources to those Mac models. Fix the scsi_type initialization for the affected models, to restore the SCSI base address to its value prior to Linux 3.18. Also rename MAC_SCSI_CCL as MAC_SCSI_LC for the sake of correct chronology. Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- arch/m68k/include/asm/macintosh.h | 2 +- arch/m68k/mac/config.c | 32 +++++++++++++++++--------------- 2 files changed, 18 insertions(+), 16 deletions(-) (limited to 'arch') diff --git a/arch/m68k/include/asm/macintosh.h b/arch/m68k/include/asm/macintosh.h index 29c7c6c3a5f2..42235e7fbeed 100644 --- a/arch/m68k/include/asm/macintosh.h +++ b/arch/m68k/include/asm/macintosh.h @@ -55,7 +55,7 @@ struct mac_model #define MAC_SCSI_QUADRA3 4 #define MAC_SCSI_IIFX 5 #define MAC_SCSI_DUO 6 -#define MAC_SCSI_CCL 7 +#define MAC_SCSI_LC 7 #define MAC_SCSI_LATE 8 #define MAC_IDE_NONE 0 diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c index e9c3756139fc..689b47d292ac 100644 --- a/arch/m68k/mac/config.c +++ b/arch/m68k/mac/config.c @@ -296,7 +296,7 @@ static struct mac_model mac_data_table[] = { .name = "IIvi", .adb_type = MAC_ADB_IISI, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -305,7 +305,7 @@ static struct mac_model mac_data_table[] = { .name = "IIvx", .adb_type = MAC_ADB_IISI, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -320,7 +320,7 @@ static struct mac_model mac_data_table[] = { .name = "Classic II", .adb_type = MAC_ADB_IISI, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -329,7 +329,7 @@ static struct mac_model mac_data_table[] = { .name = "Color Classic", .adb_type = MAC_ADB_CUDA, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_CCL, + .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -338,7 +338,7 @@ static struct mac_model mac_data_table[] = { .name = "Color Classic II", .adb_type = MAC_ADB_CUDA, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_CCL, + .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -353,7 +353,7 @@ static struct mac_model mac_data_table[] = { .name = "LC", .adb_type = MAC_ADB_IISI, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -362,7 +362,7 @@ static struct mac_model mac_data_table[] = { .name = "LC II", .adb_type = MAC_ADB_IISI, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -371,7 +371,7 @@ static struct mac_model mac_data_table[] = { .name = "LC III", .adb_type = MAC_ADB_IISI, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -499,7 +499,7 @@ static struct mac_model mac_data_table[] = { .name = "Performa 460", .adb_type = MAC_ADB_IISI, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -526,7 +526,7 @@ static struct mac_model mac_data_table[] = { .name = "Performa 520", .adb_type = MAC_ADB_CUDA, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_CCL, + .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -535,7 +535,7 @@ static struct mac_model mac_data_table[] = { .name = "Performa 550", .adb_type = MAC_ADB_CUDA, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_CCL, + .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -567,7 +567,7 @@ static struct mac_model mac_data_table[] = { .name = "TV", .adb_type = MAC_ADB_CUDA, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_CCL, + .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -576,7 +576,7 @@ static struct mac_model mac_data_table[] = { .name = "Performa 600", .adb_type = MAC_ADB_IISI, .via_type = MAC_VIA_IICI, - .scsi_type = MAC_SCSI_OLD, + .scsi_type = MAC_SCSI_LC, .scc_type = MAC_SCC_II, .nubus_type = MAC_NUBUS, .floppy_type = MAC_FLOPPY_SWIM_ADDR2, @@ -1109,8 +1109,10 @@ int __init mac_platform_init(void) platform_device_register_simple("mac_scsi", 0, mac_scsi_late_rsrc, ARRAY_SIZE(mac_scsi_late_rsrc)); break; - case MAC_SCSI_CCL: - /* Addresses from the Color Classic Developer Note. + case MAC_SCSI_LC: + /* Addresses from Mac LC data in Designing Cards & Drivers 3ed. + * Also from the Developer Notes for Classic II, LC III, + * Color Classic and IIvx. * $50F0 6000 - $50F0 7FFF: SCSI handshake * $50F1 0000 - $50F1 1FFF: SCSI * $50F1 2000 - $50F1 3FFF: SCSI DMA -- cgit v1.2.3 From 065c0034823b513d3ca95760a2ad1765e3ef629c Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Mon, 15 Dec 2014 18:43:33 +0100 Subject: KVM: arm/arm64: vgic: add init entry to VGIC KVM device Since the advent of VGIC dynamic initialization, this latter is initialized quite late on the first vcpu run or "on-demand", when injecting an IRQ or when the guest sets its registers. This initialization could be initiated explicitly much earlier by the users-space, as soon as it has provided the requested dimensioning parameters. This patch adds a new entry to the VGIC KVM device that allows the user to manually request the VGIC init: - a new KVM_DEV_ARM_VGIC_GRP_CTRL group is introduced. - Its first attribute is KVM_DEV_ARM_VGIC_CTRL_INIT The rationale behind introducing a group is to be able to add other controls later on, if needed. Signed-off-by: Eric Auger Signed-off-by: Christoffer Dall --- arch/arm/include/uapi/asm/kvm.h | 2 ++ arch/arm64/include/uapi/asm/kvm.h | 2 ++ 2 files changed, 4 insertions(+) (limited to 'arch') diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index 09ee408c1a67..0db25bc32864 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h @@ -175,6 +175,8 @@ struct kvm_arch_memory_slot { #define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0 #define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT) #define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3 +#define KVM_DEV_ARM_VGIC_GRP_CTRL 4 +#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 /* KVM_IRQ_LINE irq field index values */ #define KVM_ARM_IRQ_TYPE_SHIFT 24 diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index 8e38878c87c6..480af3461068 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -161,6 +161,8 @@ struct kvm_arch_memory_slot { #define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0 #define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT) #define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3 +#define KVM_DEV_ARM_VGIC_GRP_CTRL 4 +#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 /* KVM_IRQ_LINE irq field index values */ #define KVM_ARM_IRQ_TYPE_SHIFT 24 -- cgit v1.2.3 From d19b4fa012f45efccef1d57fb4491df1bd559291 Mon Sep 17 00:00:00 2001 From: Barry Song Date: Sun, 4 Jan 2015 14:37:27 +0800 Subject: ARM: dts: drop MARCO platform DT stuff MARCO will not be supported any more. it has been replaced by CSR atlas7. Signed-off-by: Barry Song Acked-by: Arnd Bergmann --- arch/arm/boot/dts/Makefile | 1 - arch/arm/boot/dts/marco-evb.dts | 54 --- arch/arm/boot/dts/marco.dtsi | 757 ---------------------------------------- 3 files changed, 812 deletions(-) delete mode 100644 arch/arm/boot/dts/marco-evb.dts delete mode 100644 arch/arm/boot/dts/marco.dtsi (limited to 'arch') diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 91bd5bd62857..68feb8f8b5bc 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -175,7 +175,6 @@ dtb-$(CONFIG_MACH_KIRKWOOD) += kirkwood-b3.dtb \ kirkwood-ts419-6281.dtb \ kirkwood-ts419-6282.dtb dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb -dtb-$(CONFIG_ARCH_MARCO) += marco-evb.dtb dtb-$(CONFIG_MACH_MESON6) += meson6-atv1200.dtb dtb-$(CONFIG_ARCH_MMP) += pxa168-aspenite.dtb \ pxa910-dkb.dtb \ diff --git a/arch/arm/boot/dts/marco-evb.dts b/arch/arm/boot/dts/marco-evb.dts deleted file mode 100644 index 5130aeacfca5..000000000000 --- a/arch/arm/boot/dts/marco-evb.dts +++ /dev/null @@ -1,54 +0,0 @@ -/* - * DTS file for CSR SiRFmarco Evaluation Board - * - * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company. - * - * Licensed under GPLv2 or later. - */ - -/dts-v1/; - -/include/ "marco.dtsi" - -/ { - model = "CSR SiRFmarco Evaluation Board"; - compatible = "sirf,marco-cb", "sirf,marco"; - - memory { - reg = <0x40000000 0x60000000>; - }; - - axi { - peri-iobg { - uart1: uart@cc060000 { - status = "okay"; - }; - uart2: uart@cc070000 { - status = "okay"; - }; - i2c0: i2c@cc0e0000 { - status = "okay"; - fpga-cpld@4d { - compatible = "sirf,fpga-cpld"; - reg = <0x4d>; - }; - }; - spi1: spi@cc170000 { - status = "okay"; - pinctrl-names = "default"; - pinctrl-0 = <&spi1_pins_a>; - spi@0 { - compatible = "spidev"; - reg = <0>; - spi-max-frequency = <1000000>; - }; - }; - pci-iobg { - sd0: sdhci@cd000000 { - bus-width = <8>; - status = "okay"; - }; - }; - }; - }; -}; diff --git a/arch/arm/boot/dts/marco.dtsi b/arch/arm/boot/dts/marco.dtsi deleted file mode 100644 index fb354225740a..000000000000 --- a/arch/arm/boot/dts/marco.dtsi +++ /dev/null @@ -1,757 +0,0 @@ -/* - * DTS file for CSR SiRFmarco SoC - * - * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company. - * - * Licensed under GPLv2 or later. - */ - -/include/ "skeleton.dtsi" -/ { - compatible = "sirf,marco"; - #address-cells = <1>; - #size-cells = <1>; - interrupt-parent = <&gic>; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - reg = <0>; - }; - cpu@1 { - device_type = "cpu"; - compatible = "arm,cortex-a9"; - reg = <1>; - }; - }; - - axi { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x40000000 0x40000000 0xa0000000>; - - l2-cache-controller@c0030000 { - compatible = "arm,pl310-cache"; - reg = <0xc0030000 0x1000>; - interrupts = <0 59 0>; - arm,tag-latency = <1 1 1>; - arm,data-latency = <1 1 1>; - arm,filter-ranges = <0x40000000 0x80000000>; - }; - - gic: interrupt-controller@c0011000 { - compatible = "arm,cortex-a9-gic"; - interrupt-controller; - #interrupt-cells = <3>; - reg = <0xc0011000 0x1000>, - <0xc0010100 0x0100>; - }; - - rstc-iobg { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0xc2000000 0xc2000000 0x1000000>; - - rstc: reset-controller@c2000000 { - compatible = "sirf,marco-rstc"; - reg = <0xc2000000 0x10000>; - #reset-cells = <1>; - }; - }; - - sys-iobg { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0xc3000000 0xc3000000 0x1000000>; - - clock-controller@c3000000 { - compatible = "sirf,marco-clkc"; - reg = <0xc3000000 0x1000>; - interrupts = <0 3 0>; - }; - - rsc-controller@c3010000 { - compatible = "sirf,marco-rsc"; - reg = <0xc3010000 0x1000>; - }; - }; - - mem-iobg { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0xc4000000 0xc4000000 0x1000000>; - - memory-controller@c4000000 { - compatible = "sirf,marco-memc"; - reg = <0xc4000000 0x10000>; - interrupts = <0 27 0>; - }; - }; - - disp-iobg0 { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0xc5000000 0xc5000000 0x1000000>; - - display0@c5000000 { - compatible = "sirf,marco-lcd"; - reg = <0xc5000000 0x10000>; - interrupts = <0 30 0>; - }; - - vpp0@c5010000 { - compatible = "sirf,marco-vpp"; - reg = <0xc5010000 0x10000>; - interrupts = <0 31 0>; - }; - }; - - disp-iobg1 { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0xc6000000 0xc6000000 0x1000000>; - - display1@c6000000 { - compatible = "sirf,marco-lcd"; - reg = <0xc6000000 0x10000>; - interrupts = <0 62 0>; - }; - - vpp1@c6010000 { - compatible = "sirf,marco-vpp"; - reg = <0xc6010000 0x10000>; - interrupts = <0 63 0>; - }; - }; - - graphics-iobg { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0xc8000000 0xc8000000 0x1000000>; - - graphics@c8000000 { - compatible = "powervr,sgx540"; - reg = <0xc8000000 0x1000000>; - interrupts = <0 6 0>; - }; - }; - - multimedia-iobg { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0xc9000000 0xc9000000 0x1000000>; - - multimedia@a0000000 { - compatible = "sirf,marco-video-codec"; - reg = <0xc9000000 0x1000000>; - interrupts = <0 5 0>; - }; - }; - - dsp-iobg { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0xca000000 0xca000000 0x2000000>; - - dspif@ca000000 { - compatible = "sirf,marco-dspif"; - reg = <0xca000000 0x10000>; - interrupts = <0 9 0>; - }; - - gps@ca010000 { - compatible = "sirf,marco-gps"; - reg = <0xca010000 0x10000>; - interrupts = <0 7 0>; - }; - - dsp@cb000000 { - compatible = "sirf,marco-dsp"; - reg = <0xcb000000 0x1000000>; - interrupts = <0 8 0>; - }; - }; - - peri-iobg { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0xcc000000 0xcc000000 0x2000000>; - - timer@cc020000 { - compatible = "sirf,marco-tick"; - reg = <0xcc020000 0x1000>; - interrupts = <0 0 0>, - <0 1 0>, - <0 2 0>, - <0 49 0>, - <0 50 0>, - <0 51 0>; - }; - - nand@cc030000 { - compatible = "sirf,marco-nand"; - reg = <0xcc030000 0x10000>; - interrupts = <0 41 0>; - }; - - audio@cc040000 { - compatible = "sirf,marco-audio"; - reg = <0xcc040000 0x10000>; - interrupts = <0 35 0>; - }; - - uart0: uart@cc050000 { - cell-index = <0>; - compatible = "sirf,marco-uart"; - reg = <0xcc050000 0x1000>; - interrupts = <0 17 0>; - fifosize = <128>; - status = "disabled"; - }; - - uart1: uart@cc060000 { - cell-index = <1>; - compatible = "sirf,marco-uart"; - reg = <0xcc060000 0x1000>; - interrupts = <0 18 0>; - fifosize = <32>; - status = "disabled"; - }; - - uart2: uart@cc070000 { - cell-index = <2>; - compatible = "sirf,marco-uart"; - reg = <0xcc070000 0x1000>; - interrupts = <0 19 0>; - fifosize = <128>; - status = "disabled"; - }; - - uart3: uart@cc190000 { - cell-index = <3>; - compatible = "sirf,marco-uart"; - reg = <0xcc190000 0x1000>; - interrupts = <0 66 0>; - fifosize = <128>; - status = "disabled"; - }; - - uart4: uart@cc1a0000 { - cell-index = <4>; - compatible = "sirf,marco-uart"; - reg = <0xcc1a0000 0x1000>; - interrupts = <0 69 0>; - fifosize = <128>; - status = "disabled"; - }; - - usp0: usp@cc080000 { - cell-index = <0>; - compatible = "sirf,marco-usp"; - reg = <0xcc080000 0x10000>; - interrupts = <0 20 0>; - status = "disabled"; - }; - - usp1: usp@cc090000 { - cell-index = <1>; - compatible = "sirf,marco-usp"; - reg = <0xcc090000 0x10000>; - interrupts = <0 21 0>; - status = "disabled"; - }; - - usp2: usp@cc0a0000 { - cell-index = <2>; - compatible = "sirf,marco-usp"; - reg = <0xcc0a0000 0x10000>; - interrupts = <0 22 0>; - status = "disabled"; - }; - - dmac0: dma-controller@cc0b0000 { - cell-index = <0>; - compatible = "sirf,marco-dmac"; - reg = <0xcc0b0000 0x10000>; - interrupts = <0 12 0>; - }; - - dmac1: dma-controller@cc160000 { - cell-index = <1>; - compatible = "sirf,marco-dmac"; - reg = <0xcc160000 0x10000>; - interrupts = <0 13 0>; - }; - - vip@cc0c0000 { - compatible = "sirf,marco-vip"; - reg = <0xcc0c0000 0x10000>; - }; - - spi0: spi@cc0d0000 { - cell-index = <0>; - compatible = "sirf,marco-spi"; - reg = <0xcc0d0000 0x10000>; - interrupts = <0 15 0>; - sirf,spi-num-chipselects = <1>; - cs-gpios = <&gpio 0 0>; - sirf,spi-dma-rx-channel = <25>; - sirf,spi-dma-tx-channel = <20>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - spi1: spi@cc170000 { - cell-index = <1>; - compatible = "sirf,marco-spi"; - reg = <0xcc170000 0x10000>; - interrupts = <0 16 0>; - sirf,spi-num-chipselects = <1>; - cs-gpios = <&gpio 0 0>; - sirf,spi-dma-rx-channel = <12>; - sirf,spi-dma-tx-channel = <13>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c0: i2c@cc0e0000 { - cell-index = <0>; - compatible = "sirf,marco-i2c"; - reg = <0xcc0e0000 0x10000>; - interrupts = <0 24 0>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - i2c1: i2c@cc0f0000 { - cell-index = <1>; - compatible = "sirf,marco-i2c"; - reg = <0xcc0f0000 0x10000>; - interrupts = <0 25 0>; - #address-cells = <1>; - #size-cells = <0>; - status = "disabled"; - }; - - tsc@cc110000 { - compatible = "sirf,marco-tsc"; - reg = <0xcc110000 0x10000>; - interrupts = <0 33 0>; - }; - - gpio: pinctrl@cc120000 { - #gpio-cells = <2>; - #interrupt-cells = <2>; - compatible = "sirf,marco-pinctrl"; - reg = <0xcc120000 0x10000>; - interrupts = <0 43 0>, - <0 44 0>, - <0 45 0>, - <0 46 0>, - <0 47 0>; - gpio-controller; - interrupt-controller; - - lcd_16pins_a: lcd0_0 { - lcd { - sirf,pins = "lcd_16bitsgrp"; - sirf,function = "lcd_16bits"; - }; - }; - lcd_18pins_a: lcd0_1 { - lcd { - sirf,pins = "lcd_18bitsgrp"; - sirf,function = "lcd_18bits"; - }; - }; - lcd_24pins_a: lcd0_2 { - lcd { - sirf,pins = "lcd_24bitsgrp"; - sirf,function = "lcd_24bits"; - }; - }; - lcdrom_pins_a: lcdrom0_0 { - lcd { - sirf,pins = "lcdromgrp"; - sirf,function = "lcdrom"; - }; - }; - uart0_pins_a: uart0_0 { - uart { - sirf,pins = "uart0grp"; - sirf,function = "uart0"; - }; - }; - uart1_pins_a: uart1_0 { - uart { - sirf,pins = "uart1grp"; - sirf,function = "uart1"; - }; - }; - uart2_pins_a: uart2_0 { - uart { - sirf,pins = "uart2grp"; - sirf,function = "uart2"; - }; - }; - uart2_noflow_pins_a: uart2_1 { - uart { - sirf,pins = "uart2_nostreamctrlgrp"; - sirf,function = "uart2_nostreamctrl"; - }; - }; - spi0_pins_a: spi0_0 { - spi { - sirf,pins = "spi0grp"; - sirf,function = "spi0"; - }; - }; - spi1_pins_a: spi1_0 { - spi { - sirf,pins = "spi1grp"; - sirf,function = "spi1"; - }; - }; - i2c0_pins_a: i2c0_0 { - i2c { - sirf,pins = "i2c0grp"; - sirf,function = "i2c0"; - }; - }; - i2c1_pins_a: i2c1_0 { - i2c { - sirf,pins = "i2c1grp"; - sirf,function = "i2c1"; - }; - }; - pwm0_pins_a: pwm0_0 { - pwm { - sirf,pins = "pwm0grp"; - sirf,function = "pwm0"; - }; - }; - pwm1_pins_a: pwm1_0 { - pwm { - sirf,pins = "pwm1grp"; - sirf,function = "pwm1"; - }; - }; - pwm2_pins_a: pwm2_0 { - pwm { - sirf,pins = "pwm2grp"; - sirf,function = "pwm2"; - }; - }; - pwm3_pins_a: pwm3_0 { - pwm { - sirf,pins = "pwm3grp"; - sirf,function = "pwm3"; - }; - }; - gps_pins_a: gps_0 { - gps { - sirf,pins = "gpsgrp"; - sirf,function = "gps"; - }; - }; - vip_pins_a: vip_0 { - vip { - sirf,pins = "vipgrp"; - sirf,function = "vip"; - }; - }; - sdmmc0_pins_a: sdmmc0_0 { - sdmmc0 { - sirf,pins = "sdmmc0grp"; - sirf,function = "sdmmc0"; - }; - }; - sdmmc1_pins_a: sdmmc1_0 { - sdmmc1 { - sirf,pins = "sdmmc1grp"; - sirf,function = "sdmmc1"; - }; - }; - sdmmc2_pins_a: sdmmc2_0 { - sdmmc2 { - sirf,pins = "sdmmc2grp"; - sirf,function = "sdmmc2"; - }; - }; - sdmmc3_pins_a: sdmmc3_0 { - sdmmc3 { - sirf,pins = "sdmmc3grp"; - sirf,function = "sdmmc3"; - }; - }; - sdmmc4_pins_a: sdmmc4_0 { - sdmmc4 { - sirf,pins = "sdmmc4grp"; - sirf,function = "sdmmc4"; - }; - }; - sdmmc5_pins_a: sdmmc5_0 { - sdmmc5 { - sirf,pins = "sdmmc5grp"; - sirf,function = "sdmmc5"; - }; - }; - i2s_pins_a: i2s_0 { - i2s { - sirf,pins = "i2sgrp"; - sirf,function = "i2s"; - }; - }; - ac97_pins_a: ac97_0 { - ac97 { - sirf,pins = "ac97grp"; - sirf,function = "ac97"; - }; - }; - nand_pins_a: nand_0 { - nand { - sirf,pins = "nandgrp"; - sirf,function = "nand"; - }; - }; - usp0_pins_a: usp0_0 { - usp0 { - sirf,pins = "usp0grp"; - sirf,function = "usp0"; - }; - }; - usp1_pins_a: usp1_0 { - usp1 { - sirf,pins = "usp1grp"; - sirf,function = "usp1"; - }; - }; - usp2_pins_a: usp2_0 { - usp2 { - sirf,pins = "usp2grp"; - sirf,function = "usp2"; - }; - }; - usb0_utmi_drvbus_pins_a: usb0_utmi_drvbus_0 { - usb0_utmi_drvbus { - sirf,pins = "usb0_utmi_drvbusgrp"; - sirf,function = "usb0_utmi_drvbus"; - }; - }; - usb1_utmi_drvbus_pins_a: usb1_utmi_drvbus_0 { - usb1_utmi_drvbus { - sirf,pins = "usb1_utmi_drvbusgrp"; - sirf,function = "usb1_utmi_drvbus"; - }; - }; - warm_rst_pins_a: warm_rst_0 { - warm_rst { - sirf,pins = "warm_rstgrp"; - sirf,function = "warm_rst"; - }; - }; - pulse_count_pins_a: pulse_count_0 { - pulse_count { - sirf,pins = "pulse_countgrp"; - sirf,function = "pulse_count"; - }; - }; - cko0_rst_pins_a: cko0_rst_0 { - cko0_rst { - sirf,pins = "cko0_rstgrp"; - sirf,function = "cko0_rst"; - }; - }; - cko1_rst_pins_a: cko1_rst_0 { - cko1_rst { - sirf,pins = "cko1_rstgrp"; - sirf,function = "cko1_rst"; - }; - }; - }; - - pwm@cc130000 { - compatible = "sirf,marco-pwm"; - reg = <0xcc130000 0x10000>; - }; - - efusesys@cc140000 { - compatible = "sirf,marco-efuse"; - reg = <0xcc140000 0x10000>; - }; - - pulsec@cc150000 { - compatible = "sirf,marco-pulsec"; - reg = <0xcc150000 0x10000>; - interrupts = <0 48 0>; - }; - - pci-iobg { - compatible = "sirf,marco-pciiobg", "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0xcd000000 0xcd000000 0x1000000>; - - sd0: sdhci@cd000000 { - cell-index = <0>; - compatible = "sirf,marco-sdhc"; - reg = <0xcd000000 0x100000>; - interrupts = <0 38 0>; - status = "disabled"; - }; - - sd1: sdhci@cd100000 { - cell-index = <1>; - compatible = "sirf,marco-sdhc"; - reg = <0xcd100000 0x100000>; - interrupts = <0 38 0>; - status = "disabled"; - }; - - sd2: sdhci@cd200000 { - cell-index = <2>; - compatible = "sirf,marco-sdhc"; - reg = <0xcd200000 0x100000>; - interrupts = <0 23 0>; - status = "disabled"; - }; - - sd3: sdhci@cd300000 { - cell-index = <3>; - compatible = "sirf,marco-sdhc"; - reg = <0xcd300000 0x100000>; - interrupts = <0 23 0>; - status = "disabled"; - }; - - sd4: sdhci@cd400000 { - cell-index = <4>; - compatible = "sirf,marco-sdhc"; - reg = <0xcd400000 0x100000>; - interrupts = <0 39 0>; - status = "disabled"; - }; - - sd5: sdhci@cd500000 { - cell-index = <5>; - compatible = "sirf,marco-sdhc"; - reg = <0xcd500000 0x100000>; - interrupts = <0 39 0>; - status = "disabled"; - }; - - pci-copy@cd900000 { - compatible = "sirf,marco-pcicp"; - reg = <0xcd900000 0x100000>; - interrupts = <0 40 0>; - }; - - rom-interface@cda00000 { - compatible = "sirf,marco-romif"; - reg = <0xcda00000 0x100000>; - }; - }; - }; - - rtc-iobg { - compatible = "sirf,marco-rtciobg", "sirf-marco-rtciobg-bus"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0xc1000000 0x10000>; - - gpsrtc@1000 { - compatible = "sirf,marco-gpsrtc"; - reg = <0x1000 0x1000>; - interrupts = <0 55 0>, - <0 56 0>, - <0 57 0>; - }; - - sysrtc@2000 { - compatible = "sirf,marco-sysrtc"; - reg = <0x2000 0x1000>; - interrupts = <0 52 0>, - <0 53 0>, - <0 54 0>; - }; - - pwrc@3000 { - compatible = "sirf,marco-pwrc"; - reg = <0x3000 0x1000>; - interrupts = <0 32 0>; - }; - }; - - uus-iobg { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0xce000000 0xce000000 0x1000000>; - - usb0: usb@ce000000 { - compatible = "chipidea,ci13611a-marco"; - reg = <0xce000000 0x10000>; - interrupts = <0 10 0>; - }; - - usb1: usb@ce010000 { - compatible = "chipidea,ci13611a-marco"; - reg = <0xce010000 0x10000>; - interrupts = <0 11 0>; - }; - - security@ce020000 { - compatible = "sirf,marco-security"; - reg = <0xce020000 0x10000>; - interrupts = <0 42 0>; - }; - }; - - can-iobg { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0xd0000000 0xd0000000 0x1000000>; - - can0: can@d0000000 { - compatible = "sirf,marco-can"; - reg = <0xd0000000 0x10000>; - }; - - can1: can@d0010000 { - compatible = "sirf,marco-can"; - reg = <0xd0010000 0x10000>; - }; - }; - - lvds-iobg { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0xd1000000 0xd1000000 0x1000000>; - - lvds@d1000000 { - compatible = "sirf,marco-lvds"; - reg = <0xd1000000 0x10000>; - interrupts = <0 64 0>; - }; - }; - }; -}; -- cgit v1.2.3 From 2f5ff012f84d61c141294077c340a8a951a01eba Mon Sep 17 00:00:00 2001 From: Matthias Brugger Date: Sat, 1 Aug 2015 12:03:00 +0200 Subject: ARM: mediatek: dts: Add uart to mt6589 This patch adds the uart ports to the device tree of Mediatek mt6589 SoC. Signed-off-by: Matthias Brugger --- arch/arm/boot/dts/mt6589.dtsi | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/mt6589.dtsi b/arch/arm/boot/dts/mt6589.dtsi index c91b2a9ebdc3..106b61b10030 100644 --- a/arch/arm/boot/dts/mt6589.dtsi +++ b/arch/arm/boot/dts/mt6589.dtsi @@ -65,6 +65,12 @@ clock-frequency = <32000>; #clock-cells = <0>; }; + + uart_clk: dummy26m { + compatible = "fixed-clock"; + clock-frequency = <26000000>; + #clock-cells = <0>; + }; }; soc { @@ -100,5 +106,37 @@ <0x10214000 0x2000>, <0x10216000 0x2000>; }; + + uart0: serial@11006000 { + compatible = "mediatek,mt6577-uart"; + reg = <0x11006000 0x400>; + interrupts = ; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart1: serial@11007000 { + compatible = "mediatek,mt6577-uart"; + reg = <0x11007000 0x400>; + interrupts = ; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart2: serial@11008000 { + compatible = "mediatek,mt6577-uart"; + reg = <0x11008000 0x400>; + interrupts = ; + clocks = <&uart_clk>; + status = "disabled"; + }; + + uart3: serial@11009000 { + compatible = "mediatek,mt6577-uart"; + reg = <0x11009000 0x400>; + interrupts = ; + clocks = <&uart_clk>; + status = "disabled"; + }; }; }; -- cgit v1.2.3 From 3aa2e2811ab58e0299bb9a6457a15b405be86ff0 Mon Sep 17 00:00:00 2001 From: Matthias Brugger Date: Sat, 1 Aug 2015 12:03:00 +0200 Subject: ARM: mediatek: dts: Add uart to Aquaris5 This patch enables uart port for the Aquaris5 mobile phone. Signed-off-by: Matthias Brugger --- arch/arm/boot/dts/mt6589-aquaris5.dts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/mt6589-aquaris5.dts b/arch/arm/boot/dts/mt6589-aquaris5.dts index 0da047013120..594a6f3bebda 100644 --- a/arch/arm/boot/dts/mt6589-aquaris5.dts +++ b/arch/arm/boot/dts/mt6589-aquaris5.dts @@ -21,10 +21,20 @@ compatible = "mundoreader,bq-aquaris5", "mediatek,mt6589"; chosen { - bootargs = "earlyprintk"; + bootargs = "console=ttyS0,921600n8 earlyprintk"; + stdout-path = &uart0; }; memory { reg = <0x80000000 0x40000000>; }; + +}; + +&uart0 { + status = "okay"; +}; + +&uart3 { + status = "okay"; }; -- cgit v1.2.3 From 63139885c4bb53e476d875dddfe71b571107e663 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Wed, 7 Jan 2015 15:04:07 +0000 Subject: phy: miphy365x: Pass sysconfig register offsets via syscfg dt property. Based on Arnds review comments here https://lkml.org/lkml/2014/11/13/161, update the miphy365 phy driver to access sysconfig register offsets via syscfg dt property. This is because the reg property should not be mixing address spaces like it does currently for miphy365. This change then also aligns us to how other platforms such as keystone and bcm7445 pass there syscon offsets via DT. This patch breaks DT compatibility, but this platform is considered WIP, and is only used by a few developers who are upstreaming support for it. This change has been done as a single atomic commit to ensure it is bisectable. Signed-off-by: Peter Griffin Reviewed-by: Arnd Bergmann Signed-off-by: David S. Miller --- arch/arm/boot/dts/stih416.dtsi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/stih416.dtsi b/arch/arm/boot/dts/stih416.dtsi index fad9073ddeed..85afe01c34fa 100644 --- a/arch/arm/boot/dts/stih416.dtsi +++ b/arch/arm/boot/dts/stih416.dtsi @@ -283,21 +283,21 @@ miphy365x_phy: phy@fe382000 { compatible = "st,miphy365x-phy"; - st,syscfg = <&syscfg_rear>; + st,syscfg = <&syscfg_rear 0x824 0x828>; #address-cells = <1>; #size-cells = <1>; ranges; phy_port0: port@fe382000 { #phy-cells = <1>; - reg = <0xfe382000 0x100>, <0xfe394000 0x100>, <0x824 0x4>; - reg-names = "sata", "pcie", "syscfg"; + reg = <0xfe382000 0x100>, <0xfe394000 0x100>; + reg-names = "sata", "pcie"; }; phy_port1: port@fe38a000 { #phy-cells = <1>; - reg = <0xfe38a000 0x100>, <0xfe804000 0x100>, <0x828 0x4>; - reg-names = "sata", "pcie", "syscfg"; + reg = <0xfe38a000 0x100>, <0xfe804000 0x100>; + reg-names = "sata", "pcie"; }; }; -- cgit v1.2.3 From 2720948157ca5e2bddf8bbb3337686d026c87220 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Wed, 7 Jan 2015 15:04:08 +0000 Subject: ARM: STi: DT: STiH407: Add usb2 picophy dt nodes This patch adds the dt nodes for the usb2 picophy found on the stih407 device family. It is used on stih407 by the dwc3 usb3 controller when controlling usb2/1.1 devices. Signed-off-by: Peter Griffin Reviewed-by: Arnd Bergmann Signed-off-by: David S. Miller --- arch/arm/boot/dts/stih407-family.dtsi | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi index 3e31d32133b8..d4a8f843cdc8 100644 --- a/arch/arm/boot/dts/stih407-family.dtsi +++ b/arch/arm/boot/dts/stih407-family.dtsi @@ -274,5 +274,14 @@ status = "disabled"; }; + + usb2_picophy0: phy1 { + compatible = "st,stih407-usb2-phy"; + #phy-cells = <0>; + st,syscfg = <&syscfg_core 0x100 0xf4>; + resets = <&softreset STIH407_PICOPHY_SOFTRESET>, + <&picophyreset STIH407_PICOPHY0_RESET>; + reset-names = "global", "port"; + }; }; }; -- cgit v1.2.3 From a50457c729abce29a5fe885777f49352d600367c Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Wed, 7 Jan 2015 15:04:09 +0000 Subject: ARM: STi: DT: STiH410: Add usb2 picophy dt nodes This patch adds the dt nodes for the extra usb2 picophys found on the stih410. These two picophys are used in conjunction with the extra ehci/ohci usb controllers also found on the stih410 SoC. Signed-off-by: Peter Griffin Reviewed-by: Arnd Bergmann Signed-off-by: David S. Miller --- arch/arm/boot/dts/stih410.dtsi | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/stih410.dtsi b/arch/arm/boot/dts/stih410.dtsi index c05627eb717d..2e5e9ed8b615 100644 --- a/arch/arm/boot/dts/stih410.dtsi +++ b/arch/arm/boot/dts/stih410.dtsi @@ -10,5 +10,23 @@ #include "stih407-family.dtsi" #include "stih410-pinctrl.dtsi" / { + soc { + usb2_picophy1: phy2 { + compatible = "st,stih407-usb2-phy"; + #phy-cells = <0>; + st,syscfg = <&syscfg_core 0xf8 0xf4>; + resets = <&softreset STIH407_PICOPHY_SOFTRESET>, + <&picophyreset STIH407_PICOPHY0_RESET>; + reset-names = "global", "port"; + }; + usb2_picophy2: phy3 { + compatible = "st,stih407-usb2-phy"; + #phy-cells = <0>; + st,syscfg = <&syscfg_core 0xfc 0xf4>; + resets = <&softreset STIH407_PICOPHY_SOFTRESET>, + <&picophyreset STIH407_PICOPHY1_RESET>; + reset-names = "global", "port"; + }; + }; }; -- cgit v1.2.3 From 4343129cc82656c8336b0fe953b1c422bfcfad26 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Wed, 7 Jan 2015 15:04:10 +0000 Subject: ARM: STi: DT: STiH410: Add DT nodes for the ehci and ohci usb controllers. This patch adds the DT nodes for the extra ehci and ohci usb controllers on the stih410 SoC. Signed-off-by: Peter Griffin Reviewed-by: Arnd Bergmann Signed-off-by: David S. Miller --- arch/arm/boot/dts/stih410.dtsi | 52 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/stih410.dtsi b/arch/arm/boot/dts/stih410.dtsi index 2e5e9ed8b615..37995f4739d2 100644 --- a/arch/arm/boot/dts/stih410.dtsi +++ b/arch/arm/boot/dts/stih410.dtsi @@ -28,5 +28,57 @@ <&picophyreset STIH407_PICOPHY1_RESET>; reset-names = "global", "port"; }; + + ohci0: usb@9a03c00 { + compatible = "st,st-ohci-300x"; + reg = <0x9a03c00 0x100>; + interrupts = ; + clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>; + resets = <&powerdown STIH407_USB2_PORT0_POWERDOWN>, + <&softreset STIH407_USB2_PORT0_SOFTRESET>; + reset-names = "power", "softreset"; + phys = <&usb2_picophy1>; + phy-names = "usb"; + }; + + ehci0: usb@9a03e00 { + compatible = "st,st-ehci-300x"; + reg = <0x9a03e00 0x100>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb0>; + clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>; + resets = <&powerdown STIH407_USB2_PORT0_POWERDOWN>, + <&softreset STIH407_USB2_PORT0_SOFTRESET>; + reset-names = "power", "softreset"; + phys = <&usb2_picophy1>; + phy-names = "usb"; + }; + + ohci1: usb@9a83c00 { + compatible = "st,st-ohci-300x"; + reg = <0x9a83c00 0x100>; + interrupts = ; + clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>; + resets = <&powerdown STIH407_USB2_PORT1_POWERDOWN>, + <&softreset STIH407_USB2_PORT1_SOFTRESET>; + reset-names = "power", "softreset"; + phys = <&usb2_picophy2>; + phy-names = "usb"; + }; + + ehci1: usb@9a83e00 { + compatible = "st,st-ehci-300x"; + reg = <0x9a83e00 0x100>; + interrupts = ; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb1>; + clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>; + resets = <&powerdown STIH407_USB2_PORT1_POWERDOWN>, + <&softreset STIH407_USB2_PORT1_SOFTRESET>; + reset-names = "power", "softreset"; + phys = <&usb2_picophy2>; + phy-names = "usb"; + }; }; }; -- cgit v1.2.3 From 304a11e86751302a31fa3e8b31329aedfbdb7df5 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Wed, 7 Jan 2015 15:04:11 +0000 Subject: ARM: multi_v7_defconfig: Enable stih407 usb picophy This patch enables the picoPHY usb phy which is used by the usb2 and usb3 host controllers when controlling usb2/1.1 devices. It is found in stih407 family SoC's from STMicroelectronics. Signed-off-by: Peter Griffin Acked-by: Lee Jones Reviewed-by: Arnd Bergmann Signed-off-by: David S. Miller --- arch/arm/configs/multi_v7_defconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig index bc393b7e5ece..444685c44055 100644 --- a/arch/arm/configs/multi_v7_defconfig +++ b/arch/arm/configs/multi_v7_defconfig @@ -456,6 +456,7 @@ CONFIG_OMAP_USB2=y CONFIG_TI_PIPE3=y CONFIG_PHY_MIPHY365X=y CONFIG_PHY_STIH41X_USB=y +CONFIG_PHY_STIH407_USB=y CONFIG_PHY_SUN4I_USB=y CONFIG_EXT4_FS=y CONFIG_AUTOFS4_FS=y -- cgit v1.2.3 From 9b1a6d36c38d236b42d912fce852f37d2367b593 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Wed, 7 Jan 2015 15:04:12 +0000 Subject: stmmac: dwmac-sti: Pass sysconfig register offset via syscon dt property. Based on Arnds review comments here https://lkml.org/lkml/2014/11/13/161, we should not be mixing address spaces in the reg property like this driver currently does. This patch updates the driver, dt docs and also the existing dt nodes to pass the sysconfig offset in the syscon dt property. This patch breaks DT compatibility! But this platform is considered WIP, and is only used by a few developers who are upstreaming support for it. This change has been done as a single atomic commit to ensure it is bisectable. Signed-off-by: Peter Griffin Reviewed-by: Arnd Bergmann Signed-off-by: David S. Miller --- arch/arm/boot/dts/stih415.dtsi | 12 ++++++------ arch/arm/boot/dts/stih416.dtsi | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/stih415.dtsi b/arch/arm/boot/dts/stih415.dtsi index 9198c12765ea..19b019b5f30e 100644 --- a/arch/arm/boot/dts/stih415.dtsi +++ b/arch/arm/boot/dts/stih415.dtsi @@ -153,8 +153,8 @@ compatible = "st,stih415-dwmac", "snps,dwmac", "snps,dwmac-3.610"; status = "disabled"; - reg = <0xfe810000 0x8000>, <0x148 0x4>; - reg-names = "stmmaceth", "sti-ethconf"; + reg = <0xfe810000 0x8000>; + reg-names = "stmmaceth"; interrupts = <0 147 0>, <0 148 0>, <0 149 0>; interrupt-names = "macirq", "eth_wake_irq", "eth_lpi"; @@ -165,7 +165,7 @@ snps,mixed-burst; snps,force_sf_dma_mode; - st,syscon = <&syscfg_rear>; + st,syscon = <&syscfg_rear 0x148>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_mii0>; @@ -177,8 +177,8 @@ device_type = "network"; compatible = "st,stih415-dwmac", "snps,dwmac", "snps,dwmac-3.610"; status = "disabled"; - reg = <0xfef08000 0x8000>, <0x74 0x4>; - reg-names = "stmmaceth", "sti-ethconf"; + reg = <0xfef08000 0x8000>; + reg-names = "stmmaceth"; interrupts = <0 150 0>, <0 151 0>, <0 152 0>; interrupt-names = "macirq", "eth_wake_irq", "eth_lpi"; @@ -186,7 +186,7 @@ snps,mixed-burst; snps,force_sf_dma_mode; - st,syscon = <&syscfg_sbc>; + st,syscon = <&syscfg_sbc 0x74>; resets = <&softreset STIH415_ETH1_SOFTRESET>; reset-names = "stmmaceth"; diff --git a/arch/arm/boot/dts/stih416.dtsi b/arch/arm/boot/dts/stih416.dtsi index 85afe01c34fa..ea28ebadab1a 100644 --- a/arch/arm/boot/dts/stih416.dtsi +++ b/arch/arm/boot/dts/stih416.dtsi @@ -163,8 +163,8 @@ device_type = "network"; compatible = "st,stih416-dwmac", "snps,dwmac", "snps,dwmac-3.710"; status = "disabled"; - reg = <0xfe810000 0x8000>, <0x8bc 0x4>; - reg-names = "stmmaceth", "sti-ethconf"; + reg = <0xfe810000 0x8000>; + reg-names = "stmmaceth"; interrupts = <0 133 0>, <0 134 0>, <0 135 0>; interrupt-names = "macirq", "eth_wake_irq", "eth_lpi"; @@ -172,7 +172,7 @@ snps,pbl = <32>; snps,mixed-burst; - st,syscon = <&syscfg_rear>; + st,syscon = <&syscfg_rear 0x8bc>; resets = <&softreset STIH416_ETH0_SOFTRESET>; reset-names = "stmmaceth"; pinctrl-names = "default"; @@ -185,15 +185,15 @@ device_type = "network"; compatible = "st,stih416-dwmac", "snps,dwmac", "snps,dwmac-3.710"; status = "disabled"; - reg = <0xfef08000 0x8000>, <0x7f0 0x4>; - reg-names = "stmmaceth", "sti-ethconf"; + reg = <0xfef08000 0x8000>; + reg-names = "stmmaceth"; interrupts = <0 136 0>, <0 137 0>, <0 138 0>; interrupt-names = "macirq", "eth_wake_irq", "eth_lpi"; snps,pbl = <32>; snps,mixed-burst; - st,syscon = <&syscfg_sbc>; + st,syscon = <&syscfg_sbc 0x7f0>; resets = <&softreset STIH416_ETH1_SOFTRESET>; reset-names = "stmmaceth"; -- cgit v1.2.3 From f52948ea12b61573224334ac0b637369ac56dc2f Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Fri, 9 Jan 2015 07:43:50 -0800 Subject: ARM: zynq: DT: Add pinctrl information MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add pinctrl descriptions to the zc702 and zc706 device trees. Signed-off-by: Soren Brinkmann Tested-by: Andreas Färber Reviewed-by: Linus Walleij Signed-off-by: Michal Simek --- arch/arm/boot/dts/zynq-7000.dtsi | 8 +- arch/arm/boot/dts/zynq-zc702.dts | 181 +++++++++++++++++++++++++++++++++++++++ arch/arm/boot/dts/zynq-zc706.dts | 152 ++++++++++++++++++++++++++++++++ 3 files changed, 340 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi index f1dd2a7020ae..c9b9722c0c59 100644 --- a/arch/arm/boot/dts/zynq-7000.dtsi +++ b/arch/arm/boot/dts/zynq-7000.dtsi @@ -237,7 +237,7 @@ slcr: slcr@f8000000 { #address-cells = <1>; #size-cells = <1>; - compatible = "xlnx,zynq-slcr", "syscon"; + compatible = "xlnx,zynq-slcr", "syscon", "simple-bus"; reg = <0xF8000000 0x1000>; ranges; clkc: clkc@100 { @@ -257,6 +257,12 @@ "dbg_trc", "dbg_apb"; reg = <0x100 0x100>; }; + + pinctrl0: pinctrl@700 { + compatible = "xlnx,pinctrl-zynq"; + reg = <0x700 0x200>; + syscon = <&slcr>; + }; }; dmac_s: dmac@f8003000 { diff --git a/arch/arm/boot/dts/zynq-zc702.dts b/arch/arm/boot/dts/zynq-zc702.dts index 399fed4d9c19..365bdd407eb4 100644 --- a/arch/arm/boot/dts/zynq-zc702.dts +++ b/arch/arm/boot/dts/zynq-zc702.dts @@ -45,6 +45,8 @@ &can0 { status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_can0_default>; }; &clkc { @@ -55,15 +57,24 @@ status = "okay"; phy-mode = "rgmii-id"; phy-handle = <ðernet_phy>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gem0_default>; ethernet_phy: ethernet-phy@7 { reg = <7>; }; }; +&gpio0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio0_default>; +}; + &i2c0 { status = "okay"; clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c0_default>; i2cswitch@74 { compatible = "nxp,pca9548"; @@ -137,12 +148,182 @@ }; }; +&pinctrl0 { + pinctrl_can0_default: can0-default { + mux { + function = "can0"; + groups = "can0_9_grp"; + }; + + conf { + groups = "can0_9_grp"; + slew-rate = <0>; + io-standard = <1>; + }; + + conf-rx { + pins = "MIO46"; + bias-high-impedance; + }; + + conf-tx { + pins = "MIO47"; + bias-disable; + }; + }; + + pinctrl_gem0_default: gem0-default { + mux { + function = "ethernet0"; + groups = "ethernet0_0_grp"; + }; + + conf { + groups = "ethernet0_0_grp"; + slew-rate = <0>; + io-standard = <4>; + }; + + conf-rx { + pins = "MIO22", "MIO23", "MIO24", "MIO25", "MIO26", "MIO27"; + bias-high-impedance; + low-power-disable; + }; + + conf-tx { + pins = "MIO16", "MIO17", "MIO18", "MIO19", "MIO20", "MIO21"; + bias-disable; + low-power-enable; + }; + + mux-mdio { + function = "mdio0"; + groups = "mdio0_0_grp"; + }; + + conf-mdio { + groups = "mdio0_0_grp"; + slew-rate = <0>; + io-standard = <1>; + bias-disable; + }; + }; + + pinctrl_gpio0_default: gpio0-default { + mux { + function = "gpio0"; + groups = "gpio0_7_grp", "gpio0_8_grp", "gpio0_9_grp", + "gpio0_10_grp", "gpio0_11_grp", "gpio0_12_grp", + "gpio0_13_grp", "gpio0_14_grp"; + }; + + conf { + groups = "gpio0_7_grp", "gpio0_8_grp", "gpio0_9_grp", + "gpio0_10_grp", "gpio0_11_grp", "gpio0_12_grp", + "gpio0_13_grp", "gpio0_14_grp"; + slew-rate = <0>; + io-standard = <1>; + }; + + conf-pull-up { + pins = "MIO9", "MIO10", "MIO11", "MIO12", "MIO13", "MIO14"; + bias-pull-up; + }; + + conf-pull-none { + pins = "MIO7", "MIO8"; + bias-disable; + }; + }; + + pinctrl_i2c0_default: i2c0-default { + mux { + groups = "i2c0_10_grp"; + function = "i2c0"; + }; + + conf { + groups = "i2c0_10_grp"; + bias-pull-up; + slew-rate = <0>; + io-standard = <1>; + }; + }; + + pinctrl_sdhci0_default: sdhci0-default { + mux { + groups = "sdio0_2_grp"; + function = "sdio0"; + }; + + conf { + groups = "sdio0_2_grp"; + slew-rate = <0>; + io-standard = <1>; + bias-disable; + }; + + mux-cd { + groups = "gpio0_0_grp"; + function = "sdio0_cd"; + }; + + conf-cd { + groups = "gpio0_0_grp"; + bias-high-impedance; + bias-pull-up; + slew-rate = <0>; + io-standard = <1>; + }; + + mux-wp { + groups = "gpio0_15_grp"; + function = "sdio0_wp"; + }; + + conf-wp { + groups = "gpio0_15_grp"; + bias-high-impedance; + bias-pull-up; + slew-rate = <0>; + io-standard = <1>; + }; + }; + + pinctrl_uart1_default: uart1-default { + mux { + groups = "uart1_10_grp"; + function = "uart1"; + }; + + conf { + groups = "uart1_10_grp"; + slew-rate = <0>; + io-standard = <1>; + }; + + conf-rx { + pins = "MIO49"; + bias-high-impedance; + }; + + conf-tx { + pins = "MIO48"; + bias-disable = <0>; + }; + }; +}; + &sdhci0 { status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdhci0_default>; }; &uart1 { status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1_default>; }; &usb0 { diff --git a/arch/arm/boot/dts/zynq-zc706.dts b/arch/arm/boot/dts/zynq-zc706.dts index 89cc9adc569d..6979ce23175f 100644 --- a/arch/arm/boot/dts/zynq-zc706.dts +++ b/arch/arm/boot/dts/zynq-zc706.dts @@ -41,15 +41,24 @@ status = "okay"; phy-mode = "rgmii-id"; phy-handle = <ðernet_phy>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gem0_default>; ethernet_phy: ethernet-phy@7 { reg = <7>; }; }; +&gpio0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio0_default>; +}; + &i2c0 { status = "okay"; clock-frequency = <400000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c0_default>; i2cswitch@74 { compatible = "nxp,pca9548"; @@ -115,12 +124,155 @@ }; }; +&pinctrl0 { + pinctrl_gem0_default: gem0-default { + mux { + function = "ethernet0"; + groups = "ethernet0_0_grp"; + }; + + conf { + groups = "ethernet0_0_grp"; + slew-rate = <0>; + io-standard = <4>; + }; + + conf-rx { + pins = "MIO22", "MIO23", "MIO24", "MIO25", "MIO26", "MIO27"; + bias-high-impedance; + low-power-disable; + }; + + conf-tx { + pins = "MIO16", "MIO17", "MIO18", "MIO19", "MIO20", "MIO21"; + low-power-enable; + bias-disable; + }; + + mux-mdio { + function = "mdio0"; + groups = "mdio0_0_grp"; + }; + + conf-mdio { + groups = "mdio0_0_grp"; + slew-rate = <0>; + io-standard = <1>; + bias-disable; + }; + }; + + pinctrl_gpio0_default: gpio0-default { + mux { + function = "gpio0"; + groups = "gpio0_7_grp", "gpio0_46_grp", "gpio0_47_grp"; + }; + + conf { + groups = "gpio0_7_grp", "gpio0_46_grp", "gpio0_47_grp"; + slew-rate = <0>; + io-standard = <1>; + }; + + conf-pull-up { + pins = "MIO46", "MIO47"; + bias-pull-up; + }; + + conf-pull-none { + pins = "MIO7"; + bias-disable; + }; + }; + + pinctrl_i2c0_default: i2c0-default { + mux { + groups = "i2c0_10_grp"; + function = "i2c0"; + }; + + conf { + groups = "i2c0_10_grp"; + bias-pull-up; + slew-rate = <0>; + io-standard = <1>; + }; + }; + + pinctrl_sdhci0_default: sdhci0-default { + mux { + groups = "sdio0_2_grp"; + function = "sdio0"; + }; + + conf { + groups = "sdio0_2_grp"; + slew-rate = <0>; + io-standard = <1>; + bias-disable; + }; + + mux-cd { + groups = "gpio0_14_grp"; + function = "sdio0_cd"; + }; + + conf-cd { + groups = "gpio0_14_grp"; + bias-high-impedance; + bias-pull-up; + slew-rate = <0>; + io-standard = <1>; + }; + + mux-wp { + groups = "gpio0_15_grp"; + function = "sdio0_wp"; + }; + + conf-wp { + groups = "gpio0_15_grp"; + bias-high-impedance; + bias-pull-up; + slew-rate = <0>; + io-standard = <1>; + }; + }; + + pinctrl_uart1_default: uart1-default { + mux { + groups = "uart1_10_grp"; + function = "uart1"; + }; + + conf { + groups = "uart1_10_grp"; + slew-rate = <0>; + io-standard = <1>; + }; + + conf-rx { + pins = "MIO49"; + bias-high-impedance; + }; + + conf-tx { + pins = "MIO48"; + bias-disable; + }; + }; +}; + &sdhci0 { status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdhci0_default>; }; &uart1 { status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1_default>; }; &usb0 { -- cgit v1.2.3 From 1601ce07a0c37e08319d002893a9d54d122cd0f6 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Fri, 9 Jan 2015 07:43:49 -0800 Subject: ARM: zynq: Enable pinctrl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Select pinctrl and the Zynq pinctrl driver. Signed-off-by: Soren Brinkmann Tested-by: Andreas Färber Acked-by: Linus Walleij Signed-off-by: Michal Simek --- arch/arm/mach-zynq/Kconfig | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig index aaa5162c1509..78e5e007f52d 100644 --- a/arch/arm/mach-zynq/Kconfig +++ b/arch/arm/mach-zynq/Kconfig @@ -9,6 +9,8 @@ config ARCH_ZYNQ select HAVE_ARM_TWD if SMP select ICST select MFD_SYSCON + select PINCTRL + select PINCTRL_ZYNQ select SOC_BUS help Support for Xilinx Zynq ARM Cortex A9 Platform -- cgit v1.2.3 From e1e1fddae74b72d0415965821ad00fe39aac6f13 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 20 Oct 2014 14:02:15 +0200 Subject: arm64/mm: add explicit struct_mm argument to __create_mapping() Currently, swapper_pg_dir and idmap_pg_dir share the init_mm mm_struct instance. To allow the introduction of other pg_dir instances, for instance, for UEFI's mapping of Runtime Services, make the struct_mm instance an explicit argument that gets passed down to the pmd and pte instantiation functions. Note that the consumers (pmd_populate/pgd_populate) of the mm_struct argument don't actually inspect it, but let's fix it for correctness' sake. Acked-by: Steve Capper Tested-by: Leif Lindholm Signed-off-by: Ard Biesheuvel --- arch/arm64/mm/mmu.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'arch') diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 6032f3e3056a..7d5dfe2d3de0 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -156,9 +156,9 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, } while (pte++, addr += PAGE_SIZE, addr != end); } -static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, - unsigned long end, phys_addr_t phys, - int map_io) +static void __init alloc_init_pmd(struct mm_struct *mm, pud_t *pud, + unsigned long addr, unsigned long end, + phys_addr_t phys, int map_io) { pmd_t *pmd; unsigned long next; @@ -178,7 +178,7 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, */ if (pud_none(*pud) || pud_bad(*pud)) { pmd = early_alloc(PTRS_PER_PMD * sizeof(pmd_t)); - pud_populate(&init_mm, pud, pmd); + pud_populate(mm, pud, pmd); } pmd = pmd_offset(pud, addr); @@ -202,16 +202,16 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, } while (pmd++, addr = next, addr != end); } -static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, - unsigned long end, phys_addr_t phys, - int map_io) +static void __init alloc_init_pud(struct mm_struct *mm, pgd_t *pgd, + unsigned long addr, unsigned long end, + phys_addr_t phys, int map_io) { pud_t *pud; unsigned long next; if (pgd_none(*pgd)) { pud = early_alloc(PTRS_PER_PUD * sizeof(pud_t)); - pgd_populate(&init_mm, pgd, pud); + pgd_populate(mm, pgd, pud); } BUG_ON(pgd_bad(*pgd)); @@ -240,7 +240,7 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, flush_tlb_all(); } } else { - alloc_init_pmd(pud, addr, next, phys, map_io); + alloc_init_pmd(mm, pud, addr, next, phys, map_io); } phys += next - addr; } while (pud++, addr = next, addr != end); @@ -250,9 +250,9 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, * Create the page directory entries and any necessary page tables for the * mapping specified by 'md'. */ -static void __init __create_mapping(pgd_t *pgd, phys_addr_t phys, - unsigned long virt, phys_addr_t size, - int map_io) +static void __init __create_mapping(struct mm_struct *mm, pgd_t *pgd, + phys_addr_t phys, unsigned long virt, + phys_addr_t size, int map_io) { unsigned long addr, length, end, next; @@ -262,7 +262,7 @@ static void __init __create_mapping(pgd_t *pgd, phys_addr_t phys, end = addr + length; do { next = pgd_addr_end(addr, end); - alloc_init_pud(pgd, addr, next, phys, map_io); + alloc_init_pud(mm, pgd, addr, next, phys, map_io); phys += next - addr; } while (pgd++, addr = next, addr != end); } @@ -275,7 +275,8 @@ static void __init create_mapping(phys_addr_t phys, unsigned long virt, &phys, virt); return; } - __create_mapping(pgd_offset_k(virt & PAGE_MASK), phys, virt, size, 0); + __create_mapping(&init_mm, pgd_offset_k(virt & PAGE_MASK), phys, virt, + size, 0); } void __init create_id_mapping(phys_addr_t addr, phys_addr_t size, int map_io) @@ -284,7 +285,7 @@ void __init create_id_mapping(phys_addr_t addr, phys_addr_t size, int map_io) pr_warn("BUG: not creating id mapping for %pa\n", &addr); return; } - __create_mapping(&idmap_pg_dir[pgd_index(addr)], + __create_mapping(&init_mm, &idmap_pg_dir[pgd_index(addr)], addr, addr, size, map_io); } -- cgit v1.2.3 From 8ce837cee8f51fb0eacb32c85461ea2f0fafc9f8 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 20 Oct 2014 15:42:07 +0200 Subject: arm64/mm: add create_pgd_mapping() to create private page tables For UEFI, we need to install the memory mappings used for Runtime Services in a dedicated set of page tables. Add create_pgd_mapping(), which allows us to allocate and install those page table entries early. Reviewed-by: Will Deacon Tested-by: Leif Lindholm Signed-off-by: Ard Biesheuvel --- arch/arm64/include/asm/mmu.h | 3 +++ arch/arm64/include/asm/pgtable.h | 5 +++++ arch/arm64/mm/mmu.c | 43 ++++++++++++++++++++-------------------- 3 files changed, 30 insertions(+), 21 deletions(-) (limited to 'arch') diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h index c2f006c48bdb..5fd40c43be80 100644 --- a/arch/arm64/include/asm/mmu.h +++ b/arch/arm64/include/asm/mmu.h @@ -33,5 +33,8 @@ extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt); extern void init_mem_pgprot(void); /* create an identity mapping for memory (or io if map_io is true) */ extern void create_id_mapping(phys_addr_t addr, phys_addr_t size, int map_io); +extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, + unsigned long virt, phys_addr_t size, + pgprot_t prot); #endif diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 210d632aa5ad..59079248529d 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -264,6 +264,11 @@ static inline pmd_t pte_pmd(pte_t pte) return __pmd(pte_val(pte)); } +static inline pgprot_t mk_sect_prot(pgprot_t prot) +{ + return __pgprot(pgprot_val(prot) & ~PTE_TABLE_BIT); +} + /* * THP definitions. */ diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 7d5dfe2d3de0..3f3d5aa4a8b1 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -158,20 +158,10 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, static void __init alloc_init_pmd(struct mm_struct *mm, pud_t *pud, unsigned long addr, unsigned long end, - phys_addr_t phys, int map_io) + phys_addr_t phys, pgprot_t prot) { pmd_t *pmd; unsigned long next; - pmdval_t prot_sect; - pgprot_t prot_pte; - - if (map_io) { - prot_sect = PROT_SECT_DEVICE_nGnRE; - prot_pte = __pgprot(PROT_DEVICE_nGnRE); - } else { - prot_sect = PROT_SECT_NORMAL_EXEC; - prot_pte = PAGE_KERNEL_EXEC; - } /* * Check for initial section mappings in the pgd/pud and remove them. @@ -187,7 +177,8 @@ static void __init alloc_init_pmd(struct mm_struct *mm, pud_t *pud, /* try section mapping first */ if (((addr | next | phys) & ~SECTION_MASK) == 0) { pmd_t old_pmd =*pmd; - set_pmd(pmd, __pmd(phys | prot_sect)); + set_pmd(pmd, __pmd(phys | + pgprot_val(mk_sect_prot(prot)))); /* * Check for previous table entries created during * boot (__create_page_tables) and flush them. @@ -196,7 +187,7 @@ static void __init alloc_init_pmd(struct mm_struct *mm, pud_t *pud, flush_tlb_all(); } else { alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys), - prot_pte); + prot); } phys += next - addr; } while (pmd++, addr = next, addr != end); @@ -204,7 +195,7 @@ static void __init alloc_init_pmd(struct mm_struct *mm, pud_t *pud, static void __init alloc_init_pud(struct mm_struct *mm, pgd_t *pgd, unsigned long addr, unsigned long end, - phys_addr_t phys, int map_io) + phys_addr_t phys, pgprot_t prot) { pud_t *pud; unsigned long next; @@ -222,10 +213,11 @@ static void __init alloc_init_pud(struct mm_struct *mm, pgd_t *pgd, /* * For 4K granule only, attempt to put down a 1GB block */ - if (!map_io && (PAGE_SHIFT == 12) && + if ((PAGE_SHIFT == 12) && ((addr | next | phys) & ~PUD_MASK) == 0) { pud_t old_pud = *pud; - set_pud(pud, __pud(phys | PROT_SECT_NORMAL_EXEC)); + set_pud(pud, __pud(phys | + pgprot_val(mk_sect_prot(prot)))); /* * If we have an old value for a pud, it will @@ -240,7 +232,7 @@ static void __init alloc_init_pud(struct mm_struct *mm, pgd_t *pgd, flush_tlb_all(); } } else { - alloc_init_pmd(mm, pud, addr, next, phys, map_io); + alloc_init_pmd(mm, pud, addr, next, phys, prot); } phys += next - addr; } while (pud++, addr = next, addr != end); @@ -252,7 +244,7 @@ static void __init alloc_init_pud(struct mm_struct *mm, pgd_t *pgd, */ static void __init __create_mapping(struct mm_struct *mm, pgd_t *pgd, phys_addr_t phys, unsigned long virt, - phys_addr_t size, int map_io) + phys_addr_t size, pgprot_t prot) { unsigned long addr, length, end, next; @@ -262,7 +254,7 @@ static void __init __create_mapping(struct mm_struct *mm, pgd_t *pgd, end = addr + length; do { next = pgd_addr_end(addr, end); - alloc_init_pud(mm, pgd, addr, next, phys, map_io); + alloc_init_pud(mm, pgd, addr, next, phys, prot); phys += next - addr; } while (pgd++, addr = next, addr != end); } @@ -276,7 +268,7 @@ static void __init create_mapping(phys_addr_t phys, unsigned long virt, return; } __create_mapping(&init_mm, pgd_offset_k(virt & PAGE_MASK), phys, virt, - size, 0); + size, PAGE_KERNEL_EXEC); } void __init create_id_mapping(phys_addr_t addr, phys_addr_t size, int map_io) @@ -286,7 +278,16 @@ void __init create_id_mapping(phys_addr_t addr, phys_addr_t size, int map_io) return; } __create_mapping(&init_mm, &idmap_pg_dir[pgd_index(addr)], - addr, addr, size, map_io); + addr, addr, size, + map_io ? __pgprot(PROT_DEVICE_nGnRE) + : PAGE_KERNEL_EXEC); +} + +void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, + unsigned long virt, phys_addr_t size, + pgprot_t prot) +{ + __create_mapping(mm, pgd_offset(mm, virt), phys, virt, size, prot); } static void __init map_mem(void) -- cgit v1.2.3 From 1bd0abb0c924a8b28c6466cdd6bb34ea053541dc Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 17 Nov 2014 13:50:21 +0100 Subject: arm64/efi: set EFI_ALLOC_ALIGN to 64 KB Set EFI_ALLOC_ALIGN to 64 KB so that all allocations done by the stub are naturally compatible with a 64 KB granule kernel. Acked-by: Leif Lindholm Tested-by: Leif Lindholm Signed-off-by: Ard Biesheuvel --- arch/arm64/include/asm/efi.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index a34fd3b12e2b..71291253114f 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -44,4 +44,6 @@ extern void efi_idmap_init(void); #define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) +#define EFI_ALLOC_ALIGN SZ_64K + #endif /* _ASM_EFI_H */ -- cgit v1.2.3 From 86a2d2ac5e5d452ddbad3d9522a68d77c4cb4329 Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Mon, 12 Jan 2015 17:35:49 +0900 Subject: ARM: dts: Add dts file for Odroid XU3 board Add DTS for the Hardkernel Odroid XU3. The name of the DTS file is kept the same as the vendors naming, which means it's prefixed with exynos5422 instead of exynos5800 as the SoC name even though it includes the exyno5800 dtsi. Signed-off-by: Sjoerd Simons Tested-by: Kevin Hilman Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/exynos5422-odroidxu3.dts | 332 +++++++++++++++++++++++++++++ 2 files changed, 333 insertions(+) create mode 100644 arch/arm/boot/dts/exynos5422-odroidxu3.dts (limited to 'arch') diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 91bd5bd62857..df397c22073c 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -98,6 +98,7 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos3250-monk.dtb \ exynos5420-arndale-octa.dtb \ exynos5420-peach-pit.dtb \ exynos5420-smdk5420.dtb \ + exynos5422-odroidxu3.dtb \ exynos5440-sd5v1.dtb \ exynos5440-ssdk5440.dtb \ exynos5800-peach-pi.dtb diff --git a/arch/arm/boot/dts/exynos5422-odroidxu3.dts b/arch/arm/boot/dts/exynos5422-odroidxu3.dts new file mode 100644 index 000000000000..c29123c0734d --- /dev/null +++ b/arch/arm/boot/dts/exynos5422-odroidxu3.dts @@ -0,0 +1,332 @@ +/* + * Hardkernel Odroid XU3 board device tree source + * + * Copyright (c) 2014 Collabora Ltd. + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * http://www.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. +*/ + +/dts-v1/; +#include "exynos5800.dtsi" + +/ { + model = "Hardkernel Odroid XU3"; + compatible = "hardkernel,odroid-xu3", "samsung,exynos5800", "samsung,exynos5"; + + memory { + reg = <0x40000000 0x80000000>; + }; + + chosen { + linux,stdout-path = &serial_2; + }; + + fimd@14400000 { + status = "okay"; + }; + + firmware@02073000 { + compatible = "samsung,secure-firmware"; + reg = <0x02073000 0x1000>; + }; + + fixed-rate-clocks { + oscclk { + compatible = "samsung,exynos5420-oscclk"; + clock-frequency = <24000000>; + }; + }; + + hsi2c_4: i2c@12CA0000 { + status = "okay"; + + s2mps11_pmic@66 { + compatible = "samsung,s2mps11-pmic"; + reg = <0x66>; + s2mps11,buck2-ramp-delay = <12>; + s2mps11,buck34-ramp-delay = <12>; + s2mps11,buck16-ramp-delay = <12>; + s2mps11,buck6-ramp-enable = <1>; + s2mps11,buck2-ramp-enable = <1>; + s2mps11,buck3-ramp-enable = <1>; + s2mps11,buck4-ramp-enable = <1>; + + s2mps11_osc: clocks { + #clock-cells = <1>; + clock-output-names = "s2mps11_ap", + "s2mps11_cp", "s2mps11_bt"; + }; + + regulators { + ldo1_reg: LDO1 { + regulator-name = "vdd_ldo1"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + }; + + ldo3_reg: LDO3 { + regulator-name = "vdd_ldo3"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + ldo5_reg: LDO5 { + regulator-name = "vdd_ldo5"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + ldo6_reg: LDO6 { + regulator-name = "vdd_ldo6"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + }; + + ldo7_reg: LDO7 { + regulator-name = "vdd_ldo7"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + ldo8_reg: LDO8 { + regulator-name = "vdd_ldo8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + ldo9_reg: LDO9 { + regulator-name = "vdd_ldo9"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + }; + + ldo10_reg: LDO10 { + regulator-name = "vdd_ldo10"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + ldo11_reg: LDO11 { + regulator-name = "vdd_ldo11"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + regulator-always-on; + }; + + ldo12_reg: LDO12 { + regulator-name = "vdd_ldo12"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + ldo13_reg: LDO13 { + regulator-name = "vdd_ldo13"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-always-on; + }; + + ldo15_reg: LDO15 { + regulator-name = "vdd_ldo15"; + regulator-min-microvolt = <3100000>; + regulator-max-microvolt = <3100000>; + regulator-always-on; + }; + + ldo16_reg: LDO16 { + regulator-name = "vdd_ldo16"; + regulator-min-microvolt = <2200000>; + regulator-max-microvolt = <2200000>; + regulator-always-on; + }; + + ldo17_reg: LDO17 { + regulator-name = "tsp_avdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + ldo19_reg: LDO19 { + regulator-name = "vdd_sd"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-always-on; + }; + + ldo24_reg: LDO24 { + regulator-name = "tsp_io"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-always-on; + }; + + buck1_reg: BUCK1 { + regulator-name = "vdd_mif"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1300000>; + regulator-always-on; + regulator-boot-on; + }; + + buck2_reg: BUCK2 { + regulator-name = "vdd_arm"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + regulator-boot-on; + }; + + buck3_reg: BUCK3 { + regulator-name = "vdd_int"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1400000>; + regulator-always-on; + regulator-boot-on; + }; + + buck4_reg: BUCK4 { + regulator-name = "vdd_g3d"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1400000>; + regulator-always-on; + regulator-boot-on; + }; + + buck5_reg: BUCK5 { + regulator-name = "vdd_mem"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1400000>; + regulator-always-on; + regulator-boot-on; + }; + + buck6_reg: BUCK6 { + regulator-name = "vdd_kfc"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + regulator-boot-on; + }; + + buck7_reg: BUCK7 { + regulator-name = "vdd_1.0v_ldo"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + regulator-boot-on; + }; + + buck8_reg: BUCK8 { + regulator-name = "vdd_1.8v_ldo"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + regulator-boot-on; + }; + + buck9_reg: BUCK9 { + regulator-name = "vdd_2.8v_ldo"; + regulator-min-microvolt = <3000000>; + regulator-max-microvolt = <3750000>; + regulator-always-on; + regulator-boot-on; + }; + + buck10_reg: BUCK10 { + regulator-name = "vdd_vmem"; + regulator-min-microvolt = <2850000>; + regulator-max-microvolt = <2850000>; + regulator-always-on; + regulator-boot-on; + }; + }; + }; + }; + + i2c_2: i2c@12C80000 { + samsung,i2c-sda-delay = <100>; + samsung,i2c-max-bus-freq = <66000>; + status = "okay"; + + hdmiddc@50 { + compatible = "samsung,exynos4210-hdmiddc"; + reg = <0x50>; + }; + }; + + rtc@101E0000 { + status = "okay"; + }; +}; + +&hdmi { + status = "okay"; + hpd-gpio = <&gpx3 7 0>; + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_hpd_irq>; + + vdd_osc-supply = <&ldo7_reg>; + vdd_pll-supply = <&ldo6_reg>; + vdd-supply = <&ldo6_reg>; +}; + +&mfc { + samsung,mfc-r = <0x43000000 0x800000>; + samsung,mfc-l = <0x51000000 0x800000>; +}; + +&mmc_0 { + status = "okay"; + broken-cd; + card-detect-delay = <200>; + samsung,dw-mshc-ciu-div = <3>; + samsung,dw-mshc-sdr-timing = <0 4>; + samsung,dw-mshc-ddr-timing = <0 2>; + pinctrl-names = "default"; + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4 &sd0_bus8>; + bus-width = <8>; + cap-mmc-highspeed; +}; + +&mmc_2 { + status = "okay"; + card-detect-delay = <200>; + samsung,dw-mshc-ciu-div = <3>; + samsung,dw-mshc-sdr-timing = <0 4>; + samsung,dw-mshc-ddr-timing = <0 2>; + pinctrl-names = "default"; + pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>; + bus-width = <4>; + cap-sd-highspeed; +}; + +&pinctrl_0 { + hdmi_hpd_irq: hdmi-hpd-irq { + samsung,pins = "gpx3-7"; + samsung,pin-function = <0>; + samsung,pin-pud = <1>; + samsung,pin-drv = <0>; + }; +}; + +&usbdrd_dwc3_0 { + dr_mode = "host"; +}; + +&usbdrd_dwc3_1 { + dr_mode = "otg"; +}; -- cgit v1.2.3 From adacba58199871919956603aa51002d683484182 Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Mon, 12 Jan 2015 17:46:36 +0900 Subject: ARM: EXYNOS: Recognize Samsung MFC v8 devices Also setup memory allocations for version 8 of the MFC as present in Samsung Exynos 5422/5800 SoCs Signed-off-by: Sjoerd Simons Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/exynos.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index c13d0837fa8c..b343a1a626d5 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -282,6 +282,7 @@ static void __init exynos_reserve(void) "samsung,mfc-v5", "samsung,mfc-v6", "samsung,mfc-v7", + "samsung,mfc-v8", }; for (i = 0; i < ARRAY_SIZE(mfc_mem); i++) -- cgit v1.2.3 From 11ab02b883a929a2b7f0936f0dc20d9789843ee4 Mon Sep 17 00:00:00 2001 From: Jaewon Kim Date: Mon, 12 Jan 2015 17:54:54 +0900 Subject: ARM: dts: Add exynos_usbphy node for exynos3250 This patch adds device tree node for exynos_usbphy to use USB 2.0 Device. Signed-off-by: Jaewon Kim Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos3250.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/exynos3250.dtsi b/arch/arm/boot/dts/exynos3250.dtsi index 22465494b796..27d385feca85 100644 --- a/arch/arm/boot/dts/exynos3250.dtsi +++ b/arch/arm/boot/dts/exynos3250.dtsi @@ -279,6 +279,16 @@ status = "disabled"; }; + exynos_usbphy: exynos-usbphy@125B0000 { + compatible = "samsung,exynos3250-usb2-phy"; + reg = <0x125B0000 0x100>; + samsung,pmureg-phandle = <&pmu_system_controller>; + clocks = <&cmu CLK_USBOTG>, <&cmu CLK_SCLK_UPLL>; + clock-names = "phy", "ref"; + #phy-cells = <1>; + status = "disabled"; + }; + amba { compatible = "arm,amba-bus"; #address-cells = <1>; -- cgit v1.2.3 From e0c6e929b3dd5abcb8b198bff51cd0e57f64bfc0 Mon Sep 17 00:00:00 2001 From: Jaewon Kim Date: Mon, 12 Jan 2015 17:54:54 +0900 Subject: ARM: dts: Add hsotg node for exynos3250 This patch adds device tree node for hsotg to control USB 2.0 Device. Signed-off-by: Jaewon Kim Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos3250.dtsi | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/exynos3250.dtsi b/arch/arm/boot/dts/exynos3250.dtsi index 27d385feca85..204a84be5b87 100644 --- a/arch/arm/boot/dts/exynos3250.dtsi +++ b/arch/arm/boot/dts/exynos3250.dtsi @@ -255,6 +255,17 @@ status = "disabled"; }; + hsotg: hsotg@12480000 { + compatible = "snps,dwc2"; + reg = <0x12480000 0x20000>; + interrupts = <0 141 0>; + clocks = <&cmu CLK_USBOTG>; + clock-names = "otg"; + phys = <&exynos_usbphy 0>; + phy-names = "usb2-phy"; + status = "disabled"; + }; + mshc_0: mshc@12510000 { compatible = "samsung,exynos5250-dw-mshc"; reg = <0x12510000 0x1000>; -- cgit v1.2.3 From cdc386681df4d4f26dbaa749cd98a26bbb648eed Mon Sep 17 00:00:00 2001 From: Jaewon Kim Date: Mon, 12 Jan 2015 17:54:54 +0900 Subject: ARM: dts: Enable USB node for exynos3250-rinato This patch enables hsotg and usbphy node to use USB 2.0 Device. Signed-off-by: Jaewon Kim Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos3250-rinato.dts | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/exynos3250-rinato.dts b/arch/arm/boot/dts/exynos3250-rinato.dts index 80aa8b4c4a3d..bf4c17bf8d27 100644 --- a/arch/arm/boot/dts/exynos3250-rinato.dts +++ b/arch/arm/boot/dts/exynos3250-rinato.dts @@ -125,6 +125,16 @@ }; }; +&exynos_usbphy { + status = "okay"; +}; + +&hsotg { + vusb_d-supply = <&ldo15_reg>; + vusb_a-supply = <&ldo12_reg>; + status = "okay"; +}; + &i2c_0 { #address-cells = <1>; #size-cells = <0>; -- cgit v1.2.3 From 3fc5f3a57240efec45333ab917a17626de0bd8bc Mon Sep 17 00:00:00 2001 From: Jaewon Kim Date: Mon, 12 Jan 2015 17:54:54 +0900 Subject: ARM: dts: Enable USB node for exynos3250-monk This patch adds device tree node for hsotg to control USB 2.0 Device. Signed-off-by: Jaewon Kim Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos3250-monk.dts | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/exynos3250-monk.dts b/arch/arm/boot/dts/exynos3250-monk.dts index 24822aa98057..0c1d85d0b6cf 100644 --- a/arch/arm/boot/dts/exynos3250-monk.dts +++ b/arch/arm/boot/dts/exynos3250-monk.dts @@ -134,6 +134,16 @@ }; }; +&exynos_usbphy { + status = "okay"; +}; + +&hsotg { + vusb_d-supply = <&ldo15_reg>; + vusb_a-supply = <&ldo12_reg>; + status = "okay"; +}; + &i2c_0 { #address-cells = <1>; #size-cells = <0>; -- cgit v1.2.3 From 19f0d87bc26e6579b981ce293adf3520c7e3ce38 Mon Sep 17 00:00:00 2001 From: Beomho Seo Date: Mon, 12 Jan 2015 18:00:09 +0900 Subject: ARM: dts: remove unnecessary gpio-key nodes for exynos3250 boards This patch removes unnecessary property of gpio-keys node. The gpio-keys driver doesn't use interrupts and interrupt-parent. Cc: Youngjun Cho Cc: Chanwoo Choi Reviewed-by: Chanwoo Choi Signed-off-by: Beomho Seo Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos3250-monk.dts | 2 -- arch/arm/boot/dts/exynos3250-rinato.dts | 2 -- 2 files changed, 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/exynos3250-monk.dts b/arch/arm/boot/dts/exynos3250-monk.dts index 0c1d85d0b6cf..2431b811df87 100644 --- a/arch/arm/boot/dts/exynos3250-monk.dts +++ b/arch/arm/boot/dts/exynos3250-monk.dts @@ -37,8 +37,6 @@ compatible = "gpio-keys"; power_key { - interrupt-parent = <&gpx2>; - interrupts = <7 0>; gpios = <&gpx2 7 1>; linux,code = ; label = "power key"; diff --git a/arch/arm/boot/dts/exynos3250-rinato.dts b/arch/arm/boot/dts/exynos3250-rinato.dts index bf4c17bf8d27..a2cbc6d95bbc 100644 --- a/arch/arm/boot/dts/exynos3250-rinato.dts +++ b/arch/arm/boot/dts/exynos3250-rinato.dts @@ -37,8 +37,6 @@ compatible = "gpio-keys"; power_key { - interrupt-parent = <&gpx2>; - interrupts = <7 0>; gpios = <&gpx2 7 1>; linux,code = ; label = "power key"; -- cgit v1.2.3 From 13b9b64e307db08fce12350ce2caed63dec59ddc Mon Sep 17 00:00:00 2001 From: Beomho Seo Date: Mon, 12 Jan 2015 18:00:15 +0900 Subject: ARM: dts: use macro in gpio keys for exynos3250 boards This patch replaces number by macro in gpio keys for exynos3250 boards. Cc: Youngjun Cho Cc: Chanwoo Choi Reviewed-by: Chanwoo Choi Signed-off-by: Beomho Seo Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos3250-monk.dts | 3 ++- arch/arm/boot/dts/exynos3250-rinato.dts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/exynos3250-monk.dts b/arch/arm/boot/dts/exynos3250-monk.dts index 2431b811df87..5e4a471faee1 100644 --- a/arch/arm/boot/dts/exynos3250-monk.dts +++ b/arch/arm/boot/dts/exynos3250-monk.dts @@ -15,6 +15,7 @@ /dts-v1/; #include "exynos3250.dtsi" #include +#include / { model = "Samsung Monk board"; @@ -37,7 +38,7 @@ compatible = "gpio-keys"; power_key { - gpios = <&gpx2 7 1>; + gpios = <&gpx2 7 GPIO_ACTIVE_LOW>; linux,code = ; label = "power key"; debounce-interval = <10>; diff --git a/arch/arm/boot/dts/exynos3250-rinato.dts b/arch/arm/boot/dts/exynos3250-rinato.dts index a2cbc6d95bbc..0c65155ff59e 100644 --- a/arch/arm/boot/dts/exynos3250-rinato.dts +++ b/arch/arm/boot/dts/exynos3250-rinato.dts @@ -15,6 +15,7 @@ /dts-v1/; #include "exynos3250.dtsi" #include +#include / { model = "Samsung Rinato board"; @@ -37,7 +38,7 @@ compatible = "gpio-keys"; power_key { - gpios = <&gpx2 7 1>; + gpios = <&gpx2 7 GPIO_ACTIVE_LOW>; linux,code = ; label = "power key"; debounce-interval = <10>; -- cgit v1.2.3 From b59b3afb94d42a8c29abdc9a6da799c60f0487b6 Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Mon, 12 Jan 2015 18:08:37 +0900 Subject: ARM: dts: add fimd device support for exynos3250-rinato This patch adds fimd device node which is a display controller for Exynos3250 Rinato board. Signed-off-by: Inki Dae Acked-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos3250-rinato.dts | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/exynos3250-rinato.dts b/arch/arm/boot/dts/exynos3250-rinato.dts index 0c65155ff59e..09333a966059 100644 --- a/arch/arm/boot/dts/exynos3250-rinato.dts +++ b/arch/arm/boot/dts/exynos3250-rinato.dts @@ -134,6 +134,17 @@ status = "okay"; }; +&fimd { + status = "okay"; + + i80-if-timings { + cs-setup = <0>; + wr-setup = <0>; + wr-act = <1>; + wr-hold = <0>; + }; +}; + &i2c_0 { #address-cells = <1>; #size-cells = <0>; -- cgit v1.2.3 From 2ea2473d7ae2c36f8087285f8c1461fb523a1af5 Mon Sep 17 00:00:00 2001 From: Inki Dae Date: Mon, 12 Jan 2015 18:10:27 +0900 Subject: ARM: dts: add Panel device support for exynos3250-rinato This patch adds MIPI-DSI and MIPI-DSI based S6E63J0X03 AMOLED panel device nodes for Exynos3250 Rinato board. Signed-off-by: Inki Dae Acked-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/boot/dts/exynos3250-rinato.dts | 59 +++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/exynos3250-rinato.dts b/arch/arm/boot/dts/exynos3250-rinato.dts index 09333a966059..c7f4fab6dfd9 100644 --- a/arch/arm/boot/dts/exynos3250-rinato.dts +++ b/arch/arm/boot/dts/exynos3250-rinato.dts @@ -134,6 +134,65 @@ status = "okay"; }; +&dsi_0 { + vddcore-supply = <&ldo6_reg>; + vddio-supply = <&ldo6_reg>; + samsung,pll-clock-frequency = <24000000>; + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@1 { + reg = <1>; + + dsi_out: endpoint { + remote-endpoint = <&dsi_in>; + samsung,burst-clock-frequency = <250000000>; + samsung,esc-clock-frequency = <20000000>; + }; + }; + }; + + panel@0 { + compatible = "samsung,s6e63j0x03"; + reg = <0>; + vdd3-supply = <&ldo16_reg>; + vci-supply = <&ldo20_reg>; + reset-gpios = <&gpe0 1 0>; + te-gpios = <&gpx0 6 0>; + power-on-delay= <30>; + power-off-delay= <120>; + reset-delay = <5>; + init-delay = <100>; + flip-horizontal; + flip-vertical; + panel-width-mm = <29>; + panel-height-mm = <29>; + + display-timings { + timing-0 { + clock-frequency = <0>; + hactive = <320>; + vactive = <320>; + hfront-porch = <1>; + hback-porch = <1>; + hsync-len = <1>; + vfront-porch = <150>; + vback-porch = <1>; + vsync-len = <2>; + }; + }; + + port { + dsi_in: endpoint { + remote-endpoint = <&dsi_out>; + }; + }; + }; +}; + &fimd { status = "okay"; -- cgit v1.2.3 From fbc4a8a85777e065f7a195ddc58b3245808f1e87 Mon Sep 17 00:00:00 2001 From: John Ogness Date: Tue, 9 Dec 2014 17:43:10 +0100 Subject: uio: uio_fsl_elbc_gpcm: new driver This driver provides UIO access to memory of a peripheral connected to the Freescale enhanced local bus controller (eLBC) interface using the general purpose chip-select mode (GPCM). Signed-off-by: John Ogness Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/include/asm/fsl_lbc.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h index 067fb0dca549..c7240a024b96 100644 --- a/arch/powerpc/include/asm/fsl_lbc.h +++ b/arch/powerpc/include/asm/fsl_lbc.h @@ -95,6 +95,9 @@ struct fsl_lbc_bank { #define OR_FCM_TRLX_SHIFT 2 #define OR_FCM_EHTR 0x00000002 #define OR_FCM_EHTR_SHIFT 1 + +#define OR_GPCM_AM 0xFFFF8000 +#define OR_GPCM_AM_SHIFT 15 }; struct fsl_lbc_regs { -- cgit v1.2.3 From f3cdfd239da56a4cea75a2920dc326f0f45f67e3 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 20 Oct 2014 16:27:26 +0200 Subject: arm64/efi: move SetVirtualAddressMap() to UEFI stub In order to support kexec, the kernel needs to be able to deal with the state of the UEFI firmware after SetVirtualAddressMap() has been called. To avoid having separate code paths for non-kexec and kexec, let's move the call to SetVirtualAddressMap() to the stub: this will guarantee us that it will only be called once (since the stub is not executed during kexec), and ensures that the UEFI state is identical between kexec and normal boot. This implies that the layout of the virtual mapping needs to be created by the stub as well. All regions are rounded up to a naturally aligned multiple of 64 KB (for compatibility with 64k pages kernels) and recorded in the UEFI memory map. The kernel proper reads those values and installs the mappings in a dedicated set of page tables that are swapped in during UEFI Runtime Services calls. Acked-by: Leif Lindholm Acked-by: Matt Fleming Tested-by: Leif Lindholm Signed-off-by: Ard Biesheuvel --- arch/arm64/include/asm/efi.h | 34 ++++++- arch/arm64/kernel/efi.c | 230 ++++++++++++++++++++++++------------------- arch/arm64/kernel/setup.c | 1 + 3 files changed, 160 insertions(+), 105 deletions(-) (limited to 'arch') diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index 71291253114f..effef3713c5a 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -7,28 +7,36 @@ #ifdef CONFIG_EFI extern void efi_init(void); extern void efi_idmap_init(void); +extern void efi_virtmap_init(void); #else #define efi_init() #define efi_idmap_init() +#define efi_virtmap_init() #endif #define efi_call_virt(f, ...) \ ({ \ - efi_##f##_t *__f = efi.systab->runtime->f; \ + efi_##f##_t *__f; \ efi_status_t __s; \ \ kernel_neon_begin(); \ + efi_virtmap_load(); \ + __f = efi.systab->runtime->f; \ __s = __f(__VA_ARGS__); \ + efi_virtmap_unload(); \ kernel_neon_end(); \ __s; \ }) #define __efi_call_virt(f, ...) \ ({ \ - efi_##f##_t *__f = efi.systab->runtime->f; \ + efi_##f##_t *__f; \ \ kernel_neon_begin(); \ + efi_virtmap_load(); \ + __f = efi.systab->runtime->f; \ __f(__VA_ARGS__); \ + efi_virtmap_unload(); \ kernel_neon_end(); \ }) @@ -46,4 +54,26 @@ extern void efi_idmap_init(void); #define EFI_ALLOC_ALIGN SZ_64K +/* + * On ARM systems, virtually remapped UEFI runtime services are set up in three + * distinct stages: + * - The stub retrieves the final version of the memory map from UEFI, populates + * the virt_addr fields and calls the SetVirtualAddressMap() [SVAM] runtime + * service to communicate the new mapping to the firmware (Note that the new + * mapping is not live at this time) + * - During early boot, the page tables are allocated and populated based on the + * virt_addr fields in the memory map, but only if all descriptors with the + * EFI_MEMORY_RUNTIME attribute have a non-zero value for virt_addr. If this + * succeeds, the EFI_VIRTMAP flag is set to indicate that the virtual mappings + * have been installed successfully. + * - During an early initcall(), the UEFI Runtime Services are enabled and the + * EFI_RUNTIME_SERVICES bit set if some conditions are met, i.e., we need a + * non-early mapping of the UEFI system table, and we need to have the virtmap + * installed. + */ +#define EFI_VIRTMAP EFI_ARCH_1 + +void efi_virtmap_load(void); +void efi_virtmap_unload(void); + #endif /* _ASM_EFI_H */ diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 2bb4347d0edf..755e545144ea 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -11,25 +11,31 @@ * */ +#include #include #include #include #include +#include #include #include #include +#include +#include +#include #include #include +#include #include #include #include #include +#include +#include struct efi_memory_map memmap; -static efi_runtime_services_t *runtime; - static u64 efi_system_table; static int uefi_debug __initdata; @@ -69,9 +75,33 @@ static void __init efi_setup_idmap(void) } } +/* + * Translate a EFI virtual address into a physical address: this is necessary, + * as some data members of the EFI system table are virtually remapped after + * SetVirtualAddressMap() has been called. + */ +static phys_addr_t efi_to_phys(unsigned long addr) +{ + efi_memory_desc_t *md; + + for_each_efi_memory_desc(&memmap, md) { + if (!(md->attribute & EFI_MEMORY_RUNTIME)) + continue; + if (md->virt_addr == 0) + /* no virtual mapping has been installed by the stub */ + break; + if (md->virt_addr <= addr && + (addr - md->virt_addr) < (md->num_pages << EFI_PAGE_SHIFT)) + return md->phys_addr + addr - md->virt_addr; + } + return addr; +} + static int __init uefi_init(void) { efi_char16_t *c16; + void *config_tables; + u64 table_size; char vendor[100] = "unknown"; int i, retval; @@ -99,7 +129,7 @@ static int __init uefi_init(void) efi.systab->hdr.revision & 0xffff); /* Show what we know for posterity */ - c16 = early_memremap(efi.systab->fw_vendor, + c16 = early_memremap(efi_to_phys(efi.systab->fw_vendor), sizeof(vendor)); if (c16) { for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i) @@ -112,8 +142,14 @@ static int __init uefi_init(void) efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor); - retval = efi_config_init(NULL); + table_size = sizeof(efi_config_table_64_t) * efi.systab->nr_tables; + config_tables = early_memremap(efi_to_phys(efi.systab->tables), + table_size); + + retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables, + sizeof(efi_config_table_64_t), NULL); + early_memunmap(config_tables, table_size); out: early_memunmap(efi.systab, sizeof(efi_system_table_t)); return retval; @@ -329,51 +365,14 @@ void __init efi_idmap_init(void) early_memunmap(memmap.map, memmap.map_end - memmap.map); } -static int __init remap_region(efi_memory_desc_t *md, void **new) -{ - u64 paddr, vaddr, npages, size; - - paddr = md->phys_addr; - npages = md->num_pages; - memrange_efi_to_native(&paddr, &npages); - size = npages << PAGE_SHIFT; - - if (is_normal_ram(md)) - vaddr = (__force u64)ioremap_cache(paddr, size); - else - vaddr = (__force u64)ioremap(paddr, size); - - if (!vaddr) { - pr_err("Unable to remap 0x%llx pages @ %p\n", - npages, (void *)paddr); - return 0; - } - - /* adjust for any rounding when EFI and system pagesize differs */ - md->virt_addr = vaddr + (md->phys_addr - paddr); - - if (uefi_debug) - pr_info(" EFI remap 0x%012llx => %p\n", - md->phys_addr, (void *)md->virt_addr); - - memcpy(*new, md, memmap.desc_size); - *new += memmap.desc_size; - - return 1; -} - /* - * Switch UEFI from an identity map to a kernel virtual map + * Enable the UEFI Runtime Services if all prerequisites are in place, i.e., + * non-early mapping of the UEFI system table and virtual mappings for all + * EFI_MEMORY_RUNTIME regions. */ -static int __init arm64_enter_virtual_mode(void) +static int __init arm64_enable_runtime_services(void) { - efi_memory_desc_t *md; - phys_addr_t virtmap_phys; - void *virtmap, *virt_md; - efi_status_t status; u64 mapsize; - int count = 0; - unsigned long flags; if (!efi_enabled(EFI_BOOT)) { pr_info("EFI services will not be available.\n"); @@ -395,81 +394,30 @@ static int __init arm64_enter_virtual_mode(void) efi.memmap = &memmap; - /* Map the runtime regions */ - virtmap = kmalloc(mapsize, GFP_KERNEL); - if (!virtmap) { - pr_err("Failed to allocate EFI virtual memmap\n"); - return -1; - } - virtmap_phys = virt_to_phys(virtmap); - virt_md = virtmap; - - for_each_efi_memory_desc(&memmap, md) { - if (!(md->attribute & EFI_MEMORY_RUNTIME)) - continue; - if (!remap_region(md, &virt_md)) - goto err_unmap; - ++count; - } - - efi.systab = (__force void *)efi_lookup_mapped_addr(efi_system_table); + efi.systab = (__force void *)ioremap_cache(efi_system_table, + sizeof(efi_system_table_t)); if (!efi.systab) { - /* - * If we have no virtual mapping for the System Table at this - * point, the memory map doesn't cover the physical offset where - * it resides. This means the System Table will be inaccessible - * to Runtime Services themselves once the virtual mapping is - * installed. - */ - pr_err("Failed to remap EFI System Table -- buggy firmware?\n"); - goto err_unmap; + pr_err("Failed to remap EFI System Table\n"); + return -1; } set_bit(EFI_SYSTEM_TABLES, &efi.flags); - local_irq_save(flags); - cpu_switch_mm(idmap_pg_dir, &init_mm); - - /* Call SetVirtualAddressMap with the physical address of the map */ - runtime = efi.systab->runtime; - efi.set_virtual_address_map = runtime->set_virtual_address_map; - - status = efi.set_virtual_address_map(count * memmap.desc_size, - memmap.desc_size, - memmap.desc_version, - (efi_memory_desc_t *)virtmap_phys); - cpu_set_reserved_ttbr0(); - flush_tlb_all(); - local_irq_restore(flags); - - kfree(virtmap); - free_boot_services(); - if (status != EFI_SUCCESS) { - pr_err("Failed to set EFI virtual address map! [%lx]\n", - status); + if (!efi_enabled(EFI_VIRTMAP)) { + pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n"); return -1; } /* Set up runtime services function pointers */ - runtime = efi.systab->runtime; efi_native_runtime_setup(); set_bit(EFI_RUNTIME_SERVICES, &efi.flags); efi.runtime_version = efi.systab->hdr.revision; return 0; - -err_unmap: - /* unmap all mappings that succeeded: there are 'count' of those */ - for (virt_md = virtmap; count--; virt_md += memmap.desc_size) { - md = virt_md; - iounmap((__force void __iomem *)md->virt_addr); - } - kfree(virtmap); - return -1; } -early_initcall(arm64_enter_virtual_mode); +early_initcall(arm64_enable_runtime_services); static int __init arm64_dmi_init(void) { @@ -484,3 +432,79 @@ static int __init arm64_dmi_init(void) return 0; } core_initcall(arm64_dmi_init); + +static pgd_t efi_pgd[PTRS_PER_PGD] __page_aligned_bss; + +static struct mm_struct efi_mm = { + .mm_rb = RB_ROOT, + .pgd = efi_pgd, + .mm_users = ATOMIC_INIT(2), + .mm_count = ATOMIC_INIT(1), + .mmap_sem = __RWSEM_INITIALIZER(efi_mm.mmap_sem), + .page_table_lock = __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock), + .mmlist = LIST_HEAD_INIT(efi_mm.mmlist), + INIT_MM_CONTEXT(efi_mm) +}; + +static void efi_set_pgd(struct mm_struct *mm) +{ + cpu_switch_mm(mm->pgd, mm); + flush_tlb_all(); + if (icache_is_aivivt()) + __flush_icache_all(); +} + +void efi_virtmap_load(void) +{ + preempt_disable(); + efi_set_pgd(&efi_mm); +} + +void efi_virtmap_unload(void) +{ + efi_set_pgd(current->active_mm); + preempt_enable(); +} + +void __init efi_virtmap_init(void) +{ + efi_memory_desc_t *md; + + if (!efi_enabled(EFI_BOOT)) + return; + + for_each_efi_memory_desc(&memmap, md) { + u64 paddr, npages, size; + pgprot_t prot; + + if (!(md->attribute & EFI_MEMORY_RUNTIME)) + continue; + if (WARN(md->virt_addr == 0, + "UEFI virtual mapping incomplete or missing -- no entry found for 0x%llx\n", + md->phys_addr)) + return; + + paddr = md->phys_addr; + npages = md->num_pages; + memrange_efi_to_native(&paddr, &npages); + size = npages << PAGE_SHIFT; + + pr_info(" EFI remap 0x%016llx => %p\n", + md->phys_addr, (void *)md->virt_addr); + + /* + * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be + * executable, everything else can be mapped with the XN bits + * set. + */ + if (!is_normal_ram(md)) + prot = __pgprot(PROT_DEVICE_nGnRE); + else if (md->type == EFI_RUNTIME_SERVICES_CODE) + prot = PAGE_KERNEL_EXEC; + else + prot = PAGE_KERNEL; + + create_pgd_mapping(&efi_mm, paddr, md->virt_addr, size, prot); + } + set_bit(EFI_VIRTMAP, &efi.flags); +} diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 20fe2932ad0c..beac8188fdbd 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -401,6 +401,7 @@ void __init setup_arch(char **cmdline_p) paging_init(); request_standard_resources(); + efi_virtmap_init(); efi_idmap_init(); early_ioremap_reset(); -- cgit v1.2.3 From 3033b84596eaec0093b68c5711c265738eb0745d Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 20 Oct 2014 16:35:21 +0200 Subject: arm64/efi: remove free_boot_services() and friends Now that we are calling SetVirtualAddressMap() from the stub, there is no need to reserve boot-only memory regions, which implies that there is also no reason to free them again later. Acked-by: Leif Lindholm Acked-by: Will Deacon Tested-by: Leif Lindholm Signed-off-by: Ard Biesheuvel --- arch/arm64/kernel/efi.c | 123 +----------------------------------------------- 1 file changed, 1 insertion(+), 122 deletions(-) (limited to 'arch') diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 755e545144ea..4a5d7343dddd 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -199,9 +199,7 @@ static __init void reserve_regions(void) if (is_normal_ram(md)) early_init_dt_add_memory_arch(paddr, size); - if (is_reserve_region(md) || - md->type == EFI_BOOT_SERVICES_CODE || - md->type == EFI_BOOT_SERVICES_DATA) { + if (is_reserve_region(md)) { memblock_reserve(paddr, size); if (uefi_debug) pr_cont("*"); @@ -214,123 +212,6 @@ static __init void reserve_regions(void) set_bit(EFI_MEMMAP, &efi.flags); } - -static u64 __init free_one_region(u64 start, u64 end) -{ - u64 size = end - start; - - if (uefi_debug) - pr_info(" EFI freeing: 0x%012llx-0x%012llx\n", start, end - 1); - - free_bootmem_late(start, size); - return size; -} - -static u64 __init free_region(u64 start, u64 end) -{ - u64 map_start, map_end, total = 0; - - if (end <= start) - return total; - - map_start = (u64)memmap.phys_map; - map_end = PAGE_ALIGN(map_start + (memmap.map_end - memmap.map)); - map_start &= PAGE_MASK; - - if (start < map_end && end > map_start) { - /* region overlaps UEFI memmap */ - if (start < map_start) - total += free_one_region(start, map_start); - - if (map_end < end) - total += free_one_region(map_end, end); - } else - total += free_one_region(start, end); - - return total; -} - -static void __init free_boot_services(void) -{ - u64 total_freed = 0; - u64 keep_end, free_start, free_end; - efi_memory_desc_t *md; - - /* - * If kernel uses larger pages than UEFI, we have to be careful - * not to inadvertantly free memory we want to keep if there is - * overlap at the kernel page size alignment. We do not want to - * free is_reserve_region() memory nor the UEFI memmap itself. - * - * The memory map is sorted, so we keep track of the end of - * any previous region we want to keep, remember any region - * we want to free and defer freeing it until we encounter - * the next region we want to keep. This way, before freeing - * it, we can clip it as needed to avoid freeing memory we - * want to keep for UEFI. - */ - - keep_end = 0; - free_start = 0; - - for_each_efi_memory_desc(&memmap, md) { - u64 paddr, npages, size; - - if (is_reserve_region(md)) { - /* - * We don't want to free any memory from this region. - */ - if (free_start) { - /* adjust free_end then free region */ - if (free_end > md->phys_addr) - free_end -= PAGE_SIZE; - total_freed += free_region(free_start, free_end); - free_start = 0; - } - keep_end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT); - continue; - } - - if (md->type != EFI_BOOT_SERVICES_CODE && - md->type != EFI_BOOT_SERVICES_DATA) { - /* no need to free this region */ - continue; - } - - /* - * We want to free memory from this region. - */ - paddr = md->phys_addr; - npages = md->num_pages; - memrange_efi_to_native(&paddr, &npages); - size = npages << PAGE_SHIFT; - - if (free_start) { - if (paddr <= free_end) - free_end = paddr + size; - else { - total_freed += free_region(free_start, free_end); - free_start = paddr; - free_end = paddr + size; - } - } else { - free_start = paddr; - free_end = paddr + size; - } - if (free_start < keep_end) { - free_start += PAGE_SIZE; - if (free_start >= free_end) - free_start = 0; - } - } - if (free_start) - total_freed += free_region(free_start, free_end); - - if (total_freed) - pr_info("Freed 0x%llx bytes of EFI boot services memory", - total_freed); -} - void __init efi_init(void) { struct efi_fdt_params params; @@ -402,8 +283,6 @@ static int __init arm64_enable_runtime_services(void) } set_bit(EFI_SYSTEM_TABLES, &efi.flags); - free_boot_services(); - if (!efi_enabled(EFI_VIRTMAP)) { pr_err("No UEFI virtual mapping was installed -- runtime services will not be available\n"); return -1; -- cgit v1.2.3 From 9679be103108926cfe9e6fd2f6829cefa77e47b0 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 20 Oct 2014 16:41:38 +0200 Subject: arm64/efi: remove idmap manipulations from UEFI code Now that we have moved the call to SetVirtualAddressMap() to the stub, UEFI has no use for the ID map, so we can drop the code that installs ID mappings for UEFI memory regions. Acked-by: Leif Lindholm Acked-by: Will Deacon Tested-by: Leif Lindholm Signed-off-by: Ard Biesheuvel --- arch/arm64/include/asm/efi.h | 2 -- arch/arm64/include/asm/mmu.h | 2 -- arch/arm64/kernel/efi.c | 32 +------------------------------- arch/arm64/kernel/setup.c | 1 - arch/arm64/mm/mmu.c | 12 ------------ 5 files changed, 1 insertion(+), 48 deletions(-) (limited to 'arch') diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h index effef3713c5a..7baf2cc04e1e 100644 --- a/arch/arm64/include/asm/efi.h +++ b/arch/arm64/include/asm/efi.h @@ -6,11 +6,9 @@ #ifdef CONFIG_EFI extern void efi_init(void); -extern void efi_idmap_init(void); extern void efi_virtmap_init(void); #else #define efi_init() -#define efi_idmap_init() #define efi_virtmap_init() #endif diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h index 5fd40c43be80..3d311761e3c2 100644 --- a/arch/arm64/include/asm/mmu.h +++ b/arch/arm64/include/asm/mmu.h @@ -31,8 +31,6 @@ extern void paging_init(void); extern void setup_mm_for_reboot(void); extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt); extern void init_mem_pgprot(void); -/* create an identity mapping for memory (or io if map_io is true) */ -extern void create_id_mapping(phys_addr_t addr, phys_addr_t size, int map_io); extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, unsigned long virt, phys_addr_t size, pgprot_t prot); diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c index 4a5d7343dddd..a98415b5979c 100644 --- a/arch/arm64/kernel/efi.c +++ b/arch/arm64/kernel/efi.c @@ -54,27 +54,6 @@ static int __init is_normal_ram(efi_memory_desc_t *md) return 0; } -static void __init efi_setup_idmap(void) -{ - struct memblock_region *r; - efi_memory_desc_t *md; - u64 paddr, npages, size; - - for_each_memblock(memory, r) - create_id_mapping(r->base, r->size, 0); - - /* map runtime io spaces */ - for_each_efi_memory_desc(&memmap, md) { - if (!(md->attribute & EFI_MEMORY_RUNTIME) || is_normal_ram(md)) - continue; - paddr = md->phys_addr; - npages = md->num_pages; - memrange_efi_to_native(&paddr, &npages); - size = npages << PAGE_SHIFT; - create_id_mapping(paddr, size, 1); - } -} - /* * Translate a EFI virtual address into a physical address: this is necessary, * as some data members of the EFI system table are virtually remapped after @@ -236,16 +215,6 @@ void __init efi_init(void) reserve_regions(); } -void __init efi_idmap_init(void) -{ - if (!efi_enabled(EFI_BOOT)) - return; - - /* boot time idmap_pg_dir is incomplete, so fill in missing parts */ - efi_setup_idmap(); - early_memunmap(memmap.map, memmap.map_end - memmap.map); -} - /* * Enable the UEFI Runtime Services if all prerequisites are in place, i.e., * non-early mapping of the UEFI system table and virtual mappings for all @@ -386,4 +355,5 @@ void __init efi_virtmap_init(void) create_pgd_mapping(&efi_mm, paddr, md->virt_addr, size, prot); } set_bit(EFI_VIRTMAP, &efi.flags); + early_memunmap(memmap.map, memmap.map_end - memmap.map); } diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index beac8188fdbd..199d1b7809d7 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -402,7 +402,6 @@ void __init setup_arch(char **cmdline_p) request_standard_resources(); efi_virtmap_init(); - efi_idmap_init(); early_ioremap_reset(); unflatten_device_tree(); diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 3f3d5aa4a8b1..328638548871 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -271,18 +271,6 @@ static void __init create_mapping(phys_addr_t phys, unsigned long virt, size, PAGE_KERNEL_EXEC); } -void __init create_id_mapping(phys_addr_t addr, phys_addr_t size, int map_io) -{ - if ((addr >> PGDIR_SHIFT) >= ARRAY_SIZE(idmap_pg_dir)) { - pr_warn("BUG: not creating id mapping for %pa\n", &addr); - return; - } - __create_mapping(&init_mm, &idmap_pg_dir[pgd_index(addr)], - addr, addr, size, - map_io ? __pgprot(PROT_DEVICE_nGnRE) - : PAGE_KERNEL_EXEC); -} - void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, unsigned long virt, phys_addr_t size, pgprot_t prot) -- cgit v1.2.3 From a1ad3b94a7661b643fef2efbc6fc217bd148f462 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Tue, 16 Dec 2014 19:13:50 -0800 Subject: ARM: brcmstb: update CPU power management sequence The automatic CPU power state machine for B15 CPUs does not work reliably as-is. This patch implements a manual sequence in software to replace it. This was tested successfully with over 10,000 hotplug cycles of something like this: echo 0 > /sys/devices/system/cpu/cpu1/online echo 1 > /sys/devices/system/cpu/cpu1/online whereas the existing sequence often locks up after a few hundred cycles. Fixes: 62639c2f5332 ("ARM: brcmstb: reintroduce SMP support") Acked-by: Gregory Fong Signed-off-by: Brian Norris Signed-off-by: Florian Fainelli --- arch/arm/mach-bcm/platsmp-brcmstb.c | 85 +++++++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 22 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-bcm/platsmp-brcmstb.c b/arch/arm/mach-bcm/platsmp-brcmstb.c index 31c87a284a34..e209e6fc7caf 100644 --- a/arch/arm/mach-bcm/platsmp-brcmstb.c +++ b/arch/arm/mach-bcm/platsmp-brcmstb.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -94,10 +95,35 @@ static u32 pwr_ctrl_rd(u32 cpu) return readl_relaxed(base); } -static void pwr_ctrl_wr(u32 cpu, u32 val) +static void pwr_ctrl_set(unsigned int cpu, u32 val, u32 mask) { void __iomem *base = pwr_ctrl_get_base(cpu); - writel(val, base); + writel((readl(base) & mask) | val, base); +} + +static void pwr_ctrl_clr(unsigned int cpu, u32 val, u32 mask) +{ + void __iomem *base = pwr_ctrl_get_base(cpu); + writel((readl(base) & mask) & ~val, base); +} + +#define POLL_TMOUT_MS 500 +static int pwr_ctrl_wait_tmout(unsigned int cpu, u32 set, u32 mask) +{ + const unsigned long timeo = jiffies + msecs_to_jiffies(POLL_TMOUT_MS); + u32 tmp; + + do { + tmp = pwr_ctrl_rd(cpu) & mask; + if (!set == !tmp) + return 0; + } while (time_before(jiffies, timeo)); + + tmp = pwr_ctrl_rd(cpu) & mask; + if (!set == !tmp) + return 0; + + return -ETIMEDOUT; } static void cpu_rst_cfg_set(u32 cpu, int set) @@ -139,15 +165,22 @@ static void brcmstb_cpu_power_on(u32 cpu) * The secondary cores power was cut, so we must go through * power-on initialization. */ - u32 tmp; + pwr_ctrl_set(cpu, ZONE_MAN_ISO_CNTL_MASK, 0xffffff00); + pwr_ctrl_set(cpu, ZONE_MANUAL_CONTROL_MASK, -1); + pwr_ctrl_set(cpu, ZONE_RESERVED_1_MASK, -1); - /* Request zone power up */ - pwr_ctrl_wr(cpu, ZONE_PWR_UP_REQ_MASK); + pwr_ctrl_set(cpu, ZONE_MAN_MEM_PWR_MASK, -1); - /* Wait for the power up FSM to complete */ - do { - tmp = pwr_ctrl_rd(cpu); - } while (!(tmp & ZONE_PWR_ON_STATE_MASK)); + if (pwr_ctrl_wait_tmout(cpu, 1, ZONE_MEM_PWR_STATE_MASK)) + panic("ZONE_MEM_PWR_STATE_MASK set timeout"); + + pwr_ctrl_set(cpu, ZONE_MAN_CLKEN_MASK, -1); + + if (pwr_ctrl_wait_tmout(cpu, 1, ZONE_DPG_PWR_STATE_MASK)) + panic("ZONE_DPG_PWR_STATE_MASK set timeout"); + + pwr_ctrl_clr(cpu, ZONE_MAN_ISO_CNTL_MASK, -1); + pwr_ctrl_set(cpu, ZONE_MAN_RESET_CNTL_MASK, -1); } static int brcmstb_cpu_get_power_state(u32 cpu) @@ -174,25 +207,33 @@ static void brcmstb_cpu_die(u32 cpu) static int brcmstb_cpu_kill(u32 cpu) { - u32 tmp; + /* + * Ordinarily, the hardware forbids power-down of CPU0 (which is good + * because it is the boot CPU), but this is not true when using BPCM + * manual mode. Consequently, we must avoid turning off CPU0 here to + * ensure that TI2C master reset will work. + */ + if (cpu == 0) { + pr_warn("SMP: refusing to power off CPU0\n"); + return 1; + } while (per_cpu_sw_state_rd(cpu)) ; - /* Program zone reset */ - pwr_ctrl_wr(cpu, ZONE_RESET_STATE_MASK | ZONE_BLK_RST_ASSERT_MASK | - ZONE_PWR_DN_REQ_MASK); + pwr_ctrl_set(cpu, ZONE_MANUAL_CONTROL_MASK, -1); + pwr_ctrl_clr(cpu, ZONE_MAN_RESET_CNTL_MASK, -1); + pwr_ctrl_clr(cpu, ZONE_MAN_CLKEN_MASK, -1); + pwr_ctrl_set(cpu, ZONE_MAN_ISO_CNTL_MASK, -1); + pwr_ctrl_clr(cpu, ZONE_MAN_MEM_PWR_MASK, -1); - /* Verify zone reset */ - tmp = pwr_ctrl_rd(cpu); - if (!(tmp & ZONE_RESET_STATE_MASK)) - pr_err("%s: Zone reset bit for CPU %d not asserted!\n", - __func__, cpu); + if (pwr_ctrl_wait_tmout(cpu, 0, ZONE_MEM_PWR_STATE_MASK)) + panic("ZONE_MEM_PWR_STATE_MASK clear timeout"); - /* Wait for power down */ - do { - tmp = pwr_ctrl_rd(cpu); - } while (!(tmp & ZONE_PWR_OFF_STATE_MASK)); + pwr_ctrl_clr(cpu, ZONE_RESERVED_1_MASK, -1); + + if (pwr_ctrl_wait_tmout(cpu, 0, ZONE_DPG_PWR_STATE_MASK)) + panic("ZONE_DPG_PWR_STATE_MASK clear timeout"); /* Flush pipeline before resetting CPU */ mb(); -- cgit v1.2.3 From 4b9d62e02a0124d06fbbb9c4b01bd69f3c4dcd35 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 3 Dec 2014 14:41:42 +0100 Subject: ARM: shmobile: R-Mobile: Use generic_pm_domain.attach_dev() for pm_clk setup Use the just introduced genpd attach/detach callbacks to register the devices' module clocks, instead of doing it directly, to make it DT-proof. Signed-off-by: Geert Uytterhoeven Reviewed-by: Ulf Hansson Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/pm-rmobile.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c index 6f7d56ecf969..4ea458d268fb 100644 --- a/arch/arm/mach-shmobile/pm-rmobile.c +++ b/arch/arm/mach-shmobile/pm-rmobile.c @@ -101,6 +101,36 @@ static bool rmobile_pd_active_wakeup(struct device *dev) return true; } +static int rmobile_pd_attach_dev(struct generic_pm_domain *domain, + struct device *dev) +{ + int error; + + error = pm_clk_create(dev); + if (error) { + dev_err(dev, "pm_clk_create failed %d\n", error); + return error; + } + + error = pm_clk_add(dev, NULL); + if (error) { + dev_err(dev, "pm_clk_add failed %d\n", error); + goto fail; + } + + return 0; + +fail: + pm_clk_destroy(dev); + return error; +} + +static void rmobile_pd_detach_dev(struct generic_pm_domain *domain, + struct device *dev) +{ + pm_clk_destroy(dev); +} + static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) { struct generic_pm_domain *genpd = &rmobile_pd->genpd; @@ -111,6 +141,8 @@ static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd) genpd->dev_ops.active_wakeup = rmobile_pd_active_wakeup; genpd->power_off = rmobile_pd_power_down; genpd->power_on = rmobile_pd_power_up; + genpd->attach_dev = rmobile_pd_attach_dev; + genpd->detach_dev = rmobile_pd_detach_dev; __rmobile_pd_power_up(rmobile_pd, false); } @@ -129,8 +161,6 @@ void rmobile_add_device_to_domain_td(const char *domain_name, struct device *dev = &pdev->dev; __pm_genpd_name_add_device(domain_name, dev, td); - if (pm_clk_no_clocks(dev)) - pm_clk_add(dev, NULL); } void rmobile_add_devices_to_domains(struct pm_domain_device data[], -- cgit v1.2.3 From 25717b857360760755b83b4e606d61e1fc38552f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 3 Dec 2014 14:41:44 +0100 Subject: ARM: shmobile: R-Mobile: Store SYSC base address in rmobile_pm_domain Replace the hardcoded addresses for accessing the SYSC PM domain registers by register offsets, relative to the SYSC base address stored in struct rmobile_pm_domain. In the future, the SYSC base address will come from DT. Signed-off-by: Geert Uytterhoeven Reviewed-by: Ulf Hansson Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/pm-r8a7740.c | 14 ++++++++++++++ arch/arm/mach-shmobile/pm-rmobile.c | 24 +++++++++++++----------- arch/arm/mach-shmobile/pm-rmobile.h | 1 + arch/arm/mach-shmobile/pm-sh7372.c | 11 +++++++++++ 4 files changed, 39 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c index ac2eecd6f5ea..34608fcf0648 100644 --- a/arch/arm/mach-shmobile/pm-r8a7740.c +++ b/arch/arm/mach-shmobile/pm-r8a7740.c @@ -9,10 +9,14 @@ * for more details. */ #include +#include #include + #include "common.h" #include "pm-rmobile.h" +#define SYSC_BASE IOMEM(0xe6180000) + #if defined(CONFIG_PM) && !defined(CONFIG_ARCH_MULTIPLATFORM) static int r8a7740_pd_a3sm_suspend(void) { @@ -45,41 +49,51 @@ static int r8a7740_pd_d4_suspend(void) static struct rmobile_pm_domain r8a7740_pm_domains[] = { { .genpd.name = "A4LC", + .base = SYSC_BASE, .bit_shift = 1, }, { .genpd.name = "A4MP", + .base = SYSC_BASE, .bit_shift = 2, }, { .genpd.name = "D4", + .base = SYSC_BASE, .bit_shift = 3, .gov = &pm_domain_always_on_gov, .suspend = r8a7740_pd_d4_suspend, }, { .genpd.name = "A4R", + .base = SYSC_BASE, .bit_shift = 5, }, { .genpd.name = "A3RV", + .base = SYSC_BASE, .bit_shift = 6, }, { .genpd.name = "A4S", + .base = SYSC_BASE, .bit_shift = 10, .no_debug = true, }, { .genpd.name = "A3SP", + .base = SYSC_BASE, .bit_shift = 11, .gov = &pm_domain_always_on_gov, .no_debug = true, .suspend = r8a7740_pd_a3sp_suspend, }, { .genpd.name = "A3SM", + .base = SYSC_BASE, .bit_shift = 12, .gov = &pm_domain_always_on_gov, .suspend = r8a7740_pd_a3sm_suspend, }, { .genpd.name = "A3SG", + .base = SYSC_BASE, .bit_shift = 13, }, { .genpd.name = "A4SU", + .base = SYSC_BASE, .bit_shift = 20, }, }; diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c index 4ea458d268fb..a4fcd2cae718 100644 --- a/arch/arm/mach-shmobile/pm-rmobile.c +++ b/arch/arm/mach-shmobile/pm-rmobile.c @@ -20,9 +20,9 @@ #include "pm-rmobile.h" /* SYSC */ -#define SPDCR IOMEM(0xe6180008) -#define SWUCR IOMEM(0xe6180014) -#define PSTR IOMEM(0xe6180080) +#define SPDCR 0x08 /* SYS Power Down Control Register */ +#define SWUCR 0x14 /* SYS Wakeup Control Register */ +#define PSTR 0x80 /* Power Status Register */ #define PSTR_RETRIES 100 #define PSTR_DELAY_US 10 @@ -39,12 +39,12 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd) return ret; } - if (__raw_readl(PSTR) & mask) { + if (__raw_readl(rmobile_pd->base + PSTR) & mask) { unsigned int retry_count; - __raw_writel(mask, SPDCR); + __raw_writel(mask, rmobile_pd->base + SPDCR); for (retry_count = PSTR_RETRIES; retry_count; retry_count--) { - if (!(__raw_readl(SPDCR) & mask)) + if (!(__raw_readl(rmobile_pd->base + SPDCR) & mask)) break; cpu_relax(); } @@ -52,7 +52,8 @@ static int rmobile_pd_power_down(struct generic_pm_domain *genpd) if (!rmobile_pd->no_debug) pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n", - genpd->name, mask, __raw_readl(PSTR)); + genpd->name, mask, + __raw_readl(rmobile_pd->base + PSTR)); return 0; } @@ -64,13 +65,13 @@ static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd, unsigned int retry_count; int ret = 0; - if (__raw_readl(PSTR) & mask) + if (__raw_readl(rmobile_pd->base + PSTR) & mask) goto out; - __raw_writel(mask, SWUCR); + __raw_writel(mask, rmobile_pd->base + SWUCR); for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) { - if (!(__raw_readl(SWUCR) & mask)) + if (!(__raw_readl(rmobile_pd->base + SWUCR) & mask)) break; if (retry_count > PSTR_RETRIES) udelay(PSTR_DELAY_US); @@ -82,7 +83,8 @@ static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd, if (!rmobile_pd->no_debug) pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n", - rmobile_pd->genpd.name, mask, __raw_readl(PSTR)); + rmobile_pd->genpd.name, mask, + __raw_readl(rmobile_pd->base + PSTR)); out: if (ret == 0 && rmobile_pd->resume && do_resume) diff --git a/arch/arm/mach-shmobile/pm-rmobile.h b/arch/arm/mach-shmobile/pm-rmobile.h index 8f66b343162b..0602130bb260 100644 --- a/arch/arm/mach-shmobile/pm-rmobile.h +++ b/arch/arm/mach-shmobile/pm-rmobile.h @@ -21,6 +21,7 @@ struct rmobile_pm_domain { struct dev_power_governor *gov; int (*suspend)(void); void (*resume)(void); + void __iomem *base; unsigned int bit_shift; bool no_debug; }; diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c index 0e37da654ed5..c0293ae4b013 100644 --- a/arch/arm/mach-shmobile/pm-sh7372.c +++ b/arch/arm/mach-shmobile/pm-sh7372.c @@ -45,6 +45,8 @@ #define PLLC01STPCR IOMEM(0xe61500c8) /* SYSC */ +#define SYSC_BASE IOMEM(0xe6180000) + #define SBAR IOMEM(0xe6180020) #define WUPRMSK IOMEM(0xe6180028) #define WUPSMSK IOMEM(0xe618002c) @@ -118,24 +120,28 @@ static struct rmobile_pm_domain sh7372_pm_domains[] = { .genpd.name = "A4LC", .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .base = SYSC_BASE, .bit_shift = 1, }, { .genpd.name = "A4MP", .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .base = SYSC_BASE, .bit_shift = 2, }, { .genpd.name = "D4", .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .base = SYSC_BASE, .bit_shift = 3, }, { .genpd.name = "A4R", .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .base = SYSC_BASE, .bit_shift = 5, .suspend = sh7372_a4r_pd_suspend, .resume = sh7372_intcs_resume, @@ -144,18 +150,21 @@ static struct rmobile_pm_domain sh7372_pm_domains[] = { .genpd.name = "A3RV", .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .base = SYSC_BASE, .bit_shift = 6, }, { .genpd.name = "A3RI", .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .base = SYSC_BASE, .bit_shift = 8, }, { .genpd.name = "A4S", .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .base = SYSC_BASE, .bit_shift = 10, .gov = &pm_domain_always_on_gov, .no_debug = true, @@ -166,6 +175,7 @@ static struct rmobile_pm_domain sh7372_pm_domains[] = { .genpd.name = "A3SP", .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .base = SYSC_BASE, .bit_shift = 11, .gov = &pm_domain_always_on_gov, .no_debug = true, @@ -175,6 +185,7 @@ static struct rmobile_pm_domain sh7372_pm_domains[] = { .genpd.name = "A3SG", .genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, .genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS, + .base = SYSC_BASE, .bit_shift = 13, }, }; -- cgit v1.2.3 From cb612390e5469186301a7856116fcdbfd9fb3c90 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Tue, 30 Dec 2014 06:20:27 +0000 Subject: ARM: dts: Only build dtb if associated Arch and/or SoC is enabled A number of arches (EXYNOS/IMX/TEGRA) are separated out into finer grained definitions whether it be sub ARCH or SOC definitions. The device tree blobs should only be built if the specific option is enabled that supports that device or it might be that there's an expectation that the device is supported when in actual fact it's not. This ensures only the relevant bits are built. Also standardised the line break between the arch/soc definitions and the dtbs to be on separate lines for better consistency as per feedback. Signed-off-by: Peter Robinson Reviewed-by: Lucas Stach Acked-by: Thierry Reding Acked-by: Stephen Warren Acked-by: Shawn Guo [olof: Fixed stray \ in one of the IMX rules] Signed-off-by: Olof Johansson --- arch/arm/boot/dts/Makefile | 215 ++++++++++++++++++++++++++++++--------------- 1 file changed, 142 insertions(+), 73 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index fabc56983d24..1e626f6d45c9 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -51,33 +51,43 @@ dtb-$(CONFIG_ARCH_AT91) += sama5d36ek.dtb # sama5d4 dtb-$(CONFIG_ARCH_AT91) += at91-sama5d4ek.dtb -dtb-$(CONFIG_ARCH_ATLAS6) += atlas6-evb.dtb -dtb-$(CONFIG_ARCH_AXXIA) += axm5516-amarillo.dtb -dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb -dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b-plus.dtb +dtb-$(CONFIG_ARCH_ATLAS6) += \ + atlas6-evb.dtb +dtb-$(CONFIG_ARCH_AXXIA) += \ + axm5516-amarillo.dtb +dtb-$(CONFIG_ARCH_BCM2835) += \ + bcm2835-rpi-b.dtb \ + bcm2835-rpi-b-plus.dtb dtb-$(CONFIG_ARCH_BCM_5301X) += \ bcm4708-buffalo-wzr-1750dhp.dtb \ bcm4708-netgear-r6250.dtb \ bcm4708-netgear-r6300-v2.dtb \ bcm47081-asus-rt-n18u.dtb \ bcm47081-buffalo-wzr-600dhp2.dtb -dtb-$(CONFIG_ARCH_BCM_63XX) += bcm963138dvt.dtb -dtb-$(CONFIG_ARCH_BCM_CYGNUS) += bcm911360_entphn.dtb \ +dtb-$(CONFIG_ARCH_BCM_63XX) += \ + bcm963138dvt.dtb +dtb-$(CONFIG_ARCH_BCM_CYGNUS) += \ + bcm911360_entphn.dtb \ bcm911360k.dtb \ bcm958300k.dtb -dtb-$(CONFIG_ARCH_BCM_MOBILE) += bcm28155-ap.dtb \ +dtb-$(CONFIG_ARCH_BCM_MOBILE) += \ + bcm28155-ap.dtb \ bcm21664-garnet.dtb dtb-$(CONFIG_ARCH_BERLIN) += \ - berlin2-sony-nsz-gs7.dtb \ - berlin2cd-google-chromecast.dtb \ + berlin2-sony-nsz-gs7.dtb \ + berlin2cd-google-chromecast.dtb \ berlin2q-marvell-dmp.dtb dtb-$(CONFIG_ARCH_BRCMSTB) += \ bcm7445-bcm97445svmb.dtb -dtb-$(CONFIG_ARCH_DAVINCI) += da850-enbw-cmc.dtb \ +dtb-$(CONFIG_ARCH_DAVINCI) += \ + da850-enbw-cmc.dtb \ da850-evm.dtb -dtb-$(CONFIG_ARCH_EFM32) += efm32gg-dk3750.dtb -dtb-$(CONFIG_ARCH_EXYNOS) += exynos3250-monk.dtb \ - exynos3250-rinato.dtb \ +dtb-$(CONFIG_ARCH_EFM32) += \ + efm32gg-dk3750.dtb +dtb-$(CONFIG_ARCH_EXYNOS3) += \ + exynos3250-monk.dtb \ + exynos3250-rinato.dtb +dtb-$(CONFIG_ARCH_EXYNOS4) += \ exynos4210-origen.dtb \ exynos4210-smdkv310.dtb \ exynos4210-trats.dtb \ @@ -88,7 +98,8 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos3250-monk.dtb \ exynos4412-origen.dtb \ exynos4412-smdk4412.dtb \ exynos4412-tiny4412.dtb \ - exynos4412-trats2.dtb \ + exynos4412-trats2.dtb +dtb-$(CONFIG_ARCH_EXYNOS5) += \ exynos5250-arndale.dtb \ exynos5250-smdk5250.dtb \ exynos5250-snow.dtb \ @@ -101,17 +112,24 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos3250-monk.dtb \ exynos5440-sd5v1.dtb \ exynos5440-ssdk5440.dtb \ exynos5800-peach-pi.dtb -dtb-$(CONFIG_ARCH_HI3xxx) += hi3620-hi4511.dtb -dtb-$(CONFIG_ARCH_HIX5HD2) += hisi-x5hd2-dkb.dtb -dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb \ +dtb-$(CONFIG_ARCH_HI3xxx) += \ + hi3620-hi4511.dtb +dtb-$(CONFIG_ARCH_HIX5HD2) += \ + hisi-x5hd2-dkb.dtb +dtb-$(CONFIG_ARCH_HIGHBANK) += \ + highbank.dtb \ ecx-2000.dtb -dtb-$(CONFIG_ARCH_HIP04) += hip04-d01.dtb -dtb-$(CONFIG_ARCH_INTEGRATOR) += integratorap.dtb \ +dtb-$(CONFIG_ARCH_HIP04) += \ + hip04-d01.dtb +dtb-$(CONFIG_ARCH_INTEGRATOR) += \ + integratorap.dtb \ integratorcp.dtb -dtb-$(CONFIG_ARCH_KEYSTONE) += k2hk-evm.dtb \ +dtb-$(CONFIG_ARCH_KEYSTONE) += \ + k2hk-evm.dtb \ k2l-evm.dtb \ k2e-evm.dtb -dtb-$(CONFIG_MACH_KIRKWOOD) += kirkwood-b3.dtb \ +dtb-$(CONFIG_MACH_KIRKWOOD) += \ + kirkwood-b3.dtb \ kirkwood-cloudbox.dtb \ kirkwood-d2net.dtb \ kirkwood-db-88f6281.dtb \ @@ -174,37 +192,49 @@ dtb-$(CONFIG_MACH_KIRKWOOD) += kirkwood-b3.dtb \ kirkwood-ts219-6282.dtb \ kirkwood-ts419-6281.dtb \ kirkwood-ts419-6282.dtb -dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb -dtb-$(CONFIG_ARCH_MARCO) += marco-evb.dtb -dtb-$(CONFIG_MACH_MESON6) += meson6-atv1200.dtb -dtb-$(CONFIG_ARCH_MMP) += pxa168-aspenite.dtb \ +dtb-$(CONFIG_ARCH_LPC32XX) += \ + ea3250.dtb phy3250.dtb +dtb-$(CONFIG_ARCH_MARCO) += \ + marco-evb.dtb +dtb-$(CONFIG_MACH_MESON6) += \ + meson6-atv1200.dtb +dtb-$(CONFIG_ARCH_MMP) += \ + pxa168-aspenite.dtb \ pxa910-dkb.dtb \ mmp2-brownstone.dtb -dtb-$(CONFIG_ARCH_MOXART) += moxart-uc7112lx.dtb -dtb-$(CONFIG_ARCH_MXC) += \ +dtb-$(CONFIG_ARCH_MOXART) += \ + moxart-uc7112lx.dtb +dtb-$(CONFIG_SOC_IMX1) += \ imx1-ads.dtb \ - imx1-apf9328.dtb \ + imx1-apf9328.dtb +dtb-$(CONFIG_SOC_IMX25) += \ imx25-eukrea-mbimxsd25-baseboard.dtb \ imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dtb \ imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dtb \ imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dtb \ imx25-karo-tx25.dtb \ - imx25-pdk.dtb \ + imx25-pdk.dtb +dtb-$(CONFIG_SOC_IMX31) += \ imx27-apf27.dtb \ imx27-apf27dev.dtb \ imx27-eukrea-mbimxsd27-baseboard.dtb \ imx27-pdk.dtb \ imx27-phytec-phycore-rdk.dtb \ - imx27-phytec-phycard-s-rdk.dtb \ - imx31-bug.dtb \ + imx27-phytec-phycard-s-rdk.dtb +dtb-$(CONFIG_SOC_IMX31) += \ + imx31-bug.dtb +dtb-$(CONFIG_SOC_IMX35) += \ imx35-eukrea-mbimxsd35-baseboard.dtb \ - imx35-pdk.dtb \ - imx50-evk.dtb \ + imx35-pdk.dtb +dtb-$(CONFIG_SOC_IMX50) += \ + imx50-evk.dtb +dtb-$(CONFIG_SOC_IMX51) += \ imx51-apf51.dtb \ imx51-apf51dev.dtb \ imx51-babbage.dtb \ imx51-digi-connectcore-jsk.dtb \ - imx51-eukrea-mbimxsd51-baseboard.dtb \ + imx51-eukrea-mbimxsd51-baseboard.dtb +dtb-$(CONFIG_SOC_IMX53) += \ imx53-ard.dtb \ imx53-m53evk.dtb \ imx53-mba53.dtb \ @@ -213,7 +243,8 @@ dtb-$(CONFIG_ARCH_MXC) += \ imx53-smd.dtb \ imx53-tx53-x03x.dtb \ imx53-tx53-x13x.dtb \ - imx53-voipac-bsb.dtb \ + imx53-voipac-bsb.dtb +dtb-$(CONFIG_SOC_IMX6Q) += \ imx6dl-aristainetos_4.dtb \ imx6dl-aristainetos_7.dtb \ imx6dl-cubox-i.dtb \ @@ -264,16 +295,21 @@ dtb-$(CONFIG_ARCH_MXC) += \ imx6q-tx6q-1010-comtft.dtb \ imx6q-tx6q-1020.dtb \ imx6q-tx6q-1020-comtft.dtb \ - imx6q-tx6q-1110.dtb \ - imx6sl-evk.dtb \ - imx6sx-sdb.dtb \ + imx6q-tx6q-1110.dtb +dtb-$(CONFIG_SOC_IMX6SL) += \ + imx6sl-evk.dtb +dtb-$(CONFIG_SOC_IMX6SX) += \ + imx6sx-sdb.dtb +dtb-$(CONFIG_SOC_LS1021A) += \ ls1021a-qds.dtb \ - ls1021a-twr.dtb \ + ls1021a-twr.dtb +dtb-$(CONFIG_SOC_VF610) += \ vf500-colibri-eval-v3.dtb \ vf610-colibri-eval-v3.dtb \ vf610-cosmic.dtb \ vf610-twr.dtb -dtb-$(CONFIG_ARCH_MXS) += imx23-evk.dtb \ +dtb-$(CONFIG_ARCH_MXS) += \ + imx23-evk.dtb \ imx23-olinuxino.dtb \ imx23-stmp378x_devb.dtb \ imx28-apf28.dtb \ @@ -294,17 +330,21 @@ dtb-$(CONFIG_ARCH_MXS) += imx23-evk.dtb \ imx28-m28evk.dtb \ imx28-sps1.dtb \ imx28-tx28.dtb -dtb-$(CONFIG_ARCH_NOMADIK) += ste-nomadik-s8815.dtb \ +dtb-$(CONFIG_ARCH_NOMADIK) += \ + ste-nomadik-s8815.dtb \ ste-nomadik-nhk15.dtb -dtb-$(CONFIG_ARCH_NSPIRE) += nspire-cx.dtb \ +dtb-$(CONFIG_ARCH_NSPIRE) += \ + nspire-cx.dtb \ nspire-tp.dtb \ nspire-clp.dtb -dtb-$(CONFIG_ARCH_OMAP2) += omap2420-h4.dtb \ +dtb-$(CONFIG_ARCH_OMAP2) += \ + omap2420-h4.dtb \ omap2420-n800.dtb \ omap2420-n810.dtb \ omap2420-n810-wimax.dtb \ omap2430-sdp.dtb -dtb-$(CONFIG_ARCH_OMAP3) += am3517-craneboard.dtb \ +dtb-$(CONFIG_ARCH_OMAP3) += \ + am3517-craneboard.dtb \ am3517-evm.dtb \ am3517_mt_ventoux.dtb \ omap3430-sdp.dtb \ @@ -348,7 +388,8 @@ dtb-$(CONFIG_ARCH_OMAP3) += am3517-craneboard.dtb \ omap3-sbc-t3730.dtb \ omap3-thunder.dtb \ omap3-zoom3.dtb -dtb-$(CONFIG_SOC_AM33XX) += am335x-base0033.dtb \ +dtb-$(CONFIG_SOC_AM33XX) += \ + am335x-base0033.dtb \ am335x-bone.dtb \ am335x-boneblack.dtb \ am335x-evm.dtb \ @@ -356,7 +397,8 @@ dtb-$(CONFIG_SOC_AM33XX) += am335x-base0033.dtb \ am335x-nano.dtb \ am335x-pepper.dtb \ am335x-lxm.dtb -dtb-$(CONFIG_ARCH_OMAP4) += omap4-duovero-parlor.dtb \ +dtb-$(CONFIG_ARCH_OMAP4) += \ + omap4-duovero-parlor.dtb \ omap4-panda.dtb \ omap4-panda-a4.dtb \ omap4-panda-es.dtb \ @@ -364,20 +406,25 @@ dtb-$(CONFIG_ARCH_OMAP4) += omap4-duovero-parlor.dtb \ omap4-sdp-es23plus.dtb \ omap4-var-dvk-om44.dtb \ omap4-var-stk-om44.dtb -dtb-$(CONFIG_SOC_AM43XX) += am43x-epos-evm.dtb \ +dtb-$(CONFIG_SOC_AM43XX) += \ + am43x-epos-evm.dtb \ am437x-sk-evm.dtb \ am437x-gp-evm.dtb -dtb-$(CONFIG_SOC_OMAP5) += omap5-cm-t54.dtb \ +dtb-$(CONFIG_SOC_OMAP5) += \ + omap5-cm-t54.dtb \ omap5-sbc-t54.dtb \ omap5-uevm.dtb -dtb-$(CONFIG_SOC_DRA7XX) += dra7-evm.dtb \ +dtb-$(CONFIG_SOC_DRA7XX) += \ + dra7-evm.dtb \ am57xx-beagle-x15.dtb \ dra72-evm.dtb -dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-d2-network.dtb \ +dtb-$(CONFIG_ARCH_ORION5X) += \ + orion5x-lacie-d2-network.dtb \ orion5x-lacie-ethernet-disk-mini-v2.dtb \ orion5x-maxtor-shared-storage-2.dtb \ orion5x-rd88f5182-nas.dtb -dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb +dtb-$(CONFIG_ARCH_PRIMA2) += \ + prima2-evb.dtb dtb-$(CONFIG_ARCH_QCOM) += \ qcom-apq8064-cm-qs600.dtb \ qcom-apq8064-ifc6410.dtb \ @@ -388,17 +435,21 @@ dtb-$(CONFIG_ARCH_QCOM) += \ qcom-msm8660-surf.dtb \ qcom-msm8960-cdp.dtb \ qcom-msm8974-sony-xperia-honami.dtb -dtb-$(CONFIG_ARCH_REALVIEW) += arm-realview-pb1176.dtb +dtb-$(CONFIG_ARCH_REALVIEW) += \ + arm-realview-pb1176.dtb dtb-$(CONFIG_ARCH_ROCKCHIP) += \ rk3066a-bqcurie2.dtb \ rk3066a-marsboard.dtb \ rk3188-radxarock.dtb \ rk3288-evb-act8846.dtb \ rk3288-evb-rk808.dtb -dtb-$(CONFIG_ARCH_S3C24XX) += s3c2416-smdk2416.dtb -dtb-$(CONFIG_ARCH_S3C64XX) += s3c6410-mini6410.dtb \ +dtb-$(CONFIG_ARCH_S3C24XX) += \ + s3c2416-smdk2416.dtb +dtb-$(CONFIG_ARCH_S3C64XX) += \ + s3c6410-mini6410.dtb \ s3c6410-smdk6410.dtb -dtb-$(CONFIG_ARCH_S5PV210) += s5pv210-aquila.dtb \ +dtb-$(CONFIG_ARCH_S5PV210) += \ + s5pv210-aquila.dtb \ s5pv210-goni.dtb \ s5pv210-smdkc110.dtb \ s5pv210-smdkv210.dtb \ @@ -414,7 +465,8 @@ dtb-$(CONFIG_ARCH_SHMOBILE_LEGACY) += \ sh7372-mackerel.dtb \ sh73a0-kzm9g.dtb \ sh73a0-kzm9g-reference.dtb -dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += emev2-kzm9d.dtb \ +dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += \ + emev2-kzm9d.dtb \ r7s72100-genmai.dtb \ r8a73a4-ape6evm.dtb \ r8a7740-armadillo800eva.dtb \ @@ -423,20 +475,25 @@ dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += emev2-kzm9d.dtb \ r8a7791-henninger.dtb \ r8a7791-koelsch.dtb \ r8a7794-alt.dtb -dtb-$(CONFIG_ARCH_SOCFPGA) += socfpga_arria5_socdk.dtb \ +dtb-$(CONFIG_ARCH_SOCFPGA) += \ + socfpga_arria5_socdk.dtb \ socfpga_arria10_socdk.dtb \ socfpga_cyclone5_socdk.dtb \ socfpga_cyclone5_sockit.dtb \ socfpga_cyclone5_socrates.dtb \ socfpga_vt.dtb -dtb-$(CONFIG_ARCH_SPEAR13XX) += spear1310-evb.dtb \ +dtb-$(CONFIG_ARCH_SPEAR13XX) += \ + spear1310-evb.dtb \ spear1340-evb.dtb -dtb-$(CONFIG_ARCH_SPEAR3XX)+= spear300-evb.dtb \ +dtb-$(CONFIG_ARCH_SPEAR3XX) += \ + spear300-evb.dtb \ spear310-evb.dtb \ spear320-evb.dtb \ spear320-hmi.dtb -dtb-$(CONFIG_ARCH_SPEAR6XX)+= spear600-evb.dtb -dtb-$(CONFIG_ARCH_STI)+= stih407-b2120.dtb \ +dtb-$(CONFIG_ARCH_SPEAR6XX) += \ + spear600-evb.dtb +dtb-$(CONFIG_ARCH_STI) += \ + stih407-b2120.dtb \ stih410-b2120.dtb \ stih415-b2000.dtb \ stih415-b2020.dtb \ @@ -478,7 +535,8 @@ dtb-$(CONFIG_MACH_SUN8I) += \ sun8i-a23-ippo-q8h-v5.dtb dtb-$(CONFIG_MACH_SUN9I) += \ sun9i-a80-optimus.dtb -dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \ +dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += \ + tegra20-harmony.dtb \ tegra20-iris-512.dtb \ tegra20-medcom-wide.dtb \ tegra20-paz00.dtb \ @@ -487,34 +545,43 @@ dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \ tegra20-tec.dtb \ tegra20-trimslice.dtb \ tegra20-ventana.dtb \ - tegra20-whistler.dtb \ + tegra20-whistler.dtb +dtb-$(CONFIG_ARCH_TEGRA_3x_SOC) += \ tegra30-apalis-eval.dtb \ tegra30-beaver.dtb \ tegra30-cardhu-a02.dtb \ tegra30-cardhu-a04.dtb \ - tegra30-colibri-eval-v3.dtb \ + tegra30-colibri-eval-v3.dtb +dtb-$(CONFIG_ARCH_TEGRA_114_SOC) += \ tegra114-dalmore.dtb \ tegra114-roth.dtb \ - tegra114-tn7.dtb \ + tegra114-tn7.dtb +dtb-$(CONFIG_ARCH_TEGRA_124_SOC) += \ tegra124-jetson-tk1.dtb \ tegra124-nyan-big.dtb \ tegra124-venice2.dtb -dtb-$(CONFIG_ARCH_U300) += ste-u300.dtb -dtb-$(CONFIG_ARCH_U8500) += ste-snowball.dtb \ +dtb-$(CONFIG_ARCH_U300) += \ + ste-u300.dtb +dtb-$(CONFIG_ARCH_U8500) += \ + ste-snowball.dtb \ ste-hrefprev60-stuib.dtb \ ste-hrefprev60-tvk.dtb \ ste-hrefv60plus-stuib.dtb \ ste-hrefv60plus-tvk.dtb \ ste-ccu8540.dtb \ ste-ccu9540.dtb -dtb-$(CONFIG_ARCH_VERSATILE) += versatile-ab.dtb \ +dtb-$(CONFIG_ARCH_VERSATILE) += \ + versatile-ab.dtb \ versatile-pb.dtb -dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \ +dtb-$(CONFIG_ARCH_VEXPRESS) += \ + vexpress-v2p-ca5s.dtb \ vexpress-v2p-ca9.dtb \ vexpress-v2p-ca15-tc1.dtb \ vexpress-v2p-ca15_a7.dtb -dtb-$(CONFIG_ARCH_VIRT) += xenvm-4.2.dtb -dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \ +dtb-$(CONFIG_ARCH_VIRT) += \ + xenvm-4.2.dtb +dtb-$(CONFIG_ARCH_VT8500) += \ + vt8500-bv07.dtb \ wm8505-ref.dtb \ wm8650-mid.dtb \ wm8750-apc8750.dtb \ @@ -546,13 +613,15 @@ dtb-$(CONFIG_MACH_ARMADA_XP) += \ armada-xp-netgear-rn2120.dtb \ armada-xp-openblocks-ax3-4.dtb \ armada-xp-synology-ds414.dtb -dtb-$(CONFIG_MACH_DOVE) += dove-cm-a510.dtb \ +dtb-$(CONFIG_MACH_DOVE) += \ + dove-cm-a510.dtb \ dove-cubox.dtb \ dove-cubox-es.dtb \ dove-d2plug.dtb \ dove-d3plug.dtb \ dove-dove-db.dtb -dtb-$(CONFIG_ARCH_MEDIATEK) += mt6589-aquaris5.dtb \ +dtb-$(CONFIG_ARCH_MEDIATEK) += \ + mt6589-aquaris5.dtb \ mt6592-evb.dtb \ mt8127-moose.dtb \ mt8135-evbp1.dtb -- cgit v1.2.3 From 31078ecdc7b374efb3f4b2e60c620b2abc1ed307 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 6 Jan 2015 21:01:52 +0100 Subject: ARM: shmobile: r8a7790 dtsi: Drop "renesas,rcar_sound" compatible value The "renesas,rcar_sound" compatible property value was never processed nor documented. Signed-off-by: Geert Uytterhoeven Acked-by: Kuninori Morimoto Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index af7e255f629e..7cef4d9f0377 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -1398,7 +1398,7 @@ rcar_sound: rcar_sound@ec500000 { #sound-dai-cells = <1>; - compatible = "renesas,rcar_sound-r8a7790", "renesas,rcar_sound-gen2", "renesas,rcar_sound"; + compatible = "renesas,rcar_sound-r8a7790", "renesas,rcar_sound-gen2"; reg = <0 0xec500000 0 0x1000>, /* SCU */ <0 0xec5a0000 0 0x100>, /* ADG */ <0 0xec540000 0 0x1000>, /* SSIU */ -- cgit v1.2.3 From f49cd2b3d2caf075d78fa1948fda1d7ed246d1eb Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 6 Jan 2015 21:01:53 +0100 Subject: ARM: shmobile: r8a7791 dtsi: Drop "renesas,rcar_sound" compatible value The "renesas,rcar_sound" compatible property value was never processed nor documented. Signed-off-by: Geert Uytterhoeven Acked-by: Kuninori Morimoto Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7791.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index 77c0beeb8d7c..7fdd1a66eac3 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -1382,7 +1382,7 @@ rcar_sound: rcar_sound@ec500000 { #sound-dai-cells = <1>; - compatible = "renesas,rcar_sound-r8a7791", "renesas,rcar_sound-gen2", "renesas,rcar_sound"; + compatible = "renesas,rcar_sound-r8a7791", "renesas,rcar_sound-gen2"; reg = <0 0xec500000 0 0x1000>, /* SCU */ <0 0xec5a0000 0 0x100>, /* ADG */ <0 0xec540000 0 0x1000>, /* SSIU */ -- cgit v1.2.3 From ad63241cdc328edbb0f879416ea7707bf0997f08 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 17 Dec 2014 06:11:52 +0000 Subject: ARM: shmobile: r8a7790: tidyup #sound-dai-cells settings Renesas sound driver needs #sound-dai-cells settings, but, this usage is a little bit confusable. It came from ALSA SoC historical reasons. The sound DAI naming method is different between Single/Multi DAI in the ALSA framework, and it is used for sound card matching. And this #sound-dai-cells has relationship to it. Current SoC dtsi has #sound-dai-cells = <1> as default settings (= it is assuming that board/platform has multi DAI), and board/platform side needs to overwrite it if board/platform was single DAI. This style is more confusable for users. This patch removes SoC side default settings, and force to set it by board/platform side. Signed-off-by: Kuninori Morimoto Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790-lager.dts | 1 + arch/arm/boot/dts/r8a7790.dtsi | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts index 636d53bb87a2..2bc20e44fff9 100644 --- a/arch/arm/boot/dts/r8a7790-lager.dts +++ b/arch/arm/boot/dts/r8a7790-lager.dts @@ -579,6 +579,7 @@ pinctrl-0 = <&sound_pins &sound_clk_pins>; pinctrl-names = "default"; + /* Single DAI */ #sound-dai-cells = <0>; status = "okay"; diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index 7cef4d9f0377..1543fa5f21d5 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -1397,7 +1397,12 @@ }; rcar_sound: rcar_sound@ec500000 { - #sound-dai-cells = <1>; + /* + * #sound-dai-cells is required + * + * Single DAI : #sound-dai-cells = <0>; <&rcar_sound>; + * Multi DAI : #sound-dai-cells = <1>; <&rcar_sound N>; + */ compatible = "renesas,rcar_sound-r8a7790", "renesas,rcar_sound-gen2"; reg = <0 0xec500000 0 0x1000>, /* SCU */ <0 0xec5a0000 0 0x100>, /* ADG */ -- cgit v1.2.3 From d2b541c98f5402ebb49ee1c636ef5bc31462b4ca Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 17 Dec 2014 06:12:02 +0000 Subject: ARM: shmobile: r8a7791: tidyup #sound-dai-cells settings Renesas sound driver needs #sound-dai-cells settings, but, this usage is a little bit confusable. It came from ALSA SoC historical reasons. The sound DAI naming method is different between Single/Multi DAI in the ALSA framework, and it is used for sound card matching. And this #sound-dai-cells has relationship to it. Current SoC dtsi has #sound-dai-cells = <1> as default settings (= it is assuming that board/platform has multi DAI), and board/platform side needs to overwrite it if board/platform was single DAI. This style is more confusable for users. This patch removes SoC side default settings, and force to set it by board/platform side. Signed-off-by: Kuninori Morimoto Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7791-koelsch.dts | 1 + arch/arm/boot/dts/r8a7791.dtsi | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts index 990af167c551..9c651c0b685a 100644 --- a/arch/arm/boot/dts/r8a7791-koelsch.dts +++ b/arch/arm/boot/dts/r8a7791-koelsch.dts @@ -582,6 +582,7 @@ pinctrl-0 = <&sound_pins &sound_clk_pins>; pinctrl-names = "default"; + /* Single DAI */ #sound-dai-cells = <0>; status = "okay"; diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index 7fdd1a66eac3..002dbc536bd8 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -1381,7 +1381,12 @@ }; rcar_sound: rcar_sound@ec500000 { - #sound-dai-cells = <1>; + /* + * #sound-dai-cells is required + * + * Single DAI : #sound-dai-cells = <0>; <&rcar_sound>; + * Multi DAI : #sound-dai-cells = <1>; <&rcar_sound N>; + */ compatible = "renesas,rcar_sound-r8a7791", "renesas,rcar_sound-gen2"; reg = <0 0xec500000 0 0x1000>, /* SCU */ <0 0xec5a0000 0 0x100>, /* ADG */ -- cgit v1.2.3 From aba07789d811b6cf645cffc83ac821393027819a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 3 Dec 2014 14:41:46 +0100 Subject: ARM: shmobile: r8a7740 dtsi: Add PM domain support Add a device node for the System Controller, with subnodes that represent the hardware power area hierarchy. Hook up all devices to their respective PM domains. Add a minimal device node for the Coresight-ETM hardware block, and hook it up to the D4 PM domain, so the R-Mobile System Controller driver can keep the domain powered, until the new Coresight code handles runtime PM. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7740.dtsi | 99 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7740.dtsi b/arch/arm/boot/dts/r8a7740.dtsi index 60ca62254536..52f2cf4b84d3 100644 --- a/arch/arm/boot/dts/r8a7740.dtsi +++ b/arch/arm/boot/dts/r8a7740.dtsi @@ -25,6 +25,7 @@ device_type = "cpu"; reg = <0x0>; clock-frequency = <800000000>; + power-domains = <&pd_a3sm>; }; }; @@ -41,12 +42,18 @@ interrupts = <0 83 IRQ_TYPE_LEVEL_HIGH>; }; + ptm { + compatible = "arm,coresight-etm3x"; + power-domains = <&pd_d4>; + }; + cmt1: timer@e6138000 { compatible = "renesas,cmt-48-r8a7740", "renesas,cmt-48"; reg = <0xe6138000 0x170>; interrupts = <0 58 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp3_clks R8A7740_CLK_CMT1>; clock-names = "fck"; + power-domains = <&pd_c5>; renesas,channels-mask = <0x3f>; @@ -72,6 +79,7 @@ 0 149 IRQ_TYPE_LEVEL_HIGH 0 149 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp2_clks R8A7740_CLK_INTCA>; + power-domains = <&pd_a4s>; }; /* irqpin1: IRQ8 - IRQ15 */ @@ -93,6 +101,7 @@ 0 149 IRQ_TYPE_LEVEL_HIGH 0 149 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp2_clks R8A7740_CLK_INTCA>; + power-domains = <&pd_a4s>; }; /* irqpin2: IRQ16 - IRQ23 */ @@ -114,6 +123,7 @@ 0 149 IRQ_TYPE_LEVEL_HIGH 0 149 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp2_clks R8A7740_CLK_INTCA>; + power-domains = <&pd_a4s>; }; /* irqpin3: IRQ24 - IRQ31 */ @@ -135,6 +145,7 @@ 0 149 IRQ_TYPE_LEVEL_HIGH 0 149 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp2_clks R8A7740_CLK_INTCA>; + power-domains = <&pd_a4s>; }; ether: ethernet@e9a00000 { @@ -143,6 +154,7 @@ <0xe9a01800 0x800>; interrupts = <0 110 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp3_clks R8A7740_CLK_GETHER>; + power-domains = <&pd_a4s>; phy-mode = "mii"; #address-cells = <1>; #size-cells = <0>; @@ -159,6 +171,7 @@ 0 203 IRQ_TYPE_LEVEL_HIGH 0 204 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp1_clks R8A7740_CLK_IIC0>; + power-domains = <&pd_a4r>; status = "disabled"; }; @@ -172,6 +185,7 @@ 0 72 IRQ_TYPE_LEVEL_HIGH 0 73 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp3_clks R8A7740_CLK_IIC1>; + power-domains = <&pd_a3sp>; status = "disabled"; }; @@ -181,6 +195,7 @@ interrupts = <0 100 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp2_clks R8A7740_CLK_SCIFA0>; clock-names = "sci_ick"; + power-domains = <&pd_a3sp>; status = "disabled"; }; @@ -190,6 +205,7 @@ interrupts = <0 101 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp2_clks R8A7740_CLK_SCIFA1>; clock-names = "sci_ick"; + power-domains = <&pd_a3sp>; status = "disabled"; }; @@ -199,6 +215,7 @@ interrupts = <0 102 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp2_clks R8A7740_CLK_SCIFA2>; clock-names = "sci_ick"; + power-domains = <&pd_a3sp>; status = "disabled"; }; @@ -208,6 +225,7 @@ interrupts = <0 103 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp2_clks R8A7740_CLK_SCIFA3>; clock-names = "sci_ick"; + power-domains = <&pd_a3sp>; status = "disabled"; }; @@ -217,6 +235,7 @@ interrupts = <0 104 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp2_clks R8A7740_CLK_SCIFA4>; clock-names = "sci_ick"; + power-domains = <&pd_a3sp>; status = "disabled"; }; @@ -226,6 +245,7 @@ interrupts = <0 105 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp2_clks R8A7740_CLK_SCIFA5>; clock-names = "sci_ick"; + power-domains = <&pd_a3sp>; status = "disabled"; }; @@ -235,6 +255,7 @@ interrupts = <0 106 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp2_clks R8A7740_CLK_SCIFA6>; clock-names = "sci_ick"; + power-domains = <&pd_a3sp>; status = "disabled"; }; @@ -244,6 +265,7 @@ interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp2_clks R8A7740_CLK_SCIFA7>; clock-names = "sci_ick"; + power-domains = <&pd_a3sp>; status = "disabled"; }; @@ -253,6 +275,7 @@ interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp2_clks R8A7740_CLK_SCIFB>; clock-names = "sci_ick"; + power-domains = <&pd_a3sp>; status = "disabled"; }; @@ -271,12 +294,14 @@ <&irqpin2 4 0>, <&irqpin2 5 0>, <&irqpin2 6 0>, <&irqpin2 7 0>, <&irqpin3 0 0>, <&irqpin3 1 0>, <&irqpin3 2 0>, <&irqpin3 3 0>, <&irqpin3 4 0>, <&irqpin3 5 0>, <&irqpin3 6 0>, <&irqpin3 7 0>; + power-domains = <&pd_c5>; }; tpu: pwm@e6600000 { compatible = "renesas,tpu-r8a7740", "renesas,tpu"; reg = <0xe6600000 0x100>; clocks = <&mstp3_clks R8A7740_CLK_TPU0>; + power-domains = <&pd_a3sp>; status = "disabled"; #pwm-cells = <3>; }; @@ -287,6 +312,7 @@ interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH 0 57 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp3_clks R8A7740_CLK_MMC>; + power-domains = <&pd_a3sp>; status = "disabled"; }; @@ -297,6 +323,7 @@ 0 118 IRQ_TYPE_LEVEL_HIGH 0 119 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp3_clks R8A7740_CLK_SDHI0>; + power-domains = <&pd_a3sp>; cap-sd-highspeed; cap-sdio-irq; status = "disabled"; @@ -309,6 +336,7 @@ 0 122 IRQ_TYPE_LEVEL_HIGH 0 123 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp3_clks R8A7740_CLK_SDHI1>; + power-domains = <&pd_a3sp>; cap-sd-highspeed; cap-sdio-irq; status = "disabled"; @@ -321,6 +349,7 @@ 0 126 IRQ_TYPE_LEVEL_HIGH 0 127 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp4_clks R8A7740_CLK_SDHI2>; + power-domains = <&pd_a3sp>; cap-sd-highspeed; cap-sdio-irq; status = "disabled"; @@ -332,6 +361,7 @@ reg = <0xfe1f0000 0x400>; interrupts = <0 9 0x4>; clocks = <&mstp3_clks R8A7740_CLK_FSI>; + power-domains = <&pd_a4mp>; status = "disabled"; }; @@ -343,6 +373,7 @@ <0 200 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp1_clks R8A7740_CLK_TMU0>; clock-names = "fck"; + power-domains = <&pd_a4r>; #renesas,channels = <3>; @@ -357,6 +388,7 @@ <0 172 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp1_clks R8A7740_CLK_TMU1>; clock-names = "fck"; + power-domains = <&pd_a4r>; #renesas,channels = <3>; @@ -543,4 +575,71 @@ "usbhost", "sdhi2", "usbfunc", "usphy"; }; }; + + sysc: system-controller@e6180000 { + compatible = "renesas,sysc-r8a7740", "renesas,sysc-rmobile"; + reg = <0xe6180000 0x8000>, <0xe6188000 0x8000>; + + pm-domains { + pd_c5: c5 { + #address-cells = <1>; + #size-cells = <0>; + #power-domain-cells = <0>; + + pd_a4lc: a4lc@1 { + reg = <1>; + #power-domain-cells = <0>; + }; + + pd_a4mp: a4mp@2 { + reg = <2>; + #power-domain-cells = <0>; + }; + + pd_d4: d4@3 { + reg = <3>; + #power-domain-cells = <0>; + }; + + pd_a4r: a4r@5 { + reg = <5>; + #address-cells = <1>; + #size-cells = <0>; + #power-domain-cells = <0>; + + pd_a3rv: a3rv@6 { + reg = <6>; + #power-domain-cells = <0>; + }; + }; + + pd_a4s: a4s@10 { + reg = <10>; + #address-cells = <1>; + #size-cells = <0>; + #power-domain-cells = <0>; + + pd_a3sp: a3sp@11 { + reg = <11>; + #power-domain-cells = <0>; + }; + + pd_a3sm: a3sm@12 { + reg = <12>; + #power-domain-cells = <0>; + }; + + pd_a3sg: a3sg@13 { + reg = <13>; + #power-domain-cells = <0>; + }; + }; + + pd_a4su: a4su@20 { + reg = <20>; + #power-domain-cells = <0>; + }; + }; + }; + }; }; -- cgit v1.2.3 From 2fd4e094bbe6de0dc98355c4c387c433f6de525c Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Tue, 13 Jan 2015 01:31:14 +0300 Subject: ARM: shmobile: r8a7791: fix MSTP8 input clocks I made a mistake when rebasing Andrey Gusakov's patch adding MLB+ clock to the R8A7791 device tree, inserting <&hp_clk> into the "clocks" property of the MSTP8 node at a wrong position, so that the input clocks for MLB+ and IPMMU-SGX got swapped... Fixes: 7408d3061d2f ("ARM: shmobile: r8a7791: add MLB+ clock") Signed-off-by: Sergei Shtylyov Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7791.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index 28102265cc71..946cd3a4836e 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -1154,7 +1154,7 @@ mstp8_clks: mstp8_clks@e6150990 { compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks"; reg = <0 0xe6150990 0 4>, <0 0xe61509a0 0 4>; - clocks = <&hp_clk>, <&zg_clk>, <&zg_clk>, <&zg_clk>, + clocks = <&zg_clk>, <&hp_clk>, <&zg_clk>, <&zg_clk>, <&zg_clk>, <&p_clk>, <&zs_clk>, <&zs_clk>; #clock-cells = <1>; clock-indices = < -- cgit v1.2.3 From d86a31101f7952870d50df96abb786bb983efa69 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Jan 2015 01:55:15 +0000 Subject: ARM: shmobile: r8a7790: add SRC interrupt number on DTSI Signed-off-by: Kuninori Morimoto Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7790.dtsi | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi index af30c2470f85..637e4ee10d6a 100644 --- a/arch/arm/boot/dts/r8a7790.dtsi +++ b/arch/arm/boot/dts/r8a7790.dtsi @@ -1435,16 +1435,16 @@ }; rcar_sound,src { - src0: src@0 { }; - src1: src@1 { }; - src2: src@2 { }; - src3: src@3 { }; - src4: src@4 { }; - src5: src@5 { }; - src6: src@6 { }; - src7: src@7 { }; - src8: src@8 { }; - src9: src@9 { }; + src0: src@0 { interrupts = <0 352 IRQ_TYPE_LEVEL_HIGH>; }; + src1: src@1 { interrupts = <0 353 IRQ_TYPE_LEVEL_HIGH>; }; + src2: src@2 { interrupts = <0 354 IRQ_TYPE_LEVEL_HIGH>; }; + src3: src@3 { interrupts = <0 355 IRQ_TYPE_LEVEL_HIGH>; }; + src4: src@4 { interrupts = <0 356 IRQ_TYPE_LEVEL_HIGH>; }; + src5: src@5 { interrupts = <0 357 IRQ_TYPE_LEVEL_HIGH>; }; + src6: src@6 { interrupts = <0 358 IRQ_TYPE_LEVEL_HIGH>; }; + src7: src@7 { interrupts = <0 359 IRQ_TYPE_LEVEL_HIGH>; }; + src8: src@8 { interrupts = <0 360 IRQ_TYPE_LEVEL_HIGH>; }; + src9: src@9 { interrupts = <0 361 IRQ_TYPE_LEVEL_HIGH>; }; }; rcar_sound,ssi { -- cgit v1.2.3 From 8856102dd30897e608331521f4286163700c4d59 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Jan 2015 01:55:27 +0000 Subject: ARM: shmobile: r8a7791: add SRC interrupt number on DTSI Signed-off-by: Kuninori Morimoto Signed-off-by: Simon Horman --- arch/arm/boot/dts/r8a7791.dtsi | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi index 946cd3a4836e..e3a60a22d34a 100644 --- a/arch/arm/boot/dts/r8a7791.dtsi +++ b/arch/arm/boot/dts/r8a7791.dtsi @@ -1420,16 +1420,16 @@ }; rcar_sound,src { - src0: src@0 { }; - src1: src@1 { }; - src2: src@2 { }; - src3: src@3 { }; - src4: src@4 { }; - src5: src@5 { }; - src6: src@6 { }; - src7: src@7 { }; - src8: src@8 { }; - src9: src@9 { }; + src0: src@0 { interrupts = <0 352 IRQ_TYPE_LEVEL_HIGH>; }; + src1: src@1 { interrupts = <0 353 IRQ_TYPE_LEVEL_HIGH>; }; + src2: src@2 { interrupts = <0 354 IRQ_TYPE_LEVEL_HIGH>; }; + src3: src@3 { interrupts = <0 355 IRQ_TYPE_LEVEL_HIGH>; }; + src4: src@4 { interrupts = <0 356 IRQ_TYPE_LEVEL_HIGH>; }; + src5: src@5 { interrupts = <0 357 IRQ_TYPE_LEVEL_HIGH>; }; + src6: src@6 { interrupts = <0 358 IRQ_TYPE_LEVEL_HIGH>; }; + src7: src@7 { interrupts = <0 359 IRQ_TYPE_LEVEL_HIGH>; }; + src8: src@8 { interrupts = <0 360 IRQ_TYPE_LEVEL_HIGH>; }; + src9: src@9 { interrupts = <0 361 IRQ_TYPE_LEVEL_HIGH>; }; }; rcar_sound,ssi { -- cgit v1.2.3 From e69229f2eb9d5f44981840eaf014fcb5ed60faac Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 15 Aug 2014 10:56:09 +0200 Subject: m68k/atari: Remove obsolete keyboard_tasklet scheduling If CONFIG_VT=n: arch/m68k/atari/built-in.o: In function `atari_keyboard_interrupt': atakeyb.c:(.text+0x1846): undefined reference to `keyboard_tasklet' atakeyb.c:(.text+0x1852): undefined reference to `keyboard_tasklet' I think the keyboard_tasklet scheduling is no longer needed, as I believe it's handled by drivers/tty/vt/keyboard.c based on events received from the input subsystem. So just remove it. Signed-off-by: Geert Uytterhoeven Tested-by: Michael Schmitz --- arch/m68k/atari/atakeyb.c | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c index ad919696ec88..7bea01ceff55 100644 --- a/arch/m68k/atari/atakeyb.c +++ b/arch/m68k/atari/atakeyb.c @@ -170,7 +170,6 @@ repeat: if (acia_stat & ACIA_RDRF) { /* received a character */ scancode = acia.key_data; /* get it or reset the ACIA, I'll get it! */ - tasklet_schedule(&keyboard_tasklet); interpret_scancode: switch (kb_state.state) { case KEYBOARD: -- cgit v1.2.3 From 6f540db781cf4416e348d20d63eb121f5bf1fb24 Mon Sep 17 00:00:00 2001 From: Bhuvanchandra DV Date: Tue, 6 Jan 2015 19:06:56 +0530 Subject: ARM: imx: clk-vf610: Add clock for UART4 and UART5 Add support for clock gating of UART4 and UART5. We use these UART's in a (not yet mainlined) device tree. Signed-off-by: Bhuvanchandra DV Signed-off-by: Shawn Guo --- arch/arm/mach-imx/clk-vf610.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-imx/clk-vf610.c b/arch/arm/mach-imx/clk-vf610.c index cb21777c3ab6..af338d23e6e7 100644 --- a/arch/arm/mach-imx/clk-vf610.c +++ b/arch/arm/mach-imx/clk-vf610.c @@ -267,6 +267,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) clk[VF610_CLK_UART1] = imx_clk_gate2("uart1", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(8)); clk[VF610_CLK_UART2] = imx_clk_gate2("uart2", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(9)); clk[VF610_CLK_UART3] = imx_clk_gate2("uart3", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(10)); + clk[VF610_CLK_UART4] = imx_clk_gate2("uart4", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(9)); + clk[VF610_CLK_UART5] = imx_clk_gate2("uart5", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(10)); clk[VF610_CLK_I2C0] = imx_clk_gate2("i2c0", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(6)); clk[VF610_CLK_I2C1] = imx_clk_gate2("i2c1", "ipg_bus", CCM_CCGR4, CCM_CCGRx_CGn(7)); -- cgit v1.2.3 From 60b217a03b1156a22926ec0770c2aa08679ea769 Mon Sep 17 00:00:00 2001 From: Alexander Kuleshov Date: Sat, 3 Jan 2015 12:52:21 +0600 Subject: x86, setup: Rename BOOT_ISDIGIT_H to BOOT_CTYPE_H arch/x86/boot/isdigit.h was renamed to arch/x86/boot/ctype.h in 6238b47b5848 ("x86, setup: move isdigit.h to ctype.h, header files on top.") Adjust guards too. Signed-off-by: Alexander Kuleshov Link: http://lkml.kernel.org/r/1420267941-26390-1-git-send-email-kuleshovmail@gmail.com Signed-off-by: Borislav Petkov --- arch/x86/boot/ctype.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/x86/boot/ctype.h b/arch/x86/boot/ctype.h index 25e13403193c..020f137df7a2 100644 --- a/arch/x86/boot/ctype.h +++ b/arch/x86/boot/ctype.h @@ -1,6 +1,5 @@ -#ifndef BOOT_ISDIGIT_H - -#define BOOT_ISDIGIT_H +#ifndef BOOT_CTYPE_H +#define BOOT_CTYPE_H static inline int isdigit(int ch) { -- cgit v1.2.3 From e054273a9b117f74ad8214b1f0f23e917e25522e Mon Sep 17 00:00:00 2001 From: Alexander Kuleshov Date: Wed, 31 Dec 2014 19:56:31 +0600 Subject: x86, early_serial_console: Remove unused macro XMTRDY There is no write to serial routine, no need for XMTRDY macro. Signed-off-by: Alexander Kuleshov Link: http://lkml.kernel.org/r/1420034191-20721-1-git-send-email-kuleshovmail@gmail.com Signed-off-by: Borislav Petkov --- arch/x86/boot/early_serial_console.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/boot/early_serial_console.c b/arch/x86/boot/early_serial_console.c index 5df2869c874b..790586daec83 100644 --- a/arch/x86/boot/early_serial_console.c +++ b/arch/x86/boot/early_serial_console.c @@ -2,8 +2,6 @@ #define DEFAULT_SERIAL_PORT 0x3f8 /* ttyS0 */ -#define XMTRDY 0x20 - #define DLAB 0x80 #define TXR 0 /* Transmit register (WRITE) */ -- cgit v1.2.3 From b34630014dad0ba69aadd8deb231ddc6d2efcf53 Mon Sep 17 00:00:00 2001 From: Alexander Kuleshov Date: Wed, 31 Dec 2014 13:12:38 +0600 Subject: x86, early_serial_console: Remove unnecessary check We do this check already a couple of lines up. Signed-off-by: Alexander Kuleshov Link: http://lkml.kernel.org/r/1420009958-4803-1-git-send-email-kuleshovmail@gmail.com Signed-off-by: Borislav Petkov --- arch/x86/boot/early_serial_console.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/boot/early_serial_console.c b/arch/x86/boot/early_serial_console.c index 790586daec83..45a07684bbab 100644 --- a/arch/x86/boot/early_serial_console.c +++ b/arch/x86/boot/early_serial_console.c @@ -72,8 +72,8 @@ static void parse_earlyprintk(void) static const int bases[] = { 0x3f8, 0x2f8 }; int idx = 0; - if (!strncmp(arg + pos, "ttyS", 4)) - pos += 4; + /* += strlen("ttyS"); */ + pos += 4; if (arg[pos++] == '1') idx = 1; -- cgit v1.2.3 From c205389557aac828f8403db0368d1fc2ef859213 Mon Sep 17 00:00:00 2001 From: Sanchayan Maity Date: Wed, 7 Jan 2015 12:39:29 +0530 Subject: ARM: imx: clk-vf610: Add clock for SNVS Add support for clock gating of the SNVS peripheral. Signed-off-by: Sanchayan Maity Signed-off-by: Shawn Guo --- arch/arm/mach-imx/clk-vf610.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch') diff --git a/arch/arm/mach-imx/clk-vf610.c b/arch/arm/mach-imx/clk-vf610.c index af338d23e6e7..61876ed6e11e 100644 --- a/arch/arm/mach-imx/clk-vf610.c +++ b/arch/arm/mach-imx/clk-vf610.c @@ -382,6 +382,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) clk[VF610_CLK_DMAMUX2] = imx_clk_gate2("dmamux2", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(1)); clk[VF610_CLK_DMAMUX3] = imx_clk_gate2("dmamux3", "platform_bus", CCM_CCGR6, CCM_CCGRx_CGn(2)); + clk[VF610_CLK_SNVS] = imx_clk_gate2("snvs-rtc", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(7)); + imx_check_clocks(clk, ARRAY_SIZE(clk)); clk_set_parent(clk[VF610_CLK_QSPI0_SEL], clk[VF610_CLK_PLL1_PFD4]); -- cgit v1.2.3 From 8455dd0d4f4621a41df0779bce23113656598a76 Mon Sep 17 00:00:00 2001 From: Sanchayan Maity Date: Wed, 7 Jan 2015 12:39:30 +0530 Subject: ARM: dts: vfxxx: Add SNVS node Add device tree node for the Secure Non-Volatile Storage (SNVS) on the VF610 platform. The SNVS block also has a Real Time Counter (RTC). Signed-off-by: Sanchayan Maity Signed-off-by: Shawn Guo --- arch/arm/boot/dts/vf500.dtsi | 4 ++++ arch/arm/boot/dts/vfxxx.dtsi | 14 ++++++++++++++ 2 files changed, 18 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/vf500.dtsi b/arch/arm/boot/dts/vf500.dtsi index 29016090d060..0d0de864643f 100644 --- a/arch/arm/boot/dts/vf500.dtsi +++ b/arch/arm/boot/dts/vf500.dtsi @@ -130,6 +130,10 @@ interrupts = ; }; +&snvsrtc { + interrupts = ; +}; + &src { interrupts = ; }; diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi index a55e1f9a414d..ae5c35879a53 100644 --- a/arch/arm/boot/dts/vfxxx.dtsi +++ b/arch/arm/boot/dts/vfxxx.dtsi @@ -351,6 +351,20 @@ status = "disabled"; }; + snvs0: snvs@400a7000 { + compatible = "fsl,sec-v4.0-mon", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x400a7000 0x2000>; + + snvsrtc: snvs-rtc-lp@34 { + compatible = "fsl,sec-v4.0-mon-rtc-lp"; + reg = <0x34 0x58>; + clocks = <&clks VF610_CLK_SNVS>; + clock-names = "snvs-rtc"; + }; + }; + uart4: serial@400a9000 { compatible = "fsl,vf610-lpuart"; reg = <0x400a9000 0x1000>; -- cgit v1.2.3 From b01264170cef82f3521db90a0589be72dfc7f6eb Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Sun, 11 Jan 2015 18:17:43 +0100 Subject: crypto: sparc64/aes - fix module description AES is a block cipher, not a hash. Cc: David S. Miller Signed-off-by: Mathias Krause Acked-by: David S. Miller Signed-off-by: Herbert Xu --- arch/sparc/crypto/aes_glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/sparc/crypto/aes_glue.c b/arch/sparc/crypto/aes_glue.c index 705408766ab0..2e48eb8813ff 100644 --- a/arch/sparc/crypto/aes_glue.c +++ b/arch/sparc/crypto/aes_glue.c @@ -497,7 +497,7 @@ module_init(aes_sparc64_mod_init); module_exit(aes_sparc64_mod_fini); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("AES Secure Hash Algorithm, sparc64 aes opcode accelerated"); +MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm, sparc64 aes opcode accelerated"); MODULE_ALIAS_CRYPTO("aes"); -- cgit v1.2.3 From 7d676fdbb42ddef809011e4cfcc4d11cf64989b5 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Sun, 11 Jan 2015 18:17:44 +0100 Subject: crypto: sparc64/camellia - fix module alias The module alias should be "camellia", not "aes". Cc: David S. Miller Signed-off-by: Mathias Krause Acked-by: David S. Miller Signed-off-by: Herbert Xu --- arch/sparc/crypto/camellia_glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/sparc/crypto/camellia_glue.c b/arch/sparc/crypto/camellia_glue.c index 641f55cb61c3..6bf2479a12fb 100644 --- a/arch/sparc/crypto/camellia_glue.c +++ b/arch/sparc/crypto/camellia_glue.c @@ -322,6 +322,6 @@ module_exit(camellia_sparc64_mod_fini); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Camellia Cipher Algorithm, sparc64 camellia opcode accelerated"); -MODULE_ALIAS_CRYPTO("aes"); +MODULE_ALIAS_CRYPTO("camellia"); #include "crop_devid.c" -- cgit v1.2.3 From 5001323b701449459c06a926becb6cf27708dff4 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Sun, 11 Jan 2015 18:17:45 +0100 Subject: crypto: sparc64/des - add "des3_ede" module alias This module provides implementations for "des3_ede", too. Announce those via an appropriate crypto module alias so it can be used in favour to the generic C implementation. Cc: David S. Miller Signed-off-by: Mathias Krause Acked-by: David S. Miller Signed-off-by: Herbert Xu --- arch/sparc/crypto/des_glue.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/sparc/crypto/des_glue.c b/arch/sparc/crypto/des_glue.c index d11500972994..dd6a34fa6e19 100644 --- a/arch/sparc/crypto/des_glue.c +++ b/arch/sparc/crypto/des_glue.c @@ -533,5 +533,6 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms, sparc64 des opcode accelerated"); MODULE_ALIAS_CRYPTO("des"); +MODULE_ALIAS_CRYPTO("des3_ede"); #include "crop_devid.c" -- cgit v1.2.3 From 97ef8ef5a8fe022308c33c03d24424b579eecb36 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Sun, 11 Jan 2015 18:17:46 +0100 Subject: crypto: sparc64/md5 - fix module description MD5 is not SHA1. Cc: David S. Miller Signed-off-by: Mathias Krause Acked-by: David S. Miller Signed-off-by: Herbert Xu --- arch/sparc/crypto/md5_glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/sparc/crypto/md5_glue.c b/arch/sparc/crypto/md5_glue.c index 64c7ff5f72a9..b688731d7ede 100644 --- a/arch/sparc/crypto/md5_glue.c +++ b/arch/sparc/crypto/md5_glue.c @@ -183,7 +183,7 @@ module_init(md5_sparc64_mod_init); module_exit(md5_sparc64_mod_fini); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("MD5 Secure Hash Algorithm, sparc64 md5 opcode accelerated"); +MODULE_DESCRIPTION("MD5 Message Digest Algorithm, sparc64 md5 opcode accelerated"); MODULE_ALIAS_CRYPTO("md5"); -- cgit v1.2.3 From d8219f52a72033f84c15cde73294d46578fb2d68 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Sun, 11 Jan 2015 18:17:47 +0100 Subject: crypto: x86/des3_ede - drop bogus module aliases This module implements variations of "des3_ede" only. Drop the bogus module aliases for "des". Cc: Jussi Kivilinna Signed-off-by: Mathias Krause Signed-off-by: Herbert Xu --- arch/x86/crypto/des3_ede_glue.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/x86/crypto/des3_ede_glue.c b/arch/x86/crypto/des3_ede_glue.c index 38a14f818ef1..d6fc59aaaadf 100644 --- a/arch/x86/crypto/des3_ede_glue.c +++ b/arch/x86/crypto/des3_ede_glue.c @@ -504,6 +504,4 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Triple DES EDE Cipher Algorithm, asm optimized"); MODULE_ALIAS_CRYPTO("des3_ede"); MODULE_ALIAS_CRYPTO("des3_ede-asm"); -MODULE_ALIAS_CRYPTO("des"); -MODULE_ALIAS_CRYPTO("des-asm"); MODULE_AUTHOR("Jussi Kivilinna "); -- cgit v1.2.3 From e182c570e9953859aee5cb016583217d9e68ea18 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 12 Dec 2014 01:56:04 +0200 Subject: x86/uaccess: fix sparse errors virtio wants to read bitwise types from userspace using get_user. At the moment this triggers sparse errors, since the value is passed through an integer. Fix that up using __force. Signed-off-by: Michael S. Tsirkin Acked-by: Thomas Gleixner --- arch/x86/include/asm/uaccess.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 0d592e0a5b84..ace9dec050b1 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -179,7 +179,7 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL)) asm volatile("call __get_user_%P3" \ : "=a" (__ret_gu), "=r" (__val_gu) \ : "0" (ptr), "i" (sizeof(*(ptr)))); \ - (x) = (__typeof__(*(ptr))) __val_gu; \ + (x) = (__force __typeof__(*(ptr))) __val_gu; \ __ret_gu; \ }) -- cgit v1.2.3 From 1ab5786ae45ace5d13517f21508607c5f795a822 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 12 Dec 2014 01:56:04 +0200 Subject: alpha/uaccess: fix sparse errors virtio wants to read bitwise types from userspace using get_user. At the moment this triggers sparse errors, since the value is passed through an integer. Fix that up using __force. Signed-off-by: Michael S. Tsirkin --- arch/alpha/include/asm/uaccess.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/alpha/include/asm/uaccess.h b/arch/alpha/include/asm/uaccess.h index 766fdfde2b7a..a234de79157a 100644 --- a/arch/alpha/include/asm/uaccess.h +++ b/arch/alpha/include/asm/uaccess.h @@ -96,7 +96,7 @@ extern void __get_user_unknown(void); case 8: __get_user_64(ptr); break; \ default: __get_user_unknown(); break; \ } \ - (x) = (__typeof__(*(ptr))) __gu_val; \ + (x) = (__force __typeof__(*(ptr))) __gu_val; \ __gu_err; \ }) @@ -115,7 +115,7 @@ extern void __get_user_unknown(void); default: __get_user_unknown(); break; \ } \ } \ - (x) = (__typeof__(*(ptr))) __gu_val; \ + (x) = (__force __typeof__(*(ptr))) __gu_val; \ __gu_err; \ }) -- cgit v1.2.3 From 58fff51784cb5e1bcc06a1417be26eec4288507c Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 12 Dec 2014 01:56:04 +0200 Subject: arm64/uaccess: fix sparse errors virtio wants to read bitwise types from userspace using get_user. At the moment this triggers sparse errors, since the value is passed through an integer. Fix that up using __force. Signed-off-by: Michael S. Tsirkin Acked-by: Will Deacon --- arch/arm64/include/asm/uaccess.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index 3bf8f4e99a51..9a2069bbc00d 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -147,7 +147,7 @@ do { \ default: \ BUILD_BUG(); \ } \ - (x) = (__typeof__(*(ptr)))__gu_val; \ + (x) = (__force __typeof__(*(ptr)))__gu_val; \ } while (0) #define __get_user(x, ptr) \ -- cgit v1.2.3 From 7f0db2bec363bf1a4d6da2572491c634a34dcad8 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 12 Dec 2014 01:56:04 +0200 Subject: avr32/uaccess: fix sparse errors virtio wants to read bitwise types from userspace using get_user. At the moment this triggers sparse errors, since the value is passed through an integer. Fix that up using __force. Signed-off-by: Michael S. Tsirkin Acked-by: Hans-Christian Egtvedt --- arch/avr32/include/asm/uaccess.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/avr32/include/asm/uaccess.h b/arch/avr32/include/asm/uaccess.h index 245b2ee213c9..ccd07c456f9a 100644 --- a/arch/avr32/include/asm/uaccess.h +++ b/arch/avr32/include/asm/uaccess.h @@ -191,7 +191,7 @@ extern int __put_user_bad(void); default: __gu_err = __get_user_bad(); break; \ } \ \ - x = (typeof(*(ptr)))__gu_val; \ + x = (__force typeof(*(ptr)))__gu_val; \ __gu_err; \ }) @@ -222,7 +222,7 @@ extern int __put_user_bad(void); } else { \ __gu_err = -EFAULT; \ } \ - x = (typeof(*(ptr)))__gu_val; \ + x = (__force typeof(*(ptr)))__gu_val; \ __gu_err; \ }) -- cgit v1.2.3 From f5e0c47ef3293bef8eab634e5849c2559ed48a39 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 12 Dec 2014 01:56:04 +0200 Subject: blackfin/uaccess: fix sparse errors virtio wants to read bitwise types from userspace using get_user. At the moment this triggers sparse errors, since the value is passed through an integer. Fix that up using __force. Signed-off-by: Michael S. Tsirkin Acked-by: Steven Miao --- arch/blackfin/include/asm/uaccess.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/blackfin/include/asm/uaccess.h b/arch/blackfin/include/asm/uaccess.h index 57701c3b8a59..2dcc9303355d 100644 --- a/arch/blackfin/include/asm/uaccess.h +++ b/arch/blackfin/include/asm/uaccess.h @@ -147,7 +147,7 @@ static inline int bad_user_access_length(void) } \ } else \ _err = -EFAULT; \ - x = (typeof(*(ptr)))_val; \ + x = (__force typeof(*(ptr)))_val; \ _err; \ }) -- cgit v1.2.3 From 92acb6c2ac16c7ed1383b04055966633607959cd Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 12 Dec 2014 01:56:04 +0200 Subject: cris/uaccess: fix sparse errors virtio wants to read bitwise types from userspace using get_user. At the moment this triggers sparse errors, since the value is passed through an integer. Fix that up using __force. Signed-off-by: Michael S. Tsirkin --- arch/cris/include/asm/uaccess.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/cris/include/asm/uaccess.h b/arch/cris/include/asm/uaccess.h index 914540801c5e..9cf5a23baed3 100644 --- a/arch/cris/include/asm/uaccess.h +++ b/arch/cris/include/asm/uaccess.h @@ -153,7 +153,7 @@ struct __large_struct { unsigned long buf[100]; }; ({ \ long __gu_err, __gu_val; \ __get_user_size(__gu_val,(ptr),(size),__gu_err); \ - (x) = (__typeof__(*(ptr)))__gu_val; \ + (x) = (__force __typeof__(*(ptr)))__gu_val; \ __gu_err; \ }) @@ -163,7 +163,7 @@ struct __large_struct { unsigned long buf[100]; }; const __typeof__(*(ptr)) *__gu_addr = (ptr); \ if (access_ok(VERIFY_READ,__gu_addr,size)) \ __get_user_size(__gu_val,__gu_addr,(size),__gu_err); \ - (x) = (__typeof__(*(ptr)))__gu_val; \ + (x) = (__force __typeof__(*(ptr)))__gu_val; \ __gu_err; \ }) -- cgit v1.2.3 From a6325e7256ea4a31e5382adb2ecfba406d42e289 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 12 Dec 2014 01:56:04 +0200 Subject: ia64/uaccess: fix sparse errors virtio wants to read bitwise types from userspace using get_user. At the moment this triggers sparse errors, since the value is passed through an integer. Fix that up using __force. Signed-off-by: Michael S. Tsirkin --- arch/ia64/include/asm/uaccess.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/ia64/include/asm/uaccess.h b/arch/ia64/include/asm/uaccess.h index 103bedc59644..967c312a6baf 100644 --- a/arch/ia64/include/asm/uaccess.h +++ b/arch/ia64/include/asm/uaccess.h @@ -197,7 +197,7 @@ extern void __get_user_unknown (void); case 8: __get_user_size(__gu_val, __gu_ptr, 8, __gu_err); break; \ default: __get_user_unknown(); break; \ } \ - (x) = (__typeof__(*(__gu_ptr))) __gu_val; \ + (x) = (__force __typeof__(*(__gu_ptr))) __gu_val; \ __gu_err; \ }) -- cgit v1.2.3 From a618337e8cd811f07bd660a857d5d9f0201f042b Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 12 Dec 2014 01:56:04 +0200 Subject: m32r/uaccess: fix sparse errors virtio wants to read bitwise types from userspace using get_user. At the moment this triggers sparse errors, since the value is passed through an integer. Fix that up using __force. Signed-off-by: Michael S. Tsirkin --- arch/m32r/include/asm/uaccess.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/m32r/include/asm/uaccess.h b/arch/m32r/include/asm/uaccess.h index 84fe7ba53035..d076942a7b2b 100644 --- a/arch/m32r/include/asm/uaccess.h +++ b/arch/m32r/include/asm/uaccess.h @@ -218,7 +218,7 @@ extern int fixup_exception(struct pt_regs *regs); unsigned long __gu_val; \ might_fault(); \ __get_user_size(__gu_val,(ptr),(size),__gu_err); \ - (x) = (__typeof__(*(ptr)))__gu_val; \ + (x) = (__force __typeof__(*(ptr)))__gu_val; \ __gu_err; \ }) @@ -230,7 +230,7 @@ extern int fixup_exception(struct pt_regs *regs); might_fault(); \ if (access_ok(VERIFY_READ,__gu_addr,size)) \ __get_user_size(__gu_val,__gu_addr,(size),__gu_err); \ - (x) = (__typeof__(*(ptr)))__gu_val; \ + (x) = (__force __typeof__(*(ptr)))__gu_val; \ __gu_err; \ }) -- cgit v1.2.3 From 8f4e4c1aef356ac4ce67caeffac29af4971fe048 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 12 Dec 2014 01:56:04 +0200 Subject: metag/uaccess: fix sparse errors virtio wants to read bitwise types from userspace using get_user. At the moment this triggers sparse errors, since the value is passed through an integer. Fix that up using __force. Signed-off-by: Michael S. Tsirkin Acked-by: James Hogan --- arch/metag/include/asm/uaccess.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/metag/include/asm/uaccess.h b/arch/metag/include/asm/uaccess.h index 0748b0a97986..fd863fead4af 100644 --- a/arch/metag/include/asm/uaccess.h +++ b/arch/metag/include/asm/uaccess.h @@ -135,7 +135,7 @@ extern long __get_user_bad(void); ({ \ long __gu_err, __gu_val; \ __get_user_size(__gu_val, (ptr), (size), __gu_err); \ - (x) = (__typeof__(*(ptr)))__gu_val; \ + (x) = (__force __typeof__(*(ptr)))__gu_val; \ __gu_err; \ }) @@ -145,7 +145,7 @@ extern long __get_user_bad(void); const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ if (access_ok(VERIFY_READ, __gu_addr, size)) \ __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ - (x) = (__typeof__(*(ptr)))__gu_val; \ + (x) = (__force __typeof__(*(ptr)))__gu_val; \ __gu_err; \ }) -- cgit v1.2.3 From 582a6783c56517b84a06da72e18e1e44a59558e6 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 12 Dec 2014 01:56:04 +0200 Subject: openrisc/uaccess: fix sparse errors virtio wants to read bitwise types from userspace using get_user. At the moment this triggers sparse errors, since the value is passed through an integer. Fix that up using __force. Signed-off-by: Michael S. Tsirkin --- arch/openrisc/include/asm/uaccess.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/openrisc/include/asm/uaccess.h b/arch/openrisc/include/asm/uaccess.h index ab2e7a198a4c..a6bd07ca3d6c 100644 --- a/arch/openrisc/include/asm/uaccess.h +++ b/arch/openrisc/include/asm/uaccess.h @@ -192,7 +192,7 @@ struct __large_struct { ({ \ long __gu_err, __gu_val; \ __get_user_size(__gu_val, (ptr), (size), __gu_err); \ - (x) = (__typeof__(*(ptr)))__gu_val; \ + (x) = (__force __typeof__(*(ptr)))__gu_val; \ __gu_err; \ }) @@ -202,7 +202,7 @@ struct __large_struct { const __typeof__(*(ptr)) * __gu_addr = (ptr); \ if (access_ok(VERIFY_READ, __gu_addr, size)) \ __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ - (x) = (__typeof__(*(ptr)))__gu_val; \ + (x) = (__force __typeof__(*(ptr)))__gu_val; \ __gu_err; \ }) -- cgit v1.2.3 From 079f0f269f2a64080d7fa45cf686b02662ff8e36 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 12 Dec 2014 01:56:04 +0200 Subject: parisc/uaccess: fix sparse errors virtio wants to read bitwise types from userspace using get_user. At the moment this triggers sparse errors, since the value is passed through an integer. Fix that up using __force. Signed-off-by: Michael S. Tsirkin Acked-by: Helge Deller --- arch/parisc/include/asm/uaccess.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h index a5cb070b54bf..6c79311acdaf 100644 --- a/arch/parisc/include/asm/uaccess.h +++ b/arch/parisc/include/asm/uaccess.h @@ -104,7 +104,7 @@ struct exception_data { } \ } \ \ - (x) = (__typeof__(*(ptr))) __gu_val; \ + (x) = (__force __typeof__(*(ptr))) __gu_val; \ __gu_err; \ }) -- cgit v1.2.3 From cad1c0dfc8961abeb92e5afbfa275b6122501e5f Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 12 Dec 2014 01:56:04 +0200 Subject: sh/uaccess: fix sparse errors virtio wants to read bitwise types from userspace using get_user. At the moment this triggers sparse errors, since the value is passed through an integer. Fix that up using __force. Signed-off-by: Michael S. Tsirkin --- arch/sh/include/asm/uaccess.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/sh/include/asm/uaccess.h b/arch/sh/include/asm/uaccess.h index 9486376605f4..a49635c51266 100644 --- a/arch/sh/include/asm/uaccess.h +++ b/arch/sh/include/asm/uaccess.h @@ -60,7 +60,7 @@ struct __large_struct { unsigned long buf[100]; }; const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ __chk_user_ptr(ptr); \ __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ - (x) = (__typeof__(*(ptr)))__gu_val; \ + (x) = (__force __typeof__(*(ptr)))__gu_val; \ __gu_err; \ }) @@ -71,7 +71,7 @@ struct __large_struct { unsigned long buf[100]; }; const __typeof__(*(ptr)) *__gu_addr = (ptr); \ if (likely(access_ok(VERIFY_READ, __gu_addr, (size)))) \ __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ - (x) = (__typeof__(*(ptr)))__gu_val; \ + (x) = (__force __typeof__(*(ptr)))__gu_val; \ __gu_err; \ }) -- cgit v1.2.3 From 9b7accb286982e0df140b3accae8216656b3ef37 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 12 Dec 2014 01:56:04 +0200 Subject: sparc32/uaccess: fix sparse errors virtio wants to read bitwise types from userspace using get_user. At the moment this triggers sparse errors, since the value is passed through an integer. Fix that up using __force. Signed-off-by: Michael S. Tsirkin Acked-by: David S. Miller --- arch/sparc/include/asm/uaccess_32.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/uaccess_32.h b/arch/sparc/include/asm/uaccess_32.h index 9634d086fc56..8b571a0db0f6 100644 --- a/arch/sparc/include/asm/uaccess_32.h +++ b/arch/sparc/include/asm/uaccess_32.h @@ -164,7 +164,7 @@ case 2: __get_user_asm(__gu_val,uh,addr,__gu_ret); break; \ case 4: __get_user_asm(__gu_val,,addr,__gu_ret); break; \ case 8: __get_user_asm(__gu_val,d,addr,__gu_ret); break; \ default: __gu_val = 0; __gu_ret = __get_user_bad(); break; \ -} } else { __gu_val = 0; __gu_ret = -EFAULT; } x = (type) __gu_val; __gu_ret; }) +} } else { __gu_val = 0; __gu_ret = -EFAULT; } x = (__force type) __gu_val; __gu_ret; }) #define __get_user_check_ret(x,addr,size,type,retval) ({ \ register unsigned long __gu_val __asm__ ("l1"); \ @@ -175,7 +175,7 @@ case 2: __get_user_asm_ret(__gu_val,uh,addr,retval); break; \ case 4: __get_user_asm_ret(__gu_val,,addr,retval); break; \ case 8: __get_user_asm_ret(__gu_val,d,addr,retval); break; \ default: if (__get_user_bad()) return retval; \ -} x = (type) __gu_val; } else return retval; }) +} x = (__force type) __gu_val; } else return retval; }) #define __get_user_nocheck(x,addr,size,type) ({ \ register int __gu_ret; \ @@ -186,7 +186,7 @@ case 2: __get_user_asm(__gu_val,uh,addr,__gu_ret); break; \ case 4: __get_user_asm(__gu_val,,addr,__gu_ret); break; \ case 8: __get_user_asm(__gu_val,d,addr,__gu_ret); break; \ default: __gu_val = 0; __gu_ret = __get_user_bad(); break; \ -} x = (type) __gu_val; __gu_ret; }) +} x = (__force type) __gu_val; __gu_ret; }) #define __get_user_nocheck_ret(x,addr,size,type,retval) ({ \ register unsigned long __gu_val __asm__ ("l1"); \ @@ -196,7 +196,7 @@ case 2: __get_user_asm_ret(__gu_val,uh,addr,retval); break; \ case 4: __get_user_asm_ret(__gu_val,,addr,retval); break; \ case 8: __get_user_asm_ret(__gu_val,d,addr,retval); break; \ default: if (__get_user_bad()) return retval; \ -} x = (type) __gu_val; }) +} x = (__force type) __gu_val; }) #define __get_user_asm(x,size,addr,ret) \ __asm__ __volatile__( \ -- cgit v1.2.3 From 1d638efce8cc77c1ec838886e9a64f98aa58b780 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 12 Dec 2014 01:56:04 +0200 Subject: sparc64/uaccess: fix sparse errors virtio wants to read bitwise types from userspace using get_user. At the moment this triggers sparse errors, since the value is passed through an integer. Fix that up using __force. Signed-off-by: Michael S. Tsirkin Acked-by: David S. Miller --- arch/sparc/include/asm/uaccess_64.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/uaccess_64.h b/arch/sparc/include/asm/uaccess_64.h index c990a5e577f0..b80866d90768 100644 --- a/arch/sparc/include/asm/uaccess_64.h +++ b/arch/sparc/include/asm/uaccess_64.h @@ -145,7 +145,7 @@ case 2: __get_user_asm(__gu_val,uh,addr,__gu_ret); break; \ case 4: __get_user_asm(__gu_val,uw,addr,__gu_ret); break; \ case 8: __get_user_asm(__gu_val,x,addr,__gu_ret); break; \ default: __gu_val = 0; __gu_ret = __get_user_bad(); break; \ -} data = (type) __gu_val; __gu_ret; }) +} data = (__force type) __gu_val; __gu_ret; }) #define __get_user_nocheck_ret(data,addr,size,type,retval) ({ \ register unsigned long __gu_val __asm__ ("l1"); \ @@ -155,7 +155,7 @@ case 2: __get_user_asm_ret(__gu_val,uh,addr,retval); break; \ case 4: __get_user_asm_ret(__gu_val,uw,addr,retval); break; \ case 8: __get_user_asm_ret(__gu_val,x,addr,retval); break; \ default: if (__get_user_bad()) return retval; \ -} data = (type) __gu_val; }) +} data = (__force type) __gu_val; }) #define __get_user_asm(x,size,addr,ret) \ __asm__ __volatile__( \ -- cgit v1.2.3 From 09a2f7cf6a89ec011bda8c0f0f8d0790a1176973 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 12 Dec 2014 01:56:04 +0200 Subject: m68k/uaccess: fix sparse errors virtio wants to read bitwise types from userspace using get_user. At the moment this triggers sparse errors, since the value is passed through an integer. Fix that up using __force. Signed-off-by: Michael S. Tsirkin Acked-by: Geert Uytterhoeven --- arch/m68k/include/asm/uaccess_mm.h | 40 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'arch') diff --git a/arch/m68k/include/asm/uaccess_mm.h b/arch/m68k/include/asm/uaccess_mm.h index 15901db435b9..d228601b3afc 100644 --- a/arch/m68k/include/asm/uaccess_mm.h +++ b/arch/m68k/include/asm/uaccess_mm.h @@ -128,25 +128,25 @@ asm volatile ("\n" \ #define put_user(x, ptr) __put_user(x, ptr) -#define __get_user_asm(res, x, ptr, type, bwl, reg, err) ({ \ - type __gu_val; \ - asm volatile ("\n" \ - "1: "MOVES"."#bwl" %2,%1\n" \ - "2:\n" \ - " .section .fixup,\"ax\"\n" \ - " .even\n" \ - "10: move.l %3,%0\n" \ - " sub.l %1,%1\n" \ - " jra 2b\n" \ - " .previous\n" \ - "\n" \ - " .section __ex_table,\"a\"\n" \ - " .align 4\n" \ - " .long 1b,10b\n" \ - " .previous" \ - : "+d" (res), "=&" #reg (__gu_val) \ - : "m" (*(ptr)), "i" (err)); \ - (x) = (typeof(*(ptr)))(unsigned long)__gu_val; \ +#define __get_user_asm(res, x, ptr, type, bwl, reg, err) ({ \ + type __gu_val; \ + asm volatile ("\n" \ + "1: "MOVES"."#bwl" %2,%1\n" \ + "2:\n" \ + " .section .fixup,\"ax\"\n" \ + " .even\n" \ + "10: move.l %3,%0\n" \ + " sub.l %1,%1\n" \ + " jra 2b\n" \ + " .previous\n" \ + "\n" \ + " .section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 1b,10b\n" \ + " .previous" \ + : "+d" (res), "=&" #reg (__gu_val) \ + : "m" (*(ptr)), "i" (err)); \ + (x) = (__force typeof(*(ptr)))(__force unsigned long)__gu_val; \ }) #define __get_user(x, ptr) \ @@ -188,7 +188,7 @@ asm volatile ("\n" \ "+a" (__gu_ptr) \ : "i" (-EFAULT) \ : "memory"); \ - (x) = (typeof(*(ptr)))__gu_val; \ + (x) = (__force typeof(*(ptr)))__gu_val; \ break; \ } */ \ default: \ -- cgit v1.2.3 From e8b94dea3867139fe92f03b913e38ca841e390fd Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 14:37:22 +0200 Subject: arm: fix put_user sparse errors virtio wants to write bitwise types to userspace using put_user. At the moment this triggers sparse errors, since the value is passed through an integer. For example: __le32 __user *p; __le32 x; put_user(x, p); is safe, but currently triggers a sparse warning. Fix that up using __force. Note: this does not suppress any useful sparse checks since caller assigns x to typeof(*p), which in turn forces all the necessary type checks. Signed-off-by: Michael S. Tsirkin --- arch/arm/include/asm/uaccess.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 4767eb9caa78..74fcde756fdb 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -413,14 +413,14 @@ do { \ #ifndef __ARMEB__ #define __put_user_asm_half(x,__pu_addr,err) \ ({ \ - unsigned long __temp = (unsigned long)(x); \ + unsigned long __temp = (__force unsigned long)(x); \ __put_user_asm_byte(__temp, __pu_addr, err); \ __put_user_asm_byte(__temp >> 8, __pu_addr + 1, err); \ }) #else #define __put_user_asm_half(x,__pu_addr,err) \ ({ \ - unsigned long __temp = (unsigned long)(x); \ + unsigned long __temp = (__force unsigned long)(x); \ __put_user_asm_byte(__temp >> 8, __pu_addr, err); \ __put_user_asm_byte(__temp, __pu_addr + 1, err); \ }) -- cgit v1.2.3 From 1734bffc30b80ab2447345369c84175e721ebd65 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 14:37:22 +0200 Subject: blackfin: fix put_user sparse errors virtio wants to write bitwise types to userspace using put_user. At the moment this triggers sparse errors, since the value is passed through an integer. For example: __le32 __user *p; __le32 x; put_user(x, p); is safe, but currently triggers a sparse warning. Fix that up using __force. Note: this does not suppress any useful sparse checks since caller assigns x to typeof(*p), which in turn forces all the necessary type checks. Signed-off-by: Michael S. Tsirkin --- arch/blackfin/include/asm/uaccess.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/include/asm/uaccess.h b/arch/blackfin/include/asm/uaccess.h index 2dcc9303355d..4bf968c01cf9 100644 --- a/arch/blackfin/include/asm/uaccess.h +++ b/arch/blackfin/include/asm/uaccess.h @@ -89,10 +89,10 @@ struct exception_table_entry { break; \ case 8: { \ long _xl, _xh; \ - _xl = ((long *)&_x)[0]; \ - _xh = ((long *)&_x)[1]; \ - __put_user_asm(_xl, ((long __user *)_p)+0, ); \ - __put_user_asm(_xh, ((long __user *)_p)+1, ); \ + _xl = ((__force long *)&_x)[0]; \ + _xh = ((__force long *)&_x)[1]; \ + __put_user_asm(_xl, ((__force long __user *)_p)+0, );\ + __put_user_asm(_xh, ((__force long __user *)_p)+1, );\ } break; \ default: \ _err = __put_user_bad(); \ -- cgit v1.2.3 From 9605ce7e5fe058c94fa354415d122462fb419a00 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 14:37:22 +0200 Subject: ia64: fix put_user sparse errors virtio wants to write bitwise types to userspace using put_user. At the moment this triggers sparse errors, since the value is passed through an integer. For example: __le32 __user *p; __le32 x; put_user(x, p); is safe, but currently triggers a sparse warning. Fix that up using __force. Note: this does not suppress any useful sparse checks since callers do a cast (__typeof__(*(ptr))) (x) which in turn forces all the necessary type checks. Signed-off-by: Michael S. Tsirkin --- arch/ia64/include/asm/uaccess.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/ia64/include/asm/uaccess.h b/arch/ia64/include/asm/uaccess.h index 967c312a6baf..4f3fb6ccbf21 100644 --- a/arch/ia64/include/asm/uaccess.h +++ b/arch/ia64/include/asm/uaccess.h @@ -169,10 +169,11 @@ do { \ (err) = ia64_getreg(_IA64_REG_R8); \ (val) = ia64_getreg(_IA64_REG_R9); \ } while (0) -# define __put_user_size(val, addr, n, err) \ -do { \ - __st_user("__ex_table", (unsigned long) addr, n, RELOC_TYPE, (unsigned long) (val)); \ - (err) = ia64_getreg(_IA64_REG_R8); \ +# define __put_user_size(val, addr, n, err) \ +do { \ + __st_user("__ex_table", (unsigned long) addr, n, RELOC_TYPE, \ + (__force unsigned long) (val)); \ + (err) = ia64_getreg(_IA64_REG_R8); \ } while (0) #endif /* !ASM_SUPPORTED */ -- cgit v1.2.3 From 9ef8dc161faaa24c58322aa928b3216213621daa Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 14:37:22 +0200 Subject: metag: fix put_user sparse errors virtio wants to write bitwise types to userspace using put_user. At the moment this triggers sparse errors, since the value is passed through an integer. For example: __le32 __user *p; __le32 x; put_user(x, p); is safe, but currently triggers a sparse warning. Fix that up using __force. This also fixes warnings due to writing a pointer out to userland. Note: this does not suppress any useful sparse checks since callers do a cast (__typeof__(*(ptr))) (x) which in turn forces all the necessary type checks. Suggested-by: James Hogan Signed-off-by: Michael S. Tsirkin Acked-by: James Hogan --- arch/metag/include/asm/uaccess.h | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/metag/include/asm/uaccess.h b/arch/metag/include/asm/uaccess.h index fd863fead4af..8282cbce7e39 100644 --- a/arch/metag/include/asm/uaccess.h +++ b/arch/metag/include/asm/uaccess.h @@ -107,18 +107,23 @@ extern long __put_user_asm_w(unsigned int x, void __user *addr); extern long __put_user_asm_d(unsigned int x, void __user *addr); extern long __put_user_asm_l(unsigned long long x, void __user *addr); -#define __put_user_size(x, ptr, size, retval) \ -do { \ - retval = 0; \ - switch (size) { \ +#define __put_user_size(x, ptr, size, retval) \ +do { \ + retval = 0; \ + switch (size) { \ case 1: \ - retval = __put_user_asm_b((unsigned int)x, ptr); break; \ + retval = __put_user_asm_b((__force unsigned int)x, ptr);\ + break; \ case 2: \ - retval = __put_user_asm_w((unsigned int)x, ptr); break; \ + retval = __put_user_asm_w((__force unsigned int)x, ptr);\ + break; \ case 4: \ - retval = __put_user_asm_d((unsigned int)x, ptr); break; \ + retval = __put_user_asm_d((__force unsigned int)x, ptr);\ + break; \ case 8: \ - retval = __put_user_asm_l((unsigned long long)x, ptr); break; \ + retval = __put_user_asm_l((__force unsigned long long)x,\ + ptr); \ + break; \ default: \ __put_user_bad(); \ } \ -- cgit v1.2.3 From 66959ed0e4bd673f140f550fd3f7b3a70e8dbd24 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 14:37:22 +0200 Subject: sh: fix put_user sparse errors virtio wants to write bitwise types to userspace using put_user. At the moment this triggers sparse errors, since the value is passed through an integer. For example: __le32 __user *p; __le32 x; put_user(x, p); is safe, but currently triggers a sparse warning. Fix that up using __force. Note: this does not suppress any useful sparse checks since caller assigns x to typeof(*p), which in turn forces all the necessary type checks. Signed-off-by: Michael S. Tsirkin --- arch/sh/include/asm/uaccess_64.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/sh/include/asm/uaccess_64.h b/arch/sh/include/asm/uaccess_64.h index 2e07e0f40c6a..c01376c76b86 100644 --- a/arch/sh/include/asm/uaccess_64.h +++ b/arch/sh/include/asm/uaccess_64.h @@ -59,19 +59,19 @@ do { \ switch (size) { \ case 1: \ retval = __put_user_asm_b((void *)&x, \ - (long)ptr); \ + (__force long)ptr); \ break; \ case 2: \ retval = __put_user_asm_w((void *)&x, \ - (long)ptr); \ + (__force long)ptr); \ break; \ case 4: \ retval = __put_user_asm_l((void *)&x, \ - (long)ptr); \ + (__force long)ptr); \ break; \ case 8: \ retval = __put_user_asm_q((void *)&x, \ - (long)ptr); \ + (__force long)ptr); \ break; \ default: \ __put_user_unknown(); \ -- cgit v1.2.3 From 99408c840a87e4d1f8f9e1adc95171b9da10459e Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 14:53:58 +0200 Subject: avr32: whitespace fix Align using tabs to make code prettier. Signed-off-by: Michael S. Tsirkin Acked-by: Hans-Christian Egtvedt --- arch/avr32/include/asm/uaccess.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/avr32/include/asm/uaccess.h b/arch/avr32/include/asm/uaccess.h index ccd07c456f9a..72607f32eebb 100644 --- a/arch/avr32/include/asm/uaccess.h +++ b/arch/avr32/include/asm/uaccess.h @@ -278,7 +278,7 @@ extern int __put_user_bad(void); __pu_err); \ break; \ case 8: \ - __put_user_asm("d", __pu_addr, __pu_val, \ + __put_user_asm("d", __pu_addr, __pu_val, \ __pu_err); \ break; \ default: \ -- cgit v1.2.3 From 8ccf7b2599abd08ab3a51d5f2299e301daae0860 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 14:30:51 +0200 Subject: sparc32: uaccess_32 macro whitespace fixes Macros within arch/sparc/include/asm/uaccess_32.h are made harder to read because they violate a bunch of coding style rules. Fix it up. Signed-off-by: Michael S. Tsirkin Acked-by: David S. Miller --- arch/sparc/include/asm/uaccess_32.h | 365 ++++++++++++++++++++++-------------- 1 file changed, 227 insertions(+), 138 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/uaccess_32.h b/arch/sparc/include/asm/uaccess_32.h index 8b571a0db0f6..f96656209a78 100644 --- a/arch/sparc/include/asm/uaccess_32.h +++ b/arch/sparc/include/asm/uaccess_32.h @@ -37,7 +37,7 @@ #define get_fs() (current->thread.current_ds) #define set_fs(val) ((current->thread.current_ds) = (val)) -#define segment_eq(a,b) ((a).seg == (b).seg) +#define segment_eq(a, b) ((a).seg == (b).seg) /* We have there a nice not-mapped page at PAGE_OFFSET - PAGE_SIZE, so that this test * can be fairly lightweight. @@ -46,8 +46,8 @@ */ #define __user_ok(addr, size) ({ (void)(size); (addr) < STACK_TOP; }) #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS)) -#define __access_ok(addr,size) (__user_ok((addr) & get_fs().seg,(size))) -#define access_ok(type, addr, size) \ +#define __access_ok(addr, size) (__user_ok((addr) & get_fs().seg, (size))) +#define access_ok(type, addr, size) \ ({ (void)(type); __access_ok((unsigned long)(addr), size); }) /* @@ -91,158 +91,247 @@ void __ret_efault(void); * of a performance impact. Thus we have a few rather ugly macros here, * and hide all the ugliness from the user. */ -#define put_user(x,ptr) ({ \ -unsigned long __pu_addr = (unsigned long)(ptr); \ -__chk_user_ptr(ptr); \ -__put_user_check((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr))); }) - -#define get_user(x,ptr) ({ \ -unsigned long __gu_addr = (unsigned long)(ptr); \ -__chk_user_ptr(ptr); \ -__get_user_check((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr))); }) +#define put_user(x, ptr) ({ \ + unsigned long __pu_addr = (unsigned long)(ptr); \ + __chk_user_ptr(ptr); \ + __put_user_check((__typeof__(*(ptr)))(x), __pu_addr, sizeof(*(ptr))); \ +}) + +#define get_user(x, ptr) ({ \ + unsigned long __gu_addr = (unsigned long)(ptr); \ + __chk_user_ptr(ptr); \ + __get_user_check((x), __gu_addr, sizeof(*(ptr)), __typeof__(*(ptr))); \ +}) /* * The "__xxx" versions do not do address space checking, useful when * doing multiple accesses to the same area (the user has to do the * checks by hand with "access_ok()") */ -#define __put_user(x,ptr) __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) -#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)),__typeof__(*(ptr))) +#define __put_user(x, ptr) \ + __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) +#define __get_user(x, ptr) \ + __get_user_nocheck((x), (ptr), sizeof(*(ptr)), __typeof__(*(ptr))) struct __large_struct { unsigned long buf[100]; }; #define __m(x) ((struct __large_struct __user *)(x)) -#define __put_user_check(x,addr,size) ({ \ -register int __pu_ret; \ -if (__access_ok(addr,size)) { \ -switch (size) { \ -case 1: __put_user_asm(x,b,addr,__pu_ret); break; \ -case 2: __put_user_asm(x,h,addr,__pu_ret); break; \ -case 4: __put_user_asm(x,,addr,__pu_ret); break; \ -case 8: __put_user_asm(x,d,addr,__pu_ret); break; \ -default: __pu_ret = __put_user_bad(); break; \ -} } else { __pu_ret = -EFAULT; } __pu_ret; }) - -#define __put_user_nocheck(x,addr,size) ({ \ -register int __pu_ret; \ -switch (size) { \ -case 1: __put_user_asm(x,b,addr,__pu_ret); break; \ -case 2: __put_user_asm(x,h,addr,__pu_ret); break; \ -case 4: __put_user_asm(x,,addr,__pu_ret); break; \ -case 8: __put_user_asm(x,d,addr,__pu_ret); break; \ -default: __pu_ret = __put_user_bad(); break; \ -} __pu_ret; }) - -#define __put_user_asm(x,size,addr,ret) \ +#define __put_user_check(x, addr, size) ({ \ + register int __pu_ret; \ + if (__access_ok(addr, size)) { \ + switch (size) { \ + case 1: \ + __put_user_asm(x, b, addr, __pu_ret); \ + break; \ + case 2: \ + __put_user_asm(x, h, addr, __pu_ret); \ + break; \ + case 4: \ + __put_user_asm(x, , addr, __pu_ret); \ + break; \ + case 8: \ + __put_user_asm(x, d, addr, __pu_ret); \ + break; \ + default: \ + __pu_ret = __put_user_bad(); \ + break; \ + } \ + } else { \ + __pu_ret = -EFAULT; \ + } \ + __pu_ret; \ +}) + +#define __put_user_nocheck(x, addr, size) ({ \ + register int __pu_ret; \ + switch (size) { \ + case 1: \ + __put_user_asm(x, b, addr, __pu_ret); \ + break; \ + case 2: \ + __put_user_asm(x, h, addr, __pu_ret); \ + break; \ + case 4: \ + __put_user_asm(x, , addr, __pu_ret); \ + break; \ + case 8: \ + __put_user_asm(x, d, addr, __pu_ret); \ + break; \ + default: \ + __pu_ret = __put_user_bad(); \ + break; \ + } \ + __pu_ret; \ +}) + +#define __put_user_asm(x, size, addr, ret) \ __asm__ __volatile__( \ - "/* Put user asm, inline. */\n" \ -"1:\t" "st"#size " %1, %2\n\t" \ - "clr %0\n" \ -"2:\n\n\t" \ - ".section .fixup,#alloc,#execinstr\n\t" \ - ".align 4\n" \ -"3:\n\t" \ - "b 2b\n\t" \ - " mov %3, %0\n\t" \ - ".previous\n\n\t" \ - ".section __ex_table,#alloc\n\t" \ - ".align 4\n\t" \ - ".word 1b, 3b\n\t" \ - ".previous\n\n\t" \ - : "=&r" (ret) : "r" (x), "m" (*__m(addr)), \ - "i" (-EFAULT)) + "/* Put user asm, inline. */\n" \ + "1:\t" "st"#size " %1, %2\n\t" \ + "clr %0\n" \ + "2:\n\n\t" \ + ".section .fixup,#alloc,#execinstr\n\t" \ + ".align 4\n" \ + "3:\n\t" \ + "b 2b\n\t" \ + " mov %3, %0\n\t" \ + ".previous\n\n\t" \ + ".section __ex_table,#alloc\n\t" \ + ".align 4\n\t" \ + ".word 1b, 3b\n\t" \ + ".previous\n\n\t" \ + : "=&r" (ret) : "r" (x), "m" (*__m(addr)), \ + "i" (-EFAULT)) int __put_user_bad(void); -#define __get_user_check(x,addr,size,type) ({ \ -register int __gu_ret; \ -register unsigned long __gu_val; \ -if (__access_ok(addr,size)) { \ -switch (size) { \ -case 1: __get_user_asm(__gu_val,ub,addr,__gu_ret); break; \ -case 2: __get_user_asm(__gu_val,uh,addr,__gu_ret); break; \ -case 4: __get_user_asm(__gu_val,,addr,__gu_ret); break; \ -case 8: __get_user_asm(__gu_val,d,addr,__gu_ret); break; \ -default: __gu_val = 0; __gu_ret = __get_user_bad(); break; \ -} } else { __gu_val = 0; __gu_ret = -EFAULT; } x = (__force type) __gu_val; __gu_ret; }) - -#define __get_user_check_ret(x,addr,size,type,retval) ({ \ -register unsigned long __gu_val __asm__ ("l1"); \ -if (__access_ok(addr,size)) { \ -switch (size) { \ -case 1: __get_user_asm_ret(__gu_val,ub,addr,retval); break; \ -case 2: __get_user_asm_ret(__gu_val,uh,addr,retval); break; \ -case 4: __get_user_asm_ret(__gu_val,,addr,retval); break; \ -case 8: __get_user_asm_ret(__gu_val,d,addr,retval); break; \ -default: if (__get_user_bad()) return retval; \ -} x = (__force type) __gu_val; } else return retval; }) - -#define __get_user_nocheck(x,addr,size,type) ({ \ -register int __gu_ret; \ -register unsigned long __gu_val; \ -switch (size) { \ -case 1: __get_user_asm(__gu_val,ub,addr,__gu_ret); break; \ -case 2: __get_user_asm(__gu_val,uh,addr,__gu_ret); break; \ -case 4: __get_user_asm(__gu_val,,addr,__gu_ret); break; \ -case 8: __get_user_asm(__gu_val,d,addr,__gu_ret); break; \ -default: __gu_val = 0; __gu_ret = __get_user_bad(); break; \ -} x = (__force type) __gu_val; __gu_ret; }) - -#define __get_user_nocheck_ret(x,addr,size,type,retval) ({ \ -register unsigned long __gu_val __asm__ ("l1"); \ -switch (size) { \ -case 1: __get_user_asm_ret(__gu_val,ub,addr,retval); break; \ -case 2: __get_user_asm_ret(__gu_val,uh,addr,retval); break; \ -case 4: __get_user_asm_ret(__gu_val,,addr,retval); break; \ -case 8: __get_user_asm_ret(__gu_val,d,addr,retval); break; \ -default: if (__get_user_bad()) return retval; \ -} x = (__force type) __gu_val; }) - -#define __get_user_asm(x,size,addr,ret) \ +#define __get_user_check(x, addr, size, type) ({ \ + register int __gu_ret; \ + register unsigned long __gu_val; \ + if (__access_ok(addr, size)) { \ + switch (size) { \ + case 1: \ + __get_user_asm(__gu_val, ub, addr, __gu_ret); \ + break; \ + case 2: \ + __get_user_asm(__gu_val, uh, addr, __gu_ret); \ + break; \ + case 4: \ + __get_user_asm(__gu_val, , addr, __gu_ret); \ + break; \ + case 8: \ + __get_user_asm(__gu_val, d, addr, __gu_ret); \ + break; \ + default: \ + __gu_val = 0; \ + __gu_ret = __get_user_bad(); \ + break; \ + } \ + } else { \ + __gu_val = 0; \ + __gu_ret = -EFAULT; \ + } \ + x = (__force type) __gu_val; \ + __gu_ret; \ +}) + +#define __get_user_check_ret(x, addr, size, type, retval) ({ \ + register unsigned long __gu_val __asm__ ("l1"); \ + if (__access_ok(addr, size)) { \ + switch (size) { \ + case 1: \ + __get_user_asm_ret(__gu_val, ub, addr, retval); \ + break; \ + case 2: \ + __get_user_asm_ret(__gu_val, uh, addr, retval); \ + break; \ + case 4: \ + __get_user_asm_ret(__gu_val, , addr, retval); \ + break; \ + case 8: \ + __get_user_asm_ret(__gu_val, d, addr, retval); \ + break; \ + default: \ + if (__get_user_bad()) \ + return retval; \ + } \ + x = (__force type) __gu_val; \ + } else \ + return retval; \ +}) + +#define __get_user_nocheck(x, addr, size, type) ({ \ + register int __gu_ret; \ + register unsigned long __gu_val; \ + switch (size) { \ + case 1: \ + __get_user_asm(__gu_val, ub, addr, __gu_ret); \ + break; \ + case 2: \ + __get_user_asm(__gu_val, uh, addr, __gu_ret); \ + break; \ + case 4: \ + __get_user_asm(__gu_val, , addr, __gu_ret); \ + break; \ + case 8: \ + __get_user_asm(__gu_val, d, addr, __gu_ret); \ + break; \ + default: \ + __gu_val = 0; \ + __gu_ret = __get_user_bad(); \ + break; \ + } \ + x = (__force type) __gu_val; \ + __gu_ret; \ +}) + +#define __get_user_nocheck_ret(x, addr, size, type, retval) ({ \ + register unsigned long __gu_val __asm__ ("l1"); \ + switch (size) { \ + case 1: \ + __get_user_asm_ret(__gu_val, ub, addr, retval); \ + break; \ + case 2: \ + __get_user_asm_ret(__gu_val, uh, addr, retval); \ + break; \ + case 4: \ + __get_user_asm_ret(__gu_val, , addr, retval); \ + break; \ + case 8: \ + __get_user_asm_ret(__gu_val, d, addr, retval); \ + break; \ + default: \ + if (__get_user_bad()) \ + return retval; \ + } \ + x = (__force type) __gu_val; \ +}) + +#define __get_user_asm(x, size, addr, ret) \ __asm__ __volatile__( \ - "/* Get user asm, inline. */\n" \ -"1:\t" "ld"#size " %2, %1\n\t" \ - "clr %0\n" \ -"2:\n\n\t" \ - ".section .fixup,#alloc,#execinstr\n\t" \ - ".align 4\n" \ -"3:\n\t" \ - "clr %1\n\t" \ - "b 2b\n\t" \ - " mov %3, %0\n\n\t" \ - ".previous\n\t" \ - ".section __ex_table,#alloc\n\t" \ - ".align 4\n\t" \ - ".word 1b, 3b\n\n\t" \ - ".previous\n\t" \ - : "=&r" (ret), "=&r" (x) : "m" (*__m(addr)), \ - "i" (-EFAULT)) - -#define __get_user_asm_ret(x,size,addr,retval) \ + "/* Get user asm, inline. */\n" \ + "1:\t" "ld"#size " %2, %1\n\t" \ + "clr %0\n" \ + "2:\n\n\t" \ + ".section .fixup,#alloc,#execinstr\n\t" \ + ".align 4\n" \ + "3:\n\t" \ + "clr %1\n\t" \ + "b 2b\n\t" \ + " mov %3, %0\n\n\t" \ + ".previous\n\t" \ + ".section __ex_table,#alloc\n\t" \ + ".align 4\n\t" \ + ".word 1b, 3b\n\n\t" \ + ".previous\n\t" \ + : "=&r" (ret), "=&r" (x) : "m" (*__m(addr)), \ + "i" (-EFAULT)) + +#define __get_user_asm_ret(x, size, addr, retval) \ if (__builtin_constant_p(retval) && retval == -EFAULT) \ -__asm__ __volatile__( \ - "/* Get user asm ret, inline. */\n" \ -"1:\t" "ld"#size " %1, %0\n\n\t" \ - ".section __ex_table,#alloc\n\t" \ - ".align 4\n\t" \ - ".word 1b,__ret_efault\n\n\t" \ - ".previous\n\t" \ - : "=&r" (x) : "m" (*__m(addr))); \ + __asm__ __volatile__( \ + "/* Get user asm ret, inline. */\n" \ + "1:\t" "ld"#size " %1, %0\n\n\t" \ + ".section __ex_table,#alloc\n\t" \ + ".align 4\n\t" \ + ".word 1b,__ret_efault\n\n\t" \ + ".previous\n\t" \ + : "=&r" (x) : "m" (*__m(addr))); \ else \ -__asm__ __volatile__( \ - "/* Get user asm ret, inline. */\n" \ -"1:\t" "ld"#size " %1, %0\n\n\t" \ - ".section .fixup,#alloc,#execinstr\n\t" \ - ".align 4\n" \ -"3:\n\t" \ - "ret\n\t" \ - " restore %%g0, %2, %%o0\n\n\t" \ - ".previous\n\t" \ - ".section __ex_table,#alloc\n\t" \ - ".align 4\n\t" \ - ".word 1b, 3b\n\n\t" \ - ".previous\n\t" \ - : "=&r" (x) : "m" (*__m(addr)), "i" (retval)) + __asm__ __volatile__( \ + "/* Get user asm ret, inline. */\n" \ + "1:\t" "ld"#size " %1, %0\n\n\t" \ + ".section .fixup,#alloc,#execinstr\n\t" \ + ".align 4\n" \ + "3:\n\t" \ + "ret\n\t" \ + " restore %%g0, %2, %%o0\n\n\t" \ + ".previous\n\t" \ + ".section __ex_table,#alloc\n\t" \ + ".align 4\n\t" \ + ".word 1b, 3b\n\n\t" \ + ".previous\n\t" \ + : "=&r" (x) : "m" (*__m(addr)), "i" (retval)) int __get_user_bad(void); -- cgit v1.2.3 From 7185820a0ab27f88343ff5f75be5e963c8e19113 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 14:32:17 +0200 Subject: sparc64: uaccess_64 macro whitespace fixes Macros within arch/sparc/include/asm/uaccess_64.h are made harder to read because they violate a bunch of coding style rules. Fix it up. Signed-off-by: Michael S. Tsirkin Acked-by: David S. Miller --- arch/sparc/include/asm/uaccess_64.h | 248 +++++++++++++++++++++--------------- 1 file changed, 144 insertions(+), 104 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/uaccess_64.h b/arch/sparc/include/asm/uaccess_64.h index b80866d90768..12d95947636b 100644 --- a/arch/sparc/include/asm/uaccess_64.h +++ b/arch/sparc/include/asm/uaccess_64.h @@ -41,11 +41,11 @@ #define get_fs() ((mm_segment_t){(current_thread_info()->current_ds)}) #define get_ds() (KERNEL_DS) -#define segment_eq(a,b) ((a).seg == (b).seg) +#define segment_eq(a, b) ((a).seg == (b).seg) #define set_fs(val) \ do { \ - current_thread_info()->current_ds =(val).seg; \ + current_thread_info()->current_ds = (val).seg; \ __asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" ((val).seg)); \ } while(0) @@ -88,121 +88,161 @@ void __retl_efault(void); * of a performance impact. Thus we have a few rather ugly macros here, * and hide all the ugliness from the user. */ -#define put_user(x,ptr) ({ \ -unsigned long __pu_addr = (unsigned long)(ptr); \ -__chk_user_ptr(ptr); \ -__put_user_nocheck((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr))); }) +#define put_user(x, ptr) ({ \ + unsigned long __pu_addr = (unsigned long)(ptr); \ + __chk_user_ptr(ptr); \ + __put_user_nocheck((__typeof__(*(ptr)))(x), __pu_addr, sizeof(*(ptr)));\ +}) -#define get_user(x,ptr) ({ \ -unsigned long __gu_addr = (unsigned long)(ptr); \ -__chk_user_ptr(ptr); \ -__get_user_nocheck((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr))); }) +#define get_user(x, ptr) ({ \ + unsigned long __gu_addr = (unsigned long)(ptr); \ + __chk_user_ptr(ptr); \ + __get_user_nocheck((x), __gu_addr, sizeof(*(ptr)), __typeof__(*(ptr)));\ +}) -#define __put_user(x,ptr) put_user(x,ptr) -#define __get_user(x,ptr) get_user(x,ptr) +#define __put_user(x, ptr) put_user(x, ptr) +#define __get_user(x, ptr) get_user(x, ptr) struct __large_struct { unsigned long buf[100]; }; #define __m(x) ((struct __large_struct *)(x)) -#define __put_user_nocheck(data,addr,size) ({ \ -register int __pu_ret; \ -switch (size) { \ -case 1: __put_user_asm(data,b,addr,__pu_ret); break; \ -case 2: __put_user_asm(data,h,addr,__pu_ret); break; \ -case 4: __put_user_asm(data,w,addr,__pu_ret); break; \ -case 8: __put_user_asm(data,x,addr,__pu_ret); break; \ -default: __pu_ret = __put_user_bad(); break; \ -} __pu_ret; }) - -#define __put_user_asm(x,size,addr,ret) \ +#define __put_user_nocheck(data, addr, size) ({ \ + register int __pu_ret; \ + switch (size) { \ + case 1: \ + __put_user_asm(data, b, addr, __pu_ret); \ + break; \ + case 2: \ + __put_user_asm(data, h, addr, __pu_ret); \ + break; \ + case 4: \ + __put_user_asm(data, w, addr, __pu_ret); \ + break; \ + case 8: \ + __put_user_asm(data, x, addr, __pu_ret); \ + break; \ + default: \ + __pu_ret = __put_user_bad(); \ + break; \ + } \ + __pu_ret; \ +}) + +#define __put_user_asm(x, size, addr, ret) \ __asm__ __volatile__( \ - "/* Put user asm, inline. */\n" \ -"1:\t" "st"#size "a %1, [%2] %%asi\n\t" \ - "clr %0\n" \ -"2:\n\n\t" \ - ".section .fixup,#alloc,#execinstr\n\t" \ - ".align 4\n" \ -"3:\n\t" \ - "sethi %%hi(2b), %0\n\t" \ - "jmpl %0 + %%lo(2b), %%g0\n\t" \ - " mov %3, %0\n\n\t" \ - ".previous\n\t" \ - ".section __ex_table,\"a\"\n\t" \ - ".align 4\n\t" \ - ".word 1b, 3b\n\t" \ - ".previous\n\n\t" \ - : "=r" (ret) : "r" (x), "r" (__m(addr)), \ - "i" (-EFAULT)) + "/* Put user asm, inline. */\n" \ + "1:\t" "st"#size "a %1, [%2] %%asi\n\t" \ + "clr %0\n" \ + "2:\n\n\t" \ + ".section .fixup,#alloc,#execinstr\n\t" \ + ".align 4\n" \ + "3:\n\t" \ + "sethi %%hi(2b), %0\n\t" \ + "jmpl %0 + %%lo(2b), %%g0\n\t" \ + " mov %3, %0\n\n\t" \ + ".previous\n\t" \ + ".section __ex_table,\"a\"\n\t" \ + ".align 4\n\t" \ + ".word 1b, 3b\n\t" \ + ".previous\n\n\t" \ + : "=r" (ret) : "r" (x), "r" (__m(addr)), \ + "i" (-EFAULT)) int __put_user_bad(void); -#define __get_user_nocheck(data,addr,size,type) ({ \ -register int __gu_ret; \ -register unsigned long __gu_val; \ -switch (size) { \ -case 1: __get_user_asm(__gu_val,ub,addr,__gu_ret); break; \ -case 2: __get_user_asm(__gu_val,uh,addr,__gu_ret); break; \ -case 4: __get_user_asm(__gu_val,uw,addr,__gu_ret); break; \ -case 8: __get_user_asm(__gu_val,x,addr,__gu_ret); break; \ -default: __gu_val = 0; __gu_ret = __get_user_bad(); break; \ -} data = (__force type) __gu_val; __gu_ret; }) - -#define __get_user_nocheck_ret(data,addr,size,type,retval) ({ \ -register unsigned long __gu_val __asm__ ("l1"); \ -switch (size) { \ -case 1: __get_user_asm_ret(__gu_val,ub,addr,retval); break; \ -case 2: __get_user_asm_ret(__gu_val,uh,addr,retval); break; \ -case 4: __get_user_asm_ret(__gu_val,uw,addr,retval); break; \ -case 8: __get_user_asm_ret(__gu_val,x,addr,retval); break; \ -default: if (__get_user_bad()) return retval; \ -} data = (__force type) __gu_val; }) - -#define __get_user_asm(x,size,addr,ret) \ +#define __get_user_nocheck(data, addr, size, type) ({ \ + register int __gu_ret; \ + register unsigned long __gu_val; \ + switch (size) { \ + case 1: \ + __get_user_asm(__gu_val, ub, addr, __gu_ret); \ + break; \ + case 2: \ + __get_user_asm(__gu_val, uh, addr, __gu_ret); \ + break; \ + case 4: \ + __get_user_asm(__gu_val, uw, addr, __gu_ret); \ + break; \ + case 8: \ + __get_user_asm(__gu_val, x, addr, __gu_ret); \ + break; \ + default: \ + __gu_val = 0; \ + __gu_ret = __get_user_bad(); \ + break; \ + } \ + data = (__force type) __gu_val; \ + __gu_ret; \ +}) + +#define __get_user_nocheck_ret(data, addr, size, type, retval) ({ \ + register unsigned long __gu_val __asm__ ("l1"); \ + switch (size) { \ + case 1: \ + __get_user_asm_ret(__gu_val, ub, addr, retval); \ + break; \ + case 2: \ + __get_user_asm_ret(__gu_val, uh, addr, retval); \ + break; \ + case 4: \ + __get_user_asm_ret(__gu_val, uw, addr, retval); \ + break; \ + case 8: \ + __get_user_asm_ret(__gu_val, x, addr, retval); \ + break; \ + default: \ + if (__get_user_bad()) \ + return retval; \ + } \ + data = (__force type) __gu_val; \ +}) + +#define __get_user_asm(x, size, addr, ret) \ __asm__ __volatile__( \ - "/* Get user asm, inline. */\n" \ -"1:\t" "ld"#size "a [%2] %%asi, %1\n\t" \ - "clr %0\n" \ -"2:\n\n\t" \ - ".section .fixup,#alloc,#execinstr\n\t" \ - ".align 4\n" \ -"3:\n\t" \ - "sethi %%hi(2b), %0\n\t" \ - "clr %1\n\t" \ - "jmpl %0 + %%lo(2b), %%g0\n\t" \ - " mov %3, %0\n\n\t" \ - ".previous\n\t" \ - ".section __ex_table,\"a\"\n\t" \ - ".align 4\n\t" \ - ".word 1b, 3b\n\n\t" \ - ".previous\n\t" \ - : "=r" (ret), "=r" (x) : "r" (__m(addr)), \ - "i" (-EFAULT)) - -#define __get_user_asm_ret(x,size,addr,retval) \ + "/* Get user asm, inline. */\n" \ + "1:\t" "ld"#size "a [%2] %%asi, %1\n\t" \ + "clr %0\n" \ + "2:\n\n\t" \ + ".section .fixup,#alloc,#execinstr\n\t" \ + ".align 4\n" \ + "3:\n\t" \ + "sethi %%hi(2b), %0\n\t" \ + "clr %1\n\t" \ + "jmpl %0 + %%lo(2b), %%g0\n\t" \ + " mov %3, %0\n\n\t" \ + ".previous\n\t" \ + ".section __ex_table,\"a\"\n\t" \ + ".align 4\n\t" \ + ".word 1b, 3b\n\n\t" \ + ".previous\n\t" \ + : "=r" (ret), "=r" (x) : "r" (__m(addr)), \ + "i" (-EFAULT)) + +#define __get_user_asm_ret(x, size, addr, retval) \ if (__builtin_constant_p(retval) && retval == -EFAULT) \ -__asm__ __volatile__( \ - "/* Get user asm ret, inline. */\n" \ -"1:\t" "ld"#size "a [%1] %%asi, %0\n\n\t" \ - ".section __ex_table,\"a\"\n\t" \ - ".align 4\n\t" \ - ".word 1b,__ret_efault\n\n\t" \ - ".previous\n\t" \ - : "=r" (x) : "r" (__m(addr))); \ + __asm__ __volatile__( \ + "/* Get user asm ret, inline. */\n" \ + "1:\t" "ld"#size "a [%1] %%asi, %0\n\n\t" \ + ".section __ex_table,\"a\"\n\t" \ + ".align 4\n\t" \ + ".word 1b,__ret_efault\n\n\t" \ + ".previous\n\t" \ + : "=r" (x) : "r" (__m(addr))); \ else \ -__asm__ __volatile__( \ - "/* Get user asm ret, inline. */\n" \ -"1:\t" "ld"#size "a [%1] %%asi, %0\n\n\t" \ - ".section .fixup,#alloc,#execinstr\n\t" \ - ".align 4\n" \ -"3:\n\t" \ - "ret\n\t" \ - " restore %%g0, %2, %%o0\n\n\t" \ - ".previous\n\t" \ - ".section __ex_table,\"a\"\n\t" \ - ".align 4\n\t" \ - ".word 1b, 3b\n\n\t" \ - ".previous\n\t" \ - : "=r" (x) : "r" (__m(addr)), "i" (retval)) + __asm__ __volatile__( \ + "/* Get user asm ret, inline. */\n" \ + "1:\t" "ld"#size "a [%1] %%asi, %0\n\n\t" \ + ".section .fixup,#alloc,#execinstr\n\t" \ + ".align 4\n" \ + "3:\n\t" \ + "ret\n\t" \ + " restore %%g0, %2, %%o0\n\n\t" \ + ".previous\n\t" \ + ".section __ex_table,\"a\"\n\t" \ + ".align 4\n\t" \ + ".word 1b, 3b\n\n\t" \ + ".previous\n\t" \ + : "=r" (x) : "r" (__m(addr)), "i" (retval)) int __get_user_bad(void); -- cgit v1.2.3 From 323ae3c5dd941c8257912941eb3da93aaf8d65dd Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 15:11:13 +0200 Subject: blackfin: macro whitespace fixes While working on arch/blackfin/include/asm/uaccess.h, I noticed that some macros within this header are made harder to read because they violate a coding style rule: space is missing after comma. Fix it up. Signed-off-by: Michael S. Tsirkin --- arch/blackfin/include/asm/uaccess.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/blackfin/include/asm/uaccess.h b/arch/blackfin/include/asm/uaccess.h index 4bf968c01cf9..90612a7f2cf3 100644 --- a/arch/blackfin/include/asm/uaccess.h +++ b/arch/blackfin/include/asm/uaccess.h @@ -27,7 +27,7 @@ static inline void set_fs(mm_segment_t fs) current_thread_info()->addr_limit = fs; } -#define segment_eq(a,b) ((a) == (b)) +#define segment_eq(a, b) ((a) == (b)) #define VERIFY_READ 0 #define VERIFY_WRITE 1 @@ -68,11 +68,11 @@ struct exception_table_entry { * use the right size if we just have the right pointer type. */ -#define put_user(x,p) \ +#define put_user(x, p) \ ({ \ int _err = 0; \ typeof(*(p)) _x = (x); \ - typeof(*(p)) __user *_p = (p); \ + typeof(*(p)) __user *_p = (p); \ if (!access_ok(VERIFY_WRITE, _p, sizeof(*(_p)))) {\ _err = -EFAULT; \ } \ @@ -102,7 +102,7 @@ struct exception_table_entry { _err; \ }) -#define __put_user(x,p) put_user(x,p) +#define __put_user(x, p) put_user(x, p) static inline int bad_user_access_length(void) { panic("bad_user_access_length"); @@ -121,10 +121,10 @@ static inline int bad_user_access_length(void) #define __ptr(x) ((unsigned long __force *)(x)) -#define __put_user_asm(x,p,bhw) \ +#define __put_user_asm(x, p, bhw) \ __asm__ (#bhw"[%1] = %0;\n\t" \ : /* no outputs */ \ - :"d" (x),"a" (__ptr(p)) : "memory") + :"d" (x), "a" (__ptr(p)) : "memory") #define get_user(x, ptr) \ ({ \ @@ -136,10 +136,10 @@ static inline int bad_user_access_length(void) BUILD_BUG_ON(ptr_size >= 8); \ switch (ptr_size) { \ case 1: \ - __get_user_asm(_val, _p, B,(Z)); \ + __get_user_asm(_val, _p, B, (Z)); \ break; \ case 2: \ - __get_user_asm(_val, _p, W,(Z)); \ + __get_user_asm(_val, _p, W, (Z)); \ break; \ case 4: \ __get_user_asm(_val, _p, , ); \ @@ -151,7 +151,7 @@ static inline int bad_user_access_length(void) _err; \ }) -#define __get_user(x,p) get_user(x,p) +#define __get_user(x, p) get_user(x, p) #define __get_user_bad() (bad_user_access_length(), (-EFAULT)) @@ -168,10 +168,10 @@ static inline int bad_user_access_length(void) #define __copy_to_user_inatomic __copy_to_user #define __copy_from_user_inatomic __copy_from_user -#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n))\ +#define copy_to_user_ret(to, from, n, retval) ({ if (copy_to_user(to, from, n))\ return retval; }) -#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n))\ +#define copy_from_user_ret(to, from, n, retval) ({ if (copy_from_user(to, from, n))\ return retval; }) static inline unsigned long __must_check -- cgit v1.2.3 From 4fb9bccbfbb2b95685671cc65f7ecd64e30384ff Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 15:11:13 +0200 Subject: alpha: macro whitespace fixes While working on arch/alpha/include/asm/uaccess.h, I noticed that some macros within this header are made harder to read because they violate a coding style rule: space is missing after comma. Fix it up. Signed-off-by: Michael S. Tsirkin --- arch/alpha/include/asm/uaccess.h | 82 ++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 41 deletions(-) (limited to 'arch') diff --git a/arch/alpha/include/asm/uaccess.h b/arch/alpha/include/asm/uaccess.h index a234de79157a..9b0d40093c9a 100644 --- a/arch/alpha/include/asm/uaccess.h +++ b/arch/alpha/include/asm/uaccess.h @@ -27,7 +27,7 @@ #define get_ds() (KERNEL_DS) #define set_fs(x) (current_thread_info()->addr_limit = (x)) -#define segment_eq(a,b) ((a).seg == (b).seg) +#define segment_eq(a, b) ((a).seg == (b).seg) /* * Is a address valid? This does a straightforward calculation rather @@ -39,13 +39,13 @@ * - AND "addr+size" doesn't have any high-bits set * - OR we are in kernel mode. */ -#define __access_ok(addr,size,segment) \ +#define __access_ok(addr, size, segment) \ (((segment).seg & (addr | size | (addr+size))) == 0) -#define access_ok(type,addr,size) \ +#define access_ok(type, addr, size) \ ({ \ __chk_user_ptr(addr); \ - __access_ok(((unsigned long)(addr)),(size),get_fs()); \ + __access_ok(((unsigned long)(addr)), (size), get_fs()); \ }) /* @@ -60,20 +60,20 @@ * (a) re-use the arguments for side effects (sizeof/typeof is ok) * (b) require any knowledge of processes at this stage */ -#define put_user(x,ptr) \ - __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)),get_fs()) -#define get_user(x,ptr) \ - __get_user_check((x),(ptr),sizeof(*(ptr)),get_fs()) +#define put_user(x, ptr) \ + __put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)), get_fs()) +#define get_user(x, ptr) \ + __get_user_check((x), (ptr), sizeof(*(ptr)), get_fs()) /* * The "__xxx" versions do not do address space checking, useful when * doing multiple accesses to the same area (the programmer has to do the * checks by hand with "access_ok()") */ -#define __put_user(x,ptr) \ - __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) -#define __get_user(x,ptr) \ - __get_user_nocheck((x),(ptr),sizeof(*(ptr))) +#define __put_user(x, ptr) \ + __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) +#define __get_user(x, ptr) \ + __get_user_nocheck((x), (ptr), sizeof(*(ptr))) /* * The "lda %1, 2b-1b(%0)" bits are magic to get the assembler to @@ -84,7 +84,7 @@ extern void __get_user_unknown(void); -#define __get_user_nocheck(x,ptr,size) \ +#define __get_user_nocheck(x, ptr, size) \ ({ \ long __gu_err = 0; \ unsigned long __gu_val; \ @@ -100,12 +100,12 @@ extern void __get_user_unknown(void); __gu_err; \ }) -#define __get_user_check(x,ptr,size,segment) \ +#define __get_user_check(x, ptr, size, segment) \ ({ \ long __gu_err = -EFAULT; \ unsigned long __gu_val = 0; \ const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ - if (__access_ok((unsigned long)__gu_addr,size,segment)) { \ + if (__access_ok((unsigned long)__gu_addr, size, segment)) { \ __gu_err = 0; \ switch (size) { \ case 1: __get_user_8(__gu_addr); break; \ @@ -201,31 +201,31 @@ struct __large_struct { unsigned long buf[100]; }; extern void __put_user_unknown(void); -#define __put_user_nocheck(x,ptr,size) \ +#define __put_user_nocheck(x, ptr, size) \ ({ \ long __pu_err = 0; \ __chk_user_ptr(ptr); \ switch (size) { \ - case 1: __put_user_8(x,ptr); break; \ - case 2: __put_user_16(x,ptr); break; \ - case 4: __put_user_32(x,ptr); break; \ - case 8: __put_user_64(x,ptr); break; \ + case 1: __put_user_8(x, ptr); break; \ + case 2: __put_user_16(x, ptr); break; \ + case 4: __put_user_32(x, ptr); break; \ + case 8: __put_user_64(x, ptr); break; \ default: __put_user_unknown(); break; \ } \ __pu_err; \ }) -#define __put_user_check(x,ptr,size,segment) \ +#define __put_user_check(x, ptr, size, segment) \ ({ \ long __pu_err = -EFAULT; \ __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ - if (__access_ok((unsigned long)__pu_addr,size,segment)) { \ + if (__access_ok((unsigned long)__pu_addr, size, segment)) { \ __pu_err = 0; \ switch (size) { \ - case 1: __put_user_8(x,__pu_addr); break; \ - case 2: __put_user_16(x,__pu_addr); break; \ - case 4: __put_user_32(x,__pu_addr); break; \ - case 8: __put_user_64(x,__pu_addr); break; \ + case 1: __put_user_8(x, __pu_addr); break; \ + case 2: __put_user_16(x, __pu_addr); break; \ + case 4: __put_user_32(x, __pu_addr); break; \ + case 8: __put_user_64(x, __pu_addr); break; \ default: __put_user_unknown(); break; \ } \ } \ @@ -237,7 +237,7 @@ extern void __put_user_unknown(void); * instead of writing: this is because they do not write to * any memory gcc knows about, so there are no aliasing issues */ -#define __put_user_64(x,addr) \ +#define __put_user_64(x, addr) \ __asm__ __volatile__("1: stq %r2,%1\n" \ "2:\n" \ ".section __ex_table,\"a\"\n" \ @@ -247,7 +247,7 @@ __asm__ __volatile__("1: stq %r2,%1\n" \ : "=r"(__pu_err) \ : "m" (__m(addr)), "rJ" (x), "0"(__pu_err)) -#define __put_user_32(x,addr) \ +#define __put_user_32(x, addr) \ __asm__ __volatile__("1: stl %r2,%1\n" \ "2:\n" \ ".section __ex_table,\"a\"\n" \ @@ -260,7 +260,7 @@ __asm__ __volatile__("1: stl %r2,%1\n" \ #ifdef __alpha_bwx__ /* Those lucky bastards with ev56 and later CPUs can do byte/word moves. */ -#define __put_user_16(x,addr) \ +#define __put_user_16(x, addr) \ __asm__ __volatile__("1: stw %r2,%1\n" \ "2:\n" \ ".section __ex_table,\"a\"\n" \ @@ -270,7 +270,7 @@ __asm__ __volatile__("1: stw %r2,%1\n" \ : "=r"(__pu_err) \ : "m"(__m(addr)), "rJ"(x), "0"(__pu_err)) -#define __put_user_8(x,addr) \ +#define __put_user_8(x, addr) \ __asm__ __volatile__("1: stb %r2,%1\n" \ "2:\n" \ ".section __ex_table,\"a\"\n" \ @@ -283,7 +283,7 @@ __asm__ __volatile__("1: stb %r2,%1\n" \ /* Unfortunately, we can't get an unaligned access trap for the sub-word write, so we have to do a general unaligned operation. */ -#define __put_user_16(x,addr) \ +#define __put_user_16(x, addr) \ { \ long __pu_tmp1, __pu_tmp2, __pu_tmp3, __pu_tmp4; \ __asm__ __volatile__( \ @@ -308,13 +308,13 @@ __asm__ __volatile__("1: stb %r2,%1\n" \ " .long 4b - .\n" \ " lda $31, 5b-4b(%0)\n" \ ".previous" \ - : "=r"(__pu_err), "=&r"(__pu_tmp1), \ - "=&r"(__pu_tmp2), "=&r"(__pu_tmp3), \ + : "=r"(__pu_err), "=&r"(__pu_tmp1), \ + "=&r"(__pu_tmp2), "=&r"(__pu_tmp3), \ "=&r"(__pu_tmp4) \ : "r"(addr), "r"((unsigned long)(x)), "0"(__pu_err)); \ } -#define __put_user_8(x,addr) \ +#define __put_user_8(x, addr) \ { \ long __pu_tmp1, __pu_tmp2; \ __asm__ __volatile__( \ @@ -330,7 +330,7 @@ __asm__ __volatile__("1: stb %r2,%1\n" \ " .long 2b - .\n" \ " lda $31, 3b-2b(%0)\n" \ ".previous" \ - : "=r"(__pu_err), \ + : "=r"(__pu_err), \ "=&r"(__pu_tmp1), "=&r"(__pu_tmp2) \ : "r"((unsigned long)(x)), "r"(addr), "0"(__pu_err)); \ } @@ -366,7 +366,7 @@ __copy_tofrom_user_nocheck(void *to, const void *from, long len) : "=r" (__cu_len), "=r" (__cu_from), "=r" (__cu_to) : __module_address(__copy_user) "0" (__cu_len), "1" (__cu_from), "2" (__cu_to) - : "$1","$2","$3","$4","$5","$28","memory"); + : "$1", "$2", "$3", "$4", "$5", "$28", "memory"); return __cu_len; } @@ -379,15 +379,15 @@ __copy_tofrom_user(void *to, const void *from, long len, const void __user *vali return len; } -#define __copy_to_user(to,from,n) \ +#define __copy_to_user(to, from, n) \ ({ \ __chk_user_ptr(to); \ - __copy_tofrom_user_nocheck((__force void *)(to),(from),(n)); \ + __copy_tofrom_user_nocheck((__force void *)(to), (from), (n)); \ }) -#define __copy_from_user(to,from,n) \ +#define __copy_from_user(to, from, n) \ ({ \ __chk_user_ptr(from); \ - __copy_tofrom_user_nocheck((to),(__force void *)(from),(n)); \ + __copy_tofrom_user_nocheck((to), (__force void *)(from), (n)); \ }) #define __copy_to_user_inatomic __copy_to_user @@ -418,7 +418,7 @@ __clear_user(void __user *to, long len) : "=r"(__cl_len), "=r"(__cl_to) : __module_address(__do_clear_user) "0"(__cl_len), "1"(__cl_to) - : "$1","$2","$3","$4","$5","$28","memory"); + : "$1", "$2", "$3", "$4", "$5", "$28", "memory"); return __cl_len; } -- cgit v1.2.3 From 295bb01e2666e450be7f6e6e1f5785bfb26fd60e Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 15:11:13 +0200 Subject: arm: macro whitespace fixes While working on arch/arm/include/asm/uaccess.h, I noticed that some macros within this header are made harder to read because they violate a coding style rule: space is missing after comma. Fix it up. Signed-off-by: Michael S. Tsirkin --- arch/arm/include/asm/uaccess.h | 92 +++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 46 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 74fcde756fdb..ce0786efd26c 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -73,7 +73,7 @@ static inline void set_fs(mm_segment_t fs) modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER); } -#define segment_eq(a,b) ((a) == (b)) +#define segment_eq(a, b) ((a) == (b)) #define __addr_ok(addr) ({ \ unsigned long flag; \ @@ -84,7 +84,7 @@ static inline void set_fs(mm_segment_t fs) (flag == 0); }) /* We use 33-bit arithmetic here... */ -#define __range_ok(addr,size) ({ \ +#define __range_ok(addr, size) ({ \ unsigned long flag, roksum; \ __chk_user_ptr(addr); \ __asm__("adds %1, %2, %3; sbcccs %1, %1, %0; movcc %0, #0" \ @@ -123,7 +123,7 @@ extern int __get_user_64t_4(void *); #define __GUP_CLOBBER_32t_8 "lr", "cc" #define __GUP_CLOBBER_8 "lr", "cc" -#define __get_user_x(__r2,__p,__e,__l,__s) \ +#define __get_user_x(__r2, __p, __e, __l, __s) \ __asm__ __volatile__ ( \ __asmeq("%0", "r0") __asmeq("%1", "r2") \ __asmeq("%3", "r1") \ @@ -134,7 +134,7 @@ extern int __get_user_64t_4(void *); /* narrowing a double-word get into a single 32bit word register: */ #ifdef __ARMEB__ -#define __get_user_x_32t(__r2, __p, __e, __l, __s) \ +#define __get_user_x_32t(__r2, __p, __e, __l, __s) \ __get_user_x(__r2, __p, __e, __l, 32t_8) #else #define __get_user_x_32t __get_user_x @@ -158,7 +158,7 @@ extern int __get_user_64t_4(void *); #endif -#define __get_user_check(x,p) \ +#define __get_user_check(x, p) \ ({ \ unsigned long __limit = current_thread_info()->addr_limit - 1; \ register const typeof(*(p)) __user *__p asm("r0") = (p);\ @@ -196,10 +196,10 @@ extern int __get_user_64t_4(void *); __e; \ }) -#define get_user(x,p) \ +#define get_user(x, p) \ ({ \ might_fault(); \ - __get_user_check(x,p); \ + __get_user_check(x, p); \ }) extern int __put_user_1(void *, unsigned int); @@ -207,7 +207,7 @@ extern int __put_user_2(void *, unsigned int); extern int __put_user_4(void *, unsigned int); extern int __put_user_8(void *, unsigned long long); -#define __put_user_x(__r2,__p,__e,__l,__s) \ +#define __put_user_x(__r2, __p, __e, __l, __s) \ __asm__ __volatile__ ( \ __asmeq("%0", "r0") __asmeq("%2", "r2") \ __asmeq("%3", "r1") \ @@ -216,7 +216,7 @@ extern int __put_user_8(void *, unsigned long long); : "0" (__p), "r" (__r2), "r" (__l) \ : "ip", "lr", "cc") -#define __put_user_check(x,p) \ +#define __put_user_check(x, p) \ ({ \ unsigned long __limit = current_thread_info()->addr_limit - 1; \ const typeof(*(p)) __user *__tmp_p = (p); \ @@ -242,10 +242,10 @@ extern int __put_user_8(void *, unsigned long long); __e; \ }) -#define put_user(x,p) \ +#define put_user(x, p) \ ({ \ might_fault(); \ - __put_user_check(x,p); \ + __put_user_check(x, p); \ }) #else /* CONFIG_MMU */ @@ -255,21 +255,21 @@ extern int __put_user_8(void *, unsigned long long); */ #define USER_DS KERNEL_DS -#define segment_eq(a,b) (1) -#define __addr_ok(addr) ((void)(addr),1) -#define __range_ok(addr,size) ((void)(addr),0) +#define segment_eq(a, b) (1) +#define __addr_ok(addr) ((void)(addr), 1) +#define __range_ok(addr, size) ((void)(addr), 0) #define get_fs() (KERNEL_DS) static inline void set_fs(mm_segment_t fs) { } -#define get_user(x,p) __get_user(x,p) -#define put_user(x,p) __put_user(x,p) +#define get_user(x, p) __get_user(x, p) +#define put_user(x, p) __put_user(x, p) #endif /* CONFIG_MMU */ -#define access_ok(type,addr,size) (__range_ok(addr,size) == 0) +#define access_ok(type, addr, size) (__range_ok(addr, size) == 0) #define user_addr_max() \ (segment_eq(get_fs(), KERNEL_DS) ? ~0UL : get_fs()) @@ -283,35 +283,35 @@ static inline void set_fs(mm_segment_t fs) * error occurs, and leave it unchanged on success. Note that these * versions are void (ie, don't return a value as such). */ -#define __get_user(x,ptr) \ +#define __get_user(x, ptr) \ ({ \ long __gu_err = 0; \ - __get_user_err((x),(ptr),__gu_err); \ + __get_user_err((x), (ptr), __gu_err); \ __gu_err; \ }) -#define __get_user_error(x,ptr,err) \ +#define __get_user_error(x, ptr, err) \ ({ \ - __get_user_err((x),(ptr),err); \ + __get_user_err((x), (ptr), err); \ (void) 0; \ }) -#define __get_user_err(x,ptr,err) \ +#define __get_user_err(x, ptr, err) \ do { \ unsigned long __gu_addr = (unsigned long)(ptr); \ unsigned long __gu_val; \ __chk_user_ptr(ptr); \ might_fault(); \ switch (sizeof(*(ptr))) { \ - case 1: __get_user_asm_byte(__gu_val,__gu_addr,err); break; \ - case 2: __get_user_asm_half(__gu_val,__gu_addr,err); break; \ - case 4: __get_user_asm_word(__gu_val,__gu_addr,err); break; \ + case 1: __get_user_asm_byte(__gu_val, __gu_addr, err); break; \ + case 2: __get_user_asm_half(__gu_val, __gu_addr, err); break; \ + case 4: __get_user_asm_word(__gu_val, __gu_addr, err); break; \ default: (__gu_val) = __get_user_bad(); \ } \ (x) = (__typeof__(*(ptr)))__gu_val; \ } while (0) -#define __get_user_asm_byte(x,addr,err) \ +#define __get_user_asm_byte(x, addr, err) \ __asm__ __volatile__( \ "1: " TUSER(ldrb) " %1,[%2],#0\n" \ "2:\n" \ @@ -330,7 +330,7 @@ do { \ : "cc") #ifndef __ARMEB__ -#define __get_user_asm_half(x,__gu_addr,err) \ +#define __get_user_asm_half(x, __gu_addr, err) \ ({ \ unsigned long __b1, __b2; \ __get_user_asm_byte(__b1, __gu_addr, err); \ @@ -338,7 +338,7 @@ do { \ (x) = __b1 | (__b2 << 8); \ }) #else -#define __get_user_asm_half(x,__gu_addr,err) \ +#define __get_user_asm_half(x, __gu_addr, err) \ ({ \ unsigned long __b1, __b2; \ __get_user_asm_byte(__b1, __gu_addr, err); \ @@ -347,7 +347,7 @@ do { \ }) #endif -#define __get_user_asm_word(x,addr,err) \ +#define __get_user_asm_word(x, addr, err) \ __asm__ __volatile__( \ "1: " TUSER(ldr) " %1,[%2],#0\n" \ "2:\n" \ @@ -365,35 +365,35 @@ do { \ : "r" (addr), "i" (-EFAULT) \ : "cc") -#define __put_user(x,ptr) \ +#define __put_user(x, ptr) \ ({ \ long __pu_err = 0; \ - __put_user_err((x),(ptr),__pu_err); \ + __put_user_err((x), (ptr), __pu_err); \ __pu_err; \ }) -#define __put_user_error(x,ptr,err) \ +#define __put_user_error(x, ptr, err) \ ({ \ - __put_user_err((x),(ptr),err); \ + __put_user_err((x), (ptr), err); \ (void) 0; \ }) -#define __put_user_err(x,ptr,err) \ +#define __put_user_err(x, ptr, err) \ do { \ unsigned long __pu_addr = (unsigned long)(ptr); \ __typeof__(*(ptr)) __pu_val = (x); \ __chk_user_ptr(ptr); \ might_fault(); \ switch (sizeof(*(ptr))) { \ - case 1: __put_user_asm_byte(__pu_val,__pu_addr,err); break; \ - case 2: __put_user_asm_half(__pu_val,__pu_addr,err); break; \ - case 4: __put_user_asm_word(__pu_val,__pu_addr,err); break; \ - case 8: __put_user_asm_dword(__pu_val,__pu_addr,err); break; \ + case 1: __put_user_asm_byte(__pu_val, __pu_addr, err); break; \ + case 2: __put_user_asm_half(__pu_val, __pu_addr, err); break; \ + case 4: __put_user_asm_word(__pu_val, __pu_addr, err); break; \ + case 8: __put_user_asm_dword(__pu_val, __pu_addr, err); break; \ default: __put_user_bad(); \ } \ } while (0) -#define __put_user_asm_byte(x,__pu_addr,err) \ +#define __put_user_asm_byte(x, __pu_addr, err) \ __asm__ __volatile__( \ "1: " TUSER(strb) " %1,[%2],#0\n" \ "2:\n" \ @@ -411,14 +411,14 @@ do { \ : "cc") #ifndef __ARMEB__ -#define __put_user_asm_half(x,__pu_addr,err) \ +#define __put_user_asm_half(x, __pu_addr, err) \ ({ \ unsigned long __temp = (__force unsigned long)(x); \ __put_user_asm_byte(__temp, __pu_addr, err); \ __put_user_asm_byte(__temp >> 8, __pu_addr + 1, err); \ }) #else -#define __put_user_asm_half(x,__pu_addr,err) \ +#define __put_user_asm_half(x, __pu_addr, err) \ ({ \ unsigned long __temp = (__force unsigned long)(x); \ __put_user_asm_byte(__temp >> 8, __pu_addr, err); \ @@ -426,7 +426,7 @@ do { \ }) #endif -#define __put_user_asm_word(x,__pu_addr,err) \ +#define __put_user_asm_word(x, __pu_addr, err) \ __asm__ __volatile__( \ "1: " TUSER(str) " %1,[%2],#0\n" \ "2:\n" \ @@ -451,7 +451,7 @@ do { \ #define __reg_oper1 "%R2" #endif -#define __put_user_asm_dword(x,__pu_addr,err) \ +#define __put_user_asm_dword(x, __pu_addr, err) \ __asm__ __volatile__( \ ARM( "1: " TUSER(str) " " __reg_oper1 ", [%1], #4\n" ) \ ARM( "2: " TUSER(str) " " __reg_oper0 ", [%1]\n" ) \ @@ -480,9 +480,9 @@ extern unsigned long __must_check __copy_to_user_std(void __user *to, const void extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n); extern unsigned long __must_check __clear_user_std(void __user *addr, unsigned long n); #else -#define __copy_from_user(to,from,n) (memcpy(to, (void __force *)from, n), 0) -#define __copy_to_user(to,from,n) (memcpy((void __force *)to, from, n), 0) -#define __clear_user(addr,n) (memset((void __force *)addr, 0, n), 0) +#define __copy_from_user(to, from, n) (memcpy(to, (void __force *)from, n), 0) +#define __copy_to_user(to, from, n) (memcpy((void __force *)to, from, n), 0) +#define __clear_user(addr, n) (memset((void __force *)addr, 0, n), 0) #endif static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) -- cgit v1.2.3 From 967f0e5d67518f274e397b4fa703c73cac24fe18 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 15:11:13 +0200 Subject: arm64: macro whitespace fixes While working on arch/arm64/include/asm/uaccess.h, I noticed that one macro within this header is made harder to read because it violates a coding style rule: space is missing after comma. Fix it up. Signed-off-by: Michael S. Tsirkin Acked-by: Will Deacon --- arch/arm64/include/asm/uaccess.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index 9a2069bbc00d..07e1ba449bf1 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -63,7 +63,7 @@ static inline void set_fs(mm_segment_t fs) current_thread_info()->addr_limit = fs; } -#define segment_eq(a,b) ((a) == (b)) +#define segment_eq(a, b) ((a) == (b)) /* * Return 1 if addr < current->addr_limit, 0 otherwise. -- cgit v1.2.3 From d13beabea13b528d9d9d9c95a80db6bd7b99402c Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 15:11:13 +0200 Subject: avr32: macro whitespace fixes While working on arch/avr32/include/asm/uaccess.h, I noticed that some macros within this header are made harder to read because they violate a coding style rule: space is missing after comma. Fix it up. Signed-off-by: Michael S. Tsirkin Acked-by: Hans-Christian Egtvedt --- arch/avr32/include/asm/uaccess.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'arch') diff --git a/arch/avr32/include/asm/uaccess.h b/arch/avr32/include/asm/uaccess.h index 72607f32eebb..a46f7cf3e1ea 100644 --- a/arch/avr32/include/asm/uaccess.h +++ b/arch/avr32/include/asm/uaccess.h @@ -26,7 +26,7 @@ typedef struct { * For historical reasons (Data Segment Register?), these macros are misnamed. */ #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) -#define segment_eq(a,b) ((a).is_user_space == (b).is_user_space) +#define segment_eq(a, b) ((a).is_user_space == (b).is_user_space) #define USER_ADDR_LIMIT 0x80000000 @@ -108,8 +108,8 @@ static inline __kernel_size_t __copy_from_user(void *to, * * Returns zero on success, or -EFAULT on error. */ -#define put_user(x,ptr) \ - __put_user_check((x),(ptr),sizeof(*(ptr))) +#define put_user(x, ptr) \ + __put_user_check((x), (ptr), sizeof(*(ptr))) /* * get_user: - Get a simple variable from user space. @@ -128,8 +128,8 @@ static inline __kernel_size_t __copy_from_user(void *to, * Returns zero on success, or -EFAULT on error. * On error, the variable @x is set to zero. */ -#define get_user(x,ptr) \ - __get_user_check((x),(ptr),sizeof(*(ptr))) +#define get_user(x, ptr) \ + __get_user_check((x), (ptr), sizeof(*(ptr))) /* * __put_user: - Write a simple value into user space, with less checking. @@ -150,8 +150,8 @@ static inline __kernel_size_t __copy_from_user(void *to, * * Returns zero on success, or -EFAULT on error. */ -#define __put_user(x,ptr) \ - __put_user_nocheck((x),(ptr),sizeof(*(ptr))) +#define __put_user(x, ptr) \ + __put_user_nocheck((x), (ptr), sizeof(*(ptr))) /* * __get_user: - Get a simple variable from user space, with less checking. @@ -173,8 +173,8 @@ static inline __kernel_size_t __copy_from_user(void *to, * Returns zero on success, or -EFAULT on error. * On error, the variable @x is set to zero. */ -#define __get_user(x,ptr) \ - __get_user_nocheck((x),(ptr),sizeof(*(ptr))) +#define __get_user(x, ptr) \ + __get_user_nocheck((x), (ptr), sizeof(*(ptr))) extern int __get_user_bad(void); extern int __put_user_bad(void); -- cgit v1.2.3 From 00eaf4c0c2fdb2121216fe2323fd606b109649ab Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 15:11:13 +0200 Subject: cris: macro whitespace fixes While working on arch/cris/include/asm/uaccess.h, I noticed that some macros within this header are made harder to read because they violate a coding style rule: space is missing after comma. Fix it up. Signed-off-by: Michael S. Tsirkin --- arch/cris/include/asm/uaccess.h | 113 +++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 55 deletions(-) (limited to 'arch') diff --git a/arch/cris/include/asm/uaccess.h b/arch/cris/include/asm/uaccess.h index 9cf5a23baed3..a21344ab8616 100644 --- a/arch/cris/include/asm/uaccess.h +++ b/arch/cris/include/asm/uaccess.h @@ -47,12 +47,13 @@ #define get_fs() (current_thread_info()->addr_limit) #define set_fs(x) (current_thread_info()->addr_limit = (x)) -#define segment_eq(a,b) ((a).seg == (b).seg) +#define segment_eq(a, b) ((a).seg == (b).seg) #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS)) -#define __user_ok(addr,size) (((size) <= TASK_SIZE)&&((addr) <= TASK_SIZE-(size))) -#define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size))) -#define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size)) +#define __user_ok(addr, size) \ + (((size) <= TASK_SIZE)&&((addr) <= TASK_SIZE-(size))) +#define __access_ok(addr, size) (__kernel_ok || __user_ok((addr), (size))) +#define access_ok(type, addr, size) __access_ok((unsigned long)(addr), (size)) #include @@ -92,56 +93,56 @@ struct exception_table_entry * CRIS, we can just do these as direct assignments. (Of course, the * exception handling means that it's no longer "just"...) */ -#define get_user(x,ptr) \ - __get_user_check((x),(ptr),sizeof(*(ptr))) -#define put_user(x,ptr) \ - __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) +#define get_user(x, ptr) \ + __get_user_check((x), (ptr), sizeof(*(ptr))) +#define put_user(x, ptr) \ + __put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) -#define __get_user(x,ptr) \ - __get_user_nocheck((x),(ptr),sizeof(*(ptr))) -#define __put_user(x,ptr) \ - __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) +#define __get_user(x, ptr) \ + __get_user_nocheck((x), (ptr), sizeof(*(ptr))) +#define __put_user(x, ptr) \ + __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) extern long __put_user_bad(void); -#define __put_user_size(x,ptr,size,retval) \ -do { \ - retval = 0; \ - switch (size) { \ - case 1: __put_user_asm(x,ptr,retval,"move.b"); break; \ - case 2: __put_user_asm(x,ptr,retval,"move.w"); break; \ - case 4: __put_user_asm(x,ptr,retval,"move.d"); break; \ - case 8: __put_user_asm_64(x,ptr,retval); break; \ - default: __put_user_bad(); \ - } \ +#define __put_user_size(x, ptr, size, retval) \ +do { \ + retval = 0; \ + switch (size) { \ + case 1: __put_user_asm(x, ptr, retval, "move.b"); break; \ + case 2: __put_user_asm(x, ptr, retval, "move.w"); break; \ + case 4: __put_user_asm(x, ptr, retval, "move.d"); break; \ + case 8: __put_user_asm_64(x, ptr, retval); break; \ + default: __put_user_bad(); \ + } \ } while (0) -#define __get_user_size(x,ptr,size,retval) \ -do { \ - retval = 0; \ - switch (size) { \ - case 1: __get_user_asm(x,ptr,retval,"move.b"); break; \ - case 2: __get_user_asm(x,ptr,retval,"move.w"); break; \ - case 4: __get_user_asm(x,ptr,retval,"move.d"); break; \ - case 8: __get_user_asm_64(x,ptr,retval); break; \ - default: (x) = __get_user_bad(); \ - } \ +#define __get_user_size(x, ptr, size, retval) \ +do { \ + retval = 0; \ + switch (size) { \ + case 1: __get_user_asm(x, ptr, retval, "move.b"); break; \ + case 2: __get_user_asm(x, ptr, retval, "move.w"); break; \ + case 4: __get_user_asm(x, ptr, retval, "move.d"); break; \ + case 8: __get_user_asm_64(x, ptr, retval); break; \ + default: (x) = __get_user_bad(); \ + } \ } while (0) -#define __put_user_nocheck(x,ptr,size) \ +#define __put_user_nocheck(x, ptr, size) \ ({ \ long __pu_err; \ - __put_user_size((x),(ptr),(size),__pu_err); \ + __put_user_size((x), (ptr), (size), __pu_err); \ __pu_err; \ }) -#define __put_user_check(x,ptr,size) \ -({ \ - long __pu_err = -EFAULT; \ - __typeof__(*(ptr)) *__pu_addr = (ptr); \ - if (access_ok(VERIFY_WRITE,__pu_addr,size)) \ - __put_user_size((x),__pu_addr,(size),__pu_err); \ - __pu_err; \ +#define __put_user_check(x, ptr, size) \ +({ \ + long __pu_err = -EFAULT; \ + __typeof__(*(ptr)) *__pu_addr = (ptr); \ + if (access_ok(VERIFY_WRITE, __pu_addr, size)) \ + __put_user_size((x), __pu_addr, (size), __pu_err); \ + __pu_err; \ }) struct __large_struct { unsigned long buf[100]; }; @@ -149,20 +150,20 @@ struct __large_struct { unsigned long buf[100]; }; -#define __get_user_nocheck(x,ptr,size) \ +#define __get_user_nocheck(x, ptr, size) \ ({ \ long __gu_err, __gu_val; \ - __get_user_size(__gu_val,(ptr),(size),__gu_err); \ + __get_user_size(__gu_val, (ptr), (size), __gu_err); \ (x) = (__force __typeof__(*(ptr)))__gu_val; \ __gu_err; \ }) -#define __get_user_check(x,ptr,size) \ +#define __get_user_check(x, ptr, size) \ ({ \ long __gu_err = -EFAULT, __gu_val = 0; \ const __typeof__(*(ptr)) *__gu_addr = (ptr); \ - if (access_ok(VERIFY_READ,__gu_addr,size)) \ - __get_user_size(__gu_val,__gu_addr,(size),__gu_err); \ + if (access_ok(VERIFY_READ, __gu_addr, size)) \ + __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ (x) = (__force __typeof__(*(ptr)))__gu_val; \ __gu_err; \ }) @@ -180,7 +181,7 @@ static inline unsigned long __generic_copy_to_user(void __user *to, const void *from, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) - return __copy_user(to,from,n); + return __copy_user(to, from, n); return n; } @@ -188,7 +189,7 @@ static inline unsigned long __generic_copy_from_user(void *to, const void __user *from, unsigned long n) { if (access_ok(VERIFY_READ, from, n)) - return __copy_user_zeroing(to,from,n); + return __copy_user_zeroing(to, from, n); return n; } @@ -196,7 +197,7 @@ static inline unsigned long __generic_clear_user(void __user *to, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) - return __do_clear_user(to,n); + return __do_clear_user(to, n); return n; } @@ -373,29 +374,31 @@ static inline unsigned long __generic_copy_from_user_nocheck(void *to, const void __user *from, unsigned long n) { - return __copy_user_zeroing(to,from,n); + return __copy_user_zeroing(to, from, n); } static inline unsigned long __generic_copy_to_user_nocheck(void __user *to, const void *from, unsigned long n) { - return __copy_user(to,from,n); + return __copy_user(to, from, n); } static inline unsigned long __generic_clear_user_nocheck(void __user *to, unsigned long n) { - return __do_clear_user(to,n); + return __do_clear_user(to, n); } /* without checking */ -#define __copy_to_user(to,from,n) __generic_copy_to_user_nocheck((to),(from),(n)) -#define __copy_from_user(to,from,n) __generic_copy_from_user_nocheck((to),(from),(n)) +#define __copy_to_user(to, from, n) \ + __generic_copy_to_user_nocheck((to), (from), (n)) +#define __copy_from_user(to, from, n) \ + __generic_copy_from_user_nocheck((to), (from), (n)) #define __copy_to_user_inatomic __copy_to_user #define __copy_from_user_inatomic __copy_from_user -#define __clear_user(to,n) __generic_clear_user_nocheck((to),(n)) +#define __clear_user(to, n) __generic_clear_user_nocheck((to), (n)) #define strlen_user(str) strnlen_user((str), 0x7ffffffe) -- cgit v1.2.3 From fc0ca0ee509f54530a1a90d48519dedb55adbeae Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 15:11:13 +0200 Subject: frv: macro whitespace fixes While working on arch/frv/include/asm/uaccess.h, I noticed that one macro within this header is made harder to read because it violates a coding style rule: space is missing after comma. Fix it up. Signed-off-by: Michael S. Tsirkin --- arch/frv/include/asm/segment.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/frv/include/asm/segment.h b/arch/frv/include/asm/segment.h index a2320a4a0042..4377c89a57f5 100644 --- a/arch/frv/include/asm/segment.h +++ b/arch/frv/include/asm/segment.h @@ -31,7 +31,7 @@ typedef struct { #define get_ds() (KERNEL_DS) #define get_fs() (__current_thread_info->addr_limit) -#define segment_eq(a,b) ((a).seg == (b).seg) +#define segment_eq(a, b) ((a).seg == (b).seg) #define __kernel_ds_p() segment_eq(get_fs(), KERNEL_DS) #define get_addr_limit() (get_fs().seg) -- cgit v1.2.3 From 0ab066042dea23fe03d2eabc9dc5771dab4e81d4 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 15:11:13 +0200 Subject: m32r: macro whitespace fixes While working on arch/m32r/include/asm/uaccess.h, I noticed that some macros within this header are made harder to read because they violate a coding style rule: space is missing after comma. Fix it up. Signed-off-by: Michael S. Tsirkin --- arch/m32r/include/asm/uaccess.h | 84 ++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 42 deletions(-) (limited to 'arch') diff --git a/arch/m32r/include/asm/uaccess.h b/arch/m32r/include/asm/uaccess.h index d076942a7b2b..71adff209405 100644 --- a/arch/m32r/include/asm/uaccess.h +++ b/arch/m32r/include/asm/uaccess.h @@ -54,7 +54,7 @@ static inline void set_fs(mm_segment_t s) #endif /* not CONFIG_MMU */ -#define segment_eq(a,b) ((a).seg == (b).seg) +#define segment_eq(a, b) ((a).seg == (b).seg) #define __addr_ok(addr) \ ((unsigned long)(addr) < (current_thread_info()->addr_limit.seg)) @@ -68,7 +68,7 @@ static inline void set_fs(mm_segment_t s) * * This needs 33-bit arithmetic. We have a carry... */ -#define __range_ok(addr,size) ({ \ +#define __range_ok(addr, size) ({ \ unsigned long flag, roksum; \ __chk_user_ptr(addr); \ asm ( \ @@ -103,7 +103,7 @@ static inline void set_fs(mm_segment_t s) * this function, memory access functions may still return -EFAULT. */ #ifdef CONFIG_MMU -#define access_ok(type,addr,size) (likely(__range_ok(addr,size) == 0)) +#define access_ok(type, addr, size) (likely(__range_ok(addr, size) == 0)) #else static inline int access_ok(int type, const void *addr, unsigned long size) { @@ -167,8 +167,8 @@ extern int fixup_exception(struct pt_regs *regs); * Returns zero on success, or -EFAULT on error. * On error, the variable @x is set to zero. */ -#define get_user(x,ptr) \ - __get_user_check((x),(ptr),sizeof(*(ptr))) +#define get_user(x, ptr) \ + __get_user_check((x), (ptr), sizeof(*(ptr))) /** * put_user: - Write a simple value into user space. @@ -186,8 +186,8 @@ extern int fixup_exception(struct pt_regs *regs); * * Returns zero on success, or -EFAULT on error. */ -#define put_user(x,ptr) \ - __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) +#define put_user(x, ptr) \ + __put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) /** * __get_user: - Get a simple variable from user space, with less checking. @@ -209,41 +209,41 @@ extern int fixup_exception(struct pt_regs *regs); * Returns zero on success, or -EFAULT on error. * On error, the variable @x is set to zero. */ -#define __get_user(x,ptr) \ - __get_user_nocheck((x),(ptr),sizeof(*(ptr))) +#define __get_user(x, ptr) \ + __get_user_nocheck((x), (ptr), sizeof(*(ptr))) -#define __get_user_nocheck(x,ptr,size) \ +#define __get_user_nocheck(x, ptr, size) \ ({ \ long __gu_err = 0; \ unsigned long __gu_val; \ might_fault(); \ - __get_user_size(__gu_val,(ptr),(size),__gu_err); \ + __get_user_size(__gu_val, (ptr), (size), __gu_err); \ (x) = (__force __typeof__(*(ptr)))__gu_val; \ __gu_err; \ }) -#define __get_user_check(x,ptr,size) \ +#define __get_user_check(x, ptr, size) \ ({ \ long __gu_err = -EFAULT; \ unsigned long __gu_val = 0; \ const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ might_fault(); \ - if (access_ok(VERIFY_READ,__gu_addr,size)) \ - __get_user_size(__gu_val,__gu_addr,(size),__gu_err); \ + if (access_ok(VERIFY_READ, __gu_addr, size)) \ + __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ (x) = (__force __typeof__(*(ptr)))__gu_val; \ __gu_err; \ }) extern long __get_user_bad(void); -#define __get_user_size(x,ptr,size,retval) \ +#define __get_user_size(x, ptr, size, retval) \ do { \ retval = 0; \ __chk_user_ptr(ptr); \ switch (size) { \ - case 1: __get_user_asm(x,ptr,retval,"ub"); break; \ - case 2: __get_user_asm(x,ptr,retval,"uh"); break; \ - case 4: __get_user_asm(x,ptr,retval,""); break; \ + case 1: __get_user_asm(x, ptr, retval, "ub"); break; \ + case 2: __get_user_asm(x, ptr, retval, "uh"); break; \ + case 4: __get_user_asm(x, ptr, retval, ""); break; \ default: (x) = __get_user_bad(); \ } \ } while (0) @@ -288,26 +288,26 @@ do { \ * * Returns zero on success, or -EFAULT on error. */ -#define __put_user(x,ptr) \ - __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) +#define __put_user(x, ptr) \ + __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) -#define __put_user_nocheck(x,ptr,size) \ +#define __put_user_nocheck(x, ptr, size) \ ({ \ long __pu_err; \ might_fault(); \ - __put_user_size((x),(ptr),(size),__pu_err); \ + __put_user_size((x), (ptr), (size), __pu_err); \ __pu_err; \ }) -#define __put_user_check(x,ptr,size) \ +#define __put_user_check(x, ptr, size) \ ({ \ long __pu_err = -EFAULT; \ __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ might_fault(); \ - if (access_ok(VERIFY_WRITE,__pu_addr,size)) \ - __put_user_size((x),__pu_addr,(size),__pu_err); \ + if (access_ok(VERIFY_WRITE, __pu_addr, size)) \ + __put_user_size((x), __pu_addr, (size), __pu_err); \ __pu_err; \ }) @@ -366,15 +366,15 @@ do { \ extern void __put_user_bad(void); -#define __put_user_size(x,ptr,size,retval) \ +#define __put_user_size(x, ptr, size, retval) \ do { \ retval = 0; \ __chk_user_ptr(ptr); \ switch (size) { \ - case 1: __put_user_asm(x,ptr,retval,"b"); break; \ - case 2: __put_user_asm(x,ptr,retval,"h"); break; \ - case 4: __put_user_asm(x,ptr,retval,""); break; \ - case 8: __put_user_u64((__typeof__(*ptr))(x),ptr,retval); break;\ + case 1: __put_user_asm(x, ptr, retval, "b"); break; \ + case 2: __put_user_asm(x, ptr, retval, "h"); break; \ + case 4: __put_user_asm(x, ptr, retval, ""); break; \ + case 8: __put_user_u64((__typeof__(*ptr))(x), ptr, retval); break;\ default: __put_user_bad(); \ } \ } while (0) @@ -421,7 +421,7 @@ struct __large_struct { unsigned long buf[100]; }; /* Generic arbitrary sized copy. */ /* Return the number of bytes NOT copied. */ -#define __copy_user(to,from,size) \ +#define __copy_user(to, from, size) \ do { \ unsigned long __dst, __src, __c; \ __asm__ __volatile__ ( \ @@ -478,7 +478,7 @@ do { \ : "r14", "memory"); \ } while (0) -#define __copy_user_zeroing(to,from,size) \ +#define __copy_user_zeroing(to, from, size) \ do { \ unsigned long __dst, __src, __c; \ __asm__ __volatile__ ( \ @@ -548,14 +548,14 @@ do { \ static inline unsigned long __generic_copy_from_user_nocheck(void *to, const void __user *from, unsigned long n) { - __copy_user_zeroing(to,from,n); + __copy_user_zeroing(to, from, n); return n; } static inline unsigned long __generic_copy_to_user_nocheck(void __user *to, const void *from, unsigned long n) { - __copy_user(to,from,n); + __copy_user(to, from, n); return n; } @@ -576,8 +576,8 @@ unsigned long __generic_copy_from_user(void *, const void __user *, unsigned lon * Returns number of bytes that could not be copied. * On success, this will be zero. */ -#define __copy_to_user(to,from,n) \ - __generic_copy_to_user_nocheck((to),(from),(n)) +#define __copy_to_user(to, from, n) \ + __generic_copy_to_user_nocheck((to), (from), (n)) #define __copy_to_user_inatomic __copy_to_user #define __copy_from_user_inatomic __copy_from_user @@ -595,10 +595,10 @@ unsigned long __generic_copy_from_user(void *, const void __user *, unsigned lon * Returns number of bytes that could not be copied. * On success, this will be zero. */ -#define copy_to_user(to,from,n) \ +#define copy_to_user(to, from, n) \ ({ \ might_fault(); \ - __generic_copy_to_user((to),(from),(n)); \ + __generic_copy_to_user((to), (from), (n)); \ }) /** @@ -617,8 +617,8 @@ unsigned long __generic_copy_from_user(void *, const void __user *, unsigned lon * If some data could not be copied, this function will pad the copied * data to the requested size using zero bytes. */ -#define __copy_from_user(to,from,n) \ - __generic_copy_from_user_nocheck((to),(from),(n)) +#define __copy_from_user(to, from, n) \ + __generic_copy_from_user_nocheck((to), (from), (n)) /** * copy_from_user: - Copy a block of data from user space. @@ -636,10 +636,10 @@ unsigned long __generic_copy_from_user(void *, const void __user *, unsigned lon * If some data could not be copied, this function will pad the copied * data to the requested size using zero bytes. */ -#define copy_from_user(to,from,n) \ +#define copy_from_user(to, from, n) \ ({ \ might_fault(); \ - __generic_copy_from_user((to),(from),(n)); \ + __generic_copy_from_user((to), (from), (n)); \ }) long __must_check strncpy_from_user(char *dst, const char __user *src, -- cgit v1.2.3 From e9e6d91855debc35397f35f6070d6574b47a71f6 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 15:11:13 +0200 Subject: m68k: macro whitespace fixes While working on arch/m68k/include/asm/uaccess.h, I noticed that one macro within this header is made harder to read because it violates a coding style rule: space is missing after comma. Fix it up. Signed-off-by: Michael S. Tsirkin Acked-by: Geert Uytterhoeven --- arch/m68k/include/asm/segment.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/m68k/include/asm/segment.h b/arch/m68k/include/asm/segment.h index 0fa80e97ed2d..98216b8111f0 100644 --- a/arch/m68k/include/asm/segment.h +++ b/arch/m68k/include/asm/segment.h @@ -58,7 +58,7 @@ static inline mm_segment_t get_ds(void) #define set_fs(x) (current_thread_info()->addr_limit = (x)) #endif -#define segment_eq(a,b) ((a).seg == (b).seg) +#define segment_eq(a, b) ((a).seg == (b).seg) #endif /* __ASSEMBLY__ */ -- cgit v1.2.3 From 0e8a2eb02fda7b0c55c3ff5144590a8a79f47e33 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 15:11:13 +0200 Subject: parisc: macro whitespace fixes While working on arch/parisc/include/asm/uaccess.h, I noticed that some macros within this header are made harder to read because they violate a coding style rule: space is missing after comma. Fix it up. Signed-off-by: Michael S. Tsirkin --- arch/parisc/include/asm/uaccess.h | 116 +++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 58 deletions(-) (limited to 'arch') diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h index 6c79311acdaf..0abdd4c607ed 100644 --- a/arch/parisc/include/asm/uaccess.h +++ b/arch/parisc/include/asm/uaccess.h @@ -17,7 +17,7 @@ #define KERNEL_DS ((mm_segment_t){0}) #define USER_DS ((mm_segment_t){1}) -#define segment_eq(a,b) ((a).seg == (b).seg) +#define segment_eq(a, b) ((a).seg == (b).seg) #define get_ds() (KERNEL_DS) #define get_fs() (current_thread_info()->addr_limit) @@ -42,14 +42,14 @@ static inline long access_ok(int type, const void __user * addr, #if !defined(CONFIG_64BIT) #define LDD_KERNEL(ptr) BUILD_BUG() #define LDD_USER(ptr) BUILD_BUG() -#define STD_KERNEL(x, ptr) __put_kernel_asm64(x,ptr) -#define STD_USER(x, ptr) __put_user_asm64(x,ptr) +#define STD_KERNEL(x, ptr) __put_kernel_asm64(x, ptr) +#define STD_USER(x, ptr) __put_user_asm64(x, ptr) #define ASM_WORD_INSN ".word\t" #else -#define LDD_KERNEL(ptr) __get_kernel_asm("ldd",ptr) -#define LDD_USER(ptr) __get_user_asm("ldd",ptr) -#define STD_KERNEL(x, ptr) __put_kernel_asm("std",x,ptr) -#define STD_USER(x, ptr) __put_user_asm("std",x,ptr) +#define LDD_KERNEL(ptr) __get_kernel_asm("ldd", ptr) +#define LDD_USER(ptr) __get_user_asm("ldd", ptr) +#define STD_KERNEL(x, ptr) __put_kernel_asm("std", x, ptr) +#define STD_USER(x, ptr) __put_user_asm("std", x, ptr) #define ASM_WORD_INSN ".dword\t" #endif @@ -80,68 +80,68 @@ struct exception_data { unsigned long fault_addr; }; -#define __get_user(x,ptr) \ -({ \ - register long __gu_err __asm__ ("r8") = 0; \ - register long __gu_val __asm__ ("r9") = 0; \ - \ - if (segment_eq(get_fs(),KERNEL_DS)) { \ - switch (sizeof(*(ptr))) { \ - case 1: __get_kernel_asm("ldb",ptr); break; \ - case 2: __get_kernel_asm("ldh",ptr); break; \ - case 4: __get_kernel_asm("ldw",ptr); break; \ - case 8: LDD_KERNEL(ptr); break; \ - default: BUILD_BUG(); break; \ - } \ - } \ - else { \ - switch (sizeof(*(ptr))) { \ - case 1: __get_user_asm("ldb",ptr); break; \ - case 2: __get_user_asm("ldh",ptr); break; \ - case 4: __get_user_asm("ldw",ptr); break; \ - case 8: LDD_USER(ptr); break; \ - default: BUILD_BUG(); break; \ - } \ - } \ - \ - (x) = (__force __typeof__(*(ptr))) __gu_val; \ - __gu_err; \ +#define __get_user(x, ptr) \ +({ \ + register long __gu_err __asm__ ("r8") = 0; \ + register long __gu_val __asm__ ("r9") = 0; \ + \ + if (segment_eq(get_fs(), KERNEL_DS)) { \ + switch (sizeof(*(ptr))) { \ + case 1: __get_kernel_asm("ldb", ptr); break; \ + case 2: __get_kernel_asm("ldh", ptr); break; \ + case 4: __get_kernel_asm("ldw", ptr); break; \ + case 8: LDD_KERNEL(ptr); break; \ + default: BUILD_BUG(); break; \ + } \ + } \ + else { \ + switch (sizeof(*(ptr))) { \ + case 1: __get_user_asm("ldb", ptr); break; \ + case 2: __get_user_asm("ldh", ptr); break; \ + case 4: __get_user_asm("ldw", ptr); break; \ + case 8: LDD_USER(ptr); break; \ + default: BUILD_BUG(); break; \ + } \ + } \ + \ + (x) = (__force __typeof__(*(ptr))) __gu_val; \ + __gu_err; \ }) -#define __get_kernel_asm(ldx,ptr) \ +#define __get_kernel_asm(ldx, ptr) \ __asm__("\n1:\t" ldx "\t0(%2),%0\n\t" \ ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_get_user_skip_1)\ : "=r"(__gu_val), "=r"(__gu_err) \ : "r"(ptr), "1"(__gu_err) \ : "r1"); -#define __get_user_asm(ldx,ptr) \ +#define __get_user_asm(ldx, ptr) \ __asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n\t" \ - ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_get_user_skip_1)\ + ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_get_user_skip_1)\ : "=r"(__gu_val), "=r"(__gu_err) \ : "r"(ptr), "1"(__gu_err) \ : "r1"); -#define __put_user(x,ptr) \ +#define __put_user(x, ptr) \ ({ \ register long __pu_err __asm__ ("r8") = 0; \ __typeof__(*(ptr)) __x = (__typeof__(*(ptr)))(x); \ \ - if (segment_eq(get_fs(),KERNEL_DS)) { \ + if (segment_eq(get_fs(), KERNEL_DS)) { \ switch (sizeof(*(ptr))) { \ - case 1: __put_kernel_asm("stb",__x,ptr); break; \ - case 2: __put_kernel_asm("sth",__x,ptr); break; \ - case 4: __put_kernel_asm("stw",__x,ptr); break; \ - case 8: STD_KERNEL(__x,ptr); break; \ + case 1: __put_kernel_asm("stb", __x, ptr); break; \ + case 2: __put_kernel_asm("sth", __x, ptr); break; \ + case 4: __put_kernel_asm("stw", __x, ptr); break; \ + case 8: STD_KERNEL(__x, ptr); break; \ default: BUILD_BUG(); break; \ } \ } \ else { \ switch (sizeof(*(ptr))) { \ - case 1: __put_user_asm("stb",__x,ptr); break; \ - case 2: __put_user_asm("sth",__x,ptr); break; \ - case 4: __put_user_asm("stw",__x,ptr); break; \ - case 8: STD_USER(__x,ptr); break; \ + case 1: __put_user_asm("stb", __x, ptr); break; \ + case 2: __put_user_asm("sth", __x, ptr); break; \ + case 4: __put_user_asm("stw", __x, ptr); break; \ + case 8: STD_USER(__x, ptr); break; \ default: BUILD_BUG(); break; \ } \ } \ @@ -159,18 +159,18 @@ struct exception_data { * r8/r9 are already listed as err/val. */ -#define __put_kernel_asm(stx,x,ptr) \ +#define __put_kernel_asm(stx, x, ptr) \ __asm__ __volatile__ ( \ "\n1:\t" stx "\t%2,0(%1)\n\t" \ - ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_1)\ + ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_put_user_skip_1)\ : "=r"(__pu_err) \ : "r"(ptr), "r"(x), "0"(__pu_err) \ : "r1") -#define __put_user_asm(stx,x,ptr) \ +#define __put_user_asm(stx, x, ptr) \ __asm__ __volatile__ ( \ "\n1:\t" stx "\t%2,0(%%sr3,%1)\n\t" \ - ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_1)\ + ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_put_user_skip_1)\ : "=r"(__pu_err) \ : "r"(ptr), "r"(x), "0"(__pu_err) \ : "r1") @@ -178,23 +178,23 @@ struct exception_data { #if !defined(CONFIG_64BIT) -#define __put_kernel_asm64(__val,ptr) do { \ +#define __put_kernel_asm64(__val, ptr) do { \ __asm__ __volatile__ ( \ "\n1:\tstw %2,0(%1)" \ "\n2:\tstw %R2,4(%1)\n\t" \ - ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_2)\ - ASM_EXCEPTIONTABLE_ENTRY(2b,fixup_put_user_skip_1)\ + ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_put_user_skip_2)\ + ASM_EXCEPTIONTABLE_ENTRY(2b, fixup_put_user_skip_1)\ : "=r"(__pu_err) \ : "r"(ptr), "r"(__val), "0"(__pu_err) \ : "r1"); \ } while (0) -#define __put_user_asm64(__val,ptr) do { \ +#define __put_user_asm64(__val, ptr) do { \ __asm__ __volatile__ ( \ "\n1:\tstw %2,0(%%sr3,%1)" \ "\n2:\tstw %R2,4(%%sr3,%1)\n\t" \ - ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_2)\ - ASM_EXCEPTIONTABLE_ENTRY(2b,fixup_put_user_skip_1)\ + ASM_EXCEPTIONTABLE_ENTRY(1b, fixup_put_user_skip_2)\ + ASM_EXCEPTIONTABLE_ENTRY(2b, fixup_put_user_skip_1)\ : "=r"(__pu_err) \ : "r"(ptr), "r"(__val), "0"(__pu_err) \ : "r1"); \ @@ -211,8 +211,8 @@ extern unsigned long lcopy_to_user(void __user *, const void *, unsigned long); extern unsigned long lcopy_from_user(void *, const void __user *, unsigned long); extern unsigned long lcopy_in_user(void __user *, const void __user *, unsigned long); extern long strncpy_from_user(char *, const char __user *, long); -extern unsigned lclear_user(void __user *,unsigned long); -extern long lstrnlen_user(const char __user *,long); +extern unsigned lclear_user(void __user *, unsigned long); +extern long lstrnlen_user(const char __user *, long); /* * Complex access routines -- macros */ -- cgit v1.2.3 From 3237f28e6ce3318431d6f66271a35f5eca4e6439 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 15:11:13 +0200 Subject: sh: macro whitespace fixes While working on arch/sh/include/asm/uaccess.h, I noticed that one macro within this header is made harder to read because it violates a coding style rule: space is missing after comma. Fix it up. Signed-off-by: Michael S. Tsirkin --- arch/sh/include/asm/segment.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/sh/include/asm/segment.h b/arch/sh/include/asm/segment.h index 5e2725f4ac49..ff795d3a6909 100644 --- a/arch/sh/include/asm/segment.h +++ b/arch/sh/include/asm/segment.h @@ -23,7 +23,7 @@ typedef struct { #define USER_DS KERNEL_DS #endif -#define segment_eq(a,b) ((a).seg == (b).seg) +#define segment_eq(a, b) ((a).seg == (b).seg) #define get_ds() (KERNEL_DS) -- cgit v1.2.3 From 33a3dcc2289368c2fc022c3b0b9bc388c8aa5930 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 15:11:13 +0200 Subject: xtensa: macro whitespace fixes While working on arch/xtensa/include/asm/uaccess.h, I noticed that some macros within this header are made harder to read because they violate a coding style rule: space is missing after comma. Fix it up. Signed-off-by: Michael S. Tsirkin Acked-by: Max Filippov --- arch/xtensa/include/asm/uaccess.h | 90 +++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 45 deletions(-) (limited to 'arch') diff --git a/arch/xtensa/include/asm/uaccess.h b/arch/xtensa/include/asm/uaccess.h index 876eb380aa26..147b26ed9c91 100644 --- a/arch/xtensa/include/asm/uaccess.h +++ b/arch/xtensa/include/asm/uaccess.h @@ -182,13 +182,13 @@ #define get_fs() (current->thread.current_ds) #define set_fs(val) (current->thread.current_ds = (val)) -#define segment_eq(a,b) ((a).seg == (b).seg) +#define segment_eq(a, b) ((a).seg == (b).seg) #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS)) -#define __user_ok(addr,size) \ +#define __user_ok(addr, size) \ (((size) <= TASK_SIZE)&&((addr) <= TASK_SIZE-(size))) -#define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size))) -#define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size)) +#define __access_ok(addr, size) (__kernel_ok || __user_ok((addr), (size))) +#define access_ok(type, addr, size) __access_ok((unsigned long)(addr), (size)) /* * These are the main single-value transfer routines. They @@ -204,8 +204,8 @@ * (a) re-use the arguments for side effects (sizeof is ok) * (b) require any knowledge of processes at this stage */ -#define put_user(x,ptr) __put_user_check((x),(ptr),sizeof(*(ptr))) -#define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr))) +#define put_user(x, ptr) __put_user_check((x), (ptr), sizeof(*(ptr))) +#define get_user(x, ptr) __get_user_check((x), (ptr), sizeof(*(ptr))) /* * The "__xxx" versions of the user access functions are versions that @@ -213,39 +213,39 @@ * with a separate "access_ok()" call (this is used when we do multiple * accesses to the same area of user memory). */ -#define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr))) -#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr))) +#define __put_user(x, ptr) __put_user_nocheck((x), (ptr), sizeof(*(ptr))) +#define __get_user(x, ptr) __get_user_nocheck((x), (ptr), sizeof(*(ptr))) extern long __put_user_bad(void); -#define __put_user_nocheck(x,ptr,size) \ +#define __put_user_nocheck(x, ptr, size) \ ({ \ long __pu_err; \ - __put_user_size((x),(ptr),(size),__pu_err); \ + __put_user_size((x), (ptr), (size), __pu_err); \ __pu_err; \ }) -#define __put_user_check(x,ptr,size) \ -({ \ - long __pu_err = -EFAULT; \ - __typeof__(*(ptr)) *__pu_addr = (ptr); \ - if (access_ok(VERIFY_WRITE,__pu_addr,size)) \ - __put_user_size((x),__pu_addr,(size),__pu_err); \ - __pu_err; \ +#define __put_user_check(x, ptr, size) \ +({ \ + long __pu_err = -EFAULT; \ + __typeof__(*(ptr)) *__pu_addr = (ptr); \ + if (access_ok(VERIFY_WRITE, __pu_addr, size)) \ + __put_user_size((x), __pu_addr, (size), __pu_err); \ + __pu_err; \ }) -#define __put_user_size(x,ptr,size,retval) \ +#define __put_user_size(x, ptr, size, retval) \ do { \ int __cb; \ retval = 0; \ switch (size) { \ - case 1: __put_user_asm(x,ptr,retval,1,"s8i",__cb); break; \ - case 2: __put_user_asm(x,ptr,retval,2,"s16i",__cb); break; \ - case 4: __put_user_asm(x,ptr,retval,4,"s32i",__cb); break; \ + case 1: __put_user_asm(x, ptr, retval, 1, "s8i", __cb); break; \ + case 2: __put_user_asm(x, ptr, retval, 2, "s16i", __cb); break; \ + case 4: __put_user_asm(x, ptr, retval, 4, "s32i", __cb); break; \ case 8: { \ __typeof__(*ptr) __v64 = x; \ - retval = __copy_to_user(ptr,&__v64,8); \ + retval = __copy_to_user(ptr, &__v64, 8); \ break; \ } \ default: __put_user_bad(); \ @@ -316,35 +316,35 @@ __asm__ __volatile__( \ :"=r" (err), "=r" (cb) \ :"r" ((int)(x)), "r" (addr), "i" (-EFAULT), "0" (err)) -#define __get_user_nocheck(x,ptr,size) \ +#define __get_user_nocheck(x, ptr, size) \ ({ \ long __gu_err, __gu_val; \ - __get_user_size(__gu_val,(ptr),(size),__gu_err); \ - (x) = (__force __typeof__(*(ptr)))__gu_val; \ + __get_user_size(__gu_val, (ptr), (size), __gu_err); \ + (x) = (__force __typeof__(*(ptr)))__gu_val; \ __gu_err; \ }) -#define __get_user_check(x,ptr,size) \ +#define __get_user_check(x, ptr, size) \ ({ \ long __gu_err = -EFAULT, __gu_val = 0; \ const __typeof__(*(ptr)) *__gu_addr = (ptr); \ - if (access_ok(VERIFY_READ,__gu_addr,size)) \ - __get_user_size(__gu_val,__gu_addr,(size),__gu_err); \ - (x) = (__force __typeof__(*(ptr)))__gu_val; \ + if (access_ok(VERIFY_READ, __gu_addr, size)) \ + __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ + (x) = (__force __typeof__(*(ptr)))__gu_val; \ __gu_err; \ }) extern long __get_user_bad(void); -#define __get_user_size(x,ptr,size,retval) \ +#define __get_user_size(x, ptr, size, retval) \ do { \ int __cb; \ retval = 0; \ switch (size) { \ - case 1: __get_user_asm(x,ptr,retval,1,"l8ui",__cb); break; \ - case 2: __get_user_asm(x,ptr,retval,2,"l16ui",__cb); break; \ - case 4: __get_user_asm(x,ptr,retval,4,"l32i",__cb); break; \ - case 8: retval = __copy_from_user(&x,ptr,8); break; \ + case 1: __get_user_asm(x, ptr, retval, 1, "l8ui", __cb); break;\ + case 2: __get_user_asm(x, ptr, retval, 2, "l16ui", __cb); break;\ + case 4: __get_user_asm(x, ptr, retval, 4, "l32i", __cb); break;\ + case 8: retval = __copy_from_user(&x, ptr, 8); break; \ default: (x) = __get_user_bad(); \ } \ } while (0) @@ -390,19 +390,19 @@ __asm__ __volatile__( \ */ extern unsigned __xtensa_copy_user(void *to, const void *from, unsigned n); -#define __copy_user(to,from,size) __xtensa_copy_user(to,from,size) +#define __copy_user(to, from, size) __xtensa_copy_user(to, from, size) static inline unsigned long __generic_copy_from_user_nocheck(void *to, const void *from, unsigned long n) { - return __copy_user(to,from,n); + return __copy_user(to, from, n); } static inline unsigned long __generic_copy_to_user_nocheck(void *to, const void *from, unsigned long n) { - return __copy_user(to,from,n); + return __copy_user(to, from, n); } static inline unsigned long @@ -410,7 +410,7 @@ __generic_copy_to_user(void *to, const void *from, unsigned long n) { prefetch(from); if (access_ok(VERIFY_WRITE, to, n)) - return __copy_user(to,from,n); + return __copy_user(to, from, n); return n; } @@ -419,18 +419,18 @@ __generic_copy_from_user(void *to, const void *from, unsigned long n) { prefetchw(to); if (access_ok(VERIFY_READ, from, n)) - return __copy_user(to,from,n); + return __copy_user(to, from, n); else memset(to, 0, n); return n; } -#define copy_to_user(to,from,n) __generic_copy_to_user((to),(from),(n)) -#define copy_from_user(to,from,n) __generic_copy_from_user((to),(from),(n)) -#define __copy_to_user(to,from,n) \ - __generic_copy_to_user_nocheck((to),(from),(n)) -#define __copy_from_user(to,from,n) \ - __generic_copy_from_user_nocheck((to),(from),(n)) +#define copy_to_user(to, from, n) __generic_copy_to_user((to), (from), (n)) +#define copy_from_user(to, from, n) __generic_copy_from_user((to), (from), (n)) +#define __copy_to_user(to, from, n) \ + __generic_copy_to_user_nocheck((to), (from), (n)) +#define __copy_from_user(to, from, n) \ + __generic_copy_from_user_nocheck((to), (from), (n)) #define __copy_to_user_inatomic __copy_to_user #define __copy_from_user_inatomic __copy_from_user -- cgit v1.2.3 From 4b636ba27008ce11631c89b4e0918800204575e0 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 23:29:43 +0200 Subject: sparc64: nocheck uaccess coding style tweaks Sam Ravnborg suggested packing single-lines cases in switch statements in nocheck uaccess macros makes for easier to read code. Suggested-by: Sam Ravnborg Signed-off-by: Michael S. Tsirkin Acked-by: Sam Ravnborg --- arch/sparc/include/asm/uaccess_64.h | 100 +++++++++++++----------------------- 1 file changed, 37 insertions(+), 63 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/uaccess_64.h b/arch/sparc/include/asm/uaccess_64.h index 12d95947636b..a35194b7dba0 100644 --- a/arch/sparc/include/asm/uaccess_64.h +++ b/arch/sparc/include/asm/uaccess_64.h @@ -106,26 +106,16 @@ void __retl_efault(void); struct __large_struct { unsigned long buf[100]; }; #define __m(x) ((struct __large_struct *)(x)) -#define __put_user_nocheck(data, addr, size) ({ \ - register int __pu_ret; \ - switch (size) { \ - case 1: \ - __put_user_asm(data, b, addr, __pu_ret); \ - break; \ - case 2: \ - __put_user_asm(data, h, addr, __pu_ret); \ - break; \ - case 4: \ - __put_user_asm(data, w, addr, __pu_ret); \ - break; \ - case 8: \ - __put_user_asm(data, x, addr, __pu_ret); \ - break; \ - default: \ - __pu_ret = __put_user_bad(); \ - break; \ - } \ - __pu_ret; \ +#define __put_user_nocheck(data, addr, size) ({ \ + register int __pu_ret; \ + switch (size) { \ + case 1: __put_user_asm(data, b, addr, __pu_ret); break; \ + case 2: __put_user_asm(data, h, addr, __pu_ret); break; \ + case 4: __put_user_asm(data, w, addr, __pu_ret); break; \ + case 8: __put_user_asm(data, x, addr, __pu_ret); break; \ + default: __pu_ret = __put_user_bad(); break; \ + } \ + __pu_ret; \ }) #define __put_user_asm(x, size, addr, ret) \ @@ -150,51 +140,35 @@ __asm__ __volatile__( \ int __put_user_bad(void); -#define __get_user_nocheck(data, addr, size, type) ({ \ - register int __gu_ret; \ - register unsigned long __gu_val; \ - switch (size) { \ - case 1: \ - __get_user_asm(__gu_val, ub, addr, __gu_ret); \ - break; \ - case 2: \ - __get_user_asm(__gu_val, uh, addr, __gu_ret); \ - break; \ - case 4: \ - __get_user_asm(__gu_val, uw, addr, __gu_ret); \ - break; \ - case 8: \ - __get_user_asm(__gu_val, x, addr, __gu_ret); \ - break; \ - default: \ - __gu_val = 0; \ - __gu_ret = __get_user_bad(); \ - break; \ - } \ - data = (__force type) __gu_val; \ - __gu_ret; \ +#define __get_user_nocheck(data, addr, size, type) ({ \ + register int __gu_ret; \ + register unsigned long __gu_val; \ + switch (size) { \ + case 1: __get_user_asm(__gu_val, ub, addr, __gu_ret); break; \ + case 2: __get_user_asm(__gu_val, uh, addr, __gu_ret); break; \ + case 4: __get_user_asm(__gu_val, uw, addr, __gu_ret); break; \ + case 8: __get_user_asm(__gu_val, x, addr, __gu_ret); break; \ + default: \ + __gu_val = 0; \ + __gu_ret = __get_user_bad(); \ + break; \ + } \ + data = (__force type) __gu_val; \ + __gu_ret; \ }) -#define __get_user_nocheck_ret(data, addr, size, type, retval) ({ \ - register unsigned long __gu_val __asm__ ("l1"); \ - switch (size) { \ - case 1: \ - __get_user_asm_ret(__gu_val, ub, addr, retval); \ - break; \ - case 2: \ - __get_user_asm_ret(__gu_val, uh, addr, retval); \ - break; \ - case 4: \ - __get_user_asm_ret(__gu_val, uw, addr, retval); \ - break; \ - case 8: \ - __get_user_asm_ret(__gu_val, x, addr, retval); \ - break; \ - default: \ - if (__get_user_bad()) \ - return retval; \ - } \ - data = (__force type) __gu_val; \ +#define __get_user_nocheck_ret(data, addr, size, type, retval) ({ \ + register unsigned long __gu_val __asm__ ("l1"); \ + switch (size) { \ + case 1: __get_user_asm_ret(__gu_val, ub, addr, retval); break; \ + case 2: __get_user_asm_ret(__gu_val, uh, addr, retval); break; \ + case 4: __get_user_asm_ret(__gu_val, uw, addr, retval); break; \ + case 8: __get_user_asm_ret(__gu_val, x, addr, retval); break; \ + default: \ + if (__get_user_bad()) \ + return retval; \ + } \ + data = (__force type) __gu_val; \ }) #define __get_user_asm(x, size, addr, ret) \ -- cgit v1.2.3 From 0795cb1b46e7938ed679ccd48f933e75272b30e3 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 6 Jan 2015 23:40:11 +0200 Subject: sparc32: nocheck uaccess coding style tweaks Sam Ravnborg suggested packing single-lines cases in switch statements in nocheck uaccess macros makes for easier to read code. Suggested-by: Sam Ravnborg Signed-off-by: Michael S. Tsirkin Acked-by: Sam Ravnborg --- arch/sparc/include/asm/uaccess_32.h | 96 ++++++++++++++----------------------- 1 file changed, 35 insertions(+), 61 deletions(-) (limited to 'arch') diff --git a/arch/sparc/include/asm/uaccess_32.h b/arch/sparc/include/asm/uaccess_32.h index f96656209a78..64ee103dc29d 100644 --- a/arch/sparc/include/asm/uaccess_32.h +++ b/arch/sparc/include/asm/uaccess_32.h @@ -142,24 +142,14 @@ struct __large_struct { unsigned long buf[100]; }; __pu_ret; \ }) -#define __put_user_nocheck(x, addr, size) ({ \ - register int __pu_ret; \ - switch (size) { \ - case 1: \ - __put_user_asm(x, b, addr, __pu_ret); \ - break; \ - case 2: \ - __put_user_asm(x, h, addr, __pu_ret); \ - break; \ - case 4: \ - __put_user_asm(x, , addr, __pu_ret); \ - break; \ - case 8: \ - __put_user_asm(x, d, addr, __pu_ret); \ - break; \ - default: \ - __pu_ret = __put_user_bad(); \ - break; \ +#define __put_user_nocheck(x, addr, size) ({ \ + register int __pu_ret; \ + switch (size) { \ + case 1: __put_user_asm(x, b, addr, __pu_ret); break; \ + case 2: __put_user_asm(x, h, addr, __pu_ret); break; \ + case 4: __put_user_asm(x, , addr, __pu_ret); break; \ + case 8: __put_user_asm(x, d, addr, __pu_ret); break; \ + default: __pu_ret = __put_user_bad(); break; \ } \ __pu_ret; \ }) @@ -240,51 +230,35 @@ int __put_user_bad(void); return retval; \ }) -#define __get_user_nocheck(x, addr, size, type) ({ \ - register int __gu_ret; \ - register unsigned long __gu_val; \ - switch (size) { \ - case 1: \ - __get_user_asm(__gu_val, ub, addr, __gu_ret); \ - break; \ - case 2: \ - __get_user_asm(__gu_val, uh, addr, __gu_ret); \ - break; \ - case 4: \ - __get_user_asm(__gu_val, , addr, __gu_ret); \ - break; \ - case 8: \ - __get_user_asm(__gu_val, d, addr, __gu_ret); \ - break; \ - default: \ - __gu_val = 0; \ - __gu_ret = __get_user_bad(); \ - break; \ - } \ - x = (__force type) __gu_val; \ - __gu_ret; \ +#define __get_user_nocheck(x, addr, size, type) ({ \ + register int __gu_ret; \ + register unsigned long __gu_val; \ + switch (size) { \ + case 1: __get_user_asm(__gu_val, ub, addr, __gu_ret); break; \ + case 2: __get_user_asm(__gu_val, uh, addr, __gu_ret); break; \ + case 4: __get_user_asm(__gu_val, , addr, __gu_ret); break; \ + case 8: __get_user_asm(__gu_val, d, addr, __gu_ret); break; \ + default: \ + __gu_val = 0; \ + __gu_ret = __get_user_bad(); \ + break; \ + } \ + x = (__force type) __gu_val; \ + __gu_ret; \ }) -#define __get_user_nocheck_ret(x, addr, size, type, retval) ({ \ - register unsigned long __gu_val __asm__ ("l1"); \ - switch (size) { \ - case 1: \ - __get_user_asm_ret(__gu_val, ub, addr, retval); \ - break; \ - case 2: \ - __get_user_asm_ret(__gu_val, uh, addr, retval); \ - break; \ - case 4: \ - __get_user_asm_ret(__gu_val, , addr, retval); \ - break; \ - case 8: \ - __get_user_asm_ret(__gu_val, d, addr, retval); \ - break; \ - default: \ - if (__get_user_bad()) \ - return retval; \ - } \ - x = (__force type) __gu_val; \ +#define __get_user_nocheck_ret(x, addr, size, type, retval) ({ \ + register unsigned long __gu_val __asm__ ("l1"); \ + switch (size) { \ + case 1: __get_user_asm_ret(__gu_val, ub, addr, retval); break; \ + case 2: __get_user_asm_ret(__gu_val, uh, addr, retval); break; \ + case 4: __get_user_asm_ret(__gu_val, , addr, retval); break; \ + case 8: __get_user_asm_ret(__gu_val, d, addr, retval); break; \ + default: \ + if (__get_user_bad()) \ + return retval; \ + } \ + x = (__force type) __gu_val; \ }) #define __get_user_asm(x, size, addr, ret) \ -- cgit v1.2.3 From 7d76d03b9be8ea8977df45176336cc4fec6ac603 Mon Sep 17 00:00:00 2001 From: Zhiwu Song Date: Thu, 25 Dec 2014 16:34:19 +0800 Subject: ARM: dts: add init dts file for CSR atlas7 SoC CSR atlas7 uses Network on Chip(NoC) bus architecture, there are dozens of MARCOs, in each MARCO, there are dozens of hardware modules. Signed-off-by: Zhiwu Song Signed-off-by: Hao Liu Signed-off-by: Barry Song Acked-by: Arnd Bergmann --- arch/arm/boot/dts/Makefile | 1 + arch/arm/boot/dts/atlas7-evb.dts | 110 ++++++ arch/arm/boot/dts/atlas7.dtsi | 813 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 924 insertions(+) create mode 100644 arch/arm/boot/dts/atlas7-evb.dts create mode 100644 arch/arm/boot/dts/atlas7.dtsi (limited to 'arch') diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index 68feb8f8b5bc..0048cb16370f 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -52,6 +52,7 @@ dtb-$(CONFIG_ARCH_AT91) += sama5d36ek.dtb dtb-$(CONFIG_ARCH_AT91) += at91-sama5d4ek.dtb dtb-$(CONFIG_ARCH_ATLAS6) += atlas6-evb.dtb +dtb-$(CONFIG_ARCH_ATLAS7) += atlas7-evb.dtb dtb-$(CONFIG_ARCH_AXXIA) += axm5516-amarillo.dtb dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b-plus.dtb diff --git a/arch/arm/boot/dts/atlas7-evb.dts b/arch/arm/boot/dts/atlas7-evb.dts new file mode 100644 index 000000000000..49cf59a95572 --- /dev/null +++ b/arch/arm/boot/dts/atlas7-evb.dts @@ -0,0 +1,110 @@ +/* + * DTS file for CSR SiRFatlas7 Evaluation Board + * + * Copyright (c) 2014 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +/dts-v1/; + +/include/ "atlas7.dtsi" + +/ { + model = "CSR SiRFatlas7 Evaluation Board"; + compatible = "sirf,atlas7-cb", "sirf,atlas7"; + + chosen { + bootargs = "console=ttySiRF1,115200 earlyprintk"; + }; + + memory { + device_type = "memory"; + reg = <0x40000000 0x20000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + vpp_reserved: vpp_mem@5e800000 { + compatible = "sirf,reserved-memory"; + reg = <0x5e800000 0x800000>; + }; + + nanddisk_reserved: nanddisk@46000000 { + reg = <0x46000000 0x200000>; + no-map; + }; + }; + + + noc { + mediam { + nand@17050000 { + memory-region = <&nanddisk_reserved>; + }; + }; + + gnssm { + spi1: spi@18200000 { + status = "okay"; + spiflash: macronix@0{ + status = "okay"; + compatible = "macronix,mx25l6405d"; + reg = <0>; + spi-max-frequency = <37500000>; + spi-cpha; + spi-cpol; + #address-cells = <1>; + #size-cells = <1>; + partitions@0 { + label = "myspiboot"; + reg = <0x0 0x800000>; + }; + }; + }; + }; + + btm { + uart6: uart@11000000 { + status = "okay"; + sirf,uart-has-rtscts; + }; + }; + + disp-iobg { + vpp@13110000 { + memory-region = <&vpp_reserved>; + }; + }; + + display0: display@0 { + compatible = "lvds-panel"; + source = "lvds.0"; + + bl-gpios = <&gpio_1 63 0>; + data-lines = <24>; + + display-timings { + native-mode = <&timing0>; + timing0: timing0 { + clock-frequency = <60000000>; + hactive = <1024>; + vactive = <600>; + hfront-porch = <220>; + hback-porch = <100>; + hsync-len = <1>; + vback-porch = <10>; + vfront-porch = <25>; + vsync-len = <1>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + }; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/atlas7.dtsi b/arch/arm/boot/dts/atlas7.dtsi new file mode 100644 index 000000000000..a753178abc85 --- /dev/null +++ b/arch/arm/boot/dts/atlas7.dtsi @@ -0,0 +1,813 @@ +/* + * DTS file for CSR SiRFatlas7 SoC + * + * Copyright (c) 2014 Cambridge Silicon Radio Limited, a CSR plc group company. + * + * Licensed under GPLv2 or later. + */ + +/include/ "skeleton.dtsi" +/ { + compatible = "sirf,atlas7"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&gic>; + aliases { + serial0 = &uart0; + serial1 = &uart1; + serial2 = &uart2; + serial3 = &uart3; + serial4 = &uart4; + serial5 = &uart5; + serial6 = &uart6; + serial9 = &usp2; + }; + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0>; + }; + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <1>; + }; + }; + + noc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x10000000 0x10000000 0xc0000000>; + + gic: interrupt-controller@10301000 { + compatible = "arm,cortex-a9-gic"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x10301000 0x1000>, + <0x10302000 0x0100>; + }; + + pmu_regulator: pmu_regulator@10E30020 { + compatible = "sirf,atlas7-pmu-ldo"; + reg = <0x10E30020 0x4>; + ldo: ldo { + regulator-name = "ldo"; + }; + }; + + atlas7_codec: atlas7_codec@10E30000 { + #sound-dai-cells = <0>; + compatible = "sirf,atlas7-codec"; + reg = <0x10E30000 0x400>; + clocks = <&car 62>; + ldo-supply = <&ldo>; + }; + + atlas7_iacc: atlas7_iacc@10D01000 { + #sound-dai-cells = <0>; + compatible = "sirf,atlas7-iacc"; + reg = <0x10D01000 0x100>; + dmas = <&dmac3 0>, <&dmac3 7>, <&dmac3 8>, + <&dmac3 3>, <&dmac3 9>; + dma-names = "rx", "tx0", "tx1", "tx2", "tx3"; + clocks = <&car 62>; + }; + + ipc@13240000 { + compatible = "sirf,atlas7-ipc"; + ranges = <0x13240000 0x13240000 0x00010000>; + #address-cells = <1>; + #size-cells = <1>; + + hwspinlock { + compatible = "sirf,hwspinlock"; + reg = <0x13240000 0x00010000>; + + num-spinlocks = <30>; + }; + + ns_m3_rproc@0 { + compatible = "sirf,ns2m30-rproc"; + reg = <0x13240000 0x00010000>; + interrupts = <0 123 0>; + }; + + ns_m3_rproc@1 { + compatible = "sirf,ns2m31-rproc"; + reg = <0x13240000 0x00010000>; + interrupts = <0 126 0>; + }; + + ns_kal_rproc@0 { + compatible = "sirf,ns2kal0-rproc"; + reg = <0x13240000 0x00010000>; + interrupts = <0 124 0>; + }; + + ns_kal_rproc@1 { + compatible = "sirf,ns2kal1-rproc"; + reg = <0x13240000 0x00010000>; + interrupts = <0 127 0>; + }; + }; + + pinctrl: ioc@18880000 { + compatible = "sirf,atlas7-ioc"; + reg = <0x18880000 0x1000>, + <0x10E40000 0x1000>; + }; + + pmipc { + compatible = "arteris, flexnoc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x13240000 0x13240000 0x00010000>; + pmipc@0x13240000 { + compatible = "sirf,atlas7-pmipc"; + reg = <0x13240000 0x00010000>; + }; + }; + + dramfw { + compatible = "arteris, flexnoc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x10830000 0x10830000 0x18000>; + dramfw@10820000 { + compatible = "sirf,nocfw-dramfw"; + reg = <0x10830000 0x18000>; + }; + }; + + spramfw { + compatible = "arteris, flexnoc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x10250000 0x10250000 0x3000>; + spramfw@10820000 { + compatible = "sirf,nocfw-spramfw"; + reg = <0x10250000 0x3000>; + }; + }; + + cpum { + compatible = "arteris, flexnoc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x10200000 0x10200000 0x3000>; + cpum@10200000 { + compatible = "sirf,nocfw-cpum"; + reg = <0x10200000 0x3000>; + }; + }; + + cgum { + compatible = "arteris, flexnoc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x18641000 0x18641000 0x3000>, + <0x18620000 0x18620000 0x1000>; + + cgum@18641000 { + compatible = "sirf,nocfw-cgum"; + reg = <0x18641000 0x3000>; + }; + + car: clock-controller@18620000 { + compatible = "sirf,atlas7-car"; + reg = <0x18620000 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + }; + + gnssm { + compatible = "arteris, flexnoc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x18000000 0x18000000 0x0000ffff>, + <0x18010000 0x18010000 0x1000>, + <0x18020000 0x18020000 0x1000>, + <0x18030000 0x18030000 0x1000>, + <0x18040000 0x18040000 0x1000>, + <0x18050000 0x18050000 0x1000>, + <0x18060000 0x18060000 0x1000>, + <0x18100000 0x18100000 0x3000>, + <0x18250000 0x18250000 0x10000>, + <0x18200000 0x18200000 0x1000>; + + dmac0: dma-controller@18000000 { + cell-index = <0>; + compatible = "sirf,atlas7-dmac"; + reg = <0x18000000 0x1000>; + interrupts = <0 12 0>; + clocks = <&car 89>; + dma-channels = <16>; + #dma-cells = <1>; + }; + + gnssmfw@0x18100000 { + compatible = "sirf,nocfw-gnssm"; + reg = <0x18100000 0x3000>; + }; + + uart0: uart@18010000 { + cell-index = <0>; + compatible = "sirf,atlas7-uart"; + reg = <0x18010000 0x1000>; + interrupts = <0 17 0>; + clocks = <&car 90>; + fifosize = <128>; + dmas = <&dmac0 3>, <&dmac0 2>; + dma-names = "rx", "tx"; + }; + + uart1: uart@18020000 { + cell-index = <1>; + compatible = "sirf,atlas7-uart"; + reg = <0x18020000 0x1000>; + interrupts = <0 18 0>; + clocks = <&car 88>; + fifosize = <32>; + }; + + uart2: uart@18030000 { + cell-index = <2>; + compatible = "sirf,atlas7-uart"; + reg = <0x18030000 0x1000>; + interrupts = <0 19 0>; + clocks = <&car 91>; + fifosize = <128>; + dmas = <&dmac0 6>, <&dmac0 7>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + uart3: uart@18040000 { + cell-index = <3>; + compatible = "sirf,atlas7-uart"; + reg = <0x18040000 0x1000>; + interrupts = <0 66 0>; + clocks = <&car 92>; + fifosize = <128>; + dmas = <&dmac0 4>, <&dmac0 5>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + uart4: uart@18050000 { + cell-index = <4>; + compatible = "sirf,atlas7-uart"; + reg = <0x18050000 0x1000>; + interrupts = <0 69 0>; + clocks = <&car 93>; + fifosize = <128>; + dmas = <&dmac0 0>, <&dmac0 1>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + uart5: uart@18060000 { + cell-index = <5>; + compatible = "sirf,atlas7-uart"; + reg = <0x18060000 0x1000>; + interrupts = <0 71 0>; + clocks = <&car 94>; + fifosize = <128>; + dmas = <&dmac0 8>, <&dmac0 9>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + dspub@18250000 { + compatible = "dx,cc44p"; + reg = <0x18250000 0x10000>; + interrupts = <0 27 0>; + }; + + spi1: spi@18200000 { + compatible = "sirf,prima2-spi"; + reg = <0x18200000 0x1000>; + interrupts = <0 16 0>; + clocks = <&car 95>; + #address-cells = <1>; + #size-cells = <0>; + dmas = <&dmac0 12>, <&dmac0 13>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + }; + + + gpum { + compatible = "arteris, flexnoc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x13000000 0x13000000 0x3000>; + gpum@0x13000000 { + compatible = "sirf,nocfw-gpum"; + reg = <0x13000000 0x3000>; + }; + }; + + mediam { + compatible = "arteris, flexnoc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x16000000 0x16000000 0x00200000>, + <0x17020000 0x17020000 0x1000>, + <0x17030000 0x17030000 0x1000>, + <0x17040000 0x17040000 0x1000>, + <0x17050000 0x17050000 0x10000>, + <0x17060000 0x17060000 0x200>, + <0x17060200 0x17060200 0x100>, + <0x17070000 0x17070000 0x200>, + <0x17070200 0x17070200 0x100>, + <0x170A0000 0x170A0000 0x3000>; + + mediam@170A0000 { + compatible = "sirf,nocfw-mediam"; + reg = <0x170A0000 0x3000>; + }; + + gpio_0: gpio_mediam@17040000 { + #gpio-cells = <2>; + #interrupt-cells = <2>; + compatible = "sirf,atlas7-gpio"; + reg = <0x17040000 0x1000>; + interrupts = <0 13 0>, <0 14 0>; + clocks = <&car 107>; + clock-names = "gpio0_io"; + gpio-controller; + interrupt-controller; + }; + + nand@17050000 { + compatible = "sirf,atlas7-nand"; + reg = <0x17050000 0x10000>; + interrupts = <0 41 0>; + clocks = <&car 108>, <&car 112>; + clock-names = "nand_io", "nand_nand"; + }; + + sd0: sdhci@16000000 { + cell-index = <0>; + compatible = "sirf,atlas7-sdhc"; + reg = <0x16000000 0x100000>; + interrupts = <0 38 0>; + clocks = <&car 109>, <&car 111>; + clock-names = "core", "iface"; + wp-inverted; + non-removable; + status = "disabled"; + bus-width = <8>; + }; + + sd1: sdhci@16100000 { + cell-index = <1>; + compatible = "sirf,atlas7-sdhc"; + reg = <0x16100000 0x100000>; + interrupts = <0 38 0>; + clocks = <&car 109>, <&car 111>; + clock-names = "core", "iface"; + non-removable; + status = "disabled"; + bus-width = <8>; + }; + + usb0: usb@17060000 { + cell-index = <0>; + compatible = "sirf,atlas7-usb"; + reg = <0x17060000 0x200>; + interrupts = <0 10 0>; + clocks = <&car 113>; + sirf,usbphy = <&usbphy0>; + phy_type = "utmi"; + dr_mode = "otg"; + maximum-speed = "high-speed"; + status = "okay"; + }; + + usb1: usb@17070000 { + cell-index = <1>; + compatible = "sirf,atlas7-usb"; + reg = <0x17070000 0x200>; + interrupts = <0 11 0>; + clocks = <&car 114>; + sirf,usbphy = <&usbphy1>; + phy_type = "utmi"; + dr_mode = "host"; + maximum-speed = "high-speed"; + status = "okay"; + }; + + usbphy0: usbphy@0 { + compatible = "sirf,atlas7-usbphy"; + reg = <0x17060200 0x100>; + clocks = <&car 115>; + status = "okay"; + }; + + usbphy1: usbphy@1 { + compatible = "sirf,atlas7-usbphy"; + reg = <0x17070200 0x100>; + clocks = <&car 116>; + status = "okay"; + }; + + i2c0: i2c@17020000 { + cell-index = <0>; + compatible = "sirf,prima2-i2c"; + reg = <0x17020000 0x1000>; + interrupts = <0 24 0>; + clocks = <&car 105>; + #address-cells = <1>; + #size-cells = <0>; + }; + + }; + + vdifm { + compatible = "arteris, flexnoc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x13290000 0x13290000 0x3000>, + <0x13300000 0x13300000 0x1000>, + <0x14200000 0x14200000 0x600000>; + + vdifm@13290000 { + compatible = "sirf,nocfw-vdifm"; + reg = <0x13290000 0x3000>; + }; + + gpio_1: gpio_vdifm@13300000 { + #gpio-cells = <2>; + #interrupt-cells = <2>; + compatible = "sirf,atlas7-gpio"; + reg = <0x13300000 0x1000>; + interrupts = <0 43 0>, <0 44 0>, <0 45 0>; + clocks = <&car 84>; + clock-names = "gpio1_io"; + gpio-controller; + interrupt-controller; + }; + + sd2: sdhci@14200000 { + cell-index = <2>; + compatible = "sirf,atlas7-sdhc"; + reg = <0x14200000 0x100000>; + interrupts = <0 23 0>; + clocks = <&car 70>, <&car 75>; + clock-names = "core", "iface"; + status = "disabled"; + bus-width = <4>; + sd-uhs-sdr50; + vqmmc-supply = <&vqmmc>; + vqmmc: vqmmc@2 { + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <1950000>; + regulator-name = "vqmmc-ldo"; + regulator-type = "voltage"; + regulator-boot-on; + regulator-allow-bypass; + }; + }; + + sd3: sdhci@14300000 { + cell-index = <3>; + compatible = "sirf,atlas7-sdhc"; + reg = <0x14300000 0x100000>; + interrupts = <0 23 0>; + clocks = <&car 76>, <&car 81>; + clock-names = "core", "iface"; + status = "disabled"; + bus-width = <4>; + }; + + sd5: sdhci@14500000 { + cell-index = <5>; + compatible = "sirf,atlas7-sdhc"; + reg = <0x14500000 0x100000>; + interrupts = <0 39 0>; + clocks = <&car 71>, <&car 76>; + clock-names = "core", "iface"; + status = "disabled"; + bus-width = <4>; + loop-dma; + }; + + sd6: sdhci@14600000 { + cell-index = <6>; + compatible = "sirf,atlas7-sdhc"; + reg = <0x14600000 0x100000>; + interrupts = <0 98 0>; + clocks = <&car 72>, <&car 77>; + clock-names = "core", "iface"; + status = "disabled"; + bus-width = <4>; + }; + + sd7: sdhci@14700000 { + cell-index = <7>; + compatible = "sirf,atlas7-sdhc"; + reg = <0x14700000 0x100000>; + interrupts = <0 98 0>; + clocks = <&car 72>, <&car 77>; + clock-names = "core", "iface"; + status = "disabled"; + bus-width = <4>; + }; + }; + + audiom { + compatible = "arteris, flexnoc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x10d50000 0x10d50000 0x0000ffff>, + <0x10d60000 0x10d60000 0x0000ffff>, + <0x10d80000 0x10d80000 0x0000ffff>, + <0x10d90000 0x10d90000 0x0000ffff>, + <0x10ED0000 0x10ED0000 0x3000>, + <0x10dc8000 0x10dc8000 0x1000>, + <0x10dc0000 0x10dc0000 0x1000>, + <0x10db0000 0x10db0000 0x4000>, + <0x10d40000 0x10d40000 0x1000>, + <0x10d30000 0x10d30000 0x1000>; + + timer@10dc0000 { + compatible = "sirf,atlas7-tick"; + reg = <0x10dc0000 0x1000>; + interrupts = <0 0 0>, + <0 1 0>, + <0 2 0>, + <0 49 0>, + <0 50 0>, + <0 51 0>; + clocks = <&car 47>; + }; + + timerb@10dc8000 { + compatible = "sirf,atlas7-tick"; + reg = <0x10dc8000 0x1000>; + interrupts = <0 74 0>, + <0 75 0>, + <0 76 0>, + <0 77 0>, + <0 78 0>, + <0 79 0>; + clocks = <&car 47>; + }; + + vip0@10db0000 { + compatible = "sirf,atlas7-vip0"; + reg = <0x10db0000 0x2000>; + interrupts = <0 85 0>; + sirf,vip_cma_size = <0xC00000>; + }; + + cvd@10db2000 { + compatible = "sirf,cvd"; + reg = <0x10db2000 0x2000>; + clocks = <&car 46>; + }; + + dmac2: dma-controller@10d50000 { + cell-index = <2>; + compatible = "sirf,atlas7-dmac"; + reg = <0x10d50000 0xffff>; + interrupts = <0 55 0>; + clocks = <&car 60>; + dma-channels = <16>; + #dma-cells = <1>; + }; + + dmac3: dma-controller@10d60000 { + cell-index = <3>; + compatible = "sirf,atlas7-dmac"; + reg = <0x10d60000 0xffff>; + interrupts = <0 56 0>; + clocks = <&car 61>; + dma-channels = <16>; + #dma-cells = <1>; + }; + + adc: adc@10d80000 { + compatible = "sirf,atlas7-adc"; + reg = <0x10d80000 0xffff>; + interrupts = <0 34 0>; + clocks = <&car 49>; + #io-channel-cells = <1>; + }; + + pulsec@10d90000 { + compatible = "sirf,prima2-pulsec"; + reg = <0x10d90000 0xffff>; + interrupts = <0 42 0>; + clocks = <&car 54>; + }; + + audiom@10ED0000 { + compatible = "sirf,nocfw-audiom"; + reg = <0x10ED0000 0x3000>; + interrupts = <0 102 0>; + }; + + usp1: usp@10d30000 { + cell-index = <1>; + reg = <0x10d30000 0x1000>; + fifosize = <512>; + clocks = <&car 58>; + dmas = <&dmac2 6>, <&dmac2 7>; + dma-names = "rx", "tx"; + }; + + usp2: usp@10d40000 { + cell-index = <2>; + reg = <0x10d40000 0x1000>; + interrupts = <0 22 0>; + clocks = <&car 59>; + dmas = <&dmac2 12>, <&dmac2 13>; + dma-names = "rx", "tx"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + }; + + ddrm { + compatible = "arteris, flexnoc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x10820000 0x10820000 0x3000>, + <0x10800000 0x10800000 0x2000>; + ddrm@10820000 { + compatible = "sirf,nocfw-ddrm"; + reg = <0x10820000 0x3000>; + interrupts = <0 105 0>; + }; + + memory-controller@0x10800000 { + compatible = "sirf,atlas7-memc"; + reg = <0x10800000 0x2000>; + }; + + }; + + btm { + compatible = "arteris, flexnoc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x11002000 0x11002000 0x0000ffff>, + <0x11010000 0x11010000 0x3000>, + <0x11000000 0x11000000 0x1000>, + <0x11001000 0x11001000 0x1000>; + + dmac4: dma-controller@11002000 { + cell-index = <4>; + compatible = "sirf,atlas7-dmac"; + reg = <0x11002000 0x1000>; + interrupts = <0 99 0>; + clocks = <&car 130>; + dma-channels = <16>; + #dma-cells = <1>; + }; + uart6: uart@11000000 { + cell-index = <6>; + compatible = "sirf,atlas7-bt-uart", + "sirf,atlas7-uart"; + reg = <0x11000000 0x1000>; + interrupts = <0 100 0>; + clocks = <&car 131>, <&car 133>, <&car 134>; + clock-names = "uart", "general", "noc"; + fifosize = <128>; + dmas = <&dmac4 12>, <&dmac4 13>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + usp3: usp@11001000 { + compatible = "sirf,atlas7-bt-usp", + "sirf,prima2-usp-pcm"; + cell-index = <3>; + reg = <0x11001000 0x1000>; + fifosize = <512>; + clocks = <&car 132>, <&car 129>, <&car 133>, + <&car 134>, <&car 135>; + clock-names = "usp3_io", "a7ca_btss", "a7ca_io", + "noc_btm_io", "thbtm_io"; + dmas = <&dmac4 0>, <&dmac4 1>; + dma-names = "rx", "tx"; + }; + + btm@11010000 { + compatible = "sirf,nocfw-btm"; + reg = <0x11010000 0x3000>; + }; + }; + + rtcm { + compatible = "arteris, flexnoc", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x18810000 0x18810000 0x3000>, + <0x18840000 0x18840000 0x1000>, + <0x18890000 0x18890000 0x1000>, + <0x188B0000 0x188B0000 0x10000>, + <0x188D0000 0x188D0000 0x1000>; + rtcm@18810000 { + compatible = "sirf,nocfw-rtcm"; + reg = <0x18810000 0x3000>; + interrupts = <0 109 0>; + }; + + gpio_2: gpio_rtcm@18890000 { + #gpio-cells = <2>; + #interrupt-cells = <2>; + compatible = "sirf,atlas7-gpio"; + reg = <0x18890000 0x1000>; + interrupts = <0 47 0>; + gpio-controller; + interrupt-controller; + }; + + rtc-iobg@18840000 { + compatible = "sirf,prima2-rtciobg", + "sirf-prima2-rtciobg-bus", + "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x18840000 0x1000>; + + sysrtc@2000 { + compatible = "sirf,prima2-sysrtc"; + reg = <0x2000 0x100>; + interrupts = <0 52 0>; + }; + pwrc@3000 { + compatible = "sirf,atlas7-pwrc"; + reg = <0x3000 0x100>; + }; + }; + + qspi: flash@188B0000 { + cell-index = <0>; + compatible = "sirf,atlas7-qspi-nor"; + reg = <0x188B0000 0x10000>; + interrupts = <0 15 0>; + #address-cells = <1>; + #size-cells = <0>; + }; + + retain@0x188D0000 { + compatible = "sirf,atlas7-retain"; + reg = <0x188D0000 0x1000>; + }; + + }; + disp-iobg { + /* lcdc0 */ + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x13100000 0x13100000 0x20000>, + <0x10e10000 0x10e10000 0x10000>; + + lcd@13100000 { + compatible = "sirf,atlas7-lcdc"; + reg = <0x13100000 0x10000>; + interrupts = <0 30 0>; + clocks = <&car 79>; + }; + vpp@13110000 { + compatible = "sirf,atlas7-vpp"; + reg = <0x13110000 0x10000>; + interrupts = <0 31 0>; + clocks = <&car 78>; + resets = <&car 29>; + }; + lvds@10e10000 { + compatible = "sirf,atlas7-lvdsc"; + reg = <0x10e10000 0x10000>; + interrupts = <0 64 0>; + clocks = <&car 54>; + resets = <&car 29>; + }; + + }; + + graphics-iobg { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x12000000 0x12000000 0x1000000>; + + graphics@12000000 { + compatible = "powervr,sgx531"; + reg = <0x12000000 0x1000000>; + interrupts = <0 6 0>; + clocks = <&car 126>; + }; + }; + }; +}; -- cgit v1.2.3 From d4bc3bf24804d0b2329f8c44d7855f72bd7d0779 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 10 Dec 2014 11:53:01 +0100 Subject: ARM: at91/config: sama5: Remove DEBUG_LL The sama5_defconfig can be used both on the sama5d3 and the sama5d4. Enabling DEBUG_LL is an issue though, since it will by default use the kernel addresses for the sama5d3 DBGU UART, that is located at a different address on the sama5d4. Remove this from the defconfig. Signed-off-by: Maxime Ripard Signed-off-by: Nicolas Ferre --- arch/arm/configs/sama5_defconfig | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig index afa24799477a..c04196f9632b 100644 --- a/arch/arm/configs/sama5_defconfig +++ b/arch/arm/configs/sama5_defconfig @@ -202,8 +202,6 @@ CONFIG_DEBUG_MEMORY_INIT=y # CONFIG_SCHED_DEBUG is not set # CONFIG_FTRACE is not set CONFIG_DEBUG_USER=y -CONFIG_DEBUG_LL=y -CONFIG_EARLY_PRINTK=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_USER_API_HASH=m CONFIG_CRYPTO_USER_API_SKCIPHER=m -- cgit v1.2.3 From d0f0f63ac1374c13b7862b48bd7d6514913dbcad Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 17 Dec 2014 14:06:00 +0100 Subject: MIPS: Rewrite csum_fold to plain C. This isn't only short and easier to read and fully portable but also shrinks a Malta kernel's by 160 bytes. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/checksum.h | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/checksum.h b/arch/mips/include/asm/checksum.h index 3418c51e1151..ac0f55cc6e78 100644 --- a/arch/mips/include/asm/checksum.h +++ b/arch/mips/include/asm/checksum.h @@ -103,22 +103,16 @@ __wsum csum_partial_copy_nocheck(const void *src, void *dst, /* * Fold a partial checksum without adding pseudo headers */ -static inline __sum16 csum_fold(__wsum sum) +static inline __sum16 csum_fold(__wsum csum) { - __asm__( - " .set push # csum_fold\n" - " .set noat \n" - " sll $1, %0, 16 \n" - " addu %0, $1 \n" - " sltu $1, %0, $1 \n" - " srl %0, %0, 16 \n" - " addu %0, $1 \n" - " xori %0, 0xffff \n" - " .set pop" - : "=r" (sum) - : "0" (sum)); + u32 sum = (__force u32)csum;; + + sum += (sum << 16); + csum = (sum < csum); + sum >>= 16; + sum += csum; - return (__force __sum16)sum; + return (__force __sum16)~sum; } /* -- cgit v1.2.3 From b4b5015a1c1450e008ccd414c760f4ef907a461b Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 17 Dec 2014 23:03:46 +0100 Subject: MIPS: Use Right now the MIPS still overrides all functions. This will change in the future. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/checksum.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch') diff --git a/arch/mips/include/asm/checksum.h b/arch/mips/include/asm/checksum.h index ac0f55cc6e78..64ae32c082d1 100644 --- a/arch/mips/include/asm/checksum.h +++ b/arch/mips/include/asm/checksum.h @@ -99,6 +99,7 @@ __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len, */ __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum); +#define csum_partial_copy_nocheck csum_partial_copy_nocheck /* * Fold a partial checksum without adding pseudo headers @@ -114,6 +115,7 @@ static inline __sum16 csum_fold(__wsum csum) return (__force __sum16)~sum; } +#define csum_fold csum_fold /* * This is a version of ip_compute_csum() optimized for IP headers, @@ -152,6 +154,7 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) return csum_fold(csum); } +#define ip_fast_csum ip_fast_csum static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, unsigned short proto, @@ -194,6 +197,7 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, return sum; } +#define csum_tcpudp_nofold csum_tcpudp_nofold /* * computes the checksum of the TCP/UDP pseudo-header @@ -206,6 +210,7 @@ static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, { return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); } +#define csum_tcpudp_magic csum_tcpudp_magic /* * this routine is used for miscellaneous IP-like checksums, mainly @@ -281,4 +286,6 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, return csum_fold(sum); } +#include + #endif /* _ASM_CHECKSUM_H */ -- cgit v1.2.3 From 2f26c48824ece86ccc6e8d5889fbf338ebfc67e5 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 17 Dec 2014 23:05:10 +0100 Subject: MIPS: Use generic csum_tcpudp_magic for MIPS. Its implementation is identical to MIPS. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/checksum.h | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/checksum.h b/arch/mips/include/asm/checksum.h index 64ae32c082d1..5996252680c6 100644 --- a/arch/mips/include/asm/checksum.h +++ b/arch/mips/include/asm/checksum.h @@ -199,19 +199,6 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, } #define csum_tcpudp_nofold csum_tcpudp_nofold -/* - * computes the checksum of the TCP/UDP pseudo-header - * returns a 16-bit checksum, already complemented - */ -static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, - unsigned short len, - unsigned short proto, - __wsum sum) -{ - return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); -} -#define csum_tcpudp_magic csum_tcpudp_magic - /* * this routine is used for miscellaneous IP-like checksums, mainly * in icmp.c -- cgit v1.2.3 From 7f84c0a24aab92c28899c95b641efa6638683cfa Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 2 Jan 2015 17:16:24 +0100 Subject: MIPS: ARC: Use __noreturn / unreachable in ARC termination functions. Signed-off-by: Ralf Baechle --- arch/mips/fw/arc/misc.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/mips/fw/arc/misc.c b/arch/mips/fw/arc/misc.c index f9f5307434c2..19f710117d97 100644 --- a/arch/mips/fw/arc/misc.c +++ b/arch/mips/fw/arc/misc.c @@ -9,6 +9,7 @@ * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org) * Copyright (C) 1999 Silicon Graphics, Inc. */ +#include #include #include #include @@ -19,50 +20,55 @@ #include #include -VOID +VOID __noreturn ArcHalt(VOID) { bc_disable(); local_irq_disable(); ARC_CALL0(halt); -never: goto never; + + unreachable(); } -VOID +VOID __noreturn ArcPowerDown(VOID) { bc_disable(); local_irq_disable(); ARC_CALL0(pdown); -never: goto never; + + unreachable(); } /* XXX is this a soft reset basically? XXX */ -VOID +VOID __noreturn ArcRestart(VOID) { bc_disable(); local_irq_disable(); ARC_CALL0(restart); -never: goto never; + + unreachable(); } -VOID +VOID __noreturn ArcReboot(VOID) { bc_disable(); local_irq_disable(); ARC_CALL0(reboot); -never: goto never; + + unreachable(); } -VOID +VOID __noreturn ArcEnterInteractiveMode(VOID) { bc_disable(); local_irq_disable(); ARC_CALL0(imode); -never: goto never; + + unreachable(); } LONG -- cgit v1.2.3 From efc46d136f9af6b6cd0cf5a4858a1f69849296b9 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 2 Jan 2015 15:56:28 +0100 Subject: MIPS: IP32: Use __noreturn instead of open coded attributes in declarations. Signed-off-by: Ralf Baechle --- arch/mips/sgi-ip32/ip32-reset.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c index 1f823da4c77b..44b3470a0bbb 100644 --- a/arch/mips/sgi-ip32/ip32-reset.c +++ b/arch/mips/sgi-ip32/ip32-reset.c @@ -8,6 +8,7 @@ * Copyright (C) 2003 Guido Guenther */ +#include #include #include #include @@ -35,9 +36,9 @@ static struct timer_list power_timer, blink_timer, debounce_timer; static int has_panicked, shuting_down; -static void ip32_machine_restart(char *command) __attribute__((noreturn)); -static void ip32_machine_halt(void) __attribute__((noreturn)); -static void ip32_machine_power_off(void) __attribute__((noreturn)); +static void ip32_machine_restart(char *command) __noreturn; +static void ip32_machine_halt(void) __noreturn; +static void ip32_machine_power_off(void) __noreturn; static void ip32_machine_restart(char *cmd) { -- cgit v1.2.3 From dd6e2db13fdf7084779a4737cb8934550438954c Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 2 Jan 2015 15:57:40 +0100 Subject: MIPS: IP27: Use __noreturn instead of open coded attributes in declarations. Signed-off-by: Ralf Baechle --- arch/mips/sgi-ip27/ip27-reset.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/mips/sgi-ip27/ip27-reset.c b/arch/mips/sgi-ip27/ip27-reset.c index ac37e54b3d5e..e44a15d4f573 100644 --- a/arch/mips/sgi-ip27/ip27-reset.c +++ b/arch/mips/sgi-ip27/ip27-reset.c @@ -8,6 +8,7 @@ * Copyright (C) 1997, 1998, 1999, 2000, 06 by Ralf Baechle * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ +#include #include #include #include @@ -25,9 +26,9 @@ #include #include -void machine_restart(char *command) __attribute__((noreturn)); -void machine_halt(void) __attribute__((noreturn)); -void machine_power_off(void) __attribute__((noreturn)); +void machine_restart(char *command) __noreturn; +void machine_halt(void) __noreturn; +void machine_power_off(void) __noreturn; #define noreturn while(1); /* Silence gcc. */ -- cgit v1.2.3 From bb03006ec93cb286ec0fab344e2a14d591d0bc4c Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 2 Jan 2015 15:59:06 +0100 Subject: MIPS: ARC: Use __noreturn instead of open coded attributes in declarations. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/sgialib.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/mips/include/asm/sgialib.h b/arch/mips/include/asm/sgialib.h index 753275accd18..40dc9839f63c 100644 --- a/arch/mips/include/asm/sgialib.h +++ b/arch/mips/include/asm/sgialib.h @@ -11,6 +11,7 @@ #ifndef _ASM_SGIALIB_H #define _ASM_SGIALIB_H +#include #include extern struct linux_romvec *romvec; @@ -70,8 +71,8 @@ extern LONG ArcRead(ULONG fd, PVOID buf, ULONG num, PULONG cnt); extern LONG ArcWrite(ULONG fd, PVOID buf, ULONG num, PULONG cnt); /* Misc. routines. */ -extern VOID ArcReboot(VOID) __attribute__((noreturn)); -extern VOID ArcEnterInteractiveMode(VOID) __attribute__((noreturn)); +extern VOID ArcReboot(VOID) __noreturn; +extern VOID ArcEnterInteractiveMode(VOID) __noreturn; extern VOID ArcFlushAllCaches(VOID); extern DISPLAY_STATUS *ArcGetDisplayStatus(ULONG FileID); -- cgit v1.2.3 From e9503246a2c72dbdfce38668936faf8e52198bdb Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Fri, 2 Jan 2015 16:00:58 +0100 Subject: MIPS: ARC: Add declarations for a few missing ARC firmware functions. Signed-off-by: Ralf Baechle --- arch/mips/include/asm/sgialib.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch') diff --git a/arch/mips/include/asm/sgialib.h b/arch/mips/include/asm/sgialib.h index 40dc9839f63c..195db5045ae5 100644 --- a/arch/mips/include/asm/sgialib.h +++ b/arch/mips/include/asm/sgialib.h @@ -71,6 +71,9 @@ extern LONG ArcRead(ULONG fd, PVOID buf, ULONG num, PULONG cnt); extern LONG ArcWrite(ULONG fd, PVOID buf, ULONG num, PULONG cnt); /* Misc. routines. */ +extern VOID ArcHalt(VOID) __noreturn; +extern VOID ArcPowerDown(VOID) __noreturn; +extern VOID ArcRestart(VOID) __noreturn; extern VOID ArcReboot(VOID) __noreturn; extern VOID ArcEnterInteractiveMode(VOID) __noreturn; extern VOID ArcFlushAllCaches(VOID); -- cgit v1.2.3 From e9118a4914e47e915952842828401779f09cecb8 Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Tue, 13 Jan 2015 10:04:43 -0500 Subject: tile: default to little endian on older toolchains Older toolchains may not specify __LITTLE_ENDIAN__, but older toolchains were all little endian. Don't make things unnecessarily hard for those toolchains. Signed-off-by: Chris Metcalf --- arch/tile/include/uapi/asm/byteorder.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/tile/include/uapi/asm/byteorder.h b/arch/tile/include/uapi/asm/byteorder.h index fb72ecf49218..6b8fa2e1cf6e 100644 --- a/arch/tile/include/uapi/asm/byteorder.h +++ b/arch/tile/include/uapi/asm/byteorder.h @@ -14,8 +14,6 @@ #if defined (__BIG_ENDIAN__) #include -#elif defined (__LITTLE_ENDIAN__) -#include #else -#error "__BIG_ENDIAN__ or __LITTLE_ENDIAN__ must be defined." +#include #endif -- cgit v1.2.3 From df73b7f84227fa821699477c7234c1abc39fc512 Mon Sep 17 00:00:00 2001 From: Dmitry Lifshitz Date: Sun, 28 Dec 2014 16:30:49 +0200 Subject: ARM: dts: cm-t3x: add NAND support CM-T3517, CM-T3530 and CM-T3730 features NAND storage chip connected to GPMC bus. Add GPMC DT entry into the root DT file omap3-cm-t3x.dtsi, common for all three modules. NAND timings are calculated to be safe for CM-T3x devices as it works now in non DT boot (in this case the timings are updated by U-Boot). Update GPMC ranges in boards DT files to include all connected devices. Signed-off-by: Dmitry Lifshitz Acked-by: Igor Grinberg Acked-by: Roger Quadros Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-cm-t3x.dtsi | 58 +++++++++++++++++++++++++++++++++++ arch/arm/boot/dts/omap3-cm-t3x30.dtsi | 3 +- arch/arm/boot/dts/omap3-sbc-t3517.dts | 4 +++ arch/arm/boot/dts/omap3-sbc-t3530.dts | 10 ++---- arch/arm/boot/dts/omap3-sbc-t3730.dts | 5 +-- 5 files changed, 70 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/arm/boot/dts/omap3-cm-t3x.dtsi b/arch/arm/boot/dts/omap3-cm-t3x.dtsi index 6ea6d460db30..4d091ca43e25 100644 --- a/arch/arm/boot/dts/omap3-cm-t3x.dtsi +++ b/arch/arm/boot/dts/omap3-cm-t3x.dtsi @@ -259,3 +259,61 @@ pinctrl-names = "default"; pinctrl-0 = <&mcbsp2_pins>; }; + +&gpmc { + ranges = <0 0 0x00000000 0x01000000>; + + nand@0,0 { + reg = <0 0 4>; /* CS0, offset 0, IO size 4 */ + nand-bus-width = <8>; + gpmc,device-width = <1>; + ti,nand-ecc-opt = "sw"; + + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <120>; + gpmc,cs-wr-off-ns = <120>; + + gpmc,adv-on-ns = <0>; + gpmc,adv-rd-off-ns = <120>; + gpmc,adv-wr-off-ns = <120>; + + gpmc,we-on-ns = <6>; + gpmc,we-off-ns = <90>; + + gpmc,oe-on-ns = <6>; + gpmc,oe-off-ns = <90>; + + gpmc,page-burst-access-ns = <6>; + gpmc,access-ns = <72>; + gpmc,cycle2cycle-delay-ns = <60>; + + gpmc,rd-cycle-ns = <120>; + gpmc,wr-cycle-ns = <120>; + gpmc,wr-access-ns = <186>; + gpmc,wr-data-mux-bus-ns = <90>; + + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "xloader"; + reg = <0 0x80000>; + }; + partition@0x80000 { + label = "uboot"; + reg = <0x80000 0x1e0000>; + }; + partition@0x260000 { + label = "uboot environment"; + reg = <0x260000 0x40000>; + }; + partition@0x2a0000 { + label = "linux"; + reg = <0x2a0000 0x400000>; + }; + partition@0x6a0000 { + label = "rootfs"; + reg = <0x6a0000 0x1f880000>; + }; + }; +}; diff --git a/arch/arm/boot/dts/omap3-cm-t3x30.dtsi b/arch/arm/boot/dts/omap3-cm-t3x30.dtsi index 9a4a3ab9af78..d9e92b654f85 100644 --- a/arch/arm/boot/dts/omap3-cm-t3x30.dtsi +++ b/arch/arm/boot/dts/omap3-cm-t3x30.dtsi @@ -50,7 +50,8 @@ #include "omap-gpmc-smsc911x.dtsi" &gpmc { - ranges = <5 0 0x2c000000 0x01000000>; + ranges = <5 0 0x2c000000 0x01000000>, /* CM-T3x30 SMSC9x Eth */ + <0 0 0x00000000 0x01000000>; /* CM-T3x NAND */ smsc1: ethernet@gpmc { compatible = "smsc,lan9221", "smsc,lan9115"; diff --git a/arch/arm/boot/dts/omap3-sbc-t3517.dts b/arch/arm/boot/dts/omap3-sbc-t3517.dts index 17986536c61f..c2d5c28a1a70 100644 --- a/arch/arm/boot/dts/omap3-sbc-t3517.dts +++ b/arch/arm/boot/dts/omap3-sbc-t3517.dts @@ -69,3 +69,7 @@ }; }; +&gpmc { + ranges = <4 0 0x2d000000 0x01000000>, /* SB-T35 SMSC9x Eth */ + <0 0 0x00000000 0x01000000>; /* CM-T3x NAND */ +}; diff --git a/arch/arm/boot/dts/omap3-sbc-t3530.dts b/arch/arm/boot/dts/omap3-sbc-t3530.dts index c994f0f7e38a..834bc786cd12 100644 --- a/arch/arm/boot/dts/omap3-sbc-t3530.dts +++ b/arch/arm/boot/dts/omap3-sbc-t3530.dts @@ -26,14 +26,10 @@ }; }; -/* - * The following ranges correspond to SMSC9x eth chips on CM-T3530 CoM and - * SB-T35 baseboard respectively. - * This setting includes both chips in SBC-T3530 board device tree. - */ &gpmc { - ranges = <5 0 0x2c000000 0x01000000>, - <4 0 0x2d000000 0x01000000>; + ranges = <5 0 0x2c000000 0x01000000>, /* CM-T3x30 SMSC9x Eth */ + <4 0 0x2d000000 0x01000000>, /* SB-T35 SMSC9x Eth */ + <0 0 0x00000000 0x01000000>; /* CM-T3x NAND */ }; &mmc1 { diff --git a/arch/arm/boot/dts/omap3-sbc-t3730.dts b/arch/arm/boot/dts/omap3-sbc-t3730.dts index 5bdddf29341d..73c7bf4a4a08 100644 --- a/arch/arm/boot/dts/omap3-sbc-t3730.dts +++ b/arch/arm/boot/dts/omap3-sbc-t3730.dts @@ -27,8 +27,9 @@ }; &gpmc { - ranges = <5 0 0x2c000000 0x01000000>, - <4 0 0x2d000000 0x01000000>; + ranges = <5 0 0x2c000000 0x01000000>, /* CM-T3x30 SMSC9x Eth */ + <4 0 0x2d000000 0x01000000>, /* SB-T35 SMSC9x Eth */ + <0 0 0x00000000 0x01000000>; /* CM-T3x NAND */ }; &dss { -- cgit v1.2.3 From 7300bfff886a1340cfeb252035303e265cd556d9 Mon Sep 17 00:00:00 2001 From: Marek Belisko Date: Wed, 3 Dec 2014 22:33:22 +0100 Subject: ARM: dts: omap3-gta04: Add handling for tv output Add handling for gta04 tv out chain: venc -> opa362 -> svideo Use invert-polarity in venc node because opa362 is doing polarity inversion also. Signed-off-by: Marek Belisko Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-gta04.dtsi | 49 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'arch') diff --git a/arch/arm/boot/dts/omap3-gta04.dtsi b/arch/arm/boot/dts/omap3-gta04.dtsi index 655d6e920a86..ee62d00bcbe6 100644 --- a/arch/arm/boot/dts/omap3-gta04.dtsi +++ b/arch/arm/boot/dts/omap3-gta04.dtsi @@ -83,6 +83,41 @@ compatible = "usb-nop-xceiv"; reset-gpios = <&gpio6 14 GPIO_ACTIVE_LOW>; }; + + tv0: connector@1 { + compatible = "svideo-connector"; + label = "tv"; + + port { + tv_connector_in: endpoint { + remote-endpoint = <&opa_out>; + }; + }; + }; + + tv_amp: opa362 { + compatible = "ti,opa362"; + enable-gpios = <&gpio1 23 0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + opa_in: endpoint@0 { + remote-endpoint = <&venc_out>; + }; + }; + + port@1 { + reg = <1>; + opa_out: endpoint@0 { + remote-endpoint = <&tv_connector_in>; + }; + }; + }; + }; }; &omap3_pmx_core { @@ -396,6 +431,20 @@ }; }; +&venc { + status = "okay"; + + vdda-supply = <&vdac>; + + port { + venc_out: endpoint { + remote-endpoint = <&opa_in>; + ti,channels = <2>; + ti,invert-polarity; + }; + }; +}; + &gpmc { ranges = <0 0 0x30000000 0x1000000>; /* CS0: 16MB for NAND */ -- cgit v1.2.3 From 6624cf651f1a14363d0385f36dc255d304ac7ebb Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Mon, 5 Jan 2015 19:29:21 +0800 Subject: ARM: kprobes: collects stack consumption for store instructions This patch uses the previously introduced checker functionality on store instructions to record their stack consumption information to arch_probes_insn. Signed-off-by: Wang Nan Reviewed-by: Jon Medhurst Signed-off-by: Jon Medhurst --- arch/arm/include/asm/probes.h | 1 + arch/arm/probes/decode.c | 10 +++ arch/arm/probes/kprobes/Makefile | 6 +- arch/arm/probes/kprobes/actions-arm.c | 3 +- arch/arm/probes/kprobes/actions-thumb.c | 5 +- arch/arm/probes/kprobes/checkers-arm.c | 99 +++++++++++++++++++++++++++ arch/arm/probes/kprobes/checkers-common.c | 101 +++++++++++++++++++++++++++ arch/arm/probes/kprobes/checkers-thumb.c | 110 ++++++++++++++++++++++++++++++ arch/arm/probes/kprobes/checkers.h | 54 +++++++++++++++ 9 files changed, 383 insertions(+), 6 deletions(-) create mode 100644 arch/arm/probes/kprobes/checkers-arm.c create mode 100644 arch/arm/probes/kprobes/checkers-common.c create mode 100644 arch/arm/probes/kprobes/checkers-thumb.c create mode 100644 arch/arm/probes/kprobes/checkers.h (limited to 'arch') diff --git a/arch/arm/include/asm/probes.h b/arch/arm/include/asm/probes.h index 806cfe622a9e..6026deb28794 100644 --- a/arch/arm/include/asm/probes.h +++ b/arch/arm/include/asm/probes.h @@ -38,6 +38,7 @@ struct arch_probes_insn { probes_check_cc *insn_check_cc; probes_insn_singlestep_t *insn_singlestep; probes_insn_fn_t *insn_fn; + int stack_space; }; #endif diff --git a/arch/arm/probes/decode.c b/arch/arm/probes/decode.c index c7d442018902..f9d7c423f2cc 100644 --- a/arch/arm/probes/decode.c +++ b/arch/arm/probes/decode.c @@ -425,6 +425,16 @@ probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, */ probes_opcode_t origin_insn = insn; + /* + * stack_space is initialized to 0 here. Checker functions + * should update is value if they find this is a stack store + * instruction: positive value means bytes of stack usage, + * negitive value means unable to determine stack usage + * statically. For instruction doesn't store to stack, checker + * do nothing with it. + */ + asi->stack_space = 0; + if (emulate) insn = prepare_emulated_insn(insn, asi, thumb); diff --git a/arch/arm/probes/kprobes/Makefile b/arch/arm/probes/kprobes/Makefile index eb38a428ecd6..bc8d504c3d78 100644 --- a/arch/arm/probes/kprobes/Makefile +++ b/arch/arm/probes/kprobes/Makefile @@ -1,11 +1,11 @@ -obj-$(CONFIG_KPROBES) += core.o actions-common.o +obj-$(CONFIG_KPROBES) += core.o actions-common.o checkers-common.o obj-$(CONFIG_ARM_KPROBES_TEST) += test-kprobes.o test-kprobes-objs := test-core.o ifdef CONFIG_THUMB2_KERNEL -obj-$(CONFIG_KPROBES) += actions-thumb.o +obj-$(CONFIG_KPROBES) += actions-thumb.o checkers-thumb.o test-kprobes-objs += test-thumb.o else -obj-$(CONFIG_KPROBES) += actions-arm.o +obj-$(CONFIG_KPROBES) += actions-arm.o checkers-arm.o test-kprobes-objs += test-arm.o endif diff --git a/arch/arm/probes/kprobes/actions-arm.c b/arch/arm/probes/kprobes/actions-arm.c index fbd93a9ada75..06988ef7eeb7 100644 --- a/arch/arm/probes/kprobes/actions-arm.c +++ b/arch/arm/probes/kprobes/actions-arm.c @@ -64,6 +64,7 @@ #include "../decode-arm.h" #include "core.h" +#include "checkers.h" #if __LINUX_ARM_ARCH__ >= 6 #define BLX(reg) "blx "reg" \n\t" @@ -340,4 +341,4 @@ const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = { [PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm} }; -const struct decode_checker *kprobes_arm_checkers[] = {NULL}; +const struct decode_checker *kprobes_arm_checkers[] = {arm_stack_checker, NULL}; diff --git a/arch/arm/probes/kprobes/actions-thumb.c b/arch/arm/probes/kprobes/actions-thumb.c index 2796121fe90e..07cfd9bef340 100644 --- a/arch/arm/probes/kprobes/actions-thumb.c +++ b/arch/arm/probes/kprobes/actions-thumb.c @@ -15,6 +15,7 @@ #include "../decode-thumb.h" #include "core.h" +#include "checkers.h" /* These emulation encodings are functionally equivalent... */ #define t32_emulate_rd8rn16rm0ra12_noflags \ @@ -665,5 +666,5 @@ const union decode_action kprobes_t32_actions[NUM_PROBES_T32_ACTIONS] = { .handler = t32_emulate_rdlo12rdhi8rn16rm0_noflags}, }; -const struct decode_checker *kprobes_t32_checkers[] = {NULL}; -const struct decode_checker *kprobes_t16_checkers[] = {NULL}; +const struct decode_checker *kprobes_t32_checkers[] = {t32_stack_checker, NULL}; +const struct decode_checker *kprobes_t16_checkers[] = {t16_stack_checker, NULL}; diff --git a/arch/arm/probes/kprobes/checkers-arm.c b/arch/arm/probes/kprobes/checkers-arm.c new file mode 100644 index 000000000000..f8176631d2a5 --- /dev/null +++ b/arch/arm/probes/kprobes/checkers-arm.c @@ -0,0 +1,99 @@ +/* + * arch/arm/probes/kprobes/checkers-arm.c + * + * Copyright (C) 2014 Huawei 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. + */ + +#include +#include "../decode.h" +#include "../decode-arm.h" +#include "checkers.h" + +static enum probes_insn __kprobes arm_check_stack(probes_opcode_t insn, + struct arch_probes_insn *asi, + const struct decode_header *h) +{ + /* + * PROBES_LDRSTRD, PROBES_LDMSTM, PROBES_STORE, + * PROBES_STORE_EXTRA may get here. Simply mark all normal + * insns as STACK_USE_NONE. + */ + static const union decode_item table[] = { + /* + * 'STR{,D,B,H}, Rt, [Rn, Rm]' should be marked as UNKNOWN + * if Rn or Rm is SP. + * x + * STR (register) cccc 011x x0x0 xxxx xxxx xxxx xxxx xxxx + * STRB (register) cccc 011x x1x0 xxxx xxxx xxxx xxxx xxxx + */ + DECODE_OR (0x0e10000f, 0x0600000d), + DECODE_OR (0x0e1f0000, 0x060d0000), + + /* + * x + * STRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx + * STRH (register) cccc 000x x0x0 xxxx xxxx xxxx 1011 xxxx + */ + DECODE_OR (0x0e5000bf, 0x000000bd), + DECODE_CUSTOM (0x0e5f00b0, 0x000d00b0, STACK_USE_UNKNOWN), + + /* + * For PROBES_LDMSTM, only stmdx sp, [...] need to examine + * + * Bit B/A (bit 24) encodes arithmetic operation order. 1 means + * before, 0 means after. + * Bit I/D (bit 23) encodes arithmetic operation. 1 means + * increment, 0 means decrement. + * + * So: + * B I + * / / + * A D | Rn | + * STMDX SP, [...] cccc 100x 00x0 xxxx xxxx xxxx xxxx xxxx + */ + DECODE_CUSTOM (0x0edf0000, 0x080d0000, STACK_USE_STMDX), + + /* P U W | Rn | Rt | imm12 |*/ + /* STR (immediate) cccc 010x x0x0 1101 xxxx xxxx xxxx xxxx */ + /* STRB (immediate) cccc 010x x1x0 1101 xxxx xxxx xxxx xxxx */ + /* P U W | Rn | Rt |imm4| |imm4|*/ + /* STRD (immediate) cccc 000x x1x0 1101 xxxx xxxx 1111 xxxx */ + /* STRH (immediate) cccc 000x x1x0 1101 xxxx xxxx 1011 xxxx */ + /* + * index = (P == '1'); add = (U == '1'). + * Above insns with: + * index == 0 (str{,d,h} rx, [sp], #+/-imm) or + * add == 1 (str{,d,h} rx, [sp, #+]) + * should be STACK_USE_NONE. + * Only str{,b,d,h} rx,[sp,#-n] (P == 1 and U == 0) are + * required to be examined. + */ + /* STR{,B} Rt,[SP,#-n] cccc 0101 0xx0 1101 xxxx xxxx xxxx xxxx */ + DECODE_CUSTOM (0x0f9f0000, 0x050d0000, STACK_USE_FIXED_XXX), + + /* STR{D,H} Rt,[SP,#-n] cccc 0001 01x0 1101 xxxx xxxx 1x11 xxxx */ + DECODE_CUSTOM (0x0fdf00b0, 0x014d00b0, STACK_USE_FIXED_X0X), + + /* fall through */ + DECODE_CUSTOM (0, 0, STACK_USE_NONE), + DECODE_END + }; + + return probes_decode_insn(insn, asi, table, false, false, stack_check_actions, NULL); +} + +const struct decode_checker arm_stack_checker[NUM_PROBES_ARM_ACTIONS] = { + [PROBES_LDRSTRD] = {.checker = arm_check_stack}, + [PROBES_STORE_EXTRA] = {.checker = arm_check_stack}, + [PROBES_STORE] = {.checker = arm_check_stack}, + [PROBES_LDMSTM] = {.checker = arm_check_stack}, +}; diff --git a/arch/arm/probes/kprobes/checkers-common.c b/arch/arm/probes/kprobes/checkers-common.c new file mode 100644 index 000000000000..971119c29474 --- /dev/null +++ b/arch/arm/probes/kprobes/checkers-common.c @@ -0,0 +1,101 @@ +/* + * arch/arm/probes/kprobes/checkers-common.c + * + * Copyright (C) 2014 Huawei 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. + */ + +#include +#include "../decode.h" +#include "../decode-arm.h" +#include "checkers.h" + +enum probes_insn checker_stack_use_none(probes_opcode_t insn, + struct arch_probes_insn *asi, + const struct decode_header *h) +{ + asi->stack_space = 0; + return INSN_GOOD_NO_SLOT; +} + +enum probes_insn checker_stack_use_unknown(probes_opcode_t insn, + struct arch_probes_insn *asi, + const struct decode_header *h) +{ + asi->stack_space = -1; + return INSN_GOOD_NO_SLOT; +} + +#ifdef CONFIG_THUMB2_KERNEL +enum probes_insn checker_stack_use_imm_0xx(probes_opcode_t insn, + struct arch_probes_insn *asi, + const struct decode_header *h) +{ + int imm = insn & 0xff; + asi->stack_space = imm; + return INSN_GOOD_NO_SLOT; +} + +/* + * Different from other insn uses imm8, the real addressing offset of + * STRD in T32 encoding should be imm8 * 4. See ARMARM description. + */ +enum probes_insn checker_stack_use_t32strd(probes_opcode_t insn, + struct arch_probes_insn *asi, + const struct decode_header *h) +{ + int imm = insn & 0xff; + asi->stack_space = imm << 2; + return INSN_GOOD_NO_SLOT; +} +#else +enum probes_insn checker_stack_use_imm_x0x(probes_opcode_t insn, + struct arch_probes_insn *asi, + const struct decode_header *h) +{ + int imm = ((insn & 0xf00) >> 4) + (insn & 0xf); + asi->stack_space = imm; + return INSN_GOOD_NO_SLOT; +} +#endif + +enum probes_insn checker_stack_use_imm_xxx(probes_opcode_t insn, + struct arch_probes_insn *asi, + const struct decode_header *h) +{ + int imm = insn & 0xfff; + asi->stack_space = imm; + return INSN_GOOD_NO_SLOT; +} + +enum probes_insn checker_stack_use_stmdx(probes_opcode_t insn, + struct arch_probes_insn *asi, + const struct decode_header *h) +{ + unsigned int reglist = insn & 0xffff; + int pbit = insn & (1 << 24); + asi->stack_space = (hweight32(reglist) - (!pbit ? 1 : 0)) * 4; + + return INSN_GOOD_NO_SLOT; +} + +const union decode_action stack_check_actions[] = { + [STACK_USE_NONE] = {.decoder = checker_stack_use_none}, + [STACK_USE_UNKNOWN] = {.decoder = checker_stack_use_unknown}, +#ifdef CONFIG_THUMB2_KERNEL + [STACK_USE_FIXED_0XX] = {.decoder = checker_stack_use_imm_0xx}, + [STACK_USE_T32STRD] = {.decoder = checker_stack_use_t32strd}, +#else + [STACK_USE_FIXED_X0X] = {.decoder = checker_stack_use_imm_x0x}, +#endif + [STACK_USE_FIXED_XXX] = {.decoder = checker_stack_use_imm_xxx}, + [STACK_USE_STMDX] = {.decoder = checker_stack_use_stmdx}, +}; diff --git a/arch/arm/probes/kprobes/checkers-thumb.c b/arch/arm/probes/kprobes/checkers-thumb.c new file mode 100644 index 000000000000..d608e3b9017a --- /dev/null +++ b/arch/arm/probes/kprobes/checkers-thumb.c @@ -0,0 +1,110 @@ +/* + * arch/arm/probes/kprobes/checkers-thumb.c + * + * Copyright (C) 2014 Huawei 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. + */ + +#include +#include "../decode.h" +#include "../decode-thumb.h" +#include "checkers.h" + +static enum probes_insn __kprobes t32_check_stack(probes_opcode_t insn, + struct arch_probes_insn *asi, + const struct decode_header *h) +{ + /* + * PROBES_T32_LDMSTM, PROBES_T32_LDRDSTRD and PROBES_T32_LDRSTR + * may get here. Simply mark all normal insns as STACK_USE_NONE. + */ + static const union decode_item table[] = { + + /* + * First, filter out all ldr insns to make our life easier. + * Following load insns may come here: + * LDM, LDRD, LDR. + * In T32 encoding, bit 20 is enough for distinguishing + * load and store. All load insns have this bit set, when + * all store insns have this bit clear. + */ + DECODE_CUSTOM (0x00100000, 0x00100000, STACK_USE_NONE), + + /* + * Mark all 'STR{,B,H}, Rt, [Rn, Rm]' as STACK_USE_UNKNOWN + * if Rn or Rm is SP. T32 doesn't encode STRD. + */ + /* xx | Rn | Rt | | Rm |*/ + /* STR (register) 1111 1000 0100 xxxx xxxx 0000 00xx xxxx */ + /* STRB (register) 1111 1000 0000 xxxx xxxx 0000 00xx xxxx */ + /* STRH (register) 1111 1000 0010 xxxx xxxx 0000 00xx xxxx */ + /* INVALID INSN 1111 1000 0110 xxxx xxxx 0000 00xx xxxx */ + /* By Introducing INVALID INSN, bit 21 and 22 can be ignored. */ + DECODE_OR (0xff9f0fc0, 0xf80d0000), + DECODE_CUSTOM (0xff900fcf, 0xf800000d, STACK_USE_UNKNOWN), + + + /* xx | Rn | Rt | PUW| imm8 |*/ + /* STR (imm 8) 1111 1000 0100 1101 xxxx 110x xxxx xxxx */ + /* STRB (imm 8) 1111 1000 0000 1101 xxxx 110x xxxx xxxx */ + /* STRH (imm 8) 1111 1000 0010 1101 xxxx 110x xxxx xxxx */ + /* INVALID INSN 1111 1000 0110 1101 xxxx 110x xxxx xxxx */ + /* Only consider U == 0 and P == 1: strx rx, [sp, #-] */ + DECODE_CUSTOM (0xff9f0e00, 0xf80d0c00, STACK_USE_FIXED_0XX), + + /* For STR{,B,H} (imm 12), offset is always positive, so ignore them. */ + + /* P U W | Rn | Rt | Rt2| imm8 |*/ + /* STRD (immediate) 1110 1001 01x0 1101 xxxx xxxx xxxx xxxx */ + /* + * Only consider U == 0 and P == 1. + * Also note that STRD in T32 encoding is special: + * imm = ZeroExtend(imm8:'00', 32) + */ + DECODE_CUSTOM (0xffdf0000, 0xe94d0000, STACK_USE_T32STRD), + + /* | Rn | */ + /* STMDB 1110 1001 00x0 1101 xxxx xxxx xxxx xxxx */ + DECODE_CUSTOM (0xffdf0000, 0xe90d0000, STACK_USE_STMDX), + + /* fall through */ + DECODE_CUSTOM (0, 0, STACK_USE_NONE), + DECODE_END + }; + + return probes_decode_insn(insn, asi, table, false, false, stack_check_actions, NULL); +} + +const struct decode_checker t32_stack_checker[NUM_PROBES_T32_ACTIONS] = { + [PROBES_T32_LDMSTM] = {.checker = t32_check_stack}, + [PROBES_T32_LDRDSTRD] = {.checker = t32_check_stack}, + [PROBES_T32_LDRSTR] = {.checker = t32_check_stack}, +}; + +/* + * See following comments. This insn must be 'push'. + */ +static enum probes_insn __kprobes t16_check_stack(probes_opcode_t insn, + struct arch_probes_insn *asi, + const struct decode_header *h) +{ + unsigned int reglist = insn & 0x1ff; + asi->stack_space = hweight32(reglist) * 4; + return INSN_GOOD; +} + +/* + * T16 encoding is simple: only the 'push' insn can need extra stack space. + * Other insns, like str, can only use r0-r7 as Rn. + */ +const struct decode_checker t16_stack_checker[NUM_PROBES_T16_ACTIONS] = { + [PROBES_T16_PUSH] = {.checker = t16_check_stack}, +}; diff --git a/arch/arm/probes/kprobes/checkers.h b/arch/arm/probes/kprobes/checkers.h new file mode 100644 index 000000000000..bddfa0e82389 --- /dev/null +++ b/arch/arm/probes/kprobes/checkers.h @@ -0,0 +1,54 @@ +/* + * arch/arm/probes/kprobes/checkers.h + * + * Copyright (C) 2014 Huawei 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_PROBES_CHECKERS_H +#define _ARM_KERNEL_PROBES_CHECKERS_H + +#include +#include +#include "../decode.h" + +extern probes_check_t checker_stack_use_none; +extern probes_check_t checker_stack_use_unknown; +#ifdef CONFIG_THUMB2_KERNEL +extern probes_check_t checker_stack_use_imm_0xx; +#else +extern probes_check_t checker_stack_use_imm_x0x; +#endif +extern probes_check_t checker_stack_use_imm_xxx; +extern probes_check_t checker_stack_use_stmdx; + +enum { + STACK_USE_NONE, + STACK_USE_UNKNOWN, +#ifdef CONFIG_THUMB2_KERNEL + STACK_USE_FIXED_0XX, + STACK_USE_T32STRD, +#else + STACK_USE_FIXED_X0X, +#endif + STACK_USE_FIXED_XXX, + STACK_USE_STMDX, + NUM_STACK_USE_TYPES +}; + +extern const union decode_action stack_check_actions[]; + +#ifndef CONFIG_THUMB2_KERNEL +extern const struct decode_checker arm_stack_checker[]; +#else +#endif +extern const struct decode_checker t32_stack_checker[]; +extern const struct decode_checker t16_stack_checker[]; +#endif -- cgit v1.2.3 From a0266c214fab21371a499e6ab1c9385cc6589189 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Mon, 5 Jan 2015 19:29:25 +0800 Subject: ARM: kprobes: disallow probing stack consuming instructions This patch prohibits probing instructions for which the stack requirements are unable to be determined statically. Some test cases are found not work again after the modification, this patch also removes them. Signed-off-by: Wang Nan Reviewed-by: Jon Medhurst Signed-off-by: Jon Medhurst --- arch/arm/include/asm/kprobes.h | 1 - arch/arm/include/asm/probes.h | 12 ++++++++++++ arch/arm/kernel/entry-armv.S | 3 ++- arch/arm/probes/kprobes/core.c | 9 +++++++++ arch/arm/probes/kprobes/test-arm.c | 16 ++++++++++------ 5 files changed, 33 insertions(+), 8 deletions(-) (limited to 'arch') diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h index 49fa0dfaad33..56f9ac68fbd1 100644 --- a/arch/arm/include/asm/kprobes.h +++ b/arch/arm/include/asm/kprobes.h @@ -22,7 +22,6 @@ #define __ARCH_WANT_KPROBES_INSN_SLOT #define MAX_INSN_SIZE 2 -#define MAX_STACK_SIZE 64 /* 32 would probably be OK */ #define flush_insn_slot(p) do { } while (0) #define kretprobe_blacklist_size 0 diff --git a/arch/arm/include/asm/probes.h b/arch/arm/include/asm/probes.h index 6026deb28794..cd9e81588d83 100644 --- a/arch/arm/include/asm/probes.h +++ b/arch/arm/include/asm/probes.h @@ -19,6 +19,8 @@ #ifndef _ASM_PROBES_H #define _ASM_PROBES_H +#ifndef __ASSEMBLY__ + typedef u32 probes_opcode_t; struct arch_probes_insn; @@ -41,4 +43,14 @@ struct arch_probes_insn { int stack_space; }; +#endif /* __ASSEMBLY__ */ + +/* + * We assume one instruction can consume at most 64 bytes stack, which is + * 'push {r0-r15}'. Instructions consume more or unknown stack space like + * 'str r0, [sp, #-80]' and 'str r0, [sp, r1]' should be prohibit to probe. + * Both kprobe and jprobe use this macro. + */ +#define MAX_STACK_SIZE 64 + #endif diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 2f5555d307b3..672b21942fff 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -31,6 +31,7 @@ #include "entry-header.S" #include +#include /* * Interrupt handling. @@ -249,7 +250,7 @@ __und_svc: @ 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 + svc_entry MAX_STACK_SIZE #else svc_entry #endif diff --git a/arch/arm/probes/kprobes/core.c b/arch/arm/probes/kprobes/core.c index 74f3dc3ac212..3a58db4cc1c6 100644 --- a/arch/arm/probes/kprobes/core.c +++ b/arch/arm/probes/kprobes/core.c @@ -115,6 +115,15 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) break; } + /* + * Never instrument insn like 'str r0, [sp, +/-r1]'. Also, insn likes + * 'str r0, [sp, #-68]' should also be prohibited. + * See __und_svc. + */ + if ((p->ainsn.stack_space < 0) || + (p->ainsn.stack_space > MAX_STACK_SIZE)) + return -EINVAL; + return 0; } diff --git a/arch/arm/probes/kprobes/test-arm.c b/arch/arm/probes/kprobes/test-arm.c index d9a1255f3043..fdeb300b0fc8 100644 --- a/arch/arm/probes/kprobes/test-arm.c +++ b/arch/arm/probes/kprobes/test-arm.c @@ -476,7 +476,8 @@ void kprobe_arm_test_cases(void) 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( "streqh r",14,VAL2,", [r",11,0, ", r",12, 48,"]") + TEST_UNSUPPORTED( "streqh r14, [r13, r12]") 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,"") @@ -565,7 +566,8 @@ void kprobe_arm_test_cases(void) #if __LINUX_ARM_ARCH__ >= 5 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( "strccd r",8, VAL2,", [r",11,0, ", r",12,48,"]") + TEST_UNSUPPORTED( "strccd r8, [r13, r12]") 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,"") @@ -638,13 +640,15 @@ void kprobe_arm_test_cases(void) 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",14,VAL2,", [r",11,0, ", r",12, 48,"]") \ + TEST_UNSUPPORTED("str"byte" r14, [r13, r12]") \ 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",14,VAL2,", [r",11,0, ", r",12, 32,", lsr #2]")\ + TEST_UNSUPPORTED("str"byte" r14, [r13, r12, 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]") \ @@ -668,12 +672,12 @@ void kprobe_arm_test_cases(void) LOAD_STORE("") TEST_P( "str pc, [r",0,0,", #15*4]") - TEST_R( "str pc, [sp, r",2,15*4,"]") + TEST_UNSUPPORTED( "str pc, [sp, r2]") 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_UNSUPPORTED( "str sp, [sp, r2]") TEST_BF( "ldr sp, [sp, #13*4]") TEST_BF_R("ldr sp, [sp, r",2,13*4,"]") -- cgit v1.2.3 From 8d257e95a9e643518e72232bf852b054a3d06c95 Mon Sep 17 00:00:00 2001 From: "Jon Medhurst (Tixy)" Date: Mon, 5 Jan 2015 19:29:29 +0800 Subject: ARM: kprobes: Add test cases for stack consuming instructions These have extra 'checker' functions associated with them so lets make sure those get covered by testing. As they may create uninitialised space on the stack we also update the test code to ensure such space is consistent between test runs. This is done by disabling interrupts in setup_test_context(). Signed-off-by: Jon Medhurst --- arch/arm/probes/kprobes/test-arm.c | 17 +++++++++++++++-- arch/arm/probes/kprobes/test-core.c | 9 +++++++++ arch/arm/probes/kprobes/test-thumb.c | 12 ++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/probes/kprobes/test-arm.c b/arch/arm/probes/kprobes/test-arm.c index fdeb300b0fc8..9b3b1b4a0939 100644 --- a/arch/arm/probes/kprobes/test-arm.c +++ b/arch/arm/probes/kprobes/test-arm.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "test-core.h" @@ -478,6 +479,7 @@ void kprobe_arm_test_cases(void) TEST_RPR( "strh r",0, VAL1,", [r",1, 48,", -r",2, 24,"]") TEST_RPR( "streqh r",14,VAL2,", [r",11,0, ", r",12, 48,"]") TEST_UNSUPPORTED( "streqh r14, [r13, r12]") + TEST_UNSUPPORTED( "streqh r14, [r12, r13]") 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,"") @@ -502,6 +504,9 @@ void kprobe_arm_test_cases(void) 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_RP( "strh r",3, VAL1,", [r",13,TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"]!") + TEST_UNSUPPORTED("strh r3, [r13, #-"__stringify(MAX_STACK_SIZE)"-8]!") + TEST_RP( "strh r",4, VAL1,", [r",14,TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"-8]!") TEST_UNSUPPORTED(__inst_arm(0xe1efc3b0) " @ strh r12, [pc, #48]!") TEST_UNSUPPORTED(__inst_arm(0xe0c9f3b0) " @ strh pc, [r9], #48") @@ -568,6 +573,7 @@ void kprobe_arm_test_cases(void) TEST_RPR( "strd r",0, VAL1,", [r",1, 48,", -r",2,24,"]") TEST_RPR( "strccd r",8, VAL2,", [r",11,0, ", r",12,48,"]") TEST_UNSUPPORTED( "strccd r8, [r13, r12]") + TEST_UNSUPPORTED( "strccd r8, [r12, r13]") 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,"") @@ -591,6 +597,9 @@ void kprobe_arm_test_cases(void) 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_RP( "strd r",6, VAL1,", [r",13,TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"]!") + TEST_UNSUPPORTED("strd r6, [r13, #-"__stringify(MAX_STACK_SIZE)"-8]!") + TEST_RP( "strd r",4, VAL1,", [r",12,TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"-8]!") TEST_UNSUPPORTED(__inst_arm(0xe1efc3f0) " @ strd r12, [pc, #48]!") TEST_P( "ldrd r0, [r",0, 24,", #-8]") @@ -639,16 +648,20 @@ void kprobe_arm_test_cases(void) 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_RP( "str"byte" r",3, VAL1,", [r",13,TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"]!") \ + TEST_UNSUPPORTED("str"byte" r3, [r13, #-"__stringify(MAX_STACK_SIZE)"-8]!") \ + TEST_RP( "str"byte" r",4, VAL1,", [r",10,TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"-8]!") \ TEST_RPR("str"byte" r",0, VAL1,", [r",1, 48,", -r",2, 24,"]") \ TEST_RPR("str"byte" r",14,VAL2,", [r",11,0, ", r",12, 48,"]") \ - TEST_UNSUPPORTED("str"byte" r14, [r13, r12]") \ + TEST_UNSUPPORTED("str"byte" r14, [r13, r12]") \ + TEST_UNSUPPORTED("str"byte" r14, [r12, r13]") \ 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",11,0, ", r",12, 32,", lsr #2]")\ - TEST_UNSUPPORTED("str"byte" r14, [r13, r12, lsr #2]")\ + TEST_UNSUPPORTED("str"byte" r14, [r13, r12, 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]") \ diff --git a/arch/arm/probes/kprobes/test-core.c b/arch/arm/probes/kprobes/test-core.c index 7ab633d51954..7c5ddd5a6afd 100644 --- a/arch/arm/probes/kprobes/test-core.c +++ b/arch/arm/probes/kprobes/test-core.c @@ -1196,6 +1196,13 @@ static void setup_test_context(struct pt_regs *regs) regs->uregs[arg->reg] = (unsigned long)current_stack + arg->val; memory_needs_checking = true; + /* + * Test memory at an address below SP is in danger of + * being altered by an interrupt occurring and pushing + * data onto the stack. Disable interrupts to stop this. + */ + if (arg->reg == 13) + regs->ARM_cpsr |= PSR_I_BIT; break; } case ARG_TYPE_MEM: { @@ -1272,6 +1279,8 @@ test_after_pre_handler(struct kprobe *p, struct pt_regs *regs) /* Undo any changes done to SP by the test case */ regs->ARM_sp = (unsigned long)current_stack; + /* Enable interrupts in case setup_test_context disabled them */ + regs->ARM_cpsr &= ~PSR_I_BIT; container_of(p, struct test_probe, kprobe)->hit = test_instance; return 0; diff --git a/arch/arm/probes/kprobes/test-thumb.c b/arch/arm/probes/kprobes/test-thumb.c index 6c6e9a9bb675..e8cf193db1ea 100644 --- a/arch/arm/probes/kprobes/test-thumb.c +++ b/arch/arm/probes/kprobes/test-thumb.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "test-core.h" @@ -416,6 +417,9 @@ void kprobe_thumb32_test_cases(void) 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_RRP("strd r",6, VAL1,", r",7, VAL2,", [r",13, TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"]!") + TEST_UNSUPPORTED("strd r6, r7, [r13, #-"__stringify(MAX_STACK_SIZE)"-8]!") + TEST_RRP("strd r",4, VAL1,", r",5, VAL2,", [r",14, TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"-8]!") TEST_UNSUPPORTED(__inst_thumb32(0xe9efec04) " @ strd r14, r12, [pc, #16]!") TEST_UNSUPPORTED(__inst_thumb32(0xe8efec04) " @ strd r14, r12, [pc], #16") @@ -821,14 +825,22 @@ CONDITION_INSTRUCTIONS(22, 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_UNSUPPORTED("str"size" r0, [r13, r1]") \ TEST_R( "str"size".w r",7, VAL1,", [sp, #24]") \ TEST_RP( "str"size".w r",0, VAL2,", [r",0,0, "]") \ + TEST_RP( "str"size" r",6, VAL1,", [r",13, TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"]!") \ + TEST_UNSUPPORTED("str"size" r6, [r13, #-"__stringify(MAX_STACK_SIZE)"-8]!") \ + TEST_RP( "str"size" r",4, VAL2,", [r",12, TEST_MEMORY_SIZE,", #-"__stringify(MAX_STACK_SIZE)"-8]!") \ TEST_UNSUPPORTED("str"size"t r0, [r1, #4]") SINGLE_STORE("b") SINGLE_STORE("h") SINGLE_STORE("") + TEST_UNSUPPORTED(__inst_thumb32(0xf801000d) " @ strb r0, [r1, r13]") + TEST_UNSUPPORTED(__inst_thumb32(0xf821000d) " @ strh r0, [r1, r13]") + TEST_UNSUPPORTED(__inst_thumb32(0xf841000d) " @ str r0, [r1, r13]") + TEST("str sp, [sp]") TEST_UNSUPPORTED(__inst_thumb32(0xf8cfe000) " @ str r14, [pc]") TEST_UNSUPPORTED(__inst_thumb32(0xf8cef000) " @ str pc, [r14]") -- cgit v1.2.3 From cbf6ab52add20b845f903decc973afbd5463c527 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 5 Jan 2015 19:29:32 +0800 Subject: kprobes: Pass the original kprobe for preparing optimized kprobe Pass the original kprobe for preparing an optimized kprobe arch-dep part, since for some architecture (e.g. ARM32) requires the information in original kprobe. Signed-off-by: Masami Hiramatsu Signed-off-by: Wang Nan Signed-off-by: Jon Medhurst --- arch/x86/kernel/kprobes/opt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c index 7c523bbf3dc8..0dd8d089c315 100644 --- a/arch/x86/kernel/kprobes/opt.c +++ b/arch/x86/kernel/kprobes/opt.c @@ -322,7 +322,8 @@ void arch_remove_optimized_kprobe(struct optimized_kprobe *op) * Target instructions MUST be relocatable (checked inside) * This is called when new aggr(opt)probe is allocated or reused. */ -int arch_prepare_optimized_kprobe(struct optimized_kprobe *op) +int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, + struct kprobe *__unused) { u8 *buf; int ret; -- cgit v1.2.3 From 0dc016dbd820260b8ea74337980735b8c88d4ef2 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Fri, 9 Jan 2015 14:37:36 +0800 Subject: ARM: kprobes: enable OPTPROBES for ARM 32 This patch introduce kprobeopt for ARM 32. Limitations: - Currently only kernel compiled with ARM ISA is supported. - Offset between probe point and optinsn slot must not larger than 32MiB. Masami Hiramatsu suggests replacing 2 words, it will make things complex. Futher patch can make such optimization. Kprobe opt on ARM is relatively simpler than kprobe opt on x86 because ARM instruction is always 4 bytes aligned and 4 bytes long. This patch replace probed instruction by a 'b', branch to trampoline code and then calls optimized_callback(). optimized_callback() calls opt_pre_handler() to execute kprobe handler. It also emulate/simulate replaced instruction. When unregistering kprobe, the deferred manner of unoptimizer may leave branch instruction before optimizer is called. Different from x86_64, which only copy the probed insn after optprobe_template_end and reexecute them, this patch call singlestep to emulate/simulate the insn directly. Futher patch can optimize this behavior. Signed-off-by: Wang Nan Acked-by: Masami Hiramatsu Cc: Will Deacon Reviewed-by: Jon Medhurst (Tixy) Signed-off-by: Jon Medhurst --- arch/arm/Kconfig | 1 + arch/arm/include/asm/insn.h | 29 ++++ arch/arm/include/asm/kprobes.h | 29 ++++ arch/arm/kernel/Makefile | 2 +- arch/arm/kernel/ftrace.c | 3 +- arch/arm/kernel/insn.h | 29 ---- arch/arm/kernel/jump_label.c | 3 +- arch/arm/probes/kprobes/Makefile | 1 + arch/arm/probes/kprobes/core.c | 26 ++- arch/arm/probes/kprobes/core.h | 2 + arch/arm/probes/kprobes/opt-arm.c | 322 ++++++++++++++++++++++++++++++++++++++ 11 files changed, 406 insertions(+), 41 deletions(-) create mode 100644 arch/arm/include/asm/insn.h delete mode 100644 arch/arm/kernel/insn.h create mode 100644 arch/arm/probes/kprobes/opt-arm.c (limited to 'arch') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 97d07ed60a0b..3d5dc2df835b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -60,6 +60,7 @@ config ARM select HAVE_MEMBLOCK select HAVE_MOD_ARCH_SPECIFIC if ARM_UNWIND select HAVE_OPROFILE if (HAVE_PERF_EVENTS) + select HAVE_OPTPROBES if !THUMB2_KERNEL select HAVE_PERF_EVENTS select HAVE_PERF_REGS select HAVE_PERF_USER_STACK_DUMP diff --git a/arch/arm/include/asm/insn.h b/arch/arm/include/asm/insn.h new file mode 100644 index 000000000000..e96065da4dae --- /dev/null +++ b/arch/arm/include/asm/insn.h @@ -0,0 +1,29 @@ +#ifndef __ASM_ARM_INSN_H +#define __ASM_ARM_INSN_H + +static inline unsigned long +arm_gen_nop(void) +{ +#ifdef CONFIG_THUMB2_KERNEL + return 0xf3af8000; /* nop.w */ +#else + return 0xe1a00000; /* mov r0, r0 */ +#endif +} + +unsigned long +__arm_gen_branch(unsigned long pc, unsigned long addr, bool link); + +static inline unsigned long +arm_gen_branch(unsigned long pc, unsigned long addr) +{ + return __arm_gen_branch(pc, addr, false); +} + +static inline unsigned long +arm_gen_branch_link(unsigned long pc, unsigned long addr) +{ + return __arm_gen_branch(pc, addr, true); +} + +#endif diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h index 56f9ac68fbd1..50ff3bc7928e 100644 --- a/arch/arm/include/asm/kprobes.h +++ b/arch/arm/include/asm/kprobes.h @@ -50,5 +50,34 @@ int kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr); int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *data); +/* optinsn template addresses */ +extern __visible kprobe_opcode_t optprobe_template_entry; +extern __visible kprobe_opcode_t optprobe_template_val; +extern __visible kprobe_opcode_t optprobe_template_call; +extern __visible kprobe_opcode_t optprobe_template_end; +extern __visible kprobe_opcode_t optprobe_template_sub_sp; +extern __visible kprobe_opcode_t optprobe_template_add_sp; + +#define MAX_OPTIMIZED_LENGTH 4 +#define MAX_OPTINSN_SIZE \ + ((unsigned long)&optprobe_template_end - \ + (unsigned long)&optprobe_template_entry) +#define RELATIVEJUMP_SIZE 4 + +struct arch_optimized_insn { + /* + * copy of the original instructions. + * Different from x86, ARM kprobe_opcode_t is u32. + */ +#define MAX_COPIED_INSN DIV_ROUND_UP(RELATIVEJUMP_SIZE, sizeof(kprobe_opcode_t)) + kprobe_opcode_t copied_insn[MAX_COPIED_INSN]; + /* detour code buffer */ + kprobe_opcode_t *insn; + /* + * We always copy one instruction on ARM, + * so size will always be 4, and unlike x86, there is no + * need for a size field. + */ +}; #endif /* _ARM_KPROBES_H */ diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 9c51a433e025..902397dd1000 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -52,7 +52,7 @@ 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 # Main staffs in KPROBES are in arch/arm/probes/ . -obj-$(CONFIG_KPROBES) += patch.o +obj-$(CONFIG_KPROBES) += patch.o insn.o obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o obj-$(CONFIG_ARM_THUMBEE) += thumbee.o obj-$(CONFIG_KGDB) += kgdb.o patch.o diff --git a/arch/arm/kernel/ftrace.c b/arch/arm/kernel/ftrace.c index b8c75e45a950..709ee1d6d4df 100644 --- a/arch/arm/kernel/ftrace.c +++ b/arch/arm/kernel/ftrace.c @@ -20,8 +20,7 @@ #include #include #include - -#include "insn.h" +#include #ifdef CONFIG_THUMB2_KERNEL #define NOP 0xf85deb04 /* pop.w {lr} */ diff --git a/arch/arm/kernel/insn.h b/arch/arm/kernel/insn.h deleted file mode 100644 index e96065da4dae..000000000000 --- a/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/arch/arm/kernel/jump_label.c b/arch/arm/kernel/jump_label.c index d8da075959bf..e39cbf488cfe 100644 --- a/arch/arm/kernel/jump_label.c +++ b/arch/arm/kernel/jump_label.c @@ -1,8 +1,7 @@ #include #include #include - -#include "insn.h" +#include #ifdef HAVE_JUMP_LABEL diff --git a/arch/arm/probes/kprobes/Makefile b/arch/arm/probes/kprobes/Makefile index bc8d504c3d78..76a36bf102b7 100644 --- a/arch/arm/probes/kprobes/Makefile +++ b/arch/arm/probes/kprobes/Makefile @@ -7,5 +7,6 @@ obj-$(CONFIG_KPROBES) += actions-thumb.o checkers-thumb.o test-kprobes-objs += test-thumb.o else obj-$(CONFIG_KPROBES) += actions-arm.o checkers-arm.o +obj-$(CONFIG_OPTPROBES) += opt-arm.o test-kprobes-objs += test-arm.o endif diff --git a/arch/arm/probes/kprobes/core.c b/arch/arm/probes/kprobes/core.c index 3a58db4cc1c6..a4ec240ee7ba 100644 --- a/arch/arm/probes/kprobes/core.c +++ b/arch/arm/probes/kprobes/core.c @@ -163,19 +163,31 @@ void __kprobes arch_arm_kprobe(struct kprobe *p) * 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); +struct patch { + void *addr; + unsigned int insn; +}; +static int __kprobes_remove_breakpoint(void *data) +{ + struct patch *p = data; + __patch_text(p->addr, p->insn); return 0; } +void __kprobes kprobes_remove_breakpoint(void *addr, unsigned int insn) +{ + struct patch p = { + .addr = addr, + .insn = insn, + }; + stop_machine(__kprobes_remove_breakpoint, &p, cpu_online_mask); +} + void __kprobes arch_disarm_kprobe(struct kprobe *p) { - stop_machine(__arch_disarm_kprobe, p, cpu_online_mask); + kprobes_remove_breakpoint((void *)((uintptr_t)p->addr & ~1), + p->opcode); } void __kprobes arch_remove_kprobe(struct kprobe *p) diff --git a/arch/arm/probes/kprobes/core.h b/arch/arm/probes/kprobes/core.h index f88c79fe632a..b3036c587a76 100644 --- a/arch/arm/probes/kprobes/core.h +++ b/arch/arm/probes/kprobes/core.h @@ -30,6 +30,8 @@ #define KPROBE_THUMB16_BREAKPOINT_INSTRUCTION 0xde18 #define KPROBE_THUMB32_BREAKPOINT_INSTRUCTION 0xf7f0a018 +extern void kprobes_remove_breakpoint(void *addr, unsigned int insn); + enum probes_insn __kprobes kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_probes_insn *asi, const struct decode_header *h); diff --git a/arch/arm/probes/kprobes/opt-arm.c b/arch/arm/probes/kprobes/opt-arm.c new file mode 100644 index 000000000000..13d5232118df --- /dev/null +++ b/arch/arm/probes/kprobes/opt-arm.c @@ -0,0 +1,322 @@ +/* + * Kernel Probes Jump Optimization (Optprobes) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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) IBM Corporation, 2002, 2004 + * Copyright (C) Hitachi Ltd., 2012 + * Copyright (C) Huawei Inc., 2014 + */ + +#include +#include +#include +#include +/* for arm_gen_branch */ +#include +/* for patch_text */ +#include + +#include "core.h" + +/* + * NOTE: the first sub and add instruction will be modified according + * to the stack cost of the instruction. + */ +asm ( + ".global optprobe_template_entry\n" + "optprobe_template_entry:\n" + ".global optprobe_template_sub_sp\n" + "optprobe_template_sub_sp:" + " sub sp, sp, #0xff\n" + " stmia sp, {r0 - r14} \n" + ".global optprobe_template_add_sp\n" + "optprobe_template_add_sp:" + " add r3, sp, #0xff\n" + " str r3, [sp, #52]\n" + " mrs r4, cpsr\n" + " str r4, [sp, #64]\n" + " mov r1, sp\n" + " ldr r0, 1f\n" + " ldr r2, 2f\n" + /* + * AEABI requires an 8-bytes alignment stack. If + * SP % 8 != 0 (SP % 4 == 0 should be ensured), + * alloc more bytes here. + */ + " and r4, sp, #4\n" + " sub sp, sp, r4\n" +#if __LINUX_ARM_ARCH__ >= 5 + " blx r2\n" +#else + " mov lr, pc\n" + " mov pc, r2\n" +#endif + " add sp, sp, r4\n" + " ldr r1, [sp, #64]\n" + " tst r1, #"__stringify(PSR_T_BIT)"\n" + " ldrne r2, [sp, #60]\n" + " orrne r2, #1\n" + " strne r2, [sp, #60] @ set bit0 of PC for thumb\n" + " msr cpsr_cxsf, r1\n" + " ldmia sp, {r0 - r15}\n" + ".global optprobe_template_val\n" + "optprobe_template_val:\n" + "1: .long 0\n" + ".global optprobe_template_call\n" + "optprobe_template_call:\n" + "2: .long 0\n" + ".global optprobe_template_end\n" + "optprobe_template_end:\n"); + +#define TMPL_VAL_IDX \ + ((unsigned long *)&optprobe_template_val - (unsigned long *)&optprobe_template_entry) +#define TMPL_CALL_IDX \ + ((unsigned long *)&optprobe_template_call - (unsigned long *)&optprobe_template_entry) +#define TMPL_END_IDX \ + ((unsigned long *)&optprobe_template_end - (unsigned long *)&optprobe_template_entry) +#define TMPL_ADD_SP \ + ((unsigned long *)&optprobe_template_add_sp - (unsigned long *)&optprobe_template_entry) +#define TMPL_SUB_SP \ + ((unsigned long *)&optprobe_template_sub_sp - (unsigned long *)&optprobe_template_entry) + +/* + * ARM can always optimize an instruction when using ARM ISA, except + * instructions like 'str r0, [sp, r1]' which store to stack and unable + * to determine stack space consumption statically. + */ +int arch_prepared_optinsn(struct arch_optimized_insn *optinsn) +{ + return optinsn->insn != NULL; +} + +/* + * In ARM ISA, kprobe opt always replace one instruction (4 bytes + * aligned and 4 bytes long). It is impossible to encounter another + * kprobe in the address range. So always return 0. + */ +int arch_check_optimized_kprobe(struct optimized_kprobe *op) +{ + return 0; +} + +/* Caller must ensure addr & 3 == 0 */ +static int can_optimize(struct kprobe *kp) +{ + if (kp->ainsn.stack_space < 0) + return 0; + /* + * 255 is the biggest imm can be used in 'sub r0, r0, #'. + * Number larger than 255 needs special encoding. + */ + if (kp->ainsn.stack_space > 255 - sizeof(struct pt_regs)) + return 0; + return 1; +} + +/* Free optimized instruction slot */ +static void +__arch_remove_optimized_kprobe(struct optimized_kprobe *op, int dirty) +{ + if (op->optinsn.insn) { + free_optinsn_slot(op->optinsn.insn, dirty); + op->optinsn.insn = NULL; + } +} + +extern void kprobe_handler(struct pt_regs *regs); + +static void +optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs) +{ + unsigned long flags; + struct kprobe *p = &op->kp; + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + + /* Save skipped registers */ + regs->ARM_pc = (unsigned long)op->kp.addr; + regs->ARM_ORIG_r0 = ~0UL; + + local_irq_save(flags); + + if (kprobe_running()) { + kprobes_inc_nmissed_count(&op->kp); + } else { + __this_cpu_write(current_kprobe, &op->kp); + kcb->kprobe_status = KPROBE_HIT_ACTIVE; + opt_pre_handler(&op->kp, regs); + __this_cpu_write(current_kprobe, NULL); + } + + /* In each case, we must singlestep the replaced instruction. */ + op->kp.ainsn.insn_singlestep(p->opcode, &p->ainsn, regs); + + local_irq_restore(flags); +} + +int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *orig) +{ + kprobe_opcode_t *code; + unsigned long rel_chk; + unsigned long val; + unsigned long stack_protect = sizeof(struct pt_regs); + + if (!can_optimize(orig)) + return -EILSEQ; + + code = get_optinsn_slot(); + if (!code) + return -ENOMEM; + + /* + * Verify if the address gap is in 32MiB range, because this uses + * a relative jump. + * + * kprobe opt use a 'b' instruction to branch to optinsn.insn. + * According to ARM manual, branch instruction is: + * + * 31 28 27 24 23 0 + * +------+---+---+---+---+----------------+ + * | cond | 1 | 0 | 1 | 0 | imm24 | + * +------+---+---+---+---+----------------+ + * + * imm24 is a signed 24 bits integer. The real branch offset is computed + * by: imm32 = SignExtend(imm24:'00', 32); + * + * So the maximum forward branch should be: + * (0x007fffff << 2) = 0x01fffffc = 0x1fffffc + * The maximum backword branch should be: + * (0xff800000 << 2) = 0xfe000000 = -0x2000000 + * + * We can simply check (rel & 0xfe000003): + * if rel is positive, (rel & 0xfe000000) shoule be 0 + * if rel is negitive, (rel & 0xfe000000) should be 0xfe000000 + * the last '3' is used for alignment checking. + */ + rel_chk = (unsigned long)((long)code - + (long)orig->addr + 8) & 0xfe000003; + + if ((rel_chk != 0) && (rel_chk != 0xfe000000)) { + /* + * Different from x86, we free code buf directly instead of + * calling __arch_remove_optimized_kprobe() because + * we have not fill any field in op. + */ + free_optinsn_slot(code, 0); + return -ERANGE; + } + + /* Copy arch-dep-instance from template. */ + memcpy(code, &optprobe_template_entry, + TMPL_END_IDX * sizeof(kprobe_opcode_t)); + + /* Adjust buffer according to instruction. */ + BUG_ON(orig->ainsn.stack_space < 0); + + stack_protect += orig->ainsn.stack_space; + + /* Should have been filtered by can_optimize(). */ + BUG_ON(stack_protect > 255); + + /* Create a 'sub sp, sp, #' */ + code[TMPL_SUB_SP] = __opcode_to_mem_arm(0xe24dd000 | stack_protect); + /* Create a 'add r3, sp, #' */ + code[TMPL_ADD_SP] = __opcode_to_mem_arm(0xe28d3000 | stack_protect); + + /* Set probe information */ + val = (unsigned long)op; + code[TMPL_VAL_IDX] = val; + + /* Set probe function call */ + val = (unsigned long)optimized_callback; + code[TMPL_CALL_IDX] = val; + + flush_icache_range((unsigned long)code, + (unsigned long)(&code[TMPL_END_IDX])); + + /* Set op->optinsn.insn means prepared. */ + op->optinsn.insn = code; + return 0; +} + +void __kprobes arch_optimize_kprobes(struct list_head *oplist) +{ + struct optimized_kprobe *op, *tmp; + + list_for_each_entry_safe(op, tmp, oplist, list) { + unsigned long insn; + WARN_ON(kprobe_disabled(&op->kp)); + + /* + * Backup instructions which will be replaced + * by jump address + */ + memcpy(op->optinsn.copied_insn, op->kp.addr, + RELATIVEJUMP_SIZE); + + insn = arm_gen_branch((unsigned long)op->kp.addr, + (unsigned long)op->optinsn.insn); + BUG_ON(insn == 0); + + /* + * Make it a conditional branch if replaced insn + * is consitional + */ + insn = (__mem_to_opcode_arm( + op->optinsn.copied_insn[0]) & 0xf0000000) | + (insn & 0x0fffffff); + + /* + * Similar to __arch_disarm_kprobe, operations which + * removing breakpoints must be wrapped by stop_machine + * to avoid racing. + */ + kprobes_remove_breakpoint(op->kp.addr, insn); + + list_del_init(&op->list); + } +} + +void arch_unoptimize_kprobe(struct optimized_kprobe *op) +{ + arch_arm_kprobe(&op->kp); +} + +/* + * Recover original instructions and breakpoints from relative jumps. + * Caller must call with locking kprobe_mutex. + */ +void arch_unoptimize_kprobes(struct list_head *oplist, + struct list_head *done_list) +{ + struct optimized_kprobe *op, *tmp; + + list_for_each_entry_safe(op, tmp, oplist, list) { + arch_unoptimize_kprobe(op); + list_move(&op->list, done_list); + } +} + +int arch_within_optimized_kprobe(struct optimized_kprobe *op, + unsigned long addr) +{ + return ((unsigned long)op->kp.addr <= addr && + (unsigned long)op->kp.addr + RELATIVEJUMP_SIZE > addr); +} + +void arch_remove_optimized_kprobe(struct optimized_kprobe *op) +{ + __arch_remove_optimized_kprobe(op, 1); +} -- cgit v1.2.3 From 4cd872d973c7e1ce6a41e36db9d9352152da32d4 Mon Sep 17 00:00:00 2001 From: "Jon Medhurst (Tixy)" Date: Mon, 5 Jan 2015 19:29:40 +0800 Subject: ARM: kprobes: Fix unreliable MRS instruction tests For the instruction 'mrs Rn, cpsr' the resulting value of Rn can vary due to external factors we can't control. So get the test code to mask out these indeterminate bits. Signed-off-by: Jon Medhurst --- arch/arm/probes/kprobes/test-arm.c | 6 +++--- arch/arm/probes/kprobes/test-core.c | 19 ++++++++++--------- arch/arm/probes/kprobes/test-core.h | 33 ++++++++++++++++++++++++++++----- arch/arm/probes/kprobes/test-thumb.c | 4 ++-- 4 files changed, 43 insertions(+), 19 deletions(-) (limited to 'arch') diff --git a/arch/arm/probes/kprobes/test-arm.c b/arch/arm/probes/kprobes/test-arm.c index 9b3b1b4a0939..e72b07e8cd9a 100644 --- a/arch/arm/probes/kprobes/test-arm.c +++ b/arch/arm/probes/kprobes/test-arm.c @@ -204,9 +204,9 @@ void kprobe_arm_test_cases(void) #endif TEST_GROUP("Miscellaneous instructions") - TEST("mrs r0, cpsr") - TEST("mrspl r7, cpsr") - TEST("mrs r14, cpsr") + TEST_RMASKED("mrs r",0,~PSR_IGNORE_BITS,", cpsr") + TEST_RMASKED("mrspl r",7,~PSR_IGNORE_BITS,", cpsr") + TEST_RMASKED("mrs r",14,~PSR_IGNORE_BITS,", cpsr") TEST_UNSUPPORTED(__inst_arm(0xe10ff000) " @ mrs r15, cpsr") TEST_UNSUPPORTED("mrs r0, spsr") TEST_UNSUPPORTED("mrs lr, spsr") diff --git a/arch/arm/probes/kprobes/test-core.c b/arch/arm/probes/kprobes/test-core.c index 7c5ddd5a6afd..e495127d7571 100644 --- a/arch/arm/probes/kprobes/test-core.c +++ b/arch/arm/probes/kprobes/test-core.c @@ -1056,15 +1056,6 @@ 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); @@ -1271,11 +1262,21 @@ test_case_pre_handler(struct kprobe *p, struct pt_regs *regs) static int __kprobes test_after_pre_handler(struct kprobe *p, struct pt_regs *regs) { + struct test_arg *args; + if (container_of(p, struct test_probe, kprobe)->hit == test_instance) return 0; /* Already run for this test instance */ result_regs = *regs; + + /* Mask out results which are indeterminate */ result_regs.ARM_cpsr &= ~PSR_IGNORE_BITS; + for (args = current_args; args[0].type != ARG_TYPE_END; ++args) + if (args[0].type == ARG_TYPE_REG_MASKED) { + struct test_arg_regptr *arg = + (struct test_arg_regptr *)args; + result_regs.uregs[arg->reg] &= arg->val; + } /* Undo any changes done to SP by the test case */ regs->ARM_sp = (unsigned long)current_stack; diff --git a/arch/arm/probes/kprobes/test-core.h b/arch/arm/probes/kprobes/test-core.h index 9991754947bc..94285203e9f7 100644 --- a/arch/arm/probes/kprobes/test-core.h +++ b/arch/arm/probes/kprobes/test-core.h @@ -45,10 +45,11 @@ extern int kprobe_test_cc_position; * */ -#define ARG_TYPE_END 0 -#define ARG_TYPE_REG 1 -#define ARG_TYPE_PTR 2 -#define ARG_TYPE_MEM 3 +#define ARG_TYPE_END 0 +#define ARG_TYPE_REG 1 +#define ARG_TYPE_PTR 2 +#define ARG_TYPE_MEM 3 +#define ARG_TYPE_REG_MASKED 4 #define ARG_FLAG_UNSUPPORTED 0x01 #define ARG_FLAG_SUPPORTED 0x02 @@ -61,7 +62,7 @@ struct test_arg { }; struct test_arg_regptr { - u8 type; /* ARG_TYPE_REG or ARG_TYPE_PTR */ + u8 type; /* ARG_TYPE_REG or ARG_TYPE_PTR or ARG_TYPE_REG_MASKED */ u8 reg; u8 _padding[2]; u32 val; @@ -138,6 +139,12 @@ struct test_arg_end { ".short 0 \n\t" \ ".word "#val" \n\t" +#define TEST_ARG_REG_MASKED(reg, val) \ + ".byte "__stringify(ARG_TYPE_REG_MASKED)" \n\t" \ + ".byte "#reg" \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" \ @@ -395,6 +402,22 @@ struct test_arg_end { " "codex" \n\t" \ TESTCASE_END +#define TEST_RMASKED(code1, reg, mask, code2) \ + TESTCASE_START(code1 #reg code2) \ + TEST_ARG_REG_MASKED(reg, mask) \ + TEST_ARG_END("") \ + TEST_INSTRUCTION(code1 #reg code2) \ + TESTCASE_END + +/* + * 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 Extensions, 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) + /* * Macros for defining space directives spread over multiple lines. diff --git a/arch/arm/probes/kprobes/test-thumb.c b/arch/arm/probes/kprobes/test-thumb.c index e8cf193db1ea..b683b4517458 100644 --- a/arch/arm/probes/kprobes/test-thumb.c +++ b/arch/arm/probes/kprobes/test-thumb.c @@ -778,8 +778,8 @@ CONDITION_INSTRUCTIONS(22, TEST_UNSUPPORTED("subs pc, lr, #4") - TEST("mrs r0, cpsr") - TEST("mrs r14, cpsr") + TEST_RMASKED("mrs r",0,~PSR_IGNORE_BITS,", cpsr") + TEST_RMASKED("mrs r",14,~PSR_IGNORE_BITS,", cpsr") TEST_UNSUPPORTED(__inst_thumb32(0xf3ef8d00) " @ mrs sp, spsr") TEST_UNSUPPORTED(__inst_thumb32(0xf3ef8f00) " @ mrs pc, spsr") TEST_UNSUPPORTED("mrs r0, spsr") -- cgit v1.2.3 From 28a1899db30a9325498aef114055506286dc8010 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Mon, 5 Jan 2015 19:29:44 +0800 Subject: ARM: kprobes: check register usage for probed instruction. This patch utilizes the previously introduced checker to check register usage for probed ARM instruction and saves it in a mask. A further patch will use such information to avoid simulation or emulation. Signed-off-by: Wang Nan Reviewed-by: Jon Medhurst Signed-off-by: Jon Medhurst --- arch/arm/include/asm/probes.h | 1 + arch/arm/probes/decode.c | 7 +++ arch/arm/probes/kprobes/actions-arm.c | 2 +- arch/arm/probes/kprobes/checkers-arm.c | 93 ++++++++++++++++++++++++++++++++++ arch/arm/probes/kprobes/checkers.h | 1 + 5 files changed, 103 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/include/asm/probes.h b/arch/arm/include/asm/probes.h index cd9e81588d83..b668e60f759c 100644 --- a/arch/arm/include/asm/probes.h +++ b/arch/arm/include/asm/probes.h @@ -41,6 +41,7 @@ struct arch_probes_insn { probes_insn_singlestep_t *insn_singlestep; probes_insn_fn_t *insn_fn; int stack_space; + unsigned long register_usage_flags; }; #endif /* __ASSEMBLY__ */ diff --git a/arch/arm/probes/decode.c b/arch/arm/probes/decode.c index f9d7c423f2cc..880ebe0cdf19 100644 --- a/arch/arm/probes/decode.c +++ b/arch/arm/probes/decode.c @@ -435,6 +435,13 @@ probes_decode_insn(probes_opcode_t insn, struct arch_probes_insn *asi, */ asi->stack_space = 0; + /* + * Similarly to stack_space, register_usage_flags is filled by + * checkers. Its default value is set to ~0, which is 'all + * registers are used', to prevent any potential optimization. + */ + asi->register_usage_flags = ~0UL; + if (emulate) insn = prepare_emulated_insn(insn, asi, thumb); diff --git a/arch/arm/probes/kprobes/actions-arm.c b/arch/arm/probes/kprobes/actions-arm.c index 06988ef7eeb7..b9056d649607 100644 --- a/arch/arm/probes/kprobes/actions-arm.c +++ b/arch/arm/probes/kprobes/actions-arm.c @@ -341,4 +341,4 @@ const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = { [PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm} }; -const struct decode_checker *kprobes_arm_checkers[] = {arm_stack_checker, NULL}; +const struct decode_checker *kprobes_arm_checkers[] = {arm_stack_checker, arm_regs_checker, NULL}; diff --git a/arch/arm/probes/kprobes/checkers-arm.c b/arch/arm/probes/kprobes/checkers-arm.c index f8176631d2a5..7b9817333b68 100644 --- a/arch/arm/probes/kprobes/checkers-arm.c +++ b/arch/arm/probes/kprobes/checkers-arm.c @@ -97,3 +97,96 @@ const struct decode_checker arm_stack_checker[NUM_PROBES_ARM_ACTIONS] = { [PROBES_STORE] = {.checker = arm_check_stack}, [PROBES_LDMSTM] = {.checker = arm_check_stack}, }; + +static enum probes_insn __kprobes arm_check_regs_nouse(probes_opcode_t insn, + struct arch_probes_insn *asi, + const struct decode_header *h) +{ + asi->register_usage_flags = 0; + return INSN_GOOD; +} + +static enum probes_insn arm_check_regs_normal(probes_opcode_t insn, + struct arch_probes_insn *asi, + const struct decode_header *h) +{ + u32 regs = h->type_regs.bits >> DECODE_TYPE_BITS; + int i; + + asi->register_usage_flags = 0; + for (i = 0; i < 5; regs >>= 4, insn >>= 4, i++) + if (regs & 0xf) + asi->register_usage_flags |= 1 << (insn & 0xf); + + return INSN_GOOD; +} + + +static enum probes_insn arm_check_regs_ldmstm(probes_opcode_t insn, + struct arch_probes_insn *asi, + const struct decode_header *h) +{ + unsigned int reglist = insn & 0xffff; + unsigned int rn = (insn >> 16) & 0xf; + asi->register_usage_flags = reglist | (1 << rn); + return INSN_GOOD; +} + +static enum probes_insn arm_check_regs_mov_ip_sp(probes_opcode_t insn, + struct arch_probes_insn *asi, + const struct decode_header *h) +{ + /* Instruction is 'mov ip, sp' i.e. 'mov r12, r13' */ + asi->register_usage_flags = (1 << 12) | (1<< 13); + return INSN_GOOD; +} + +/* + * | Rn |Rt/d| | Rm | + * LDRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1101 xxxx + * STRD (register) cccc 000x x0x0 xxxx xxxx xxxx 1111 xxxx + * | Rn |Rt/d| |imm4L| + * LDRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1101 xxxx + * STRD (immediate) cccc 000x x1x0 xxxx xxxx xxxx 1111 xxxx + * + * Such instructions access Rt/d and its next register, so different + * from others, a specific checker is required to handle this extra + * implicit register usage. + */ +static enum probes_insn arm_check_regs_ldrdstrd(probes_opcode_t insn, + struct arch_probes_insn *asi, + const struct decode_header *h) +{ + int rdt = (insn >> 12) & 0xf; + arm_check_regs_normal(insn, asi, h); + asi->register_usage_flags |= 1 << (rdt + 1); + return INSN_GOOD; +} + + +const struct decode_checker arm_regs_checker[NUM_PROBES_ARM_ACTIONS] = { + [PROBES_MRS] = {.checker = arm_check_regs_normal}, + [PROBES_SATURATING_ARITHMETIC] = {.checker = arm_check_regs_normal}, + [PROBES_MUL1] = {.checker = arm_check_regs_normal}, + [PROBES_MUL2] = {.checker = arm_check_regs_normal}, + [PROBES_MUL_ADD_LONG] = {.checker = arm_check_regs_normal}, + [PROBES_MUL_ADD] = {.checker = arm_check_regs_normal}, + [PROBES_LOAD] = {.checker = arm_check_regs_normal}, + [PROBES_LOAD_EXTRA] = {.checker = arm_check_regs_normal}, + [PROBES_STORE] = {.checker = arm_check_regs_normal}, + [PROBES_STORE_EXTRA] = {.checker = arm_check_regs_normal}, + [PROBES_DATA_PROCESSING_REG] = {.checker = arm_check_regs_normal}, + [PROBES_DATA_PROCESSING_IMM] = {.checker = arm_check_regs_normal}, + [PROBES_SEV] = {.checker = arm_check_regs_nouse}, + [PROBES_WFE] = {.checker = arm_check_regs_nouse}, + [PROBES_SATURATE] = {.checker = arm_check_regs_normal}, + [PROBES_REV] = {.checker = arm_check_regs_normal}, + [PROBES_MMI] = {.checker = arm_check_regs_normal}, + [PROBES_PACK] = {.checker = arm_check_regs_normal}, + [PROBES_EXTEND] = {.checker = arm_check_regs_normal}, + [PROBES_EXTEND_ADD] = {.checker = arm_check_regs_normal}, + [PROBES_BITFIELD] = {.checker = arm_check_regs_normal}, + [PROBES_LDMSTM] = {.checker = arm_check_regs_ldmstm}, + [PROBES_MOV_IP_SP] = {.checker = arm_check_regs_mov_ip_sp}, + [PROBES_LDRSTRD] = {.checker = arm_check_regs_ldrdstrd}, +}; diff --git a/arch/arm/probes/kprobes/checkers.h b/arch/arm/probes/kprobes/checkers.h index bddfa0e82389..cf6c9e74d666 100644 --- a/arch/arm/probes/kprobes/checkers.h +++ b/arch/arm/probes/kprobes/checkers.h @@ -47,6 +47,7 @@ extern const union decode_action stack_check_actions[]; #ifndef CONFIG_THUMB2_KERNEL extern const struct decode_checker arm_stack_checker[]; +extern const struct decode_checker arm_regs_checker[]; #else #endif extern const struct decode_checker t32_stack_checker[]; -- cgit v1.2.3 From 4d62dbda8561a73976988262d4a7420b28ab9236 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 13 Jan 2015 08:15:46 -0800 Subject: ARM: OMAP3: Remove legacy support for am3517-evm This board is working with device tree based booting so there should not be any need to keep the legacy booting support around. People using this board can boot it with appended DTB with existing bootloader. By removing the 3517 legacy booting support we can get a bit closer to making all of omap3 boot in device tree only mode. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Kconfig | 6 - arch/arm/mach-omap2/Makefile | 2 - arch/arm/mach-omap2/board-am3517evm.c | 373 ---------------------------------- 3 files changed, 381 deletions(-) delete mode 100644 arch/arm/mach-omap2/board-am3517evm.c (limited to 'arch') diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 6ab656cc4f16..dcf126d17f52 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -213,12 +213,6 @@ config MACH_OVERO default y select OMAP_PACKAGE_CBB -config MACH_OMAP3517EVM - bool "OMAP3517/ AM3517 EVM board" - depends on ARCH_OMAP3 - default y - select OMAP_PACKAGE_CBB - config MACH_CRANEBOARD bool "AM3517/05 CRANE board" depends on ARCH_OMAP3 diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 5d27dfdef66b..b68fb6654ded 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -253,8 +253,6 @@ obj-$(CONFIG_MACH_CM_T35) += board-cm-t35.o obj-$(CONFIG_MACH_CM_T3517) += board-cm-t3517.o obj-$(CONFIG_MACH_TOUCHBOOK) += board-omap3touchbook.o -obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o - obj-$(CONFIG_MACH_CRANEBOARD) += board-am3517crane.o obj-$(CONFIG_MACH_SBC3530) += board-omap3stalker.o diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c deleted file mode 100644 index 1c091b3fa312..000000000000 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ /dev/null @@ -1,373 +0,0 @@ -/* - * linux/arch/arm/mach-omap2/board-am3517evm.c - * - * Copyright (C) 2009 Texas Instruments Incorporated - * Author: Ranjith Lohithakshan - * - * Based on mach-omap2/board-omap3evm.c - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, - * whether express or implied; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "am35xx.h" -#include -#include -#include - -#include "common.h" -#include