[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 4/6] target-mips: add MDI semihosting support to mip
From: |
Nathan Froyd |
Subject: |
[Qemu-devel] [PATCH 4/6] target-mips: add MDI semihosting support to mipssim machine |
Date: |
Mon, 3 Aug 2009 07:45:09 -0700 |
We need to grovel through the .sdeosabi section to find out where
_mdi_syscall is located. Once we find it, we can set a breakpoint
there.
We use BP_CPU breakpoints to implement the semihosting breakpoint.
Writing BREAK instructions means that users could unintentionally remove
breakpoints, either by means of buggy programs, or mistyped commands.
Using BP_CPU breakpoints means that the user cannot access them and
therefore that they will not be removed (although BP_CPU breakpoints can
be overridden by BP_GDB breakpoints; we assume that the user knows what
he or she is doing if a breakpoint is set at _mdi_syscall).
The shuffling of #includes in helper.c is to deal with peculiarities of
dyngen-exec.h.
Signed-off-by: Nathan Froyd <address@hidden>
---
hw/mips_mipssim.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++--
target-mips/cpu.h | 2 +
target-mips/helper.c | 50 +++++++++++++++++++++++++++++++++++++++---
3 files changed, 103 insertions(+), 7 deletions(-)
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index 6080dc8..7da3269 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -48,6 +48,50 @@ static struct _loaderparams {
const char *initrd_filename;
} loaderparams;
+static uint32_t mdi_semihost_bkpt;
+
+static void find_sdeosabi_section (int fd, int must_swab,
+ uint64_t size, uint64_t offset,
+ char *name)
+{
+/* We don't support semihosting for 64-bit targets */
+#ifndef TARGET_MIPS64
+ if (semihosting_enabled &&
+ size >= 8 &&
+ strcmp (name, ".sdeosabi") == 0) {
+ uint64_t section_offset = 0;
+
+ if (lseek(fd, offset, SEEK_SET) < 0)
+ return;
+
+ while (section_offset < size) {
+ /* .sdeosabi is organized into pairs of 4-byte words. The
+ first word in each pair is a numeric tag; the second word
+ is interpreted according to the tag. For our purposes,
+ we're looking for tag 2. The second word will be the
+ address of the _mdi_syscall function. */
+ uint32_t bkpt_info[2];
+
+ if (read(fd, bkpt_info, sizeof(bkpt_info)) == sizeof(bkpt_info)) {
+ if (must_swab) {
+ bswap32s (&bkpt_info[0]);
+ bswap32s (&bkpt_info[1]);
+ }
+
+ if (bkpt_info[0] == 2 && bkpt_info[1]) {
+ mdi_semihost_bkpt = bkpt_info[1];
+ break;
+ }
+ } else {
+ break;
+ }
+
+ section_offset += sizeof(bkpt_info);
+ }
+ }
+#endif
+}
+
static void load_kernel (CPUState *env)
{
int64_t entry, kernel_low, kernel_high;
@@ -55,9 +99,12 @@ static void load_kernel (CPUState *env)
long initrd_size;
ram_addr_t initrd_offset;
- kernel_size = load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND,
- (uint64_t *)&entry, (uint64_t *)&kernel_low,
- (uint64_t *)&kernel_high);
+ kernel_size = load_elf_introspect(loaderparams.kernel_filename,
+ VIRT_TO_PHYS_ADDEND,
+ (uint64_t *)&entry,
+ (uint64_t *)&kernel_low,
+ (uint64_t *)&kernel_high,
+ find_sdeosabi_section);
if (kernel_size >= 0) {
if ((entry & ~0x7fffffffULL) == 0x80000000)
entry = (int32_t)entry;
@@ -68,6 +115,11 @@ static void load_kernel (CPUState *env)
exit(1);
}
+ /* set up semihosting */
+ if (semihosting_enabled && mdi_semihost_bkpt) {
+ install_semihosting_breakpoint(env, mdi_semihost_bkpt);
+ }
+
/* load initrd */
initrd_size = 0;
initrd_offset = 0;
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 1510244..eb495fd 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -588,6 +588,8 @@ void do_interrupt (CPUState *env);
void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra);
void do_mips_semihosting(CPUState *env);
+void install_semihosting_breakpoint(CPUState *env, uint32_t bkpt_address);
+
static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
{
env->active_tc.PC = tb->pc;
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 7369025..db9ee8d 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -18,13 +18,10 @@
*/
#include <stdarg.h>
#include <stdlib.h>
-#include <stdio.h>
#include <string.h>
-#include <inttypes.h>
#include <signal.h>
-#include "cpu.h"
-#include "exec-all.h"
+#include "exec.h"
enum {
TLBRET_DIRTY = -4,
@@ -340,6 +337,51 @@ static const char * const excp_names[EXCP_LAST + 1] = {
[EXCP_CACHE] = "cache error",
};
+#if !defined(CONFIG_USER_ONLY)
+extern int semihosting_enabled;
+static uint32_t mdi_semihost_breakpoint;
+
+static CPUDebugExcpHandler *prev_debug_excp_handler;
+static CPUBreakpoint *semihosting_breakpoint;
+
+static void breakpoint_handler(CPUState *env)
+{
+ CPUBreakpoint *bp;
+ int semihosting_done = 0;
+
+ TAILQ_FOREACH(bp, &env->breakpoints, entry) {
+ if (bp->pc == env->active_tc.PC &&
+ semihosting_enabled &&
+ mdi_semihost_breakpoint &&
+ bp->pc == mdi_semihost_breakpoint &&
+ bp->flags & BP_CPU) {
+ do_mips_semihosting(env);
+ semihosting_done = 1;
+ break;
+ }
+ }
+ if (prev_debug_excp_handler) {
+ prev_debug_excp_handler(env);
+ }
+ if (semihosting_done) {
+ /* Reset exception state and return. */
+ env->exception_index = -1;
+ cpu_loop_exit();
+ }
+}
+
+void install_semihosting_breakpoint(CPUState *env, uint32_t bkpt_address)
+{
+ if (!semihosting_breakpoint && semihosting_enabled) {
+ mdi_semihost_breakpoint = bkpt_address & ~(uint32_t)1;
+ cpu_breakpoint_insert(env, mdi_semihost_breakpoint, BP_CPU,
+ &semihosting_breakpoint);
+ prev_debug_excp_handler =
+ cpu_set_debug_excp_handler(breakpoint_handler);
+ }
+}
+#endif
+
void do_interrupt (CPUState *env)
{
#if !defined(CONFIG_USER_ONLY)
--
1.6.3.2
- [Qemu-devel] [PATCH 0/6] target-mips: add MDI semihosting, v2, Nathan Froyd, 2009/08/03
- [Qemu-devel] [PATCH 5/6] enable --semihosting option for TARGET_MIPS, Nathan Froyd, 2009/08/03
- [Qemu-devel] [PATCH 1/6] sysemu: add section_callback argument to ELF loader, Nathan Froyd, 2009/08/03
- [Qemu-devel] [PATCH 6/6] gdbstub: add qSymbol handling for TARGET_MIPS, Nathan Froyd, 2009/08/03
- [Qemu-devel] [PATCH 2/6] add softmmu_target_strlen, Nathan Froyd, 2009/08/03
- [Qemu-devel] [PATCH 3/6] add implementation of MIPS semihosting, Nathan Froyd, 2009/08/03
- [Qemu-devel] [PATCH 4/6] target-mips: add MDI semihosting support to mipssim machine,
Nathan Froyd <=