aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target/arm/arm-semi.c44
1 files changed, 37 insertions, 7 deletions
diff --git a/target/arm/arm-semi.c b/target/arm/arm-semi.c
index 02cd673..e5f1e2a 100644
--- a/target/arm/arm-semi.c
+++ b/target/arm/arm-semi.c
@@ -109,6 +109,7 @@ static int open_modeflags[12] = {
typedef enum GuestFDType {
GuestFDUnused = 0,
GuestFDHost = 1,
+ GuestFDGDB = 2,
} GuestFDType;
/*
@@ -172,14 +173,14 @@ static GuestFD *do_get_guestfd(int guestfd)
/*
* Associate the specified guest fd (which must have been
* allocated via alloc_fd() and not previously used) with
- * the specified host fd.
+ * the specified host/gdb fd.
*/
static void associate_guestfd(int guestfd, int hostfd)
{
GuestFD *gf = do_get_guestfd(guestfd);
assert(gf);
- gf->type = GuestFDHost;
+ gf->type = use_gdb_syscalls() ? GuestFDGDB : GuestFDHost;
gf->hostfd = hostfd;
}
@@ -376,6 +377,39 @@ static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
return is_a64(env) ? env->xregs[0] : env->regs[0];
}
+/*
+ * Types for functions implementing various semihosting calls
+ * for specific types of guest file descriptor. These must all
+ * do the work and return the required return value for the guest,
+ * setting the guest errno if appropriate.
+ */
+typedef uint32_t sys_closefn(ARMCPU *cpu, GuestFD *gf);
+
+static uint32_t host_closefn(ARMCPU *cpu, GuestFD *gf)
+{
+ CPUARMState *env = &cpu->env;
+
+ return set_swi_errno(env, close(gf->hostfd));
+}
+
+static uint32_t gdb_closefn(ARMCPU *cpu, GuestFD *gf)
+{
+ return arm_gdb_syscall(cpu, arm_semi_cb, "close,%x", gf->hostfd);
+}
+
+typedef struct GuestFDFunctions {
+ sys_closefn *closefn;
+} GuestFDFunctions;
+
+static const GuestFDFunctions guestfd_fns[] = {
+ [GuestFDHost] = {
+ .closefn = host_closefn,
+ },
+ [GuestFDGDB] = {
+ .closefn = gdb_closefn,
+ },
+};
+
/* Read the input value from the argument block; fail the semihosting
* call if the memory read fails.
*/
@@ -485,11 +519,7 @@ target_ulong do_arm_semihosting(CPUARMState *env)
return set_swi_errno(env, -1);
}
- if (use_gdb_syscalls()) {
- ret = arm_gdb_syscall(cpu, arm_semi_cb, "close,%x", gf->hostfd);
- } else {
- ret = set_swi_errno(env, close(gf->hostfd));
- }
+ ret = guestfd_fns[gf->type].closefn(cpu, gf);
dealloc_guestfd(arg0);
return ret;
case TARGET_SYS_WRITEC: