Enable alignment faults on arm32 for both kernel and userland.

If COMPAT_15 and EXEC_AOUT are defined, support per-process
alignment checking where AFLTs are always enabled when running
kernel code and userland ELF binaries, and dynamically disabled/
enabled when switching to/from a.out binaries. This is necessary
in order to execute older a.out binaries, where gcc made
deliberate use of misaligned loads under certain circumstances.
This commit is contained in:
scw 2003-10-25 19:44:42 +00:00
parent 987510aee5
commit 84c17a8163
6 changed files with 200 additions and 24 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: arm_machdep.c,v 1.6 2003/01/17 22:28:48 thorpej Exp $ */
/* $NetBSD: arm_machdep.c,v 1.7 2003/10/25 19:44:42 scw Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@ -72,10 +72,11 @@
*/
#include "opt_compat_netbsd.h"
#include "opt_execfmt.h"
#include <sys/param.h>
__KERNEL_RCSID(0, "$NetBSD: arm_machdep.c,v 1.6 2003/01/17 22:28:48 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: arm_machdep.c,v 1.7 2003/10/25 19:44:42 scw Exp $");
#include <sys/exec.h>
#include <sys/proc.h>
@ -133,6 +134,11 @@ setregs(struct lwp *l, struct exec_package *pack, u_long stack)
tf->tf_spsr = PSR_USR32_MODE;
#endif
#if defined(COMPAT_15) && defined(EXEC_AOUT)
if (pack->ep_es->es_check == exec_aout_makecmds)
l->l_addr->u_pcb.pcb_flags = PCB_NOALIGNFLT;
else
#endif
l->l_addr->u_pcb.pcb_flags = 0;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpufunc.c,v 1.63 2003/09/06 09:31:37 rearnsha Exp $ */
/* $NetBSD: cpufunc.c,v 1.64 2003/10/25 19:44:42 scw Exp $ */
/*
* arm7tdmi support code Copyright (c) 2001 John Fremlin
@ -46,7 +46,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: cpufunc.c,v 1.63 2003/09/06 09:31:37 rearnsha Exp $");
__KERNEL_RCSID(0, "$NetBSD: cpufunc.c,v 1.64 2003/10/25 19:44:42 scw Exp $");
#include "opt_compat_netbsd.h"
#include "opt_cpuoptions.h"
@ -1614,7 +1614,8 @@ arm6_setup(args)
/* Set up default control registers bits */
cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
| CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
| CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE;
| CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE
| CPU_CONTROL_AFLT_ENABLE;
cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
| CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
| CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE
@ -1662,7 +1663,8 @@ arm7_setup(args)
cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
| CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
| CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE;
| CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE
| CPU_CONTROL_AFLT_ENABLE;
cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
| CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
| CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE
@ -1750,7 +1752,8 @@ arm8_setup(args)
cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
| CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
| CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE;
| CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE
| CPU_CONTROL_AFLT_ENABLE;
cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
| CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
| CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE
@ -1830,7 +1833,7 @@ arm9_setup(args)
cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
| CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
| CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
| CPU_CONTROL_WBUF_ENABLE;
| CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_AFLT_ENABLE;
cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
| CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
| CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
@ -1876,7 +1879,8 @@ arm10_setup(args)
cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
| CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
| CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_BPRD_ENABLE;
| CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_BPRD_ENABLE
| CPU_CONTROL_AFLT_ENABLE;
cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE
| CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
| CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE
@ -1931,7 +1935,7 @@ sa110_setup(args)
cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
| CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
| CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
| CPU_CONTROL_WBUF_ENABLE;
| CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_AFLT_ENABLE;
cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
| CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
| CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
@ -1988,7 +1992,8 @@ sa11x0_setup(args)
cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
| CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
| CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
| CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE;
| CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
| CPU_CONTROL_AFLT_ENABLE;
cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
| CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
| CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
@ -2036,7 +2041,7 @@ ixp12x0_setup(args)
cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE
| CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_SYST_ENABLE
| CPU_CONTROL_IC_ENABLE;
| CPU_CONTROL_IC_ENABLE | CPU_CONTROL_AFLT_ENABLE;
cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_AFLT_ENABLE
| CPU_CONTROL_DC_ENABLE | CPU_CONTROL_WBUF_ENABLE
@ -2097,7 +2102,7 @@ xscale_setup(args)
| CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
| CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE
| CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE
| CPU_CONTROL_BPRD_ENABLE;
| CPU_CONTROL_BPRD_ENABLE | CPU_CONTROL_AFLT_ENABLE;
cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE
| CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE
| CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE

View File

