From a946ce802002fe6233adbf1a6222d0837d44fc33 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Tue, 22 Apr 2014 20:18:41 +0200 Subject: [PATCH 1/4] test: lm32: make test cases independent Make test cases independent from from each other. Eg. if a test case needs a specific value in register A, don't rely on the fact that it is already set by the preceding test case. Signed-off-by: Michael Walle --- tests/tcg/lm32/test_lb.S | 4 ++++ tests/tcg/lm32/test_lbu.S | 4 ++++ tests/tcg/lm32/test_lh.S | 4 ++++ tests/tcg/lm32/test_lhu.S | 4 ++++ tests/tcg/lm32/test_lw.S | 2 ++ tests/tcg/lm32/test_sb.S | 2 ++ tests/tcg/lm32/test_sh.S | 2 ++ tests/tcg/lm32/test_sw.S | 3 +++ 8 files changed, 25 insertions(+) diff --git a/tests/tcg/lm32/test_lb.S b/tests/tcg/lm32/test_lb.S index f84d21ead9..d677eea4c4 100644 --- a/tests/tcg/lm32/test_lb.S +++ b/tests/tcg/lm32/test_lb.S @@ -8,10 +8,12 @@ lb r3, (r1+0) check_r3 0x7e test_name LB_2 +load r1 data lb r3, (r1+1) check_r3 0x7f test_name LB_3 +load r1 data lb r3, (r1+-1) check_r3 0x7d @@ -21,10 +23,12 @@ lb r3, (r1+0) check_r3 0xfffffffe test_name LB_5 +load r1 data_msb lb r3, (r1+1) check_r3 0xffffffff test_name LB_6 +load r1 data_msb lb r3, (r1+-1) check_r3 0xfffffffd diff --git a/tests/tcg/lm32/test_lbu.S b/tests/tcg/lm32/test_lbu.S index 4c1786ad71..dc5d5f67d3 100644 --- a/tests/tcg/lm32/test_lbu.S +++ b/tests/tcg/lm32/test_lbu.S @@ -8,10 +8,12 @@ lbu r3, (r1+0) check_r3 0x7e test_name LBU_2 +load r1 data lbu r3, (r1+1) check_r3 0x7f test_name LBU_3 +load r1 data lbu r3, (r1+-1) check_r3 0x7d @@ -21,10 +23,12 @@ lbu r3, (r1+0) check_r3 0xfe test_name LBU_5 +load r1 data_msb lbu r3, (r1+1) check_r3 0xff test_name LBU_6 +load r1 data_msb lbu r3, (r1+-1) check_r3 0xfd diff --git a/tests/tcg/lm32/test_lh.S b/tests/tcg/lm32/test_lh.S index e57d9e35cf..397996bddd 100644 --- a/tests/tcg/lm32/test_lh.S +++ b/tests/tcg/lm32/test_lh.S @@ -8,10 +8,12 @@ lh r3, (r1+0) check_r3 0x7e7f test_name LH_2 +load r1 data lh r3, (r1+2) check_r3 0x7071 test_name LH_3 +load r1 data lh r3, (r1+-2) check_r3 0x7c7d @@ -21,10 +23,12 @@ lh r3, (r1+0) check_r3 0xfffffeff test_name LH_5 +load r1 data_msb lh r3, (r1+2) check_r3 0xfffff0f1 test_name LH_6 +load r1 data_msb lh r3, (r1+-2) check_r3 0xfffffcfd diff --git a/tests/tcg/lm32/test_lhu.S b/tests/tcg/lm32/test_lhu.S index e648775d94..8de7c52560 100644 --- a/tests/tcg/lm32/test_lhu.S +++ b/tests/tcg/lm32/test_lhu.S @@ -8,10 +8,12 @@ lhu r3, (r1+0) check_r3 0x7e7f test_name LHU_2 +load r1 data lhu r3, (r1+2) check_r3 0x7071 test_name LHU_3 +load r1 data lhu r3, (r1+-2) check_r3 0x7c7d @@ -21,10 +23,12 @@ lhu r3, (r1+0) check_r3 0xfeff test_name LHU_5 +load r1 data_msb lhu r3, (r1+2) check_r3 0xf0f1 test_name LHU_6 +load r1 data_msb lhu r3, (r1+-2) check_r3 0xfcfd diff --git a/tests/tcg/lm32/test_lw.S b/tests/tcg/lm32/test_lw.S index f8c919d2b8..996e5f8c88 100644 --- a/tests/tcg/lm32/test_lw.S +++ b/tests/tcg/lm32/test_lw.S @@ -8,10 +8,12 @@ lw r3, (r1+0) check_r3 0x7e7f7071 test_name LW_2 +load r1 data lw r3, (r1+4) check_r3 0x72737475 test_name LW_3 +load r1 data lw r3, (r1+-4) check_r3 0x7a7b7c7d diff --git a/tests/tcg/lm32/test_sb.S b/tests/tcg/lm32/test_sb.S index 89e39d621d..b15a89d342 100644 --- a/tests/tcg/lm32/test_sb.S +++ b/tests/tcg/lm32/test_sb.S @@ -9,11 +9,13 @@ sb (r1+0), r2 check_mem data 0xaa000000 test_name SB_2 +load r1 data load r2 0xf0f1f2bb sb (r1+1), r2 check_mem data 0xaabb0000 test_name SB_3 +load r1 data load r2 0xf0f1f2cc sb (r1+-1), r2 check_mem data0 0x000000cc diff --git a/tests/tcg/lm32/test_sh.S b/tests/tcg/lm32/test_sh.S index ea8b3f2067..bba10224f6 100644 --- a/tests/tcg/lm32/test_sh.S +++ b/tests/tcg/lm32/test_sh.S @@ -9,11 +9,13 @@ sh (r1+0), r2 check_mem data 0xaaaa0000 test_name SH_2 +load r1 data load r2 0xf0f1bbbb sh (r1+2), r2 check_mem data 0xaaaabbbb test_name SH_3 +load r1 data load r2 0xf0f1cccc sh (r1+-2), r2 check_mem data0 0x0000cccc diff --git a/tests/tcg/lm32/test_sw.S b/tests/tcg/lm32/test_sw.S index d1fdadce61..2b1c017e7b 100644 --- a/tests/tcg/lm32/test_sw.S +++ b/tests/tcg/lm32/test_sw.S @@ -9,16 +9,19 @@ sw (r1+0), r2 check_mem data 0xaabbccdd test_name SW_2 +load r1 data load r2 0x00112233 sw (r1+4), r2 check_mem data1 0x00112233 test_name SW_3 +load r1 data load r2 0x44556677 sw (r1+-4), r2 check_mem data0 0x44556677 test_name SW_4 +load r1 data sw (r1+0), r1 lw r3, (r1+0) check_r3 data From f7bbcfb5c303a07322f1e0f258a936a720183169 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Tue, 22 Apr 2014 20:18:42 +0200 Subject: [PATCH 2/4] target-lm32: add semihosting support Intercept certain system calls if semihosting is enabled. This should behave like the GDB simulator. Signed-off-by: Michael Walle --- qemu-options.hx | 3 +- target-lm32/Makefile.objs | 1 + target-lm32/README | 9 ++ target-lm32/cpu.h | 1 + target-lm32/helper.c | 14 ++- target-lm32/lm32-semi.c | 215 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 240 insertions(+), 3 deletions(-) create mode 100644 target-lm32/lm32-semi.c diff --git a/qemu-options.hx b/qemu-options.hx index c2c0823911..4011d46d62 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -3071,7 +3071,8 @@ STEXI Set OpenBIOS nvram @var{variable} to given @var{value} (PPC, SPARC only). ETEXI DEF("semihosting", 0, QEMU_OPTION_semihosting, - "-semihosting semihosting mode\n", QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA) + "-semihosting semihosting mode\n", + QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_LM32) STEXI @item -semihosting @findex -semihosting diff --git a/target-lm32/Makefile.objs b/target-lm32/Makefile.objs index 40236876c8..c3e1bd6bd6 100644 --- a/target-lm32/Makefile.objs +++ b/target-lm32/Makefile.objs @@ -1,3 +1,4 @@ obj-y += translate.o op_helper.o helper.o cpu.o obj-y += gdbstub.o +obj-y += lm32-semi.o obj-$(CONFIG_SOFTMMU) += machine.o diff --git a/target-lm32/README b/target-lm32/README index a1c2c7eb1e..03ddbffc54 100644 --- a/target-lm32/README +++ b/target-lm32/README @@ -26,6 +26,15 @@ first BSP which instantiate this model. A (32 bit) write to 0xfff0000 causes a vm shutdown. +Semihosting +----------- +Semihosting on this target is supported. Some system calls like read, write +and exit are executed on the host if semihosting is enabled. See +target/lm32-semi.c for all supported system calls. Emulation aware programs +can use this mechanism to shut down the virtual machine and print to the +host console. See the tcg tests for an example. + + Special instructions -------------------- The translation recognizes one special instruction to halt the cpu: diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h index 24bde78502..70600aa47a 100644 --- a/target-lm32/cpu.h +++ b/target-lm32/cpu.h @@ -217,6 +217,7 @@ void lm32_breakpoint_remove(CPULM32State *env, int index); void lm32_watchpoint_insert(CPULM32State *env, int index, target_ulong address, lm32_wp_t wp_type); void lm32_watchpoint_remove(CPULM32State *env, int index); +bool lm32_cpu_do_semihosting(CPUState *cs); static inline CPULM32State *cpu_init(const char *cpu_model) { diff --git a/target-lm32/helper.c b/target-lm32/helper.c index 783aa16a45..1bca1961af 100644 --- a/target-lm32/helper.c +++ b/target-lm32/helper.c @@ -1,7 +1,7 @@ /* * LatticeMico32 helper routines. * - * Copyright (c) 2010 Michael Walle + * Copyright (c) 2010-2014 Michael Walle * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,6 +19,7 @@ #include "cpu.h" #include "qemu/host-utils.h" +#include "sysemu/sysemu.h" int lm32_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw, int mmu_idx) @@ -159,11 +160,20 @@ void lm32_cpu_do_interrupt(CPUState *cs) "exception at pc=%x type=%x\n", env->pc, cs->exception_index); switch (cs->exception_index) { + case EXCP_SYSTEMCALL: + if (unlikely(semihosting_enabled)) { + /* do_semicall() returns true if call was handled. Otherwise + * do the normal exception handling. */ + if (lm32_cpu_do_semihosting(cs)) { + env->pc += 4; + break; + } + } + /* fall through */ case EXCP_INSN_BUS_ERROR: case EXCP_DATA_BUS_ERROR: case EXCP_DIVIDE_BY_ZERO: case EXCP_IRQ: - case EXCP_SYSTEMCALL: /* non-debug exceptions */ env->regs[R_EA] = env->pc; env->ie |= (env->ie & IE_IE) ? IE_EIE : 0; diff --git a/target-lm32/lm32-semi.c b/target-lm32/lm32-semi.c new file mode 100644 index 0000000000..fc9d2d1c73 --- /dev/null +++ b/target-lm32/lm32-semi.c @@ -0,0 +1,215 @@ +/* + * Lattice Mico32 semihosting syscall interface + * + * Copyright (c) 2014 Michael Walle + * + * Based on target-m68k/m68k-semi.c, which is + * Copyright (c) 2005-2007 CodeSourcery. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include +#include +#include +#include +#include "cpu.h" +#include "helper.h" +#include "qemu/log.h" +#include "exec/softmmu-semi.h" + +enum { + TARGET_SYS_exit = 1, + TARGET_SYS_open = 2, + TARGET_SYS_close = 3, + TARGET_SYS_read = 4, + TARGET_SYS_write = 5, + TARGET_SYS_lseek = 6, + TARGET_SYS_fstat = 10, + TARGET_SYS_stat = 15, +}; + +enum { + NEWLIB_O_RDONLY = 0x0, + NEWLIB_O_WRONLY = 0x1, + NEWLIB_O_RDWR = 0x2, + NEWLIB_O_APPEND = 0x8, + NEWLIB_O_CREAT = 0x200, + NEWLIB_O_TRUNC = 0x400, + NEWLIB_O_EXCL = 0x800, +}; + +static int translate_openflags(int flags) +{ + int hf; + + if (flags & NEWLIB_O_WRONLY) { + hf = O_WRONLY; + } else if (flags & NEWLIB_O_RDWR) { + hf = O_RDWR; + } else { + hf = O_RDONLY; + } + + if (flags & NEWLIB_O_APPEND) { + hf |= O_APPEND; + } + + if (flags & NEWLIB_O_CREAT) { + hf |= O_CREAT; + } + + if (flags & NEWLIB_O_TRUNC) { + hf |= O_TRUNC; + } + + if (flags & NEWLIB_O_EXCL) { + hf |= O_EXCL; + } + + return hf; +} + +struct newlib_stat { + int16_t newlib_st_dev; /* device */ + uint16_t newlib_st_ino; /* inode */ + uint16_t newlib_st_mode; /* protection */ + uint16_t newlib_st_nlink; /* number of hard links */ + uint16_t newlib_st_uid; /* user ID of owner */ + uint16_t newlib_st_gid; /* group ID of owner */ + int16_t newlib_st_rdev; /* device type (if inode device) */ + int32_t newlib_st_size; /* total size, in bytes */ + int32_t newlib_st_atime; /* time of last access */ + uint32_t newlib_st_spare1; + int32_t newlib_st_mtime; /* time of last modification */ + uint32_t newlib_st_spare2; + int32_t newlib_st_ctime; /* time of last change */ + uint32_t newlib_st_spare3; +} QEMU_PACKED; + +static int translate_stat(CPULM32State *env, target_ulong addr, + struct stat *s) +{ + struct newlib_stat *p; + + p = lock_user(VERIFY_WRITE, addr, sizeof(struct newlib_stat), 0); + if (!p) { + return 0; + } + p->newlib_st_dev = cpu_to_be16(s->st_dev); + p->newlib_st_ino = cpu_to_be16(s->st_ino); + p->newlib_st_mode = cpu_to_be16(s->st_mode); + p->newlib_st_nlink = cpu_to_be16(s->st_nlink); + p->newlib_st_uid = cpu_to_be16(s->st_uid); + p->newlib_st_gid = cpu_to_be16(s->st_gid); + p->newlib_st_rdev = cpu_to_be16(s->st_rdev); + p->newlib_st_size = cpu_to_be32(s->st_size); + p->newlib_st_atime = cpu_to_be32(s->st_atime); + p->newlib_st_mtime = cpu_to_be32(s->st_mtime); + p->newlib_st_ctime = cpu_to_be32(s->st_ctime); + unlock_user(p, addr, sizeof(struct newlib_stat)); + + return 1; +} + +bool lm32_cpu_do_semihosting(CPUState *cs) +{ + LM32CPU *cpu = LM32_CPU(cs); + CPULM32State *env = &cpu->env; + + int ret = -1; + target_ulong nr, arg0, arg1, arg2; + void *p; + struct stat s; + + nr = env->regs[R_R8]; + arg0 = env->regs[R_R1]; + arg1 = env->regs[R_R2]; + arg2 = env->regs[R_R3]; + + switch (nr) { + case TARGET_SYS_exit: + /* void _exit(int rc) */ + exit(arg0); + + case TARGET_SYS_open: + /* int open(const char *pathname, int flags) */ + p = lock_user_string(arg0); + if (!p) { + ret = -1; + } else { + ret = open(p, translate_openflags(arg2)); + unlock_user(p, arg0, 0); + } + break; + + case TARGET_SYS_read: + /* ssize_t read(int fd, const void *buf, size_t count) */ + p = lock_user(VERIFY_WRITE, arg1, arg2, 0); + if (!p) { + ret = -1; + } else { + ret = read(arg0, p, arg2); + unlock_user(p, arg1, arg2); + } + break; + + case TARGET_SYS_write: + /* ssize_t write(int fd, const void *buf, size_t count) */ + p = lock_user(VERIFY_READ, arg1, arg2, 1); + if (!p) { + ret = -1; + } else { + ret = write(arg0, p, arg2); + unlock_user(p, arg1, 0); + } + break; + + case TARGET_SYS_close: + /* int close(int fd) */ + /* don't close stdin/stdout/stderr */ + if (arg0 > 2) { + ret = close(arg0); + } else { + ret = 0; + } + break; + + case TARGET_SYS_lseek: + /* off_t lseek(int fd, off_t offset, int whence */ + ret = lseek(arg0, arg1, arg2); + break; + + case TARGET_SYS_stat: + /* int stat(const char *path, struct stat *buf) */ + p = lock_user_string(arg0); + if (!p) { + ret = -1; + } else { + ret = stat(p, &s); + unlock_user(p, arg0, 0); + if (translate_stat(env, arg1, &s) == 0) { + ret = -1; + } + } + break; + + case TARGET_SYS_fstat: + /* int stat(int fd, struct stat *buf) */ + ret = fstat(arg0, &s); + if (ret == 0) { + if (translate_stat(env, arg1, &s) == 0) { + ret = -1; + } + } + break; + + default: + /* unhandled */ + return false; + } + + env->regs[R_R1] = ret; + return true; +} From 4e7d30a22a46b6bb5551725db781c2d94db2d5f8 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Tue, 22 Apr 2014 20:18:43 +0200 Subject: [PATCH 3/4] test: lm32: use semihosting for testing Instead of the lm32-sys device, use semihosting to print to the host console and exit the test. Signed-off-by: Michael Walle --- tests/tcg/lm32/Makefile | 15 +++++---- tests/tcg/lm32/crt.S | 4 +-- tests/tcg/lm32/helper.S | 65 +++++++++++++++++++++++++++++++++++++ tests/tcg/lm32/macros.inc | 37 +++++++++++++-------- tests/tcg/lm32/test_scall.S | 4 +++ 5 files changed, 103 insertions(+), 22 deletions(-) create mode 100644 tests/tcg/lm32/helper.S diff --git a/tests/tcg/lm32/Makefile b/tests/tcg/lm32/Makefile index 8e5d405459..57e7363b2c 100644 --- a/tests/tcg/lm32/Makefile +++ b/tests/tcg/lm32/Makefile @@ -3,7 +3,7 @@ CROSS=lm32-elf- SIM = qemu-system-lm32 -SIMFLAGS = -M lm32-evr -nographic -device lm32-sys -net none -kernel +SIMFLAGS = -M lm32-evr -nographic -semihosting -net none -kernel CC = $(CROSS)gcc AS = $(CROSS)as @@ -18,6 +18,7 @@ LDFLAGS = -T$(TSRC_PATH)/linker.ld ASFLAGS += -Wa,-I,$(TSRC_PATH)/ CRT = crt.o +HELPER = helper.o TESTCASES += test_add.tst TESTCASES += test_addi.tst TESTCASES += test_and.tst @@ -91,15 +92,15 @@ all: build %.o: $(TSRC_PATH)/%.S $(AS) $(ASFLAGS) -c $< -o $@ -%.tst: %.o $(TSRC_PATH)/macros.inc $(CRT) - $(LD) $(LDFLAGS) $(NOSTDFLAGS) $(CRT) $< -o $@ +%.tst: %.o $(TSRC_PATH)/macros.inc $(CRT) $(HELPER) + $(LD) $(LDFLAGS) $(NOSTDFLAGS) $(CRT) $(HELPER) $< -o $@ -build: $(CRT) $(TESTCASES) +build: $(TESTCASES) check: $(TESTCASES:test_%.tst=check_%) -check_%: test_%.tst $(CRT) $(SYS) - $(SIM) $(SIMFLAGS) $< +check_%: test_%.tst + @$(SIM) $(SIMFLAGS) $< clean: - $(RM) -fr $(TESTCASES) $(CRT) + $(RM) -fr $(TESTCASES) $(CRT) $(HELPER) diff --git a/tests/tcg/lm32/crt.S b/tests/tcg/lm32/crt.S index 5f9cfd95d3..fc437a3de1 100644 --- a/tests/tcg/lm32/crt.S +++ b/tests/tcg/lm32/crt.S @@ -8,9 +8,9 @@ _reset_handler: ori r1, r1, lo(_start) wcsr eba, r1 wcsr deba, r1 + mvhi sp, hi(_fstack) + ori sp, sp, lo(_fstack) bi _main - nop - nop _breakpoint_handler: ori r25, r25, 1 diff --git a/tests/tcg/lm32/helper.S b/tests/tcg/lm32/helper.S new file mode 100644 index 0000000000..3351d41e84 --- /dev/null +++ b/tests/tcg/lm32/helper.S @@ -0,0 +1,65 @@ +.text +.global _start, _write, _exit +.global _tc_fail, _tc_pass + +_write: + addi sp, sp, -4 + sw (sp+4), r8 + mvi r8, 5 + scall + lw r8, (sp+4) + addi sp, sp, 4 + ret + +_exit: + mvi r8, 1 + scall +1: + bi 1b + +_tc_pass: +.data +1: + .ascii "OK\n" +2: +.text + addi sp, sp, -16 + sw (sp+4), ra + sw (sp+8), r1 + sw (sp+12), r2 + sw (sp+16), r3 + mvi r1, 1 + mvhi r2, hi(1b) + ori r2, r2, lo(1b) + mvi r3, (2b - 1b) + calli _write + lw r3, (sp+16) + lw r2, (sp+12) + lw r1, (sp+8) + lw ra, (sp+4) + addi sp, sp, 16 + ret + +_tc_fail: +.data +1: + .ascii "FAILED\n" +2: +.text + addi sp, sp, -16 + sw (sp+4), ra + sw (sp+8), r1 + sw (sp+12), r2 + sw (sp+16), r3 + sw (sp+4), ra + mvi r1, 1 + mvhi r2, hi(1b) + ori r2, r2, lo(1b) + mvi r3, (2b - 1b) + calli _write + lw r3, (sp+16) + lw r2, (sp+12) + lw r1, (sp+8) + lw ra, (sp+4) + addi sp, sp, 16 + ret diff --git a/tests/tcg/lm32/macros.inc b/tests/tcg/lm32/macros.inc index 367c7c50d8..360ad53c9f 100644 --- a/tests/tcg/lm32/macros.inc +++ b/tests/tcg/lm32/macros.inc @@ -1,12 +1,26 @@ +.equ MAX_TESTNAME_LEN, 32 .macro test_name name .data tn_\name: - .asciz "\name" + .ascii "\name" + .space MAX_TESTNAME_LEN - (. - tn_\name), ' ' .text - mvhi r13, hi(tn_\name) - ori r13, r13, lo(tn_\name) - sw (r12+8), r13 + .global \name +\name: + addi sp, sp, -12 + sw (sp+4), r1 + sw (sp+8), r2 + sw (sp+12), r3 + mvi r1, 1 + mvhi r2, hi(tn_\name) + ori r2, r2, lo(tn_\name) + mvi r3, MAX_TESTNAME_LEN + calli _write + lw r3, (sp+12) + lw r2, (sp+8) + lw r1, (sp+4) + addi sp, sp, 12 .endm .macro load reg val @@ -15,13 +29,12 @@ tn_\name: .endm .macro tc_pass - mvi r13, 0 - sw (r12+4), r13 + calli _tc_pass .endm .macro tc_fail - mvi r13, 1 - sw (r12+4), r13 + addi r12, r12, 1 + calli _tc_fail .endm .macro check_r3 val @@ -63,14 +76,12 @@ tn_\name: .global _main .text _main: - mvhi r12, hi(0xffff0000) # base address of test block - ori r12, r12, lo(0xffff0000) + mvi r12, 0 .endm .macro end - sw (r12+0), r0 -1: - bi 1b + mv r1, r12 + calli _exit .endm # base + diff --git a/tests/tcg/lm32/test_scall.S b/tests/tcg/lm32/test_scall.S index b442e32374..46032f841d 100644 --- a/tests/tcg/lm32/test_scall.S +++ b/tests/tcg/lm32/test_scall.S @@ -5,6 +5,10 @@ start test_name SCALL_1 mvi r1, 1 wcsr IE, r1 +# we are running in a semi hosted environment +# therefore we have to set r8 to some unused system +# call +mvi r8, 0 insn: scall check_excp 64 From 25156d10617794f9399d676ccd9a20f52e0c9f21 Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Tue, 22 Apr 2014 20:18:44 +0200 Subject: [PATCH 4/4] lm32: remove lm32_sys Since we have now semihosting on the lm32 target, this device is no longer needed. Remove it. Signed-off-by: Michael Walle --- hw/misc/Makefile.objs | 1 - hw/misc/lm32_sys.c | 179 ------------------------------------------ target-lm32/README | 10 --- trace-events | 3 - 4 files changed, 193 deletions(-) delete mode 100644 hw/misc/lm32_sys.c diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index f6743659f7..979e532fdf 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -29,7 +29,6 @@ obj-$(CONFIG_NSERIES) += cbus.o obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o obj-$(CONFIG_IMX) += imx_ccm.o -obj-$(CONFIG_LM32) += lm32_sys.o obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o obj-$(CONFIG_MAINSTONE) += mst_fpga.o diff --git a/hw/misc/lm32_sys.c b/hw/misc/lm32_sys.c deleted file mode 100644 index 778eb6e042..0000000000 --- a/hw/misc/lm32_sys.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * QEMU model of the LatticeMico32 system control block. - * - * Copyright (c) 2010 Michael Walle - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ - -/* - * This model is mainly intended for testing purposes and doesn't fit to any - * real hardware. On the one hand it provides a control register (R_CTRL) on - * the other hand it supports the lm32 tests. - * - * A write to the control register causes a system shutdown. - * Tests first write the pointer to a test name to the test name register - * (R_TESTNAME) and then write a zero to the pass/fail register (R_PASSFAIL) if - * the test is passed or any non-zero value to it if the test is failed. - */ - -#include "hw/hw.h" -#include "hw/sysbus.h" -#include "trace.h" -#include "qemu/log.h" -#include "qemu/error-report.h" -#include "sysemu/sysemu.h" - -enum { - R_CTRL = 0, - R_PASSFAIL, - R_TESTNAME, - R_MAX -}; - -#define MAX_TESTNAME_LEN 32 - -#define TYPE_LM32_SYS "lm32-sys" -#define LM32_SYS(obj) OBJECT_CHECK(LM32SysState, (obj), TYPE_LM32_SYS) - -struct LM32SysState { - SysBusDevice parent_obj; - - MemoryRegion iomem; - uint32_t base; - uint32_t regs[R_MAX]; - uint8_t testname[MAX_TESTNAME_LEN]; -}; -typedef struct LM32SysState LM32SysState; - -static void copy_testname(LM32SysState *s) -{ - cpu_physical_memory_read(s->regs[R_TESTNAME], s->testname, - MAX_TESTNAME_LEN); - s->testname[MAX_TESTNAME_LEN - 1] = '\0'; -} - -static void sys_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - LM32SysState *s = opaque; - char *testname; - - trace_lm32_sys_memory_write(addr, value); - - addr >>= 2; - switch (addr) { - case R_CTRL: - qemu_system_shutdown_request(); - break; - case R_PASSFAIL: - s->regs[addr] = value; - testname = (char *)s->testname; - fprintf(stderr, "TC %-*s %s\n", MAX_TESTNAME_LEN, - testname, (value) ? "FAILED" : "OK"); - if (value) { - cpu_dump_state(qemu_get_cpu(0), stderr, fprintf, 0); - } - break; - case R_TESTNAME: - s->regs[addr] = value; - copy_testname(s); - break; - - default: - error_report("lm32_sys: write access to unknown register 0x" - TARGET_FMT_plx, addr << 2); - break; - } -} - -static bool sys_ops_accepts(void *opaque, hwaddr addr, - unsigned size, bool is_write) -{ - return is_write && size == 4; -} - -static const MemoryRegionOps sys_ops = { - .write = sys_write, - .valid.accepts = sys_ops_accepts, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void sys_reset(DeviceState *d) -{ - LM32SysState *s = LM32_SYS(d); - int i; - - for (i = 0; i < R_MAX; i++) { - s->regs[i] = 0; - } - memset(s->testname, 0, MAX_TESTNAME_LEN); -} - -static int lm32_sys_init(SysBusDevice *dev) -{ - LM32SysState *s = LM32_SYS(dev); - - memory_region_init_io(&s->iomem, OBJECT(dev), &sys_ops , s, - "sys", R_MAX * 4); - sysbus_init_mmio(dev, &s->iomem); - - /* Note: This device is not created in the board initialization, - * instead it has to be added with the -device parameter. Therefore, - * the device maps itself. */ - sysbus_mmio_map(dev, 0, s->base); - - return 0; -} - -static const VMStateDescription vmstate_lm32_sys = { - .name = "lm32-sys", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32_ARRAY(regs, LM32SysState, R_MAX), - VMSTATE_BUFFER(testname, LM32SysState), - VMSTATE_END_OF_LIST() - } -}; - -static Property lm32_sys_properties[] = { - DEFINE_PROP_UINT32("base", LM32SysState, base, 0xffff0000), - DEFINE_PROP_END_OF_LIST(), -}; - -static void lm32_sys_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = lm32_sys_init; - dc->reset = sys_reset; - dc->vmsd = &vmstate_lm32_sys; - dc->props = lm32_sys_properties; -} - -static const TypeInfo lm32_sys_info = { - .name = TYPE_LM32_SYS, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(LM32SysState), - .class_init = lm32_sys_class_init, -}; - -static void lm32_sys_register_types(void) -{ - type_register_static(&lm32_sys_info); -} - -type_init(lm32_sys_register_types) diff --git a/target-lm32/README b/target-lm32/README index 03ddbffc54..ba3508a711 100644 --- a/target-lm32/README +++ b/target-lm32/README @@ -16,16 +16,6 @@ This will make serial0 (the lm32_uart) and serial1 (the JTAG UART) available as virtual consoles. -Programmatically terminate the emulator ----------------------------------------- -Originally neither the LatticeMico32 nor its peripherals support a -mechanism to shut down the machine. Emulation aware programs can write to a -to a special register within the system control block to shut down the -virtual machine. For more details see hw/lm32_sys.c. The lm32-evr is the -first BSP which instantiate this model. A (32 bit) write to 0xfff0000 -causes a vm shutdown. - - Semihosting ----------- Semihosting on this target is supported. Some system calls like read, write diff --git a/trace-events b/trace-events index b6d289d720..7a415d952a 100644 --- a/trace-events +++ b/trace-events @@ -627,9 +627,6 @@ lm32_uart_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" lm32_uart_memory_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" lm32_uart_irq_state(int level) "irq state %d" -# hw/misc/lm32_sys.c -lm32_sys_memory_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x" - # hw/scsi/megasas.c megasas_init_firmware(uint64_t pa) "pa %" PRIx64 " " megasas_init_queue(uint64_t queue_pa, int queue_len, uint64_t head, uint64_t tail, uint32_t flags) "queue at %" PRIx64 " len %d head %" PRIx64 " tail %" PRIx64 " flags %x"