diff --git a/arch/arc/include/asm/disasm.h b/arch/arc/include/asm/disasm.h index 61fb4d7affa7c5..c50a3767761bc4 100644 --- a/arch/arc/include/asm/disasm.h +++ b/arch/arc/include/asm/disasm.h @@ -99,7 +99,27 @@ static inline int is_short_instr(unsigned long addr) { uint16_t word = *((uint16_t *)addr); int opcode = (word >> 11) & 0x1F; +#ifdef CONFIG_ISA_ARCOMPACT return (opcode >= 0x0B); +#elif defined(CONFIG_ISA_ARCV2) + return (opcode >= 0x08); +#else /* CONFIG_ISA_ARCV3 */ + #ifdef CONFIG_64BIT + if (opcode < 8) + return 0; + else if (opcode == 0xB || opcode == 0xD || opcode == 0x1C) + return 0; + else + return 1; + #else + if (opcode < 8) + return 0; + else if (opcode == 0xD || opcode == 0x1C) + return 0; + else + return 1; + #endif +#endif } void disasm_instr(unsigned long addr, struct disasm_state *state, diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h index 090d0703888e4f..896527a814d3b9 100644 --- a/arch/arc/include/asm/ptrace.h +++ b/arch/arc/include/asm/ptrace.h @@ -67,7 +67,7 @@ struct pt_regs { unsigned long bta; /* erbta */ - unsigned long fp; + unsigned long fp; /* r27 */ unsigned long r30; unsigned long r12; unsigned long gp; /* r26 */ @@ -79,12 +79,12 @@ struct pt_regs { unsigned long DSP_CTRL; #endif - unsigned long sp; /* user/kernel sp depending on entry */ + unsigned long sp; /* user/kernel sp depending on entry, r28 */ /*------- Below list auto saved by h/w -----------*/ unsigned long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11; - unsigned long blink; + unsigned long blink; /* r31 */ #ifndef CONFIG_ARC_LACKS_ZOL unsigned long lp_end, lp_start, lp_count; @@ -112,13 +112,13 @@ struct pt_regs { #endif ecr_reg ecr; unsigned long bta; - unsigned long fp; + unsigned long fp; /* r27 */ unsigned long gp; /* r30 */ - unsigned long sp; + unsigned long sp; /* r28 */ /*------- Below list auto saved by h/w -----------*/ unsigned long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13; - unsigned long blink; + unsigned long blink; /* r31 */ unsigned long ret; unsigned long status32; diff --git a/arch/arc/kernel/disasm.c b/arch/arc/kernel/disasm.c index 49be4e45b847de..bb355dd973dd57 100644 --- a/arch/arc/kernel/disasm.c +++ b/arch/arc/kernel/disasm.c @@ -48,7 +48,7 @@ void __kprobes disasm_instr(unsigned long addr, struct disasm_state *state, state->major_opcode = (word1 >> 11) & 0x1F; /* Check if the instruction is 32 bit or 16 bit instruction */ - if (state->major_opcode < 0x0B) { + if (state->major_opcode < 0x0C) { if (bytes_not_copied > 4) goto fault; state->instr_len = 4; @@ -434,6 +434,8 @@ long __kprobes get_reg(int reg, struct pt_regs *regs, { long *p; +#ifdef CONFIG_ISA_ARCOMPACT + if (reg <= 12) { p = ®s->r0; return p[-reg]; @@ -441,7 +443,31 @@ long __kprobes get_reg(int reg, struct pt_regs *regs, if (cregs && (reg <= 25)) { p = &cregs->r13; - return p[13-reg]; + return p[13 - reg]; + } + + if (reg == 26) + return regs->gp; + if (reg == 27) + return regs->fp; + if (reg == 28) + return regs->sp; + if (reg == 31) + return regs->blink; + +#elif defined(CONFIG_ISA_ARCV2) + + if (reg <= 11) { + p = ®s->r0; + return p[reg]; + } + + if (reg == 12) + return regs->r12; + + if (cregs && (reg <= 25)) { + p = &cregs->r13; + return p[13 - reg]; } if (reg == 26) @@ -453,6 +479,28 @@ long __kprobes get_reg(int reg, struct pt_regs *regs, if (reg == 31) return regs->blink; +#else /* CONFIG_ISA_ARCV3 */ + + if (reg <= 13) { + p = ®s->r0; + return p[reg]; + } + + if (cregs && (reg <= 26)) { + p = &cregs->r14; + return p[reg - 14]; + } + + if (reg == 27) + return regs->fp; + if (reg == 28) + return regs->sp; + if (reg == 30) + return regs->gp; + if (reg == 31) + return regs->blink; + +#endif return 0; } @@ -461,6 +509,8 @@ void __kprobes set_reg(int reg, long val, struct pt_regs *regs, { long *p; +#ifdef CONFIG_ISA_ARCOMPACT + switch (reg) { case 0 ... 12: p = ®s->r0; @@ -469,7 +519,39 @@ void __kprobes set_reg(int reg, long val, struct pt_regs *regs, case 13 ... 25: if (cregs) { p = &cregs->r13; - p[13-reg] = val; + p[13 - reg] = val; + } + break; + case 26: + regs->gp = val; + break; + case 27: + regs->fp = val; + break; + case 28: + regs->sp = val; + break; + case 31: + regs->blink = val; + break; + default: + break; + } + +#elif defined(CONFIG_ISA_ARCV2) + + switch (reg) { + case 0 ... 11: + p = ®s->r0; + p[reg] = val; + break; + case 12: + regs->r12 = val; + break; + case 13 ... 25: + if (cregs) { + p = &cregs->r13; + p[13 - reg] = val; } break; case 26: @@ -487,6 +569,38 @@ void __kprobes set_reg(int reg, long val, struct pt_regs *regs, default: break; } + +#else /* CONFIG_ISA_ARCV3 */ + + switch (reg) { + case 0 ... 13: + p = ®s->r0; + p[reg] = val; + break; + case 14 ... 26: + if (cregs) { + p = &cregs->r14; + p[reg - 14] = val; + } + break; + case 27: + regs->fp = val; + break; + case 28: + regs->sp = val; + break; + case 30: + regs->gp = val; + break; + case 31: + regs->blink = val; + break; + default: + break; + } + +#endif + } /* diff --git a/arch/arc/mm/cache-arcv3.c b/arch/arc/mm/cache-arcv3.c index c4de4ac2c014f7..75f66b0769d3a3 100644 --- a/arch/arc/mm/cache-arcv3.c +++ b/arch/arc/mm/cache-arcv3.c @@ -613,7 +613,19 @@ void flush_icache_range(unsigned long kvaddr, unsigned long kvend) { unsigned int tot_sz = kvend - kvaddr; - BUG_ON((kvaddr < VMALLOC_START) || (kvend > VMALLOC_END)); + WARN(kvaddr < TASK_SIZE, "%s() can't handle user vaddr", __func__); + + /* Case: Kernel Phy addr (0x8000_0000 onwards) */ + if (likely(kvaddr > PAGE_OFFSET)) { + /* + * The 2nd arg despite being paddr will be used to index icache + * This is OK since no alternate virtual mappings will exist + * given the callers for this case: kprobe/kgdb in built-in + * kernel code only. + */ + __sync_icache_dcache(kvaddr, kvaddr, kvend - kvaddr); + return; + } while (tot_sz > 0) { unsigned int off, sz;