summaryrefslogtreecommitdiff
path: root/sys/arch/mips64/include
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2010-11-24 21:16:29 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2010-11-24 21:16:29 +0000
commit1a6ca4c1794c5f70d8e81d3515a8b2fb580e2c02 (patch)
treeb8ab39d08cd8a362978c5f402aa6785fca618484 /sys/arch/mips64/include
parent410a2cfa8b7417b4d090af83fc0bc8a91f8ada14 (diff)
Floating-point emulation code for systems lacking proper FPU (i.e. Octeon),
enabled by option FPUEMUL. This is pretty straightforward, except for conditional branch on FPU condition codes emulation (bc1f/bc1fl/bc1t/bc1tl instructions): unlike most RISC-with-delay-slots designs (m88k, sparc), the branch pipeline is not exposed to the kernel on Mips, therefore we can not resume a branch without losing the delay slot instruction. Some other operating systems work around this issue by emulating the delay slot instruction, but this is error-prone (and requires the kernel code to be aware of all supported instructions of the processor it is currently running on), some use dedicated breakpoints to single-step through the delay slot and then resume the branch as expected, but this causes a lot of copy-on-write allocations. This code chooses a third path, of copying the delay slot instructions to run toa special `magic' page, followed by a special trap instruction to give control back to the kernel. This makes sure the instruction will actually be run by the processor, and that no more than one page per process is wasted, regardless of the number of branches to emulate. Tested on octeon (big-endian) by syuu@ and on loongson (little-endian) by me. Note that enabling option FPUEMUL in the kernel will completely disable the hardware FPU, if there is one; there is currently no way to build a kernel supporting both hardware and software FPU, and there is no reason to change this until there is a strong need to support both.
Diffstat (limited to 'sys/arch/mips64/include')
-rw-r--r--sys/arch/mips64/include/_types.h3
-rw-r--r--sys/arch/mips64/include/cpu.h8
-rw-r--r--sys/arch/mips64/include/proc.h15
3 files changed, 22 insertions, 4 deletions
diff --git a/sys/arch/mips64/include/_types.h b/sys/arch/mips64/include/_types.h
index bd59a97e6e8..e22ed5c01bf 100644
--- a/sys/arch/mips64/include/_types.h
+++ b/sys/arch/mips64/include/_types.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: _types.h,v 1.7 2009/11/04 19:14:10 kettenis Exp $ */
+/* $OpenBSD: _types.h,v 1.8 2010/11/24 21:16:26 miod Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -135,5 +135,6 @@ typedef struct label_t {
/* Feature test macros */
#define __HAVE_TIMECOUNTER
+#define __HAVE_EXEC_MD_MAP
#endif /* _MIPS64__TYPES_H_ */
diff --git a/sys/arch/mips64/include/cpu.h b/sys/arch/mips64/include/cpu.h
index a7843f21435..2ef12590d9d 100644
--- a/sys/arch/mips64/include/cpu.h
+++ b/sys/arch/mips64/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.68 2010/10/24 15:40:03 miod Exp $ */
+/* $OpenBSD: cpu.h,v 1.69 2010/11/24 21:16:26 miod Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -279,11 +279,13 @@ extern vaddr_t uncached_base;
#define BREAK_BRKPT_VAL 514
#define BREAK_SOVER_VAL 515
#define BREAK_DDB_VAL 516
+#define BREAK_FPUEMUL_VAL 517
#define BREAK_KDB (BREAK_INSTR | (BREAK_KDB_VAL << BREAK_VAL_SHIFT))
#define BREAK_SSTEP (BREAK_INSTR | (BREAK_SSTEP_VAL << BREAK_VAL_SHIFT))
#define BREAK_BRKPT (BREAK_INSTR | (BREAK_BRKPT_VAL << BREAK_VAL_SHIFT))
#define BREAK_SOVER (BREAK_INSTR | (BREAK_SOVER_VAL << BREAK_VAL_SHIFT))
#define BREAK_DDB (BREAK_INSTR | (BREAK_DDB_VAL << BREAK_VAL_SHIFT))
+#define BREAK_FPUEMUL (BREAK_INSTR | (BREAK_FPUEMUL_VAL << BREAK_VAL_SHIFT))
/*
* The floating point version and status registers.
@@ -550,6 +552,7 @@ void cpu_startclock(struct cpu_info *);
extern vaddr_t CpuCacheAliasMask;
+struct exec_package;
struct tlb_entry;
struct user;
@@ -604,10 +607,13 @@ int tlb_update(vaddr_t, unsigned);
void tlb_read(int, struct tlb_entry *);
void build_trampoline(vaddr_t, vaddr_t);
+int exec_md_map(struct proc *, struct exec_package *);
void savectx(struct user *, int);
void enable_fpu(struct proc *);
void save_fpu(void);
+int fpe_branch_emulate(struct proc *, struct trap_frame *, uint32_t,
+ vaddr_t);
int guarded_read_4(paddr_t, uint32_t *);
int guarded_write_4(paddr_t, uint32_t);
diff --git a/sys/arch/mips64/include/proc.h b/sys/arch/mips64/include/proc.h
index b78d8f109e8..f4d31e7201a 100644
--- a/sys/arch/mips64/include/proc.h
+++ b/sys/arch/mips64/include/proc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: proc.h,v 1.6 2010/11/24 21:01:02 miod Exp $ */
+/* $OpenBSD: proc.h,v 1.7 2010/11/24 21:16:26 miod Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -50,6 +50,11 @@ struct mdproc {
vaddr_t md_ss_addr; /* single step address */
uint32_t md_ss_instr; /* saved single step instruction */
+ /* fpu emulation fields */
+ vaddr_t md_fppgva; /* vaddr of the branch emulation page */
+ vaddr_t md_fpbranchva; /* vaddr of fp branch destination */
+ vaddr_t md_fpslotva; /* initial vaddr of delay slot */
+
/* The following is RM7000 dependent, but kept in for compatibility */
int md_pc_ctrl; /* performance counter control */
int md_pc_count; /* performance counter */
@@ -59,7 +64,13 @@ struct mdproc {
int md_watch_m;
};
-/* md_flags */
+/*
+ * Values for md_flags.
+ * MDP_FPUSED has two meanings: if the floating point hardware (coprocessor
+ * #1) is available, it means it has been used; if there is no floating
+ * point hardware, it means the process is currently running a duplicated
+ * delay slot, created by the branch emulation logic.
+ */
#define MDP_FPUSED 0x00000001 /* floating point coprocessor used */
#define MDP_PERF 0x00010000 /* Performance counter used */
#define MDP_WATCH1 0x00020000 /* Watch register 1 used */