summaryrefslogtreecommitdiffstats
path: root/sys/ia64
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2005-01-02 00:20:54 +0000
committermarcel <marcel@FreeBSD.org>2005-01-02 00:20:54 +0000
commit35d2e4e388757f8dde5e8b084b286c2c552eea0b (patch)
tree6fc2eacd89cae5c2eb2f513b16f82744fe878497 /sys/ia64
parent33e59b46a0c600a04b3a71fcb6507f64c8efa421 (diff)
downloadFreeBSD-src-35d2e4e388757f8dde5e8b084b286c2c552eea0b.zip
FreeBSD-src-35d2e4e388757f8dde5e8b084b286c2c552eea0b.tar.gz
Further enhance the handling of misaligned loads and stores:
o implement double-extended and single precision loads and stores, o implement double precision stores, o replace the machdep.unaligned_print sysctl with debug.unaligned_print and change the default value to 0, o replace the machdep.unaligned_sigbus sysctl with debug.unaligned_test, o Remmove the fillfd() function. The function is trvial enough for inline assembly. The debug.unaligned_test sysctl is used to test the emulation of misaligned loads and stores. When PSR.ac is 0, the CPU will handle misaligned memory accesses itselfi and we don't get an exception for it. When PSR.ac is 1, the process needs to be signalled and we should not emulate. The sysctl takes effect when PSR.ac is 1 and tells us that we should emulate and not send a signal. PR: 72268 MFC after: 1 week
Diffstat (limited to 'sys/ia64')
-rw-r--r--sys/ia64/ia64/support.S10
-rw-r--r--sys/ia64/ia64/unaligned.c71
-rw-r--r--sys/ia64/include/md_var.h1
3 files changed, 59 insertions, 23 deletions
diff --git a/sys/ia64/ia64/support.S b/sys/ia64/ia64/support.S
index 9c7a858..589c1ab 100644
--- a/sys/ia64/ia64/support.S
+++ b/sys/ia64/ia64/support.S
@@ -891,16 +891,6 @@ ENTRY(copyerr, 0)
br.ret.sptk.few rp
END(copyerr)
-/*
- * Support functions for handling of unaligned memory accesses.
- */
-ENTRY(spillfd, 2)
- ldfd f6 = [r32]
- ;;
- stf.spill [r33] = f6
- br.ret.sptk rp
-END(spillfd)
-
#if defined(GPROF)
/*
* Important registers:
diff --git a/sys/ia64/ia64/unaligned.c b/sys/ia64/ia64/unaligned.c
index 2124e99..09c2fc5 100644
--- a/sys/ia64/ia64/unaligned.c
+++ b/sys/ia64/ia64/unaligned.c
@@ -38,14 +38,13 @@
#include <machine/md_var.h>
#include <ia64/disasm/disasm.h>
-static int ia64_unaligned_print = 1; /* warn about unaligned accesses. */
-static int ia64_unaligned_sigbus = 0; /* SIGBUS on all unaligned accesses. */
-
-SYSCTL_INT(_machdep, OID_AUTO, unaligned_print, CTLFLAG_RW,
+static int ia64_unaligned_print = 0;
+SYSCTL_INT(_debug, OID_AUTO, unaligned_print, CTLFLAG_RW,
&ia64_unaligned_print, 0, "warn about unaligned accesses");
-SYSCTL_INT(_machdep, OID_AUTO, unaligned_sigbus, CTLFLAG_RW,
- &ia64_unaligned_sigbus, 0, "do not SIGBUS on fixed-up accesses");
+static int ia64_unaligned_test = 0;
+SYSCTL_INT(_debug, OID_AUTO, unaligned_test, CTLFLAG_RW,
+ &ia64_unaligned_test, 0, "test emulation when PSR.ac is set");
static void *
fpreg_ptr(mcontext_t *mc, int fr)
@@ -129,7 +128,9 @@ fixup(struct asm_inst *i, mcontext_t *mc, uint64_t va)
{
union {
double d;
+ long double e;
uint64_t i;
+ float s;
} buf;
void *reg;
uint64_t postinc;
@@ -157,11 +158,28 @@ fixup(struct asm_inst *i, mcontext_t *mc, uint64_t va)
wrreg(reg, buf.i);
break;
case ASM_OP_LDFD:
- copyin((void*)va, (void*)&buf.d, 8);
+ copyin((void*)va, (void*)&buf.d, sizeof(buf.d));
+ reg = fpreg_ptr(mc, (int)i->i_oper[1].o_value);
+ if (reg == NULL)
+ return (EINVAL);
+ __asm("ldfd f6=%1;; stf.spill %0=f6" : "=m"(*(double *)reg) :
+ "m"(buf.d) : "f6");
+ break;
+ case ASM_OP_LDFE:
+ copyin((void*)va, (void*)&buf.e, sizeof(buf.e));
+ reg = fpreg_ptr(mc, (int)i->i_oper[1].o_value);
+ if (reg == NULL)
+ return (EINVAL);
+ __asm("ldfe f6=%1;; stf.spill %0=f6" :
+ "=m"(*(long double *)reg) : "m"(buf.e) : "f6");
+ break;
+ case ASM_OP_LDFS:
+ copyin((void*)va, (void*)&buf.s, sizeof(buf.s));
reg = fpreg_ptr(mc, (int)i->i_oper[1].o_value);
if (reg == NULL)
return (EINVAL);
- spillfd((void*)&buf.d, reg);
+ __asm("ldfs f6=%1;; stf.spill %0=f6" : "=m"(*(float *)reg) :
+ "m"(buf.s) : "f6");
break;
case ASM_OP_ST2:
reg = greg_ptr(mc, (int)i->i_oper[2].o_value);
@@ -184,6 +202,30 @@ fixup(struct asm_inst *i, mcontext_t *mc, uint64_t va)
buf.i = rdreg(reg);
copyout((void*)&buf.i, (void*)va, 8);
break;
+ case ASM_OP_STFD:
+ reg = fpreg_ptr(mc, (int)i->i_oper[2].o_value);
+ if (reg == NULL)
+ return (EINVAL);
+ __asm("ldf.fill f6=%1;; stfd %0=f6" : "=m"(buf.d) :
+ "m"(*(double *)reg) : "f6");
+ copyout((void*)&buf.d, (void*)va, sizeof(buf.d));
+ break;
+ case ASM_OP_STFE:
+ reg = fpreg_ptr(mc, (int)i->i_oper[2].o_value);
+ if (reg == NULL)
+ return (EINVAL);
+ __asm("ldf.fill f6=%1;; stfe %0=f6" : "=m"(buf.e) :
+ "m"(*(long double *)reg) : "f6");
+ copyout((void*)&buf.e, (void*)va, sizeof(buf.e));
+ break;
+ case ASM_OP_STFS:
+ reg = fpreg_ptr(mc, (int)i->i_oper[2].o_value);
+ if (reg == NULL)
+ return (EINVAL);
+ __asm("ldf.fill f6=%1;; stfs %0=f6" : "=m"(buf.s) :
+ "m"(*(float *)reg) : "f6");
+ copyout((void*)&buf.s, (void*)va, sizeof(buf.s));
+ break;
default:
return (ENOENT);
}
@@ -224,11 +266,16 @@ unaligned_fixup(struct trapframe *tf, struct thread *td)
}
/*
- * If PSR.ac is set, then the process wants to know about misaligned
- * loads and stores. Send it a SIGBUS so that it can deal with them.
- * We also send a SIGBUS if configured to do so.
+ * If PSR.ac is set, the process wants to be signalled about mis-
+ * aligned loads and stores. Send it a SIGBUS. In order for us to
+ * test the emulation of misaligned loads and stores, we have a
+ * sysctl that tells us that we must emulate the load or store,
+ * instead of sending the signal. We need the sysctl because if
+ * PSR.ac is not set, the CPU may (and likely will) deal with the
+ * misaligned load or store itself. As such, we won't get the
+ * exception.
*/
- if ((tf->tf_special.psr & IA64_PSR_AC) || ia64_unaligned_sigbus)
+ if ((tf->tf_special.psr & IA64_PSR_AC) && !ia64_unaligned_test)
return (SIGBUS);
if (!asm_decode(tf->tf_special.iip, &bundle))
diff --git a/sys/ia64/include/md_var.h b/sys/ia64/include/md_var.h
index d1515fe..437c2ce 100644
--- a/sys/ia64/include/md_var.h
+++ b/sys/ia64/include/md_var.h
@@ -88,7 +88,6 @@ void map_gateway_page(void);
void map_pal_code(void);
void os_boot_rendez(void);
void os_mca(void);
-void spillfd(void *src, void *dst);
int syscall(struct trapframe *);
void trap(int, struct trapframe *);
void trap_panic(int, struct trapframe *);
OpenPOWER on IntegriCloud