mirror of
https://gitlab.com/qemu-project/qemu.git
synced 2026-10-28 14:04:39 +08:00
semihosting: use new semihosting ops
Now that all targets implement this interface, we can replace function calls with the new interface. We assume semihosting ops are set on this code path, and do not perform a NULL check. Reviewed-by: Brian Cain <brian.cain@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Link: https://lore.kernel.org/qemu-devel/20261014210526.104215-11-pierrick.bouvier@oss.qualcomm.com Signed-off-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
This commit is contained in:
1 parent
01c92016db
commit
3a076f7a70
1 file changed
+28
-28
@@ -188,7 +188,7 @@ static LayoutInfo common_semi_find_bases(CPUState *cs)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define GET_ARG(n) do { \
|
#define GET_ARG(n) do { \
|
||||||
if (is_64bit_semihosting(env)) { \
|
if (cs->cc->semi_ops->is_64bit(cs)) { \
|
||||||
if (get_user_u64(arg ## n, args + (n) * 8)) { \
|
if (get_user_u64(arg ## n, args + (n) * 8)) { \
|
||||||
goto do_fault; \
|
goto do_fault; \
|
||||||
} \
|
} \
|
||||||
@@ -200,7 +200,7 @@ static LayoutInfo common_semi_find_bases(CPUState *cs)
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define SET_ARG(n, val) \
|
#define SET_ARG(n, val) \
|
||||||
(is_64bit_semihosting(env) ? \
|
(cs->cc->semi_ops->is_64bit(cs) ? \
|
||||||
put_user_u64(val, args + (n) * 8) : \
|
put_user_u64(val, args + (n) * 8) : \
|
||||||
put_user_u32(val, args + (n) * 4))
|
put_user_u32(val, args + (n) * 4))
|
||||||
|
|
||||||
@@ -237,10 +237,10 @@ void common_semi_cb(CPUState *cs, uint64_t ret, int err)
|
|||||||
ts->swi_errno = err;
|
ts->swi_errno = err;
|
||||||
#else
|
#else
|
||||||
syscall_err = err;
|
syscall_err = err;
|
||||||
common_semi_set_err(cs, err);
|
cs->cc->semi_ops->set_err(cs, err);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
common_semi_set_ret(cs, ret);
|
cs->cc->semi_ops->set_ret(cs, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -249,7 +249,7 @@ void common_semi_cb(CPUState *cs, uint64_t ret, int err)
|
|||||||
*/
|
*/
|
||||||
static void common_semi_dead_cb(CPUState *cs, uint64_t ret, int err)
|
static void common_semi_dead_cb(CPUState *cs, uint64_t ret, int err)
|
||||||
{
|
{
|
||||||
common_semi_set_ret(cs, 0xdeadbeef);
|
cs->cc->semi_ops->set_ret(cs, 0xdeadbeef);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -260,7 +260,7 @@ static void common_semi_rw_cb(CPUState *cs, uint64_t ret, int err)
|
|||||||
{
|
{
|
||||||
/* Recover the original length from the third argument. */
|
/* Recover the original length from the third argument. */
|
||||||
CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
|
CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
|
||||||
uint64_t args = common_semi_arg(cs, 1);
|
uint64_t args = cs->cc->semi_ops->arg(cs, 1);
|
||||||
uint64_t arg2;
|
uint64_t arg2;
|
||||||
GET_ARG(2);
|
GET_ARG(2);
|
||||||
|
|
||||||
@@ -268,7 +268,7 @@ static void common_semi_rw_cb(CPUState *cs, uint64_t ret, int err)
|
|||||||
do_fault:
|
do_fault:
|
||||||
ret = 0; /* error: no bytes transmitted */
|
ret = 0; /* error: no bytes transmitted */
|
||||||
}
|
}
|
||||||
common_semi_set_ret(cs, arg2 - ret);
|
cs->cc->semi_ops->set_ret(cs, arg2 - ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -302,7 +302,7 @@ static void common_semi_seek_cb(CPUState *cs, uint64_t ret, int err)
|
|||||||
*/
|
*/
|
||||||
static uint64_t common_semi_flen_buf(CPUState *cs)
|
static uint64_t common_semi_flen_buf(CPUState *cs)
|
||||||
{
|
{
|
||||||
vaddr sp = common_semi_stack_bottom(cs);
|
vaddr sp = cs->cc->semi_ops->stack_bottom(cs);
|
||||||
return sp - 64;
|
return sp - 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,7 +330,7 @@ common_semi_readc_cb(CPUState *cs, uint64_t ret, int err)
|
|||||||
CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
|
CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
|
||||||
uint8_t ch;
|
uint8_t ch;
|
||||||
|
|
||||||
if (get_user_u8(ch, common_semi_stack_bottom(cs) - 1)) {
|
if (get_user_u8(ch, cs->cc->semi_ops->stack_bottom(cs) - 1)) {
|
||||||
ret = -1, err = EFAULT;
|
ret = -1, err = EFAULT;
|
||||||
} else {
|
} else {
|
||||||
ret = ch;
|
ret = ch;
|
||||||
@@ -385,7 +385,7 @@ void semihosting_arm_compatible_init(void)
|
|||||||
*/
|
*/
|
||||||
void do_common_semihosting(CPUState *cs)
|
void do_common_semihosting(CPUState *cs)
|
||||||
{
|
{
|
||||||
CPUArchState *env = cpu_env(cs);
|
CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
|
||||||
uint64_t args;
|
uint64_t args;
|
||||||
uint64_t arg0, arg1, arg2, arg3;
|
uint64_t arg0, arg1, arg2, arg3;
|
||||||
uint64_t ul_ret;
|
uint64_t ul_ret;
|
||||||
@@ -393,8 +393,8 @@ void do_common_semihosting(CPUState *cs)
|
|||||||
int nr;
|
int nr;
|
||||||
int64_t elapsed;
|
int64_t elapsed;
|
||||||
|
|
||||||
nr = common_semi_arg(cs, 0) & 0xffffffffU;
|
nr = cs->cc->semi_ops->arg(cs, 0) & 0xffffffffU;
|
||||||
args = common_semi_arg(cs, 1);
|
args = cs->cc->semi_ops->arg(cs, 1);
|
||||||
|
|
||||||
switch (nr) {
|
switch (nr) {
|
||||||
case TARGET_SYS_OPEN:
|
case TARGET_SYS_OPEN:
|
||||||
@@ -494,15 +494,15 @@ void do_common_semihosting(CPUState *cs)
|
|||||||
|
|
||||||
case TARGET_SYS_READC:
|
case TARGET_SYS_READC:
|
||||||
semihost_sys_read_gf(cs, common_semi_readc_cb, &console_in_gf,
|
semihost_sys_read_gf(cs, common_semi_readc_cb, &console_in_gf,
|
||||||
common_semi_stack_bottom(cs) - 1, 1);
|
cs->cc->semi_ops->stack_bottom(cs) - 1, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TARGET_SYS_ISERROR:
|
case TARGET_SYS_ISERROR:
|
||||||
{
|
{
|
||||||
GET_ARG(0);
|
GET_ARG(0);
|
||||||
bool ret = is_64bit_semihosting(env) ?
|
bool ret = cs->cc->semi_ops->is_64bit(cs) ?
|
||||||
(int64_t)arg0 < 0 : (int32_t)arg0 < 0;
|
(int64_t)arg0 < 0 : (int32_t)arg0 < 0;
|
||||||
common_semi_set_ret(cs, ret);
|
cs->cc->semi_ops->set_ret(cs, ret);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TARGET_SYS_ISTTY:
|
case TARGET_SYS_ISTTY:
|
||||||
@@ -533,7 +533,7 @@ void do_common_semihosting(CPUState *cs)
|
|||||||
len = asprintf(&s, "%s/qemu-%x%02x", g_get_tmp_dir(),
|
len = asprintf(&s, "%s/qemu-%x%02x", g_get_tmp_dir(),
|
||||||
getpid(), (int)arg1 & 0xff);
|
getpid(), (int)arg1 & 0xff);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
common_semi_set_ret(cs, -1);
|
cs->cc->semi_ops->set_ret(cs, -1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -542,7 +542,7 @@ void do_common_semihosting(CPUState *cs)
|
|||||||
/* Make sure there's enough space in the buffer */
|
/* Make sure there's enough space in the buffer */
|
||||||
if (len > arg2) {
|
if (len > arg2) {
|
||||||
free(s);
|
free(s);
|
||||||
common_semi_set_ret(cs, -1);
|
cs->cc->semi_ops->set_ret(cs, -1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
p = lock_user(VERIFY_WRITE, arg0, len, 0);
|
p = lock_user(VERIFY_WRITE, arg0, len, 0);
|
||||||
@@ -553,7 +553,7 @@ void do_common_semihosting(CPUState *cs)
|
|||||||
memcpy(p, s, len);
|
memcpy(p, s, len);
|
||||||
unlock_user(p, arg0, len);
|
unlock_user(p, arg0, len);
|
||||||
free(s);
|
free(s);
|
||||||
common_semi_set_ret(cs, 0);
|
cs->cc->semi_ops->set_ret(cs, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -572,7 +572,7 @@ void do_common_semihosting(CPUState *cs)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TARGET_SYS_CLOCK:
|
case TARGET_SYS_CLOCK:
|
||||||
common_semi_set_ret(cs, clock() / (CLOCKS_PER_SEC / 100));
|
cs->cc->semi_ops->set_ret(cs, clock() / (CLOCKS_PER_SEC / 100));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TARGET_SYS_TIME:
|
case TARGET_SYS_TIME:
|
||||||
@@ -587,7 +587,7 @@ void do_common_semihosting(CPUState *cs)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TARGET_SYS_ERRNO:
|
case TARGET_SYS_ERRNO:
|
||||||
common_semi_set_ret(cs, get_swi_errno(cs));
|
cs->cc->semi_ops->set_ret(cs, get_swi_errno(cs));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TARGET_SYS_GET_CMDLINE:
|
case TARGET_SYS_GET_CMDLINE:
|
||||||
@@ -734,7 +734,7 @@ void do_common_semihosting(CPUState *cs)
|
|||||||
for (i = 0; i < ARRAY_SIZE(retvals); i++) {
|
for (i = 0; i < ARRAY_SIZE(retvals); i++) {
|
||||||
bool fail;
|
bool fail;
|
||||||
|
|
||||||
if (is_64bit_semihosting(env)) {
|
if (cs->cc->semi_ops->is_64bit(cs)) {
|
||||||
fail = put_user_u64(retvals[i], arg0 + i * 8);
|
fail = put_user_u64(retvals[i], arg0 + i * 8);
|
||||||
} else {
|
} else {
|
||||||
fail = put_user_u32(retvals[i], arg0 + i * 4);
|
fail = put_user_u32(retvals[i], arg0 + i * 4);
|
||||||
@@ -745,7 +745,7 @@ void do_common_semihosting(CPUState *cs)
|
|||||||
goto do_fault;
|
goto do_fault;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
common_semi_set_ret(cs, 0);
|
cs->cc->semi_ops->set_ret(cs, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -755,7 +755,7 @@ void do_common_semihosting(CPUState *cs)
|
|||||||
uint32_t ret;
|
uint32_t ret;
|
||||||
|
|
||||||
if (nr == TARGET_SYS_EXIT_EXTENDED ||
|
if (nr == TARGET_SYS_EXIT_EXTENDED ||
|
||||||
common_semi_sys_exit_is_extended(cs)) {
|
cs->cc->semi_ops->sys_exit_is_extended(cs)) {
|
||||||
/*
|
/*
|
||||||
* The A64 version of SYS_EXIT takes a parameter block,
|
* The A64 version of SYS_EXIT takes a parameter block,
|
||||||
* so the application-exit type can return a subcode which
|
* so the application-exit type can return a subcode which
|
||||||
@@ -786,7 +786,7 @@ void do_common_semihosting(CPUState *cs)
|
|||||||
|
|
||||||
case TARGET_SYS_ELAPSED:
|
case TARGET_SYS_ELAPSED:
|
||||||
elapsed = get_clock() - clock_start;
|
elapsed = get_clock() - clock_start;
|
||||||
if (is_64bit_semihosting(env)) {
|
if (cs->cc->semi_ops->is_64bit(cs)) {
|
||||||
if (SET_ARG(0, elapsed)) {
|
if (SET_ARG(0, elapsed)) {
|
||||||
goto do_fault;
|
goto do_fault;
|
||||||
}
|
}
|
||||||
@@ -796,12 +796,12 @@ void do_common_semihosting(CPUState *cs)
|
|||||||
goto do_fault;
|
goto do_fault;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
common_semi_set_ret(cs, 0);
|
cs->cc->semi_ops->set_ret(cs, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TARGET_SYS_TICKFREQ:
|
case TARGET_SYS_TICKFREQ:
|
||||||
/* qemu always uses nsec */
|
/* qemu always uses nsec */
|
||||||
common_semi_set_ret(cs, 1000000000);
|
cs->cc->semi_ops->set_ret(cs, 1000000000);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TARGET_SYS_SYNCCACHE:
|
case TARGET_SYS_SYNCCACHE:
|
||||||
@@ -810,8 +810,8 @@ void do_common_semihosting(CPUState *cs)
|
|||||||
* virtual address range. This is a nop for us since we don't
|
* virtual address range. This is a nop for us since we don't
|
||||||
* implement caches. This is only present on A64.
|
* implement caches. This is only present on A64.
|
||||||
*/
|
*/
|
||||||
if (common_semi_has_synccache(env)) {
|
if (cs->cc->semi_ops->has_synccache(cs)) {
|
||||||
common_semi_set_ret(cs, 0);
|
cs->cc->semi_ops->set_ret(cs, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
|||||||
Reference in new issue
Block a user