From: Nathan Froyd <froydnj@codesourcery.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 4/6] target-mips: add MDI semihosting support to mipssim machine
Date: Mon, 3 Aug 2009 07:45:09 -0700 [thread overview]
Message-ID: <1249310711-8873-5-git-send-email-froydnj@codesourcery.com> (raw)
In-Reply-To: <1249310711-8873-1-git-send-email-froydnj@codesourcery.com>
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 <froydnj@codesourcery.com>
---
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
next prev parent reply other threads:[~2009-08-03 15:45 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-08-03 14:45 [Qemu-devel] [PATCH 0/6] target-mips: add MDI semihosting, v2 Nathan Froyd
2009-08-03 14:45 ` [Qemu-devel] [PATCH 1/6] sysemu: add section_callback argument to ELF loader Nathan Froyd
2009-08-03 14:45 ` [Qemu-devel] [PATCH 2/6] add softmmu_target_strlen Nathan Froyd
2009-08-03 14:45 ` [Qemu-devel] [PATCH 3/6] add implementation of MIPS semihosting Nathan Froyd
2009-08-03 14:45 ` Nathan Froyd [this message]
2009-08-03 14:45 ` [Qemu-devel] [PATCH 5/6] enable --semihosting option for TARGET_MIPS Nathan Froyd
2009-08-03 14:45 ` [Qemu-devel] [PATCH 6/6] gdbstub: add qSymbol handling " Nathan Froyd
-- strict thread matches above, loose matches on Subject: below --
2009-07-17 20:33 [Qemu-devel] [PATCH 0/6] target-mips: add MDI semihosting Nathan Froyd
2009-07-17 20:33 ` [Qemu-devel] [PATCH 4/6] target-mips: add MDI semihosting support to mipssim machine Nathan Froyd
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1249310711-8873-5-git-send-email-froydnj@codesourcery.com \
--to=froydnj@codesourcery.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).