From patchwork Thu Jun 18 16:00:56 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leon Alrae X-Patchwork-Id: 486370 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 0A06914027C for ; Fri, 19 Jun 2015 02:02:10 +1000 (AEST) Received: from localhost ([::1]:53656 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z5cGV-000086-Ty for incoming@patchwork.ozlabs.org; Thu, 18 Jun 2015 12:02:07 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40265) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z5cFi-0007Lq-W8 for qemu-devel@nongnu.org; Thu, 18 Jun 2015 12:01:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Z5cFb-000439-Ea for qemu-devel@nongnu.org; Thu, 18 Jun 2015 12:01:18 -0400 Received: from mailapp01.imgtec.com ([195.59.15.196]:61196) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z5cFb-000434-6V for qemu-devel@nongnu.org; Thu, 18 Jun 2015 12:01:11 -0400 Received: from KLMAIL01.kl.imgtec.org (unknown [192.168.5.35]) by Websense Email Security Gateway with ESMTPS id 235F4EB8A23F1; Thu, 18 Jun 2015 17:01:06 +0100 (IST) Received: from lalrae-linux.kl.imgtec.org (192.168.14.163) by KLMAIL01.kl.imgtec.org (192.168.5.35) with Microsoft SMTP Server (TLS) id 14.3.195.1; Thu, 18 Jun 2015 17:01:08 +0100 From: Leon Alrae To: Date: Thu, 18 Jun 2015 17:00:56 +0100 Message-ID: <1434643256-16858-3-git-send-email-leon.alrae@imgtec.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1434643256-16858-1-git-send-email-leon.alrae@imgtec.com> References: <1434643256-16858-1-git-send-email-leon.alrae@imgtec.com> MIME-Version: 1.0 X-Originating-IP: [192.168.14.163] X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 195.59.15.196 Cc: peter.maydell@linaro.org, christopher.covington@linaro.org, matthew.fortune@imgtec.com, ilg@livius.net Subject: [Qemu-devel] [PATCH v5 2/2] semihosting: add --semihosting-config arg sub-argument X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Add new "arg" sub-argument to the --semihosting-config allowing the user to pass multiple input arguments separately. It is required for example by UHI semihosting to construct argc and argv. Also, update ARM semihosting to support new option (at the moment it is the only target which cares about arguments). If the semihosting is enabled and no semihosting args have been specified, then fall back to -kernel/-append. The -append string is split on whitespace before initializing semihosting.argv[1..n]; this is different from what QEMU MIPS machines' pseudo-bootloaders do (i.e. argv[1] contains the whole -append), but is more intuitive from UHI user's point of view and Linux kernel just does not care as it concatenates argv[1..n] into single cmdline string anyway. Signed-off-by: Leon Alrae --- include/exec/semihost.h | 18 ++++++++++++++ qemu-options.hx | 21 ++++++++++++---- target-arm/arm-semi.c | 10 +++----- vl.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 12 deletions(-) diff --git a/include/exec/semihost.h b/include/exec/semihost.h index c2f0bcb..5980939 100644 --- a/include/exec/semihost.h +++ b/include/exec/semihost.h @@ -36,9 +36,27 @@ static inline SemihostingTarget semihosting_get_target(void) { return SEMIHOSTING_TARGET_AUTO; } + +static inline const char *semihosting_get_arg(int i) +{ + return NULL; +} + +static inline int semihosting_get_argc(void) +{ + return 0; +} + +static inline const char *semihosting_get_cmdline(void) +{ + return NULL; +} #else bool semihosting_enabled(void); SemihostingTarget semihosting_get_target(void); +const char *semihosting_get_arg(int i); +int semihosting_get_argc(void); +const char *semihosting_get_cmdline(void); #endif #endif diff --git a/qemu-options.hx b/qemu-options.hx index 5438f98..7959dd0 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -3351,14 +3351,25 @@ STEXI Enable semihosting mode (ARM, M68K, Xtensa only). ETEXI DEF("semihosting-config", HAS_ARG, QEMU_OPTION_semihosting_config, - "-semihosting-config [enable=on|off,]target=native|gdb|auto semihosting configuration\n", + "-semihosting-config [enable=on|off][,target=native|gdb|auto][,arg=str[,...]]\n" \ + " semihosting configuration\n", QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_LM32) STEXI -@item -semihosting-config [enable=on|off,]target=native|gdb|auto +@item -semihosting-config [enable=on|off][,target=native|gdb|auto][,arg=str[,...]] @findex -semihosting-config -Enable semihosting and define where the semihosting calls will be addressed, -to QEMU (@code{native}) or to GDB (@code{gdb}). The default is @code{auto}, which means -@code{gdb} during debug sessions and @code{native} otherwise (ARM, M68K, Xtensa only). +Enable and configure semihosting (ARM, M68K, Xtensa only). +@table @option +@item target=@code{native|gdb|auto} +Defines where the semihosting calls will be addressed, to QEMU (@code{native}) +or to GDB (@code{gdb}). The default is @code{auto}, which means @code{gdb} +during debug sessions and @code{native} otherwise. +@item arg=@var{str1},arg=@var{str2},... +Allows the user to pass input arguments, and can be used multiple times to build +up a list. The old-style @code{-kernel}/@code{-append} method of passing a +command line is still supported for backward compatibility. If both the +@code{--semihosting-config arg} and the @code{-kernel}/@code{-append} are +specified, the former is passed to semihosting as it always takes precedence. +@end table ETEXI DEF("old-param", 0, QEMU_OPTION_old_param, "-old-param old param mode\n", QEMU_ARCH_ARM) diff --git a/target-arm/arm-semi.c b/target-arm/arm-semi.c index a8b83e6..74a67e9 100644 --- a/target-arm/arm-semi.c +++ b/target-arm/arm-semi.c @@ -27,6 +27,7 @@ #include #include "cpu.h" +#include "exec/semihost.h" #ifdef CONFIG_USER_ONLY #include "qemu.h" @@ -440,10 +441,7 @@ uint32_t do_arm_semihosting(CPUARMState *env) input_size = arg1; /* Compute the size of the output string. */ #if !defined(CONFIG_USER_ONLY) - output_size = strlen(ts->boot_info->kernel_filename) - + 1 /* Separating space. */ - + strlen(ts->boot_info->kernel_cmdline) - + 1; /* Terminating null byte. */ + output_size = strlen(semihosting_get_cmdline()) + 1; #else unsigned int i; @@ -474,9 +472,7 @@ uint32_t do_arm_semihosting(CPUARMState *env) /* Copy the command-line arguments. */ #if !defined(CONFIG_USER_ONLY) - pstrcpy(output_buffer, output_size, ts->boot_info->kernel_filename); - pstrcat(output_buffer, output_size, " "); - pstrcat(output_buffer, output_size, ts->boot_info->kernel_cmdline); + pstrcpy(output_buffer, output_size, semihosting_get_cmdline()); #else if (output_size == 1) { /* Empty command-line. */ diff --git a/vl.c b/vl.c index a286877..278cd6a 100644 --- a/vl.c +++ b/vl.c @@ -488,6 +488,9 @@ static QemuOptsList qemu_semihosting_config_opts = { }, { .name = "target", .type = QEMU_OPT_STRING, + }, { + .name = "arg", + .type = QEMU_OPT_STRING, }, { /* end of list */ } }, @@ -1251,6 +1254,9 @@ static void configure_msg(QemuOpts *opts) typedef struct SemihostingConfig { bool enabled; SemihostingTarget target; + const char **argv; + int argc; + const char *cmdline; /* concatenated argv */ } SemihostingConfig; static SemihostingConfig semihosting; @@ -1265,6 +1271,58 @@ SemihostingTarget semihosting_get_target(void) return semihosting.target; } +const char *semihosting_get_arg(int i) +{ + if (i >= semihosting.argc) { + return NULL; + } + return semihosting.argv[i]; +} + +int semihosting_get_argc(void) +{ + return semihosting.argc; +} + +const char *semihosting_get_cmdline(void) +{ + if (semihosting.cmdline == NULL && semihosting.argc > 0) { + semihosting.cmdline = g_strjoinv(" ", (gchar **)semihosting.argv); + } + return semihosting.cmdline; +} + +static int add_semihosting_arg(void *opaque, + const char *name, const char *val, + Error **errp) +{ + SemihostingConfig *s = opaque; + if (strcmp(name, "arg") == 0) { + s->argc++; + /* one extra element as g_strjoinv() expects NULL-terminated array */ + s->argv = g_realloc(s->argv, (s->argc + 1) * sizeof(void *)); + s->argv[s->argc - 1] = val; + s->argv[s->argc] = NULL; + } + return 0; +} + +/* Use strings passed via -kernel/-append to initialize semihosting.argv[] */ +static inline void semihosting_arg_fallback(const char *file, const char *cmd) +{ + char *cmd_token; + + /* argv[0] */ + add_semihosting_arg(&semihosting, "arg", file, NULL); + + /* split -append and initialize argv[1..n] */ + cmd_token = strtok(g_strdup(cmd), " "); + while (cmd_token) { + add_semihosting_arg(&semihosting, "arg", cmd_token, NULL); + cmd_token = strtok(NULL, " "); + } +} + /***********************************************************/ /* USB devices */ @@ -3669,6 +3727,9 @@ int main(int argc, char **argv, char **envp) } else { semihosting.target = SEMIHOSTING_TARGET_AUTO; } + /* Set semihosting argument count and vector */ + qemu_opt_foreach(opts, add_semihosting_arg, + &semihosting, NULL); } else { fprintf(stderr, "Unsupported semihosting-config %s\n", optarg); @@ -4237,6 +4298,11 @@ int main(int argc, char **argv, char **envp) exit(1); } + if (semihosting_enabled() && !semihosting_get_argc() && kernel_filename) { + /* fall back to the -kernel/-append */ + semihosting_arg_fallback(kernel_filename, kernel_cmdline); + } + os_set_line_buffering(); #ifdef CONFIG_SPICE