Skip to content

Commit

Permalink
ARC: Unaligned access emulation
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Vineet Gupta committed Feb 15, 2013
1 parent bf14e3b commit 2e651ea
Show file tree
Hide file tree
Showing 9 changed files with 329 additions and 2 deletions.
11 changes: 11 additions & 0 deletions arch/arc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,17 @@ config ARC_CURR_IN_REG
This reserved Register R25 to point to Current Task in
kernel mode. This saves memory access for each such access


config ARC_MISALIGN_ACCESS
bool "Emulate unaligned memory access (userspace only)"
default N
select SYSCTL_ARCH_UNALIGN_NO_WARN
select SYSCTL_ARCH_UNALIGN_ALLOW
help
This enables misaligned 16 & 32 bit memory access from user space.
Use ONLY-IF-ABS-NECESSARY as it will be very slow and also can hide
potential bugs in code

config ARC_STACK_NONEXEC
bool "Make stack non-executable"
default n
Expand Down
1 change: 0 additions & 1 deletion arch/arc/include/asm/Kbuild
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ generic-y += topology.h
generic-y += trace_clock.h
generic-y += types.h
generic-y += ucontext.h
generic-y += unaligned.h
generic-y += user.h
generic-y += vga.h
generic-y += xor.h
3 changes: 3 additions & 0 deletions arch/arc/include/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ struct callee_regs {
sp; \
})

/* return 1 if PC in delay slot */
#define delay_mode(regs) ((regs->status32 & STATUS_DE_MASK) == STATUS_DE_MASK)

#define in_syscall(regs) (regs->event & orig_r8_IS_SCALL)
#define in_brkpt_trap(regs) (regs->event & orig_r8_IS_BRKPT)

Expand Down
29 changes: 29 additions & 0 deletions arch/arc/include/asm/unaligned.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.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.
*/

#ifndef _ASM_ARC_UNALIGNED_H
#define _ASM_ARC_UNALIGNED_H

/* ARC700 can't handle unaligned Data accesses. */

#include <asm-generic/unaligned.h>
#include <asm/ptrace.h>

#ifdef CONFIG_ARC_MISALIGN_ACCESS
int misaligned_fixup(unsigned long address, struct pt_regs *regs,
unsigned long cause, struct callee_regs *cregs);
#else
static inline int
misaligned_fixup(unsigned long address, struct pt_regs *regs,
unsigned long cause, struct callee_regs *cregs)
{
return 0;
}
#endif

#endif /* _ASM_ARC_UNALIGNED_H */
1 change: 1 addition & 0 deletions arch/arc/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ obj-$(CONFIG_MODULES) += arcksyms.o module.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_ARC_DW2_UNWIND) += unwind.o
obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_ARC_MISALIGN_ACCESS) += unaligned.o

obj-$(CONFIG_ARC_FPU_SAVE_RESTORE) += fpu.o
CFLAGS_fpu.o += -mdpfp
Expand Down
2 changes: 1 addition & 1 deletion arch/arc/kernel/disasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#include <asm/disasm.h>
#include <asm/uaccess.h>

#if defined(CONFIG_KGDB) || defined(CONFIG_MISALIGN_ACCESS) || \
#if defined(CONFIG_KGDB) || defined(CONFIG_ARC_MISALIGN_ACCESS) || \
defined(CONFIG_KPROBES)

/* disasm_instr: Analyses instruction at addr, stores
Expand Down
13 changes: 13 additions & 0 deletions arch/arc/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* vineetg: May 2011
* -Userspace unaligned access emulation
*
* vineetg: Feb 2011 (ptrace low level code fixes)
* -traced syscall return code (r0) was not saved into pt_regs for restoring
* into user reg-file when traded task rets to user space.
Expand Down Expand Up @@ -387,7 +390,17 @@ ARC_ENTRY EV_TLBProtV
mov r1, r4 ; faulting address
mov r2, sp ; pt_regs

#ifdef CONFIG_ARC_MISALIGN_ACCESS
SAVE_CALLEE_SAVED_USER
mov r3, sp ; callee_regs
#endif

bl do_misaligned_access

#ifdef CONFIG_ARC_MISALIGN_ACCESS
DISCARD_CALLEE_SAVED_USER
#endif

b ret_from_exception

ARC_EXIT EV_TLBProtV
Expand Down
26 changes: 26 additions & 0 deletions arch/arc/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* vineetg: May 2011
* -user-space unaligned access emulation
*
* Rahul Trivedi: Codito Technologies 2004
*/

Expand All @@ -16,6 +19,7 @@
#include <asm/ptrace.h>
#include <asm/setup.h>
#include <asm/kprobes.h>
#include <asm/unaligned.h>

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

#ifdef CONFIG_ARC_MISALIGN_ACCESS
/*
* Entry Point for Misaligned Data access Exception, for emulating in software
*/
int do_misaligned_access(unsigned long cause, unsigned long address,
struct pt_regs *regs, struct callee_regs *cregs)
{
if (misaligned_fixup(address, regs, cause, cregs) != 0) {
siginfo_t info;

info.si_signo = SIGBUS;
info.si_errno = 0;
info.si_code = BUS_ADRALN;
info.si_addr = (void __user *)address;
return handle_exception(cause, "Misaligned Access", regs,
&info);
}
return 0;
}

#else
DO_ERROR_INFO(SIGSEGV, "Misaligned Access", do_misaligned_access, SEGV_ACCERR)
#endif

/*
* Entry point for miscll errors such as Nested Exceptions
Expand Down
Loading

0 comments on commit 2e651ea

Please sign in to comment.