Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/aarch64/aarch64 add support swp,swpb instruction em...
details: https://anonhg.NetBSD.org/src/rev/0ca5c3cbaaaa
branches: trunk
changeset: 974186:0ca5c3cbaaaa
user: ryo <ryo%NetBSD.org@localhost>
date: Sun Jul 26 07:26:52 2020 +0000
description:
add support swp,swpb instruction emulation
diffstat:
sys/arch/aarch64/aarch64/trap.c | 53 +++++++++++++++++++++++++++++++++++++++-
1 files changed, 51 insertions(+), 2 deletions(-)
diffs (81 lines):
diff -r d9c669137313 -r 0ca5c3cbaaaa sys/arch/aarch64/aarch64/trap.c
--- a/sys/arch/aarch64/aarch64/trap.c Sun Jul 26 07:25:38 2020 +0000
+++ b/sys/arch/aarch64/aarch64/trap.c Sun Jul 26 07:26:52 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.32 2020/07/26 07:25:38 ryo Exp $ */
+/* $NetBSD: trap.c,v 1.33 2020/07/26 07:26:52 ryo Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: trap.c,v 1.32 2020/07/26 07:25:38 ryo Exp $");
+__KERNEL_RCSID(1, "$NetBSD: trap.c,v 1.33 2020/07/26 07:26:52 ryo Exp $");
#include "opt_arm_intr_impl.h"
#include "opt_compat_netbsd32.h"
@@ -588,6 +588,46 @@
return (!match != !invert);
}
+uint8_t atomic_swap_8(volatile uint8_t *, uint8_t);
+
+static int
+emul_arm_swp(uint32_t insn, struct trapframe *tf)
+{
+ struct faultbuf fb;
+ vaddr_t vaddr;
+ uint32_t val;
+ int Rn, Rd, Rm, error;
+
+ Rn = __SHIFTOUT(insn, 0x000f0000);
+ Rd = __SHIFTOUT(insn, 0x0000f000);
+ Rm = __SHIFTOUT(insn, 0x0000000f);
+
+ vaddr = tf->tf_reg[Rn] & 0xffffffff;
+ val = tf->tf_reg[Rm];
+
+ /* fault if insn is swp, and unaligned access */
+ if ((insn & 0x00400000) == 0 && (vaddr & 3) != 0) {
+ tf->tf_far = vaddr;
+ return EFAULT;
+ }
+
+ /* vaddr will always point to userspace, since it has only 32bit */
+ if ((error = cpu_set_onfault(&fb)) == 0) {
+ if (insn & 0x00400000) {
+ /* swpb */
+ val = atomic_swap_8(vaddr, val);
+ } else {
+ /* swp */
+ val = atomic_swap_32(vaddr, val);
+ }
+ cpu_unset_onfault();
+ tf->tf_reg[Rd] = val;
+ } else {
+ tf->tf_far = reg_far_el1_read();
+ }
+ return error;
+}
+
static enum emul_arm_result
emul_thumb_insn(struct trapframe *tf, uint32_t insn, int insn_size)
{
@@ -635,6 +675,15 @@
if ((insn & 0xf0000000) == 0xf0000000)
goto unknown_insn;
+ /* swp,swpb */
+ if ((insn & 0x0fb00ff0) == 0x01000090) {
+ if (arm_cond_match(insn, tf->tf_spsr)) {
+ if (emul_arm_swp(insn, tf) != 0)
+ return EMUL_ARM_FAULT;
+ }
+ goto emulated;
+ }
+
/*
* Emulate ARMv6 instructions with cache operations
* register (c7), that can be used in user mode.
Home |
Main Index |
Thread Index |
Old Index