diff options
author | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2015-12-14 20:34:50 +0100 |
---|---|---|
committer | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2015-12-14 20:34:50 +0100 |
commit | 9ea26e897dad9f186a37346cceba380c81fa7e9a (patch) | |
tree | ee1d39fe7c66cc996f282d9b162f3efd7cf72ebd | |
parent | 9cd722820c1211157199154242bb6b4baf90e86d (diff) | |
parent | 764df269b7e4e2784ab4acb841e503b364552641 (diff) | |
download | kernel_samsung_smdk4412-9ea26e897dad9f186a37346cceba380c81fa7e9a.zip kernel_samsung_smdk4412-9ea26e897dad9f186a37346cceba380c81fa7e9a.tar.gz kernel_samsung_smdk4412-9ea26e897dad9f186a37346cceba380c81fa7e9a.tar.bz2 |
Merge remote-tracking branch 'cyanogen/cm-13.0' into replicant-6.0
22 files changed, 359 insertions, 2 deletions
diff --git a/arch/arm/configs/cyanogenmod_d710_defconfig b/arch/arm/configs/cyanogenmod_d710_defconfig index 5311522..daf36bc 100644 --- a/arch/arm/configs/cyanogenmod_d710_defconfig +++ b/arch/arm/configs/cyanogenmod_d710_defconfig @@ -3128,6 +3128,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM=y CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_SHA512=y # CONFIG_CRYPTO_TGR192 is not set @@ -3137,6 +3138,7 @@ CONFIG_CRYPTO_SHA512=y # Ciphers # CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES_ARM=y # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set diff --git a/arch/arm/configs/cyanogenmod_i777_defconfig b/arch/arm/configs/cyanogenmod_i777_defconfig index 28a6d72..e3b1141 100644 --- a/arch/arm/configs/cyanogenmod_i777_defconfig +++ b/arch/arm/configs/cyanogenmod_i777_defconfig @@ -3106,6 +3106,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM=y CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_SHA512=y # CONFIG_CRYPTO_TGR192 is not set @@ -3115,6 +3116,7 @@ CONFIG_CRYPTO_SHA512=y # Ciphers # CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES_ARM=y # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set diff --git a/arch/arm/configs/cyanogenmod_i9100_defconfig b/arch/arm/configs/cyanogenmod_i9100_defconfig index 5e61b22..ff104fc 100644 --- a/arch/arm/configs/cyanogenmod_i9100_defconfig +++ b/arch/arm/configs/cyanogenmod_i9100_defconfig @@ -3105,6 +3105,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM=y CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_SHA512=y # CONFIG_CRYPTO_TGR192 is not set @@ -3114,6 +3115,7 @@ CONFIG_CRYPTO_SHA512=y # Ciphers # CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES_ARM=y # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set diff --git a/arch/arm/configs/cyanogenmod_i925_defconfig b/arch/arm/configs/cyanogenmod_i925_defconfig index 90a8492..c1fcebe 100644 --- a/arch/arm/configs/cyanogenmod_i925_defconfig +++ b/arch/arm/configs/cyanogenmod_i925_defconfig @@ -3297,6 +3297,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM=y CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -3306,6 +3307,7 @@ CONFIG_CRYPTO_SHA256=y # Ciphers # CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES_ARM=y # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set diff --git a/arch/arm/configs/cyanogenmod_i9300_defconfig b/arch/arm/configs/cyanogenmod_i9300_defconfig index 9703150..3b79080 100644 --- a/arch/arm/configs/cyanogenmod_i9300_defconfig +++ b/arch/arm/configs/cyanogenmod_i9300_defconfig @@ -587,6 +587,7 @@ CONFIG_ARM_TRUSTZONE=y CONFIG_ARM_THUMB=y # CONFIG_ARM_THUMBEE is not set CONFIG_SWP_EMULATE=y +CONFIG_IDIV_EMULATE=y # CONFIG_CPU_ICACHE_DISABLE is not set # CONFIG_CPU_DCACHE_DISABLE is not set # CONFIG_CPU_BPREDICT_DISABLE is not set @@ -3287,6 +3288,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM=y CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -3296,6 +3298,7 @@ CONFIG_CRYPTO_SHA256=y # Ciphers # CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES_ARM=y # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set diff --git a/arch/arm/configs/cyanogenmod_i9305_defconfig b/arch/arm/configs/cyanogenmod_i9305_defconfig index 4368295..1f8b728 100755 --- a/arch/arm/configs/cyanogenmod_i9305_defconfig +++ b/arch/arm/configs/cyanogenmod_i9305_defconfig @@ -3259,6 +3259,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM=y CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -3268,6 +3269,7 @@ CONFIG_CRYPTO_SHA256=y # Ciphers # CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES_ARM=y # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set diff --git a/arch/arm/configs/cyanogenmod_n5100_defconfig b/arch/arm/configs/cyanogenmod_n5100_defconfig index ff5a726..23c2d35 100644 --- a/arch/arm/configs/cyanogenmod_n5100_defconfig +++ b/arch/arm/configs/cyanogenmod_n5100_defconfig @@ -3354,6 +3354,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM=y CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -3363,6 +3364,7 @@ CONFIG_CRYPTO_SHA256=y # Ciphers # CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES_ARM=y # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set diff --git a/arch/arm/configs/cyanogenmod_n5110_defconfig b/arch/arm/configs/cyanogenmod_n5110_defconfig index 7d54d75..e529f35 100644 --- a/arch/arm/configs/cyanogenmod_n5110_defconfig +++ b/arch/arm/configs/cyanogenmod_n5110_defconfig @@ -3354,6 +3354,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM=y CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -3363,6 +3364,7 @@ CONFIG_CRYPTO_SHA256=y # Ciphers # CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES_ARM=y # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set diff --git a/arch/arm/configs/cyanogenmod_n5120_defconfig b/arch/arm/configs/cyanogenmod_n5120_defconfig index 5aacdbb..4b22234 100644 --- a/arch/arm/configs/cyanogenmod_n5120_defconfig +++ b/arch/arm/configs/cyanogenmod_n5120_defconfig @@ -3351,6 +3351,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM=y CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -3360,6 +3361,7 @@ CONFIG_CRYPTO_SHA256=y # Ciphers # CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES_ARM=y # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set diff --git a/arch/arm/configs/cyanogenmod_n7000_defconfig b/arch/arm/configs/cyanogenmod_n7000_defconfig index 2880b47..b31ba0b 100644 --- a/arch/arm/configs/cyanogenmod_n7000_defconfig +++ b/arch/arm/configs/cyanogenmod_n7000_defconfig @@ -3123,6 +3123,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM=y CONFIG_CRYPTO_SHA256=y CONFIG_CRYPTO_SHA512=y # CONFIG_CRYPTO_TGR192 is not set @@ -3132,6 +3133,7 @@ CONFIG_CRYPTO_SHA512=y # Ciphers # CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES_ARM=y # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set diff --git a/arch/arm/configs/cyanogenmod_n7100_defconfig b/arch/arm/configs/cyanogenmod_n7100_defconfig index 69e9eb9..68bf454 100644 --- a/arch/arm/configs/cyanogenmod_n7100_defconfig +++ b/arch/arm/configs/cyanogenmod_n7100_defconfig @@ -3293,6 +3293,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM=y CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -3302,6 +3303,7 @@ CONFIG_CRYPTO_SHA256=y # Ciphers # CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES_ARM=y # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set diff --git a/arch/arm/configs/cyanogenmod_n8000_defconfig b/arch/arm/configs/cyanogenmod_n8000_defconfig index 019f2d2..8852d50 100644 --- a/arch/arm/configs/cyanogenmod_n8000_defconfig +++ b/arch/arm/configs/cyanogenmod_n8000_defconfig @@ -3261,6 +3261,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM=y CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -3270,6 +3271,7 @@ CONFIG_CRYPTO_SHA256=y # Ciphers # CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES_ARM=y # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set diff --git a/arch/arm/configs/cyanogenmod_n8013_defconfig b/arch/arm/configs/cyanogenmod_n8013_defconfig index e004715..738be1f 100644 --- a/arch/arm/configs/cyanogenmod_n8013_defconfig +++ b/arch/arm/configs/cyanogenmod_n8013_defconfig @@ -3220,6 +3220,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM=y CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -3229,6 +3230,7 @@ CONFIG_CRYPTO_SHA256=y # Ciphers # CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES_ARM=y # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set diff --git a/arch/arm/configs/cyanogenmod_t0lte_defconfig b/arch/arm/configs/cyanogenmod_t0lte_defconfig index 28bcec8..3b181d5 100755 --- a/arch/arm/configs/cyanogenmod_t0lte_defconfig +++ b/arch/arm/configs/cyanogenmod_t0lte_defconfig @@ -3267,6 +3267,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM=y CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -3276,6 +3277,7 @@ CONFIG_CRYPTO_SHA256=y # Ciphers # CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES_ARM=y # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set diff --git a/arch/arm/configs/cyanogenmod_t0ltecdma_defconfig b/arch/arm/configs/cyanogenmod_t0ltecdma_defconfig index 6660aab..befda82 100755 --- a/arch/arm/configs/cyanogenmod_t0ltecdma_defconfig +++ b/arch/arm/configs/cyanogenmod_t0ltecdma_defconfig @@ -3267,6 +3267,7 @@ CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM=y CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -3276,6 +3277,7 @@ CONFIG_CRYPTO_SHA256=y # Ciphers # CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES_ARM=y # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h new file mode 100644 index 0000000..c0efdd6 --- /dev/null +++ b/arch/arm/include/asm/opcodes.h @@ -0,0 +1,20 @@ +/* + * arch/arm/include/asm/opcodes.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_ARM_OPCODES_H +#define __ASM_ARM_OPCODES_H + +#ifndef __ASSEMBLY__ +extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr); +#endif + +#define ARM_OPCODE_CONDTEST_FAIL 0 +#define ARM_OPCODE_CONDTEST_PASS 1 +#define ARM_OPCODE_CONDTEST_UNCOND 2 + +#endif /* __ASM_ARM_OPCODES_H */ diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 6dccbbf..2d8dfa1 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -13,7 +13,7 @@ CFLAGS_REMOVE_return_address.o = -pg # Object file lists. -obj-y := elf.o entry-armv.o entry-common.o irq.o \ +obj-y := elf.o entry-armv.o entry-common.o irq.o opcodes.o \ process.o ptrace.o return_address.o setup.o signal.o \ sys_arm.o stacktrace.o time.o traps.o @@ -49,6 +49,7 @@ obj-$(CONFIG_OF) += devtree.o obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_SWP_EMULATE) += swp_emulate.o CFLAGS_swp_emulate.o := -Wa,-march=armv7-a +obj-$(CONFIG_IDIV_EMULATE) += idiv_emulate.o obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o diff --git a/arch/arm/kernel/idiv_emulate.c b/arch/arm/kernel/idiv_emulate.c new file mode 100644 index 0000000..e5818db --- /dev/null +++ b/arch/arm/kernel/idiv_emulate.c @@ -0,0 +1,195 @@ +/* + * linux/arch/arm/kernel/idiv_emulate.c + * + * This code is based on swp_emulate.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Implements emulation of the SDIV/UDIV instructions. They are defined for + * ARMv7-R and ARMv7-M profiles (in Thumb state only) and are UNDEFINED in the + * ARMv7-A profile. SDIV/UDIV are present by default on Cortex-A15. + * + * This emulation allow using integer divide instructions in case hardware is + * not presented + * + * Syntax of SDIV/UDIV instructions: SDIV/UDIV<c> <Rd>,<Rn>,<Rm> + * Where: Rd = the destination register. + * Rn = the register that contains the dividend. + * Rm = the register that contains the divisor. + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/proc_fs.h> +#include <linux/sched.h> +#include <linux/syscalls.h> +#include <linux/perf_event.h> + +#include <asm/opcodes.h> +#include <asm/traps.h> +#include <asm/uaccess.h> + +/* + * Macros/defines for extracting register numbers from instruction. + */ +#define EXTRACT_REG_NUM(instruction, offset) \ + (((instruction) & (0xf << (offset))) >> (offset)) + +/* + * Offsets for ARM mode + */ +#define RD_OFFSET 16 +#define RN_OFFSET 0 +#define RM_OFFSET 8 + +/* + * Offsets for Thumb mode + */ +#define RD_T_OFFSET 8 +#define RN_T_OFFSET 16 +#define RM_T_OFFSET 0 + +#define TYPE_OF_DIV (1 << 21) + +static unsigned long sdivcounter; +static unsigned long udivcounter; +static pid_t previous_pid; + +#ifdef CONFIG_PROC_FS +static int proc_read_status(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + char *p = page; + int len; + + p += sprintf(p, "Emulated UDIV:\t\t%lu\n", udivcounter); + p += sprintf(p, "Emulated SDIV:\t\t%lu\n", sdivcounter); + if (previous_pid != 0) + p += sprintf(p, "Last process:\t\t%d\n", previous_pid); + + len = (p - page) - off; + if (len < 0) + len = 0; + + *eof = (len <= count) ? 1 : 0; + *start = page + off; + + return len; +} +#endif + +static u32 emulate_udiv(u32 n, u32 base) +{ + udivcounter++; + + return n/base; +} + +static s32 emulate_sdiv(s32 n, s32 base) +{ + sdivcounter++; + + return n/base; +} + +static int idiv_handler(struct pt_regs *regs, unsigned int instr) +{ + long dividend, divisor, dest, res; + + perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, regs->ARM_pc); + + res = arm_check_condition(instr, regs->ARM_cpsr); + + switch (res) { + case ARM_OPCODE_CONDTEST_PASS: + break; + case ARM_OPCODE_CONDTEST_FAIL: + /* Condition failed - return to next instruction */ + regs->ARM_pc += 4; + return 0; + case ARM_OPCODE_CONDTEST_UNCOND: + if (!thumb_mode(regs)) + return -EFAULT; + break; + default: + return -EINVAL; + } + + if (current->pid != previous_pid) { + pr_debug("\"%s\" (%ld) uses idiv instruction\n", + current->comm, (unsigned long)current->pid); + previous_pid = current->pid; + } + + if (!thumb_mode(regs)) { + dividend = regs->uregs[EXTRACT_REG_NUM(instr, RN_OFFSET)]; + divisor = regs->uregs[EXTRACT_REG_NUM(instr, RM_OFFSET)]; + dest = EXTRACT_REG_NUM(instr, RD_OFFSET); + } else { + dividend = regs->uregs[EXTRACT_REG_NUM(instr, RN_T_OFFSET)]; + divisor = regs->uregs[EXTRACT_REG_NUM(instr, RM_T_OFFSET)]; + dest = EXTRACT_REG_NUM(instr, RD_T_OFFSET); + } + +/* + * In an ARMv7-A profile implementation that supports the SDIV and UDIV + * instructions, divide-by-zero always returns a zero result. + * In fact, integer division emulation provided by gcc lib has already handle + * division by zero case sending the signal to the caused process. Emulate this + * behavior here as well. + */ + if (!divisor) { + siginfo_t info; + + info.si_code = FPE_INTDIV; + info.si_signo = SIGFPE; + info.si_errno = 0; + + arm_notify_die("Division by zero", regs, &info, 0, 0); + + goto out; + } + + if (instr & TYPE_OF_DIV) + res = emulate_udiv((u32)dividend, (u32)divisor); + else + res = emulate_sdiv((s32)dividend, (s32)divisor); + + regs->ARM_pc += 4; + regs->uregs[dest] = res; + +out: + return 0; +} + +static struct undef_hook idiv_hook = { + .instr_mask = 0x0310f010, + .instr_val = 0x0310f010, + .cpsr_mask = MODE_MASK, + .cpsr_val = USR_MODE, + .fn = idiv_handler +}; + +static int __init idiv_emulation_init(void) +{ +#ifdef CONFIG_PROC_FS + struct proc_dir_entry *res; + + res = create_proc_entry("cpu/idiv_emulation", S_IRUGO, NULL); + + if (!res) + return -ENOMEM; + + res->read_proc = proc_read_status; +#endif /* CONFIG_PROC_FS */ + + pr_notice("Registering SDIV/UDIV emulation handler\n"); + + register_undef_hook(&idiv_hook); + + return 0; +} + +late_initcall(idiv_emulation_init); diff --git a/arch/arm/kernel/opcodes.c b/arch/arm/kernel/opcodes.c new file mode 100644 index 0000000..f8179c6 --- /dev/null +++ b/arch/arm/kernel/opcodes.c @@ -0,0 +1,72 @@ +/* + * linux/arch/arm/kernel/opcodes.c + * + * A32 condition code lookup feature moved from nwfpe/fpopcode.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <asm/opcodes.h> + +#define ARM_OPCODE_CONDITION_UNCOND 0xf + +/* + * condition code lookup table + * index into the table is test code: EQ, NE, ... LT, GT, AL, NV + * + * bit position in short is condition code: NZCV + */ +static const unsigned short cc_map[16] = { + 0xF0F0, /* EQ == Z set */ + 0x0F0F, /* NE */ + 0xCCCC, /* CS == C set */ + 0x3333, /* CC */ + 0xFF00, /* MI == N set */ + 0x00FF, /* PL */ + 0xAAAA, /* VS == V set */ + 0x5555, /* VC */ + 0x0C0C, /* HI == C set && Z clear */ + 0xF3F3, /* LS == C clear || Z set */ + 0xAA55, /* GE == (N==V) */ + 0x55AA, /* LT == (N!=V) */ + 0x0A05, /* GT == (!Z && (N==V)) */ + 0xF5FA, /* LE == (Z || (N!=V)) */ + 0xFFFF, /* AL always */ + 0 /* NV */ +}; + +/* + * Returns: + * ARM_OPCODE_CONDTEST_FAIL - if condition fails + * ARM_OPCODE_CONDTEST_PASS - if condition passes (including AL) + * ARM_OPCODE_CONDTEST_UNCOND - if NV condition, or separate unconditional + * opcode space from v5 onwards + * + * Code that tests whether a conditional instruction would pass its condition + * check should check that return value == ARM_OPCODE_CONDTEST_PASS. + * + * Code that tests if a condition means that the instruction would be executed + * (regardless of conditional or unconditional) should instead check that the + * return value != ARM_OPCODE_CONDTEST_FAIL. + */ +asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr) +{ + u32 cc_bits = opcode >> 28; + u32 psr_cond = psr >> 28; + unsigned int ret; + + if (cc_bits != ARM_OPCODE_CONDITION_UNCOND) { + if ((cc_map[cc_bits] >> (psr_cond)) & 1) + ret = ARM_OPCODE_CONDTEST_PASS; + else + ret = ARM_OPCODE_CONDTEST_FAIL; + } else { + ret = ARM_OPCODE_CONDTEST_UNCOND; + } + + return ret; +} +EXPORT_SYMBOL_GPL(arm_check_condition); diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 56b2715..599ea93 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -365,6 +365,19 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) if (call_undef_hook(regs, instr) == 0) return; + /* STARGO: hack for DIV emulation */ + if ((processor_mode(regs) != SVC_MODE) && thumb_mode(regs)) { + if ((instr & 0x0310) == 0x0310) { /* Retry for division */ + unsigned int instr2; + get_user(instr2, (u16 __user *)pc + 1); + instr <<= 16; + instr |= instr2; + if (call_undef_hook(regs, instr) == 0) + return; + } + } + /* END: STARGO: hack for DIV emulation */ + #ifdef CONFIG_DEBUG_USER if (user_debug & UDBG_UNDEFINED) { printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n", diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index cbab5c5..ebaee8e 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -687,6 +687,32 @@ config SWP_EMULATE If unsure, say Y. +config IDIV_EMULATE + bool "Emulate SDIV/UDIV instructions" + depends on !CPU_USE_DOMAINS && CPU_V7 + select HAVE_PROC_CPU if PROC_FS + default y if SMP + help + + The Virtualization Extensions introduce the requirement for an + ARMv7-A implementation to include SDIV and UDIV. Any + implementation of the Virtualization Extensions must include + the SDIV and UDIV instructions in the Thumb and ARM + instruction sets. + + In an ARMv7-A implementation that does not include the + Virtualization Extensions, it is IMPLEMENTATION DEFINED whether: + * SDIV and UDIV are not implemented + * SDIV and UDIV are implemented only in the Thumb instruction set + * SDIV and UDIV are implemented in the Thumb and ARM + instruction sets. + + This option allows to handle exeptions due to unimplemented + SDIV and UDIV instructions in ARM and Thumb modes. + + If unsure, say Y. + + config CPU_BIG_ENDIAN bool "Build big-endian kernel" depends on ARCH_SUPPORTS_BIG_ENDIAN diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index 5121318..1b38564 100644 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -18,7 +18,6 @@ DHDCFLAGS += -Wall -Wstrict-prototypes -Dlinux -DLINUX -DBCMDRIVER \ DHDCFLAGS += -DCUSTOMER_HW4 DHDCFLAGS += -DDEBUGFS_CFG80211 -DHDCFLAGS += -DBLOCK_IPV6_PACKET DHDCFLAGS += -DSUPPORT_DEEP_SLEEP DHDCFLAGS += -DSIMPLE_MAC_PRINT |