@ -1,4 +1,4 @@
/* $NetBSD: exception.S,v 1.8 2003/01/06 13:05:00 wiz Exp $ */
/* $NetBSD: exception.S,v 1.9 2003/10/25 19:44:42 scw Exp $ */
/*
* Copyright (c) 1994-1997 Mark Brinicombe.
@ -46,6 +46,9 @@
*/
#include "opt_ipkdb.h"
#include "opt_compat_netbsd.h"
#include "opt_execfmt.h"
#include "opt_multiprocessor.h"
#include <machine/asm.h>
#include <machine/cpu.h>
#include <machine/frame.h>
@ -54,8 +57,45 @@
.text
.align 0
Lastpending:
.Lastpending:
.word _C_LABEL(astpending)
#if defined(COMPAT_15) && defined(EXEC_AOUT)
.Lcpufuncs:
.word _C_LABEL(cpufuncs)
#ifndef MULTIPROCESSOR
.Lcurpcb:
.word _C_LABEL(curpcb)
.Lcpu_info_store:
.word _C_LABEL(cpu_info_store)
#define GET_CURPCB \
ldr r1, .Lcurpcb ;\
ldr r1, [r1]
#define GET_CPUINFO \
ldr r0, .Lcpu_info_store
#else
.Lcpu_info:
.word _C_LABEL(cpu_info)
#define GET_CURPCB \
ldr r4, .Lcpu_info ;\
bl _C_LABEL(cpu_number) ;\
ldr r0, [r4, r0, lsl #2] ;\
ldr r1, [r0, #CI_CURPCB]
#define GET_CPUINFO /* nothing to do */
#endif
#define ENABLE_ALIGNMENT_FAULTS \
GET_CURPCB ;\
ldr r1, [r1, #PCB_FLAGS] /* Fetch curpcb->pcb_flags */ ;\
tst r1, #PCB_NOALIGNFLT ;\
beq 1f /* Alignment faults already enabled */ ;\
GET_CPUINFO ;\
ldr r2, .Lcpufuncs ;\
ldr r1, [r0, #CI_CTRL] /* Fetch control register */ ;\
mov r0, #-1 ;\
mov lr, pc ;\
ldr pc, [r2, #CF_CONTROL] /* Enable alignment faults */ ;\
1:
#endif /* COMPAT_15 && EXEC_AOUT */
/*
* General exception exit handler
@ -77,7 +117,11 @@ exception_exit:
teq r0, #(PSR_USR32_MODE)
bne .Ldo_exit /* Not USR mode so no AST delivery */
ldr r5, Lastpending /* Get address of astpending */
ldr r5, .Lastpending /* Get address of astpending */
#if defined(COMPAT_15) && defined(EXEC_AOUT) && !defined(MULTIPROCESSOR)
ldr r6, .Lcurpcb
ldr r7, .Lcpu_info_store
#endif
Lexception_exit_loop:
orr r0, r4, #(I32_bit) /* Block IRQs */
@ -87,6 +131,28 @@ Lexception_exit_loop:
teq r1, #0x00000000
bne .Ldo_ast
#if defined(COMPAT_15) && defined(EXEC_AOUT)
/* Disable alignment faults for the process, if necessary. */
#ifdef MULTIPROCESSOR
ldr r7, .Lcpu_info
bl _C_LABEL(cpu_number)
ldr r7, [r7, r0, lsl #2]
ldr r1, [r7, #CI_CURPCB]
#else
ldr r1, [r6]
#endif
ldr r1, [r1, #PCB_FLAGS] /* Fetch curpcb->pcb_flags */
tst r1, #PCB_NOALIGNFLT
beq 1f /* Keep alignment faults enabled */
ldr r1, [r7, #CI_CTRL] /* Fetch control register */
ldr r2, .Lcpufuncs
mov r0, #-1
bic r1, r1, #CPU_CONTROL_AFLT_ENABLE /* Disable alignment faults */
mov lr, pc
ldr pc, [r2, #CF_CONTROL] /* Set the new control register value */
1:
#endif
PULLFRAMEFROMSVCANDEXIT /* No AST so exit */
.Ldo_ast:
@ -127,12 +193,20 @@ Lreset_panicmsg:
ASENTRY_NP(swi_entry)
PUSHFRAME
#if defined(COMPAT_15) && defined(EXEC_AOUT)
ENABLE_ALIGNMENT_FAULTS
#endif
mov r0, sp /* Pass the frame to any function */
bl _C_LABEL(swi_handler) /* It's a SWI ! */
ldr r5, Lastpending /* Get address of astpending */
ldr r5, .Lastpending /* Get address of astpending */
mrs r4, cpsr /* Get CPSR */
#if defined(COMPAT_15) && defined(EXEC_AOUT) && !defined(MULTIPROCESSOR)
ldr r6, .Lcurpcb
ldr r7, .Lcpu_info_store
#endif
.Lswi_exit_loop:
orr r0, r4, #(I32_bit) /* Disable IRQs */
@ -142,6 +216,27 @@ ASENTRY_NP(swi_entry)
teq r1, #0x00000000
bne .Ldo_swi_ast
#if defined(COMPAT_15) && defined(EXEC_AOUT)
/* Disable alignment faults for the process, if necessary. */
#ifdef MULTIPROCESSOR
ldr r7, .Lcpu_info
bl _C_LABEL(cpu_number)
ldr r7, [r7, r0, lsl #2]
ldr r1, [r7, #CI_CURPCB]
#else
ldr r1, [r6]
#endif
ldr r1, [r1, #PCB_FLAGS] /* Fetch curpcb->pcb_flags */
tst r1, #PCB_NOALIGNFLT
beq 1f /* Keep alignment faults enabled */
ldr r1, [r7, #CI_CTRL] /* Fetch control register */
ldr r2, .Lcpufuncs
mov r0, #-1
bic r1, r1, #CPU_CONTROL_AFLT_ENABLE /* Disable alignment faults */
mov lr, pc
ldr pc, [r2, #CF_CONTROL] /* Set the new control register value */
1:
#endif
PULLFRAME
movs pc, lr /* Exit */
@ -165,6 +260,10 @@ ASENTRY_NP(prefetch_abort_entry)
PUSHFRAMEINSVC
#if defined(COMPAT_15) && defined(EXEC_AOUT)
ENABLE_ALIGNMENT_FAULTS
#endif
mov r0, sp /* pass the stack pointer as r0 */
adr lr, exception_exit
@ -200,6 +299,10 @@ ASENTRY_NP(data_abort_entry)
PUSHFRAMEINSVC /* Push trap frame and switch */
/* to SVC32 mode */
#if defined(COMPAT_15) && defined(EXEC_AOUT)
ENABLE_ALIGNMENT_FAULTS
#endif
mov r0, sp /* pass the stack pointer as r0 */
adr lr, exception_exit
@ -307,10 +410,37 @@ ASENTRY_NP(undefined_entry)
* Now to IPKDB.
*/
.Lgoipkdb:
#if defined(COMPAT_15) && defined(EXEC_AOUT)
ENABLE_ALIGNMENT_FAULTS
#endif
mov r0, sp
bl _C_LABEL(ipkdb_trap_glue)
ldr r1, .Lipkdb_trap_return
str r0,[r1]
#if defined(COMPAT_15) && defined(EXEC_AOUT)
#ifdef MULTIPROCESSOR
ldr r7, .Lcpu_info
bl _C_LABEL(cpu_number)
ldr r7, [r7, r0, lsl #2]
ldr r1, [r7, #CI_CURPCB]
#else
ldr r6, .Lcurpcb
ldr r7, .Lcpu_info_store
ldr r1, [r6]
#endif
ldr r1, [r1, #PCB_FLAGS] /* Fetch curpcb->pcb_flags */
tst r1, #PCB_NOALIGNFLT
beq 1f /* Keep alignment faults enabled */
ldr r1, [r7, #CI_CTRL] /* Fetch control register */
ldr r2, .Lcpufuncs
mov r0, #-1
bic r1, r1, #CPU_CONTROL_AFLT_ENABLE /* Disable alignment faults */
mov lr, pc
ldr pc, [r2, #CF_CONTROL] /* Set the new control register value */
1:
#endif
/*
* Have to load all registers from the stack.
*
@ -392,6 +522,9 @@ Lundefined_handler_indirection:
ENTRY_NP(undefinedinstruction_bounce)
PUSHFRAMEINSVC
#if defined(COMPAT_15) && defined(EXEC_AOUT)
ENABLE_ALIGNMENT_FAULTS
#endif
mov r0, sp
bl _C_LABEL(undefinedinstruction)

View File

@ -1,4 +1,4 @@
/* $NetBSD: fault.c,v 1.37 2003/10/15 14:07:03 scw Exp $ */
/* $NetBSD: fault.c,v 1.38 2003/10/25 19:44:42 scw Exp $ */
/*
* Copyright 2003 Wasabi Systems, Inc.
@ -82,7 +82,7 @@
#include "opt_pmap_debug.h"
#include <sys/types.h>
__KERNEL_RCSID(0, "$NetBSD: fault.c,v 1.37 2003/10/15 14:07:03 scw Exp $");
__KERNEL_RCSID(0, "$NetBSD: fault.c,v 1.38 2003/10/25 19:44:42 scw Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -240,14 +240,18 @@ badaddr_read(void *addr, size_t size, void *rptr)
#define TRAP_CODE ((fault_status & 0x0f) | (fault_address & 0xfffffff0))
/* Determine if 'x' is an alignment fault */
#define IS_ALIGN_FAULT(x) \
(((1 << (x)) & \
((1 << FAULT_ALIGN_0) | (1 << FAULT_ALIGN_1))) != 0)
/* Determine if we can recover from a fault */
#define IS_FATAL_FAULT(x) \
(((1 << (x)) & \
((1 << FAULT_WRTBUF_0) | (1 << FAULT_WRTBUF_1) | \
(1 << FAULT_BUSERR_0) | (1 << FAULT_BUSERR_1) | \
(1 << FAULT_BUSERR_2) | (1 << FAULT_BUSERR_3) | \
(1 << FAULT_BUSTRNL1) | (1 << FAULT_BUSTRNL2) | \
(1 << FAULT_ALIGN_0) | (1 << FAULT_ALIGN_1))) != 0)
(1 << FAULT_BUSTRNL1) | (1 << FAULT_BUSTRNL2))) != 0)
void
data_abort_handler(frame)
@ -400,6 +404,26 @@ copyfault:
};
/* Now act on the fault type */
if (IS_ALIGN_FAULT(fault_code)) {
if (user) {
KSI_INIT_TRAP(&ksi);
ksi.ksi_signo = SIGBUS;
ksi.ksi_code = BUS_ADRALN;
ksi.ksi_addr = (u_int32_t *)fault_address;
ksi.ksi_trap = TRAP_CODE;
ksi.ksi_errno = error;
goto trapsignal;
}
#if defined(DDB) || defined(KGDB)
printf("Alignment fault in kernel (frame = %p)\n", frame);
report_abort(NULL, fault_status, fault_address, fault_pc);
kdb_trap(T_FAULT, frame);
return;
#else
panic("Alignment fault in kernel - we're dead");
#endif
}
if (fatal_fault) {
/*
* None of these faults should happen on a perfectly

View File

@ -1,4 +1,4 @@
# $NetBSD: genassym.cf,v 1.25 2003/09/11 18:54:33 scw Exp $
# $NetBSD: genassym.cf,v 1.26 2003/10/25 19:44:42 scw Exp $
# Copyright (c) 1982, 1990 The Regents of the University of California.
# All rights reserved.
@ -57,6 +57,8 @@ include <machine/frame.h>
include <machine/vmparam.h>
include "opt_multiprocessor.h"
include "opt_compat_netbsd.h"
include "opt_execfmt.h"
define __PROG32 1
ifdef __ARM_FIQ_INDIRECT
@ -108,6 +110,7 @@ define PCB_LR offsetof(struct pcb, pcb_un.un_32.pcb32_lr)
define PCB_PC offsetof(struct pcb, pcb_un.un_32.pcb32_pc)
define PCB_UND_SP offsetof(struct pcb, pcb_un.un_32.pcb32_und_sp)
define PCB_ONFAULT offsetof(struct pcb, pcb_onfault)
define PCB_NOALIGNFLT PCB_NOALIGNFLT
define USER_SIZE sizeof(struct user)
@ -147,12 +150,16 @@ define CF_DCACHE_WB_RANGE offsetof(struct cpu_functions, cf_dcache_wb_range)
define CF_TLB_FLUSHID_SE offsetof(struct cpu_functions, cf_tlb_flushID_SE)
define CF_CONTEXT_SWITCH offsetof(struct cpu_functions, cf_context_switch)
define CF_SLEEP offsetof(struct cpu_functions, cf_sleep)
define CF_CONTROL offsetof(struct cpu_functions, cf_control)
define CI_CURPRIORITY offsetof(struct cpu_info, ci_schedstate.spc_curpriority)
ifdef MULTIPROCESSOR
define CI_CURLWP offsetof(struct cpu_info, ci_curlwp)
define CI_CURPCB offsetof(struct cpu_info, ci_curpcb)
endif
if defined(COMPAT_15) && defined(EXEC_AOUT)
define CI_CTRL offsetof(struct cpu_info, ci_ctrl)
endif
# Constants required for in_cksum() and friends.
define M_LEN offsetof(struct mbuf, m_len)

View File

@ -1,4 +1,4 @@
/* $NetBSD: pcb.h,v 1.10 2003/10/13 21:46:39 scw Exp $ */
/* $NetBSD: pcb.h,v 1.11 2003/10/25 19:44:42 scw Exp $ */
/*
* Copyright (c) 2001 Matt Thomas <matt@3am-software.com>.
@ -82,6 +82,7 @@ struct pcb_arm26 {
struct pcb {
u_int pcb_flags;
#define PCB_OWNFPU 0x00000001
#define PCB_NOALIGNFLT 0x00000002 /* For COMPAT_15/EXEC_AOUT */
struct trapframe *pcb_tf;
caddr_t pcb_onfault; /* On fault handler */
union {