Skip to contentSkip to conversation

Arm semihosting support.

PATCH New Paul Brook 1 participant 1 message Apr 17, 2005 Kbuild

lore
Share & tools
lore

Paul Brook

author
#0 lore raw

PATCH 1/1 Arm semihosting support.

The attached patch adds support for ARM "Angel" semihosting syscalls. This is a simple syscall layer which provides basic OS services to embedded applications. It is implemented by several free and proprietary toolchains/ debugging tools, including newlib and the GDB simulator. It's what you get if you configure for "arm-elf".

Paul

Index: Makefile.target
===================================================================
RCS file: /cvsroot/qemu/qemu/Makefile.target,v
retrieving revision 1.64

Makefile.target +1 -1
diff -u -p -r1.64 Makefile.target
@@ -233,7 +233,7 @@ endif
 ifeq ($(TARGET_ARCH), arm)
 OBJS+=nwfpe/fpa11.o nwfpe/fpa11_cpdo.o \
 nwfpe/fpa11_cpdt.o nwfpe/fpa11_cprt.o nwfpe/fpopcode.o nwfpe/single_cpdo.o \
- nwfpe/double_cpdo.o nwfpe/extended_cpdo.o
+ nwfpe/double_cpdo.o nwfpe/extended_cpdo.o arm-semi.o
 endif
 SRCS:= $(OBJS:.o=.c)
 OBJS+= libqemu.a

Index: linux-user/arm-semi.c
===================================================================
RCS file: linux-user/arm-semi.c

arm-semi.c new file +194 -0

194 lines not on this page · raw message

Index: linux-user/main.c
===================================================================
RCS file: /cvsroot/qemu/qemu/linux-user/main.c,v
retrieving revision 1.63

main.c +7 -0
diff -u -p -r1.63 main.c
@@ -363,6 +363,9 @@ void cpu_loop(CPUARMState *env)
                 n = insn & 0xffffff;
                 if (n == ARM_NR_cacheflush) {
                     arm_cache_flush(env->regs[0], env->regs[1]);
+                } else if (n == ARM_NR_semihosting
+                           || n == ARM_NR_thumb_semihosting) {
+                    env->regs[0] = do_arm_semihosting (env);
                 } else if (n >= ARM_SYSCALL_BASE) {
                     /* linux syscall */
                     n -= ARM_SYSCALL_BASE;
@@ -1207,6 +1210,10 @@ int main(int argc, char **argv)
             env->regs[i] = regs->uregs[i];
         }
         env->cpsr = regs->uregs[16];
+        ts->stack_base = info->start_stack;
+        ts->heap_base = info->brk;
+        /* This will be filled in on the first SYS_HEAPINFO call.  */
+        ts->heap_limit = 0;
     }
 #elif defined(TARGET_SPARC)
     {

Index: linux-user/qemu.h
===================================================================
RCS file: /cvsroot/qemu/qemu/linux-user/qemu.h,v
retrieving revision 1.23

qemu.h +6 -0
diff -u -p -r1.23 qemu.h
@@ -62,6 +62,11 @@ typedef struct TaskState {
 #ifdef TARGET_ARM
     /* FPA state */
     FPA11 fpa;
+    /* Extra fields for semihosted binaries.  */
+    uint32_t stack_base;
+    uint32_t heap_base;
+    uint32_t heap_limit;
+    int swi_errno;
 #endif
 #ifdef TARGET_I386
     struct target_vm86plus_struct *target_v86;
@@ -80,6 +85,7 @@ int elf_exec(const char * filename, char
              struct target_pt_regs * regs, struct image_info *infop);
 
 void target_set_brk(char *new_brk);
+long do_brk(char *new_brk);
 void syscall_init(void);
 long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, 
                 long arg4, long arg5, long arg6);

Index: linux-user/syscall.c
===================================================================
RCS file: /cvsroot/qemu/qemu/linux-user/syscall.c,v retrieving revision 1.58

syscall.c +1 -1
diff -u -p -r1.58 syscall.c
@@ -264,7 +264,7 @@ void target_set_brk(char *new_brk)
     target_original_brk = new_brk;
 }
 
-static long do_brk(char *new_brk)
+long do_brk(char *new_brk)
 {
     char *brk_page;
     long mapped_addr;

Index: linux-user/arm/syscall.h
===================================================================
RCS file: /cvsroot/qemu/qemu/linux-user/arm/syscall.h,v retrieving revision 1.4

arm/syscall.h +5 -0
diff -u -p -r1.4 syscall.h
@@ -29,8 +29,13 @@ struct target_pt_regs {
 
 #define ARM_NR_cacheflush (ARM_SYSCALL_BASE + 0xf0000 + 2)
 
+#define ARM_NR_semihosting	  0x123456
+#define ARM_NR_thumb_semihosting  0xAB
+
 #if defined(TARGET_WORDS_BIGENDIAN)
 #define UNAME_MACHINE "armv5teb"
 #else
 #define UNAME_MACHINE "armv5tel"
 #endif
+
+uint32_t do_arm_semihosting(CPUState *);