Skip to content

Commit 2e651ea

Browse files
committed
ARC: Unaligned access emulation
ARC700 doesn't natively support unaligned access, but can be emulated -Unaligned Access Exception -Disassembly at the Fault address to find the exact insn (long/short) Also per Arnd's comment, we runtime control it using 2 sysctl knobs: * SYSCTL_ARCH_UNALIGN_ALLOW: Runtime enable/disble * SYSCTL_ARCH_UNALIGN_NO_WARN: Warn on each emulation attempt Originally contributed by Tim Yao <tim.yao@amlogic.com> Signed-off-by: Vineet Gupta <vgupta@synopsys.com> Cc: Tim Yao <tim.yao@amlogic.com> Acked-by: Arnd Bergmann <arnd@arndb.de>
1 parent bf14e3b commit 2e651ea

9 files changed

Lines changed: 329 additions & 2 deletions

File tree

arch/arc/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,17 @@ config ARC_CURR_IN_REG
336336
This reserved Register R25 to point to Current Task in
337337
kernel mode. This saves memory access for each such access
338338

339+
340+
config ARC_MISALIGN_ACCESS
341+
bool "Emulate unaligned memory access (userspace only)"
342+
default N
343+
select SYSCTL_ARCH_UNALIGN_NO_WARN
344+
select SYSCTL_ARCH_UNALIGN_ALLOW
345+
help
346+
This enables misaligned 16 & 32 bit memory access from user space.
347+
Use ONLY-IF-ABS-NECESSARY as it will be very slow and also can hide
348+
potential bugs in code
349+
339350
config ARC_STACK_NONEXEC
340351
bool "Make stack non-executable"
341352
default n

arch/arc/include/asm/Kbuild

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ generic-y += topology.h
5252
generic-y += trace_clock.h
5353
generic-y += types.h
5454
generic-y += ucontext.h
55-
generic-y += unaligned.h
5655
generic-y += user.h
5756
generic-y += vga.h
5857
generic-y += xor.h

arch/arc/include/asm/ptrace.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ struct callee_regs {
9797
sp; \
9898
})
9999

100+
/* return 1 if PC in delay slot */
101+
#define delay_mode(regs) ((regs->status32 & STATUS_DE_MASK) == STATUS_DE_MASK)
102+
100103
#define in_syscall(regs) (regs->event & orig_r8_IS_SCALL)
101104
#define in_brkpt_trap(regs) (regs->event & orig_r8_IS_BRKPT)
102105

arch/arc/include/asm/unaligned.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License version 2 as
6+
* published by the Free Software Foundation.
7+
*/
8+
9+
#ifndef _ASM_ARC_UNALIGNED_H
10+
#define _ASM_ARC_UNALIGNED_H
11+
12+
/* ARC700 can't handle unaligned Data accesses. */
13+
14+
#include <asm-generic/unaligned.h>
15+
#include <asm/ptrace.h>
16+
17+
#ifdef CONFIG_ARC_MISALIGN_ACCESS
18+
int misaligned_fixup(unsigned long address, struct pt_regs *regs,
19+
unsigned long cause, struct callee_regs *cregs);
20+
#else
21+
static inline int
22+
misaligned_fixup(unsigned long address, struct pt_regs *regs,
23+
unsigned long cause, struct callee_regs *cregs)
24+
{
25+
return 0;
26+
}
27+
#endif
28+
29+
#endif /* _ASM_ARC_UNALIGNED_H */

arch/arc/kernel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ obj-$(CONFIG_MODULES) += arcksyms.o module.o
1616
obj-$(CONFIG_SMP) += smp.o
1717
obj-$(CONFIG_ARC_DW2_UNWIND) += unwind.o
1818
obj-$(CONFIG_KPROBES) += kprobes.o
19+
obj-$(CONFIG_ARC_MISALIGN_ACCESS) += unaligned.o
1920

2021
obj-$(CONFIG_ARC_FPU_SAVE_RESTORE) += fpu.o
2122
CFLAGS_fpu.o += -mdpfp

arch/arc/kernel/disasm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#include <asm/disasm.h>
1616
#include <asm/uaccess.h>
1717

18-
#if defined(CONFIG_KGDB) || defined(CONFIG_MISALIGN_ACCESS) || \
18+
#if defined(CONFIG_KGDB) || defined(CONFIG_ARC_MISALIGN_ACCESS) || \
1919
defined(CONFIG_KPROBES)
2020

2121
/* disasm_instr: Analyses instruction at addr, stores

arch/arc/kernel/entry.S

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
* it under the terms of the GNU General Public License version 2 as
88
* published by the Free Software Foundation.
99
*
10+
* vineetg: May 2011
11+
* -Userspace unaligned access emulation
12+
*
1013
* vineetg: Feb 2011 (ptrace low level code fixes)
1114
* -traced syscall return code (r0) was not saved into pt_regs for restoring
1215
* into user reg-file when traded task rets to user space.
@@ -387,7 +390,17 @@ ARC_ENTRY EV_TLBProtV
387390
mov r1, r4 ; faulting address
388391
mov r2, sp ; pt_regs
389392

393+
#ifdef CONFIG_ARC_MISALIGN_ACCESS
394+
SAVE_CALLEE_SAVED_USER
395+
mov r3, sp ; callee_regs
396+
#endif
397+
390398
bl do_misaligned_access
399+
400+
#ifdef CONFIG_ARC_MISALIGN_ACCESS
401+
DISCARD_CALLEE_SAVED_USER
402+
#endif
403+
391404
b ret_from_exception
392405

393406
ARC_EXIT EV_TLBProtV

arch/arc/kernel/traps.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
* it under the terms of the GNU General Public License version 2 as
88
* published by the Free Software Foundation.
99
*
10+
* vineetg: May 2011
11+
* -user-space unaligned access emulation
12+
*
1013
* Rahul Trivedi: Codito Technologies 2004
1114
*/
1215

@@ -16,6 +19,7 @@
1619
#include <asm/ptrace.h>
1720
#include <asm/setup.h>
1821
#include <asm/kprobes.h>
22+
#include <asm/unaligned.h>
1923

2024
void __init trap_init(void)
2125
{
@@ -79,7 +83,29 @@ DO_ERROR_INFO(SIGILL, "Illegal Insn (or Seq)", insterror_is_error, ILL_ILLOPC)
7983
DO_ERROR_INFO(SIGBUS, "Invalid Mem Access", do_memory_error, BUS_ADRERR)
8084
DO_ERROR_INFO(SIGTRAP, "Breakpoint Set", trap_is_brkpt, TRAP_BRKPT)
8185

86+
#ifdef CONFIG_ARC_MISALIGN_ACCESS
87+
/*
88+
* Entry Point for Misaligned Data access Exception, for emulating in software
89+
*/
90+
int do_misaligned_access(unsigned long cause, unsigned long address,
91+
struct pt_regs *regs, struct callee_regs *cregs)
92+
{
93+
if (misaligned_fixup(address, regs, cause, cregs) != 0) {
94+
siginfo_t info;
95+
96+
info.si_signo = SIGBUS;
97+
info.si_errno = 0;
98+
info.si_code = BUS_ADRALN;
99+
info.si_addr = (void __user *)address;
100+
return handle_exception(cause, "Misaligned Access", regs,
101+
&info);
102+
}
103+
return 0;
104+
}
105+
106+
#else
82107
DO_ERROR_INFO(SIGSEGV, "Misaligned Access", do_misaligned_access, SEGV_ACCERR)
108+
#endif
83109

84110
/*
85111
* Entry point for miscll errors such as Nested Exceptions

0 commit comments

Comments
 (0)