Revisión | f38a71b01f839c7b65ea73ddd507903cb9489ed6 (tree) |
---|---|
Tiempo | 2020-01-10 22:19:34 |
Autor | Peter Maydell <peter.maydell@lina...> |
Commiter | Peter Maydell |
Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-and-semihosting-090120-2' into staging
Testing fixes and semiconsole support:
# gpg: Signature made Thu 09 Jan 2020 11:42:51 GMT
# gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44
# gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full]
# Primary key fingerprint: 6685 AE99 E751 67BC AFC8 DF35 FBD0 DB09 5A9E 2A44
* remotes/stsquad/tags/pull-testing-and-semihosting-090120-2:
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
@@ -51,13 +51,6 @@ addons: | ||
51 | 51 | - sparse |
52 | 52 | - uuid-dev |
53 | 53 | - gcovr |
54 | - homebrew: | |
55 | - packages: | |
56 | - - ccache | |
57 | - - glib | |
58 | - - pixman | |
59 | - - gnu-sed | |
60 | - update: true | |
61 | 54 | |
62 | 55 | |
63 | 56 | # The channel name "irc.oftc.net#qemu" is encrypted against qemu/qemu |
@@ -89,12 +82,12 @@ git: | ||
89 | 82 | |
90 | 83 | |
91 | 84 | before_script: |
92 | - - if [ "$TRAVIS_OS_NAME" == "osx" ] ; then export PATH="/usr/local/opt/ccache/libexec:$PATH" ; fi | |
93 | 85 | - if command -v ccache ; then ccache --zero-stats ; fi |
94 | 86 | - mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR} |
95 | 87 | - ${SRC_DIR}/configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; } |
96 | 88 | script: |
97 | - - make -j3 && travis_retry ${TEST_CMD} | |
89 | + - BUILD_RC=0 && make -j3 || BUILD_RC=$? | |
90 | + - if [ "$BUILD_RC" -eq 0 ] ; then travis_retry ${TEST_CMD} ; else $(exit $BUILD_RC); fi | |
98 | 91 | after_script: |
99 | 92 | - if command -v ccache ; then ccache --show-stats ; fi |
100 | 93 |
@@ -239,6 +232,21 @@ matrix: | ||
239 | 232 | os: osx |
240 | 233 | osx_image: xcode10.3 |
241 | 234 | compiler: clang |
235 | + addons: | |
236 | + homebrew: | |
237 | + packages: | |
238 | + - ccache | |
239 | + - glib | |
240 | + - pixman | |
241 | + - gnu-sed | |
242 | + - python | |
243 | + update: true | |
244 | + before_script: | |
245 | + - brew link --overwrite python | |
246 | + - export PATH="/usr/local/opt/ccache/libexec:$PATH" | |
247 | + - if command -v ccache ; then ccache --zero-stats ; fi | |
248 | + - mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR} | |
249 | + - ${SRC_DIR}/configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; } | |
242 | 250 | |
243 | 251 | |
244 | 252 | # Python builds |
@@ -262,8 +270,8 @@ matrix: | ||
262 | 270 | - env: |
263 | 271 | - CONFIG="--python=/usr/bin/python3 --target-list=x86_64-softmmu,mips-softmmu,mips64el-softmmu,aarch64-softmmu,arm-softmmu,s390x-softmmu,alpha-softmmu,ppc-softmmu,ppc64-softmmu,m68k-softmmu,sparc-softmmu" |
264 | 272 | - TEST_CMD="make check-acceptance" |
265 | - after_failure: | |
266 | - - cat tests/results/latest/job.log | |
273 | + after_script: | |
274 | + - python3 -c 'import json; r = json.load(open("tests/results/latest/results.json")); [print(t["logfile"]) for t in r["tests"] if t["status"] not in ("PASS", "SKIP")]' | xargs cat | |
267 | 275 | addons: |
268 | 276 | apt: |
269 | 277 | packages: |
@@ -32,3 +32,12 @@ X86IOMMUState *x86_iommu_get_default(void) | ||
32 | 32 | return NULL; |
33 | 33 | } |
34 | 34 | |
35 | +bool x86_iommu_ir_supported(X86IOMMUState *s) | |
36 | +{ | |
37 | + return false; | |
38 | +} | |
39 | + | |
40 | +IommuType x86_iommu_get_type(void) | |
41 | +{ | |
42 | + abort(); | |
43 | +} |
@@ -20,8 +20,15 @@ | ||
20 | 20 | #include "hw/semihosting/semihost.h" |
21 | 21 | #include "hw/semihosting/console.h" |
22 | 22 | #include "exec/gdbstub.h" |
23 | +#include "exec/exec-all.h" | |
23 | 24 | #include "qemu/log.h" |
24 | 25 | #include "chardev/char.h" |
26 | +#include <pthread.h> | |
27 | +#include "chardev/char-fe.h" | |
28 | +#include "sysemu/sysemu.h" | |
29 | +#include "qemu/main-loop.h" | |
30 | +#include "qapi/error.h" | |
31 | +#include "qemu/fifo8.h" | |
25 | 32 | |
26 | 33 | int qemu_semihosting_log_out(const char *s, int len) |
27 | 34 | { |
@@ -98,3 +105,75 @@ void qemu_semihosting_console_outc(CPUArchState *env, target_ulong addr) | ||
98 | 105 | __func__, addr); |
99 | 106 | } |
100 | 107 | } |
108 | + | |
109 | +#define FIFO_SIZE 1024 | |
110 | + | |
111 | +/* Access to this structure is protected by the BQL */ | |
112 | +typedef struct SemihostingConsole { | |
113 | + CharBackend backend; | |
114 | + GSList *sleeping_cpus; | |
115 | + bool got; | |
116 | + Fifo8 fifo; | |
117 | +} SemihostingConsole; | |
118 | + | |
119 | +static SemihostingConsole console; | |
120 | + | |
121 | +static int console_can_read(void *opaque) | |
122 | +{ | |
123 | + SemihostingConsole *c = opaque; | |
124 | + int ret; | |
125 | + g_assert(qemu_mutex_iothread_locked()); | |
126 | + ret = (int) fifo8_num_free(&c->fifo); | |
127 | + return ret; | |
128 | +} | |
129 | + | |
130 | +static void console_wake_up(gpointer data, gpointer user_data) | |
131 | +{ | |
132 | + CPUState *cs = (CPUState *) data; | |
133 | + /* cpu_handle_halt won't know we have work so just unbung here */ | |
134 | + cs->halted = 0; | |
135 | + qemu_cpu_kick(cs); | |
136 | +} | |
137 | + | |
138 | +static void console_read(void *opaque, const uint8_t *buf, int size) | |
139 | +{ | |
140 | + SemihostingConsole *c = opaque; | |
141 | + g_assert(qemu_mutex_iothread_locked()); | |
142 | + while (size-- && !fifo8_is_full(&c->fifo)) { | |
143 | + fifo8_push(&c->fifo, *buf++); | |
144 | + } | |
145 | + g_slist_foreach(c->sleeping_cpus, console_wake_up, NULL); | |
146 | + c->sleeping_cpus = NULL; | |
147 | +} | |
148 | + | |
149 | +target_ulong qemu_semihosting_console_inc(CPUArchState *env) | |
150 | +{ | |
151 | + uint8_t ch; | |
152 | + SemihostingConsole *c = &console; | |
153 | + g_assert(qemu_mutex_iothread_locked()); | |
154 | + g_assert(current_cpu); | |
155 | + if (fifo8_is_empty(&c->fifo)) { | |
156 | + c->sleeping_cpus = g_slist_prepend(c->sleeping_cpus, current_cpu); | |
157 | + current_cpu->halted = 1; | |
158 | + current_cpu->exception_index = EXCP_HALTED; | |
159 | + cpu_loop_exit(current_cpu); | |
160 | + /* never returns */ | |
161 | + } | |
162 | + ch = fifo8_pop(&c->fifo); | |
163 | + return (target_ulong) ch; | |
164 | +} | |
165 | + | |
166 | +void qemu_semihosting_console_init(void) | |
167 | +{ | |
168 | + Chardev *chr = semihosting_get_chardev(); | |
169 | + | |
170 | + if (chr) { | |
171 | + fifo8_create(&console.fifo, FIFO_SIZE); | |
172 | + qemu_chr_fe_init(&console.backend, chr, &error_abort); | |
173 | + qemu_chr_fe_set_handlers(&console.backend, | |
174 | + console_can_read, | |
175 | + console_read, | |
176 | + NULL, NULL, &console, | |
177 | + NULL, true); | |
178 | + } | |
179 | +} |
@@ -38,6 +38,22 @@ int qemu_semihosting_console_outs(CPUArchState *env, target_ulong s); | ||
38 | 38 | void qemu_semihosting_console_outc(CPUArchState *env, target_ulong c); |
39 | 39 | |
40 | 40 | /** |
41 | + * qemu_semihosting_console_inc: | |
42 | + * @env: CPUArchState | |
43 | + * | |
44 | + * Receive single character from debug console. This may be the remote | |
45 | + * gdb session if a softmmu guest is currently being debugged. As this | |
46 | + * call may block if no data is available we suspend the CPU and will | |
47 | + * re-execute the instruction when data is there. Therefore two | |
48 | + * conditions must be met: | |
49 | + * - CPUState is synchronized before calling this function | |
50 | + * - pc is only updated once the character is successfully returned | |
51 | + * | |
52 | + * Returns: character read OR cpu_loop_exit! | |
53 | + */ | |
54 | +target_ulong qemu_semihosting_console_inc(CPUArchState *env); | |
55 | + | |
56 | +/** | |
41 | 57 | * qemu_semihosting_log_out: |
42 | 58 | * @s: pointer to string |
43 | 59 | * @len: length of string |
@@ -56,6 +56,9 @@ static inline Chardev *semihosting_get_chardev(void) | ||
56 | 56 | { |
57 | 57 | return NULL; |
58 | 58 | } |
59 | +static inline void qemu_semihosting_console_init(void) | |
60 | +{ | |
61 | +} | |
59 | 62 | #else /* !CONFIG_USER_ONLY */ |
60 | 63 | bool semihosting_enabled(void); |
61 | 64 | SemihostingTarget semihosting_get_target(void); |
@@ -68,6 +71,7 @@ Chardev *semihosting_get_chardev(void); | ||
68 | 71 | void qemu_semihosting_enable(void); |
69 | 72 | int qemu_semihosting_config_options(const char *opt); |
70 | 73 | void qemu_semihosting_connect_chardevs(void); |
74 | +void qemu_semihosting_console_init(void); | |
71 | 75 | #endif /* CONFIG_USER_ONLY */ |
72 | 76 | |
73 | 77 | #endif /* SEMIHOST_H */ |
@@ -130,6 +130,7 @@ void cpu_loop(CPUARMState *env) | ||
130 | 130 | break; |
131 | 131 | case EXCP_SEMIHOST: |
132 | 132 | env->xregs[0] = do_arm_semihosting(env); |
133 | + env->pc += 4; | |
133 | 134 | break; |
134 | 135 | case EXCP_YIELD: |
135 | 136 | /* nothing to do here for user-mode, just resume guest code */ |
@@ -377,6 +377,7 @@ void cpu_loop(CPUARMState *env) | ||
377 | 377 | break; |
378 | 378 | case EXCP_SEMIHOST: |
379 | 379 | env->regs[0] = do_arm_semihosting(env); |
380 | + env->regs[15] += env->thumb ? 2 : 4; | |
380 | 381 | break; |
381 | 382 | case EXCP_INTERRUPT: |
382 | 383 | /* just indicate that signals should be handled asap */ |
@@ -14,6 +14,7 @@ | ||
14 | 14 | #include "cpu.h" |
15 | 15 | #include "hw/semihosting/console.h" |
16 | 16 | #include "qemu.h" |
17 | +#include <termios.h> | |
17 | 18 | |
18 | 19 | int qemu_semihosting_console_outs(CPUArchState *env, target_ulong addr) |
19 | 20 | { |
@@ -47,3 +48,29 @@ void qemu_semihosting_console_outc(CPUArchState *env, target_ulong addr) | ||
47 | 48 | } |
48 | 49 | } |
49 | 50 | } |
51 | + | |
52 | +/* | |
53 | + * For linux-user we can safely block. However as we want to return as | |
54 | + * soon as a character is read we need to tweak the termio to disable | |
55 | + * line buffering. We restore the old mode afterwards in case the | |
56 | + * program is expecting more normal behaviour. This is slow but | |
57 | + * nothing using semihosting console reading is expecting to be fast. | |
58 | + */ | |
59 | +target_ulong qemu_semihosting_console_inc(CPUArchState *env) | |
60 | +{ | |
61 | + uint8_t c; | |
62 | + struct termios old_tio, new_tio; | |
63 | + | |
64 | + /* Disable line-buffering and echo */ | |
65 | + tcgetattr(STDIN_FILENO, &old_tio); | |
66 | + new_tio = old_tio; | |
67 | + new_tio.c_lflag &= (~ICANON & ~ECHO); | |
68 | + tcsetattr(STDIN_FILENO, TCSANOW, &new_tio); | |
69 | + | |
70 | + c = getchar(); | |
71 | + | |
72 | + /* restore config */ | |
73 | + tcsetattr(STDIN_FILENO, TCSANOW, &old_tio); | |
74 | + | |
75 | + return (target_ulong) c; | |
76 | +} |
@@ -69,3 +69,7 @@ void semihosting_arg_fallback(const char *file, const char *cmd) | ||
69 | 69 | void qemu_semihosting_connect_chardevs(void) |
70 | 70 | { |
71 | 71 | } |
72 | + | |
73 | +void qemu_semihosting_console_init(void) | |
74 | +{ | |
75 | +} |
@@ -802,8 +802,7 @@ target_ulong do_arm_semihosting(CPUARMState *env) | ||
802 | 802 | |
803 | 803 | return guestfd_fns[gf->type].readfn(cpu, gf, arg1, len); |
804 | 804 | case TARGET_SYS_READC: |
805 | - qemu_log_mask(LOG_UNIMP, "%s: SYS_READC not implemented", __func__); | |
806 | - return 0; | |
805 | + return qemu_semihosting_console_inc(env); | |
807 | 806 | case TARGET_SYS_ISTTY: |
808 | 807 | GET_ARG(0); |
809 | 808 |
@@ -8566,12 +8566,6 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs) | ||
8566 | 8566 | case EXCP_VFIQ: |
8567 | 8567 | addr += 0x100; |
8568 | 8568 | break; |
8569 | - case EXCP_SEMIHOST: | |
8570 | - qemu_log_mask(CPU_LOG_INT, | |
8571 | - "...handling as semihosting call 0x%" PRIx64 "\n", | |
8572 | - env->xregs[0]); | |
8573 | - env->xregs[0] = do_arm_semihosting(env); | |
8574 | - return; | |
8575 | 8569 | default: |
8576 | 8570 | cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index); |
8577 | 8571 | } |
@@ -8620,11 +8614,13 @@ static void handle_semihosting(CPUState *cs) | ||
8620 | 8614 | "...handling as semihosting call 0x%" PRIx64 "\n", |
8621 | 8615 | env->xregs[0]); |
8622 | 8616 | env->xregs[0] = do_arm_semihosting(env); |
8617 | + env->pc += 4; | |
8623 | 8618 | } else { |
8624 | 8619 | qemu_log_mask(CPU_LOG_INT, |
8625 | 8620 | "...handling as semihosting call 0x%x\n", |
8626 | 8621 | env->regs[0]); |
8627 | 8622 | env->regs[0] = do_arm_semihosting(env); |
8623 | + env->regs[15] += env->thumb ? 2 : 4; | |
8628 | 8624 | } |
8629 | 8625 | } |
8630 | 8626 | #endif |
@@ -2185,6 +2185,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) | ||
2185 | 2185 | "...handling as semihosting call 0x%x\n", |
2186 | 2186 | env->regs[0]); |
2187 | 2187 | env->regs[0] = do_arm_semihosting(env); |
2188 | + env->regs[15] += env->thumb ? 2 : 4; | |
2188 | 2189 | return; |
2189 | 2190 | case EXCP_BKPT: |
2190 | 2191 | armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG, false); |
@@ -1937,7 +1937,7 @@ static void disas_exc(DisasContext *s, uint32_t insn) | ||
1937 | 1937 | break; |
1938 | 1938 | } |
1939 | 1939 | #endif |
1940 | - gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST); | |
1940 | + gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST); | |
1941 | 1941 | } else { |
1942 | 1942 | unsupported_encoding(s, insn); |
1943 | 1943 | } |
@@ -1124,7 +1124,7 @@ static inline void gen_hlt(DisasContext *s, int imm) | ||
1124 | 1124 | s->current_el != 0 && |
1125 | 1125 | #endif |
1126 | 1126 | (imm == (s->thumb ? 0x3c : 0xf000))) { |
1127 | - gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST); | |
1127 | + gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST); | |
1128 | 1128 | return; |
1129 | 1129 | } |
1130 | 1130 |
@@ -8457,7 +8457,7 @@ static bool trans_BKPT(DisasContext *s, arg_BKPT *a) | ||
8457 | 8457 | !IS_USER(s) && |
8458 | 8458 | #endif |
8459 | 8459 | (a->imm == 0xab)) { |
8460 | - gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST); | |
8460 | + gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST); | |
8461 | 8461 | } else { |
8462 | 8462 | gen_exception_bkpt_insn(s, syn_aa32_bkpt(a->imm, false)); |
8463 | 8463 | } |
@@ -10266,7 +10266,7 @@ static bool trans_SVC(DisasContext *s, arg_SVC *a) | ||
10266 | 10266 | !IS_USER(s) && |
10267 | 10267 | #endif |
10268 | 10268 | (a->imm == semihost_imm)) { |
10269 | - gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST); | |
10269 | + gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST); | |
10270 | 10270 | } else { |
10271 | 10271 | gen_set_pc_im(s, s->base.pc_next); |
10272 | 10272 | s->svc_imm = a->imm; |
@@ -969,7 +969,7 @@ FP_TEST_BIN=$(BUILD_DIR)/tests/fp/fp-test | ||
969 | 969 | |
970 | 970 | # the build dir is created by configure |
971 | 971 | .PHONY: $(FP_TEST_BIN) |
972 | -$(FP_TEST_BIN): | |
972 | +$(FP_TEST_BIN): config-host.h $(test-util-obj-y) | |
973 | 973 | $(call quiet-command, \ |
974 | 974 | $(MAKE) $(SUBDIR_MAKEFLAGS) -C $(dir $@) V="$(V)" $(notdir $@), \ |
975 | 975 | "BUILD", "$(notdir $@)") |
@@ -554,15 +554,13 @@ TF_OBJS_LIB += $(TF_OBJS_TEST) | ||
554 | 554 | |
555 | 555 | BINARIES := fp-test$(EXESUF) fp-bench$(EXESUF) |
556 | 556 | |
557 | -# everything depends on config-host.h because platform.h includes it | |
558 | -all: $(BUILD_DIR)/config-host.h | |
559 | - $(MAKE) $(BINARIES) | |
557 | +# We require artefacts from the main build including config-host.h | |
558 | +# because platform.h includes it. Rather than re-invoking the main | |
559 | +# build we just error out if things aren't there. | |
560 | +$(LIBQEMUUTIL) $(BUILD_DIR)/config-host.h: | |
561 | + $(error $@ missing, re-run parent build) | |
560 | 562 | |
561 | -$(LIBQEMUUTIL): | |
562 | - $(MAKE) -C $(BUILD_DIR) libqemuutil.a | |
563 | - | |
564 | -$(BUILD_DIR)/config-host.h: | |
565 | - $(MAKE) -C $(BUILD_DIR) config-host.h | |
563 | +all: $(BUILD_DIR)/config-host.h $(BINARIES) | |
566 | 564 | |
567 | 565 | # libtestfloat.a depends on libsoftfloat.a, so specify it first |
568 | 566 | FP_TEST_LIBS := libtestfloat.a libsoftfloat.a $(LIBQEMUUTIL) |
@@ -31,7 +31,16 @@ LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc | ||
31 | 31 | memory: CFLAGS+=-DCHECK_UNALIGNED=1 |
32 | 32 | |
33 | 33 | # Running |
34 | -QEMU_OPTS+=-M virt -cpu max -display none -semihosting-config enable=on,target=native,chardev=output -kernel | |
34 | +QEMU_BASE_MACHINE=-M virt -cpu max -display none | |
35 | +QEMU_OPTS+=$(QEMU_BASE_MACHINE) -semihosting-config enable=on,target=native,chardev=output -kernel | |
36 | + | |
37 | +# console test is manual only | |
38 | +QEMU_SEMIHOST=-chardev stdio,mux=on,id=stdio0 -semihosting-config enable=on,chardev=stdio0 -mon chardev=stdio0,mode=readline | |
39 | +run-semiconsole: QEMU_OPTS=$(QEMU_BASE_MACHINE) $(QEMU_SEMIHOST) -kernel | |
40 | +run-semiconsole: semiconsole | |
41 | + $(call skip-test, $<, "MANUAL ONLY") | |
42 | +run-plugin-semiconsole-with-%: semiconsole | |
43 | + $(call skip-test, $<, "MANUAL ONLY") | |
35 | 44 | |
36 | 45 | # Simple Record/Replay Test |
37 | 46 | .PHONY: memory-record |
@@ -32,4 +32,11 @@ run-plugin-semihosting-with-%: | ||
32 | 32 | $(call strip-plugin,$<) 2> $<.err, \ |
33 | 33 | "$< on $(TARGET_NAME) with $*") |
34 | 34 | |
35 | +AARCH64_TESTS += semiconsole | |
36 | +run-semiconsole: semiconsole | |
37 | + $(call skip-test, $<, "MANUAL ONLY") | |
38 | + | |
39 | +run-plugin-semiconsole-with-%: | |
40 | + $(call skip-test, $<, "MANUAL ONLY") | |
41 | + | |
35 | 42 | TESTS += $(AARCH64_TESTS) |
@@ -0,0 +1,38 @@ | ||
1 | +/* | |
2 | + * Semihosting Console Test | |
3 | + * | |
4 | + * Copyright (c) 2019 Linaro Ltd | |
5 | + * | |
6 | + * SPDX-License-Identifier: GPL-2.0-or-later | |
7 | + */ | |
8 | + | |
9 | +#include <inttypes.h> | |
10 | +#include <minilib.h> | |
11 | + | |
12 | +#define SYS_READC 0x7 | |
13 | + | |
14 | +uintptr_t __semi_call(uintptr_t type, uintptr_t arg0) | |
15 | +{ | |
16 | + register uintptr_t t asm("x0") = type; | |
17 | + register uintptr_t a0 asm("x1") = arg0; | |
18 | + asm("hlt 0xf000" | |
19 | + : "=r" (t) | |
20 | + : "r" (t), "r" (a0)); | |
21 | + | |
22 | + return t; | |
23 | +} | |
24 | + | |
25 | +int main(void) | |
26 | +{ | |
27 | + char c; | |
28 | + | |
29 | + ml_printf("Semihosting Console Test\n"); | |
30 | + ml_printf("hit X to exit:"); | |
31 | + | |
32 | + do { | |
33 | + c = __semi_call(SYS_READC, 0); | |
34 | + __sys_outc(c); | |
35 | + } while (c != 'X'); | |
36 | + | |
37 | + return 0; | |
38 | +} |
@@ -31,15 +31,43 @@ run-fcvt: fcvt | ||
31 | 31 | |
32 | 32 | # Semihosting smoke test for linux-user |
33 | 33 | ARM_TESTS += semihosting |
34 | +semihosting: CFLAGS += -mthumb | |
34 | 35 | run-semihosting: semihosting |
35 | 36 | $(call run-test,$<,$(QEMU) $< 2> $<.err, "$< on $(TARGET_NAME)") |
36 | 37 | |
38 | +ARM_TESTS += semihosting-arm | |
39 | +semihosting-arm: CFLAGS += -marm | |
40 | +semihosting-arm: semihosting.c | |
41 | + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) | |
42 | + | |
43 | +run-semihosting-arm: semihosting-arm | |
44 | + $(call run-test,$<,$(QEMU) $< 2> $<.err, "$< on $(TARGET_NAME)") | |
45 | + | |
37 | 46 | run-plugin-semihosting-with-%: |
38 | 47 | $(call run-test, $@, $(QEMU) $(QEMU_OPTS) \ |
39 | 48 | -plugin $(PLUGIN_DIR)/$(call extract-plugin,$@) \ |
40 | 49 | $(call strip-plugin,$<) 2> $<.err, \ |
41 | 50 | "$< on $(TARGET_NAME) with $*") |
42 | 51 | |
52 | +ARM_TESTS += semiconsole semiconsole-arm | |
53 | + | |
54 | +semiconsole: CFLAGS += -mthumb | |
55 | +run-semiconsole: semiconsole | |
56 | + $(call skip-test, $<, "MANUAL ONLY") | |
57 | + | |
58 | +run-plugin-semiconsole-with-%: | |
59 | + $(call skip-test, $<, "MANUAL ONLY") | |
60 | + | |
61 | +semiconsole-arm: CFLAGS += -marm | |
62 | +semiconsole-arm: semiconsole.c | |
63 | + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) | |
64 | + | |
65 | +run-semiconsole-arm: semiconsole-arm | |
66 | + $(call skip-test, $<, "MANUAL ONLY") | |
67 | + | |
68 | +run-plugin-semiconsole-arm-with-%: | |
69 | + $(call skip-test, $<, "MANUAL ONLY") | |
70 | + | |
43 | 71 | TESTS += $(ARM_TESTS) |
44 | 72 | |
45 | 73 | # On ARM Linux only supports 4k pages |
@@ -0,0 +1,35 @@ | ||
1 | +/* | |
2 | + * Semihosting Tests | |
3 | + * | |
4 | + * Copyright (c) 2019 | |
5 | + * Written by Alex Bennée <alex.bennee@linaro.org> | |
6 | + * | |
7 | + * SPDX-License-Identifier: GPL-3.0-or-later | |
8 | + */ | |
9 | + | |
10 | +#define SYS_WRITE0 0x04 | |
11 | +#define SYS_READC 0x07 | |
12 | +#define SYS_REPORTEXC 0x18 | |
13 | + | |
14 | +uintptr_t __semi_call(uintptr_t type, uintptr_t arg0) | |
15 | +{ | |
16 | +#if defined(__arm__) | |
17 | + register uintptr_t t asm("r0") = type; | |
18 | + register uintptr_t a0 asm("r1") = arg0; | |
19 | +#ifdef __thumb__ | |
20 | +# define SVC "svc 0xab" | |
21 | +#else | |
22 | +# define SVC "svc 0x123456" | |
23 | +#endif | |
24 | + asm(SVC : "=r" (t) | |
25 | + : "r" (t), "r" (a0)); | |
26 | +#else | |
27 | + register uintptr_t t asm("x0") = type; | |
28 | + register uintptr_t a0 asm("x1") = arg0; | |
29 | + asm("hlt 0xf000" | |
30 | + : "=r" (t) | |
31 | + : "r" (t), "r" (a0)); | |
32 | +#endif | |
33 | + | |
34 | + return t; | |
35 | +} |
@@ -0,0 +1,27 @@ | ||
1 | +/* | |
2 | + * linux-user semihosting console | |
3 | + * | |
4 | + * Copyright (c) 2019 | |
5 | + * Written by Alex Bennée <alex.bennee@linaro.org> | |
6 | + * | |
7 | + * SPDX-License-Identifier: GPL-3.0-or-later | |
8 | + */ | |
9 | + | |
10 | +#include <stdio.h> | |
11 | +#include <stdint.h> | |
12 | +#include "semicall.h" | |
13 | + | |
14 | +int main(void) | |
15 | +{ | |
16 | + char c; | |
17 | + | |
18 | + printf("Semihosting Console Test\n"); | |
19 | + printf("hit X to exit:"); | |
20 | + | |
21 | + do { | |
22 | + c = __semi_call(SYS_READC, 0); | |
23 | + printf("got '%c'\n", c); | |
24 | + } while (c != 'X'); | |
25 | + | |
26 | + return 0; | |
27 | +} |
@@ -8,26 +8,7 @@ | ||
8 | 8 | */ |
9 | 9 | |
10 | 10 | #include <stdint.h> |
11 | - | |
12 | -#define SYS_WRITE0 0x04 | |
13 | -#define SYS_REPORTEXC 0x18 | |
14 | - | |
15 | -void __semi_call(uintptr_t type, uintptr_t arg0) | |
16 | -{ | |
17 | -#if defined(__arm__) | |
18 | - register uintptr_t t asm("r0") = type; | |
19 | - register uintptr_t a0 asm("r1") = arg0; | |
20 | - asm("svc 0xab" | |
21 | - : /* no return */ | |
22 | - : "r" (t), "r" (a0)); | |
23 | -#else | |
24 | - register uintptr_t t asm("x0") = type; | |
25 | - register uintptr_t a0 asm("x1") = arg0; | |
26 | - asm("hlt 0xf000" | |
27 | - : /* no return */ | |
28 | - : "r" (t), "r" (a0)); | |
29 | -#endif | |
30 | -} | |
11 | +#include "semicall.h" | |
31 | 12 | |
32 | 13 | int main(int argc, char *argv[argc]) |
33 | 14 | { |
@@ -32,6 +32,7 @@ class FreeBSDVM(basevm.BaseVM): | ||
32 | 32 | "git", |
33 | 33 | "pkgconf", |
34 | 34 | "bzip2", |
35 | + "python37", | |
35 | 36 | |
36 | 37 | # gnu tools |
37 | 38 | "bash", |
@@ -63,7 +64,7 @@ class FreeBSDVM(basevm.BaseVM): | ||
63 | 64 | mkdir src build; cd src; |
64 | 65 | tar -xf /dev/vtbd1; |
65 | 66 | cd ../build |
66 | - ../src/configure --python=python3.6 {configure_opts}; | |
67 | + ../src/configure --python=python3.7 {configure_opts}; | |
67 | 68 | gmake --output-sync -j{jobs} {target} {verbose}; |
68 | 69 | """ |
69 | 70 |
@@ -22,8 +22,8 @@ class OpenBSDVM(basevm.BaseVM): | ||
22 | 22 | name = "openbsd" |
23 | 23 | arch = "x86_64" |
24 | 24 | |
25 | - link = "https://cdn.openbsd.org/pub/OpenBSD/6.5/amd64/install65.iso" | |
26 | - csum = "38d1f8cadd502f1c27bf05c5abde6cc505dd28f3f34f8a941048ff9a54f9f608" | |
25 | + link = "https://cdn.openbsd.org/pub/OpenBSD/6.6/amd64/install66.iso" | |
26 | + csum = "b22e63df56e6266de6bbeed8e9be0fbe9ee2291551c5bc03f3cc2e4ab9436ee3" | |
27 | 27 | size = "20G" |
28 | 28 | pkgs = [ |
29 | 29 | # tools |
@@ -4238,6 +4238,9 @@ int main(int argc, char **argv, char **envp) | ||
4238 | 4238 | qemu_opts_foreach(qemu_find_opts("mon"), |
4239 | 4239 | mon_init_func, NULL, &error_fatal); |
4240 | 4240 | |
4241 | + /* connect semihosting console input if requested */ | |
4242 | + qemu_semihosting_console_init(); | |
4243 | + | |
4241 | 4244 | if (foreach_device_config(DEV_SERIAL, serial_parse) < 0) |
4242 | 4245 | exit(1); |
4243 | 4246 | if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0) |