Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/powerpc Add routines to fix unaligned memory access...
details: https://anonhg.NetBSD.org/src/rev/8329a5442747
branches: trunk
changeset: 366546:8329a5442747
user: rin <rin%NetBSD.org@localhost>
date: Mon May 30 13:58:51 2022 +0000
description:
Add routines to fix unaligned memory access for userland process.
Mainly intended for 403, which cannot handle unaligned memory access
at all (not only ones across page boundaries like 601).
For more details, see comments in fix_unaligned.c.
diffstat:
sys/arch/powerpc/include/instr.h | 20 +-
sys/arch/powerpc/powerpc/fix_unaligned.c | 520 +++++++++++++++++++++++++++++++
2 files changed, 539 insertions(+), 1 deletions(-)
diffs (truncated from 558 to 300 lines):
diff -r 4744c490526a -r 8329a5442747 sys/arch/powerpc/include/instr.h
--- a/sys/arch/powerpc/include/instr.h Mon May 30 09:56:02 2022 +0000
+++ b/sys/arch/powerpc/include/instr.h Mon May 30 13:58:51 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: instr.h,v 1.10 2022/05/29 11:55:05 rin Exp $ */
+/* $NetBSD: instr.h,v 1.11 2022/05/30 13:58:51 rin Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -318,6 +318,24 @@
#define OPC31_OR 0x1bc
/*
+ * Opcode 31 sub-types (load/store multiple bytes)
+ */
+#define OPC31_LWZX 0x017
+#define OPC31_LWZUX 0x037
+#define OPC31_STWX 0x097
+#define OPC31_STWUX 0x0b7
+#define OPC31_LHZX 0x117
+#define OPC31_LHZUX 0x137
+#define OPC31_LHAX 0x157
+#define OPC31_LHAUX 0x177
+#define OPC31_STHX 0x197
+#define OPC31_STHUX 0x1b7
+#define OPC31_LWBRX 0x216
+#define OPC31_STWBRX 0x296
+#define OPC31_LHBRX 0x316
+#define OPC31_STHBRX 0x396
+
+/*
* Opcode 59 sub-types:
*/
diff -r 4744c490526a -r 8329a5442747 sys/arch/powerpc/powerpc/fix_unaligned.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/powerpc/powerpc/fix_unaligned.c Mon May 30 13:58:51 2022 +0000
@@ -0,0 +1,520 @@
+/* $NetBSD: fix_unaligned.c,v 1.1 2022/05/30 13:58:51 rin Exp $ */
+
+/*
+ * Copyright (c) 2022 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Rin Okuyama.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Routines to fix unaligned memory access for userland process.
+ *
+ * Intended mainly for PPC_IBM403 at the moment:
+ *
+ * - Fetch and decode insn; 403 does not have DSISR.
+ *
+ * - Only for integer insn; unaligned floating-point load/store are taken
+ * care of by FPU emulator. (Support for FPU insn should be trivial.)
+ *
+ * Also note:
+ *
+ * - For invalid forms, behaviors are undefined and not documented in
+ * processor manuals. Here, we mimic what described in
+ * "AIX 7.2 Assembler language reference":
+ *
+ * - For "u" variants, ra is not updated if ra == 0 (or rd for load).
+ *
+ * - Fix for {l,st}mw is disabled by default.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: fix_unaligned.c,v 1.1 2022/05/30 13:58:51 rin Exp $");
+
+#include "opt_ddb.h"
+#include "opt_ppcarch.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/evcnt.h>
+#include <sys/siginfo.h>
+#include <sys/systm.h>
+
+#include <powerpc/frame.h>
+#include <powerpc/instr.h>
+#include <powerpc/trap.h>
+
+#define UA_EVCNT_ATTACH(name) \
+ static struct evcnt unaligned_ev_##name = \
+ EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "unaligned", #name); \
+ EVCNT_ATTACH_STATIC(unaligned_ev_##name)
+
+#define UA_EVCNT_INCR(name) unaligned_ev_##name.ev_count++
+
+UA_EVCNT_ATTACH(lwz);
+UA_EVCNT_ATTACH(lwzu);
+UA_EVCNT_ATTACH(stw);
+UA_EVCNT_ATTACH(stwu);
+UA_EVCNT_ATTACH(lhz);
+UA_EVCNT_ATTACH(lhzu);
+UA_EVCNT_ATTACH(lha);
+UA_EVCNT_ATTACH(lhau);
+UA_EVCNT_ATTACH(sth);
+UA_EVCNT_ATTACH(sthu);
+
+UA_EVCNT_ATTACH(lwzx);
+UA_EVCNT_ATTACH(lwzux);
+UA_EVCNT_ATTACH(stwx);
+UA_EVCNT_ATTACH(stwux);
+UA_EVCNT_ATTACH(lhzx);
+UA_EVCNT_ATTACH(lhzux);
+UA_EVCNT_ATTACH(lhax);
+UA_EVCNT_ATTACH(lhaux);
+UA_EVCNT_ATTACH(sthx);
+UA_EVCNT_ATTACH(sthux);
+UA_EVCNT_ATTACH(lwbrx);
+UA_EVCNT_ATTACH(stwbrx);
+UA_EVCNT_ATTACH(lhbrx);
+UA_EVCNT_ATTACH(sthbrx);
+
+UA_EVCNT_ATTACH(lmw);
+UA_EVCNT_ATTACH(stmw);
+
+UA_EVCNT_ATTACH(isi);
+UA_EVCNT_ATTACH(dsi);
+UA_EVCNT_ATTACH(unknown);
+UA_EVCNT_ATTACH(invalid);
+
+#if 0
+#define UNALIGNED_DEBUG 1
+#define FIX_UNALIGNED_LSTMW 1
+#endif
+
+#if defined(UNALIGNED_DEBUG)
+int unaligned_debug = 1;
+#elif defined(DEBUG)
+int unaligned_debug = 0;
+#endif
+
+#if defined(UNALIGNED_DEBUG) || defined(DEBUG)
+#define DPRINTF(fmt, args...) \
+ do { \
+ if (unaligned_debug) \
+ printf("%s: " fmt, __func__, ##args); \
+ } while (0)
+#else
+#define DPRINTF(fmt, args...) __nothing
+#endif
+
+#if defined(DDB) && (defined(UNALIGNED_DEBUG) || defined(DEBUG))
+extern vaddr_t opc_disasm(vaddr_t, int);
+#define DISASM(tf, insn) \
+ do { \
+ if (unaligned_debug) \
+ opc_disasm((tf)->tf_srr0, (insn)->i_int); \
+ } while (0)
+#else
+#define DISASM(tf, insn) __nothing
+#endif
+
+static bool emul_unaligned(struct trapframe *, ksiginfo_t *,
+ const union instr *);
+static bool do_lst(struct trapframe *, const union instr *, int);
+#ifdef FIX_UNALIGNED_LSTMW
+static bool do_lstmw(struct trapframe *, const union instr *, int);
+#endif
+
+bool
+fix_unaligned(struct trapframe *tf, ksiginfo_t *ksi)
+{
+ union instr insn;
+ int ret;
+
+ KSI_INIT_TRAP(ksi);
+
+ ret = ufetch_32((uint32_t *)tf->tf_srr0, (uint32_t *)&insn.i_int);
+ if (ret) {
+ UA_EVCNT_INCR(isi);
+ DPRINTF("EXC_ISI: ret: %d, srr0: 0x%08lx dear: 0x%08lx\n",
+ ret, tf->tf_srr0, tf->tf_dear);
+ ksi->ksi_signo = SIGSEGV;
+ ksi->ksi_trap = EXC_ISI;
+ ksi->ksi_code = SEGV_MAPERR;
+ ksi->ksi_addr = (void *)tf->tf_srr0;
+ return true;
+ }
+
+ if (emul_unaligned(tf, ksi, &insn))
+ return true;
+
+ CTASSERT(sizeof(insn) == 4); /* It was broken before... */
+ tf->tf_srr0 += sizeof(insn);
+ return false;
+}
+
+#define UAF_STORE 0
+#define UAF_LOAD __BIT(0)
+#define UAF_HALF __BIT(1)
+#define UAF_ALGEBRA __BIT(2)
+#define UAF_REVERSE __BIT(3)
+#define UAF_UPDATE __BIT(4)
+
+static bool
+emul_unaligned(struct trapframe *tf, ksiginfo_t *ksi, const union instr *insn)
+{
+ int flags;
+
+ switch (insn->i_any.i_opcd) {
+ case OPC_LMW:
+ UA_EVCNT_INCR(lmw);
+#ifdef FIX_UNALIGNED_LSTMW
+ flags = UAF_LOAD;
+ if (do_lstmw(tf, insn, flags))
+ goto fault;
+ return false;
+#else
+ goto unknown;
+#endif
+
+ case OPC_STMW:
+ UA_EVCNT_INCR(stmw);
+#ifdef FIX_UNALIGNED_LSTMW
+ flags = UAF_STORE;
+ if (do_lstmw(tf, insn, flags))
+ goto fault;
+ return false;
+#else
+ goto unknown;
+#endif
+
+ case OPC_integer_31:
+ switch (insn->i_x.i_xo) {
+ case OPC31_LWZX:
+ UA_EVCNT_INCR(lwzx);
+ flags = UAF_LOAD;
+ break;
+
+ case OPC31_LWZUX:
+ UA_EVCNT_INCR(lwzux);
+ flags = UAF_LOAD | UAF_UPDATE;
+ break;
+
+ case OPC31_STWX:
+ UA_EVCNT_INCR(stwx);
+ flags = UAF_STORE;
+ break;
+
+ case OPC31_STWUX:
+ UA_EVCNT_INCR(stwux);
+ flags = UAF_STORE | UAF_UPDATE;
+ break;
+
+ case OPC31_LHZX:
+ UA_EVCNT_INCR(lhzx);
+ flags = UAF_LOAD | UAF_HALF;
+ break;
+
+ case OPC31_LHZUX:
+ UA_EVCNT_INCR(lhzux);
+ flags = UAF_LOAD | UAF_HALF | UAF_UPDATE;
+ break;
+
+ case OPC31_LHAX:
+ UA_EVCNT_INCR(lhax);
+ flags = UAF_LOAD | UAF_HALF | UAF_ALGEBRA;
+ break;
+
+ case OPC31_LHAUX:
+ UA_EVCNT_INCR(lhaux);
+ flags = UAF_LOAD | UAF_HALF | UAF_ALGEBRA | UAF_UPDATE;
+ break;
+
+ case OPC31_STHX:
+ UA_EVCNT_INCR(sthx);
+ flags = UAF_STORE | UAF_HALF;
+ break;
+
+ case OPC31_STHUX:
+ UA_EVCNT_INCR(sthux);
+ flags = UAF_STORE | UAF_HALF | UAF_UPDATE;
+ break;
Home |
Main Index |
Thread Index |
Old Index