All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Alex Bennée" <alex.bennee@linaro.org>
To: Richard Henderson <richard.henderson@linaro.org>
Cc: qemu-devel@nongnu.org, Peter Maydell <peter.maydell@linaro.org>,
	keithp@keithp.com, Riku Voipio <riku.voipio@iki.fi>,
	Laurent Vivier <laurent@vivier.eu>,
	"open list:ARM TCG CPUs" <qemu-arm@nongnu.org>,
	pbonzini@redhat.com
Subject: Re: [PATCH v1 3/4] semihosting: add qemu_semihosting_console_inc for SYS_READC
Date: Thu, 19 Dec 2019 11:14:01 +0000	[thread overview]
Message-ID: <87v9qcefeu.fsf@linaro.org> (raw)
In-Reply-To: <5ca1462e-5129-2b32-f014-a732a26a0587@linaro.org>


Richard Henderson <richard.henderson@linaro.org> writes:

> On 12/18/19 8:00 AM, Alex Bennée wrote:
>> From: Keith Packard <keithp@keithp.com>
>> 
>> Provides a blocking call to read a character from the console using
>> semihosting.chardev, if specified. This takes some careful command
>> line options to use stdio successfully as the serial ports, monitor
>> and semihost all want to use stdio. Here's a sample set of command
>> line options which share stdio betwen semihost, monitor and serial
>
> between.
>
>> +/**
>> + * qemu_semihosting_console_inc:
>> + * @env: CPUArchState
>> + *
>> + * Receive single character from debug console. This may be the remote
>> + * gdb session if a softmmu guest is currently being debugged. As this
>> + * call may block if no data is available we suspend the CPU and will
>> + * rexecute the instruction when data is there. Therefor two
>
> re-execute, Therefore
>
>> + * conditions must be met:
>> + *   - CPUState is syncronised before callinging this function
>
> synchronized, calling
>
>> + *   - pc is only updated once the character is succesfully returned
>
> successfully.
>
>
>> +static int console_can_read(void *opaque)
>> +{
>> +    SemihostingConsole *c = opaque;
>> +    int ret;
>> +    g_assert(qemu_mutex_iothread_locked());
>> +    ret = (int) fifo8_num_free(&c->fifo);
>> +    return ret;
>> +}
>
> Boolean result; better as
>
>   return fifo8_num_free(&c->fifo) > 0
>
> (We could usefully change IOCanReadHandler to return bool to emphasize
> this.)

It's documented as the amount you can read and other handlers return
amounts as well. I'm not sure I want to go messing with the chardev code
in this series (although I need to look at Phillipe's series).

>
>> +static void console_wake_up(gpointer data, gpointer user_data)
>> +{
>> +    CPUState *cs = (CPUState *) data;
>> +    /* cpu_handle_halt won't know we have work so just unbung here */
>> +    cs->halted = 0;
>> +    qemu_cpu_kick(cs);
>> +}
>> +
>> +static void console_read(void *opaque, const uint8_t *buf, int size)
>> +{
>> +    SemihostingConsole *c = opaque;
>> +    g_assert(qemu_mutex_iothread_locked());
>> +    while (size-- && !fifo8_is_full(&c->fifo)) {
>> +        fifo8_push(&c->fifo, *buf++);
>> +    }
>> +    g_slist_foreach(c->sleeping_cpus, console_wake_up, NULL);
>> +}
>
> I think you should be clearing sleeping_cpus here, after they've all been kicked.
>
>> +target_ulong qemu_semihosting_console_inc(CPUArchState *env)
>> +{
>> +    uint8_t ch;
>> +    SemihostingConsole *c = &console;
>> +    g_assert(qemu_mutex_iothread_locked());
>> +    g_assert(current_cpu);
>> +    if (fifo8_is_empty(&c->fifo)) {
>> +        c->sleeping_cpus = g_slist_prepend(c->sleeping_cpus, current_cpu);
>> +        current_cpu->halted = 1;
>> +        current_cpu->exception_index = EXCP_HALTED;
>> +        cpu_loop_exit(current_cpu);
>> +        /* never returns */
>> +    }
>> +    c->sleeping_cpus = g_slist_remove_all(c->sleeping_cpus, current_cpu);
>
> Which would mean you would not have to do this, because current_cpu is only on
> the list when it is halted.
>
> I presume all semihosting holds the BQL before we reach here, and we are not
> racing on this datastructure?

Yeah this is all under BQL - which I assert is the case. I'll add a
comment to the structure.

>
>> +target_ulong qemu_semihosting_console_inc(CPUArchState *env)
>> +{
>> +    uint8_t c;
>> +    struct pollfd pollfd = {
>> +        .fd = STDIN_FILENO,
>> +        .events = POLLIN
>> +    };
>> +
>> +    if (poll(&pollfd, 1, -1) != 1) {
>> +        qemu_log_mask(LOG_UNIMP, "%s: unexpected read from stdin failure",
>> +                      __func__);
>> +        return (target_ulong) -1;
>> +    }
>
> Why are you polling stdin?  linux-user isn't system mode, there isn't a
> separate monitor thread to get blocked, and you aren't even blocking the thread
> to try again just returning -1 to the guest.

Hmm not sure - I guess we should just bite the bullet and potentially
block here. semihosting is linux-user is a bit of a weird use case
because we are not providing "hardware" but it seems it is used by a
bunch of testcases that want to test things like M-profile non-glibc
binaries without the baggage of a full simulation.

>
>
> r~


-- 
Alex Bennée

WARNING: multiple messages have this Message-ID (diff)
From: "Alex Bennée" <alex.bennee@linaro.org>
To: Richard Henderson <richard.henderson@linaro.org>
Cc: Peter Maydell <peter.maydell@linaro.org>,
	keithp@keithp.com, Riku Voipio <riku.voipio@iki.fi>,
	qemu-devel@nongnu.org, Laurent Vivier <laurent@vivier.eu>,
	"open list:ARM TCG CPUs" <qemu-arm@nongnu.org>,
	pbonzini@redhat.com
Subject: Re: [PATCH v1 3/4] semihosting: add qemu_semihosting_console_inc for SYS_READC
Date: Thu, 19 Dec 2019 11:14:01 +0000	[thread overview]
Message-ID: <87v9qcefeu.fsf@linaro.org> (raw)
In-Reply-To: <5ca1462e-5129-2b32-f014-a732a26a0587@linaro.org>


Richard Henderson <richard.henderson@linaro.org> writes:

> On 12/18/19 8:00 AM, Alex Bennée wrote:
>> From: Keith Packard <keithp@keithp.com>
>> 
>> Provides a blocking call to read a character from the console using
>> semihosting.chardev, if specified. This takes some careful command
>> line options to use stdio successfully as the serial ports, monitor
>> and semihost all want to use stdio. Here's a sample set of command
>> line options which share stdio betwen semihost, monitor and serial
>
> between.
>
>> +/**
>> + * qemu_semihosting_console_inc:
>> + * @env: CPUArchState
>> + *
>> + * Receive single character from debug console. This may be the remote
>> + * gdb session if a softmmu guest is currently being debugged. As this
>> + * call may block if no data is available we suspend the CPU and will
>> + * rexecute the instruction when data is there. Therefor two
>
> re-execute, Therefore
>
>> + * conditions must be met:
>> + *   - CPUState is syncronised before callinging this function
>
> synchronized, calling
>
>> + *   - pc is only updated once the character is succesfully returned
>
> successfully.
>
>
>> +static int console_can_read(void *opaque)
>> +{
>> +    SemihostingConsole *c = opaque;
>> +    int ret;
>> +    g_assert(qemu_mutex_iothread_locked());
>> +    ret = (int) fifo8_num_free(&c->fifo);
>> +    return ret;
>> +}
>
> Boolean result; better as
>
>   return fifo8_num_free(&c->fifo) > 0
>
> (We could usefully change IOCanReadHandler to return bool to emphasize
> this.)

It's documented as the amount you can read and other handlers return
amounts as well. I'm not sure I want to go messing with the chardev code
in this series (although I need to look at Phillipe's series).

>
>> +static void console_wake_up(gpointer data, gpointer user_data)
>> +{
>> +    CPUState *cs = (CPUState *) data;
>> +    /* cpu_handle_halt won't know we have work so just unbung here */
>> +    cs->halted = 0;
>> +    qemu_cpu_kick(cs);
>> +}
>> +
>> +static void console_read(void *opaque, const uint8_t *buf, int size)
>> +{
>> +    SemihostingConsole *c = opaque;
>> +    g_assert(qemu_mutex_iothread_locked());
>> +    while (size-- && !fifo8_is_full(&c->fifo)) {
>> +        fifo8_push(&c->fifo, *buf++);
>> +    }
>> +    g_slist_foreach(c->sleeping_cpus, console_wake_up, NULL);
>> +}
>
> I think you should be clearing sleeping_cpus here, after they've all been kicked.
>
>> +target_ulong qemu_semihosting_console_inc(CPUArchState *env)
>> +{
>> +    uint8_t ch;
>> +    SemihostingConsole *c = &console;
>> +    g_assert(qemu_mutex_iothread_locked());
>> +    g_assert(current_cpu);
>> +    if (fifo8_is_empty(&c->fifo)) {
>> +        c->sleeping_cpus = g_slist_prepend(c->sleeping_cpus, current_cpu);
>> +        current_cpu->halted = 1;
>> +        current_cpu->exception_index = EXCP_HALTED;
>> +        cpu_loop_exit(current_cpu);
>> +        /* never returns */
>> +    }
>> +    c->sleeping_cpus = g_slist_remove_all(c->sleeping_cpus, current_cpu);
>
> Which would mean you would not have to do this, because current_cpu is only on
> the list when it is halted.
>
> I presume all semihosting holds the BQL before we reach here, and we are not
> racing on this datastructure?

Yeah this is all under BQL - which I assert is the case. I'll add a
comment to the structure.

>
>> +target_ulong qemu_semihosting_console_inc(CPUArchState *env)
>> +{
>> +    uint8_t c;
>> +    struct pollfd pollfd = {
>> +        .fd = STDIN_FILENO,
>> +        .events = POLLIN
>> +    };
>> +
>> +    if (poll(&pollfd, 1, -1) != 1) {
>> +        qemu_log_mask(LOG_UNIMP, "%s: unexpected read from stdin failure",
>> +                      __func__);
>> +        return (target_ulong) -1;
>> +    }
>
> Why are you polling stdin?  linux-user isn't system mode, there isn't a
> separate monitor thread to get blocked, and you aren't even blocking the thread
> to try again just returning -1 to the guest.

Hmm not sure - I guess we should just bite the bullet and potentially
block here. semihosting is linux-user is a bit of a weird use case
because we are not providing "hardware" but it seems it is used by a
bunch of testcases that want to test things like M-profile non-glibc
binaries without the baggage of a full simulation.

>
>
> r~


-- 
Alex Bennée


  reply	other threads:[~2019-12-19 11:14 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-18 18:00 [PATCH v1 0/4] semihosting read console support Alex Bennée
2019-12-18 18:00 ` [PATCH v1 1/4] target/arm: remove unused EXCP_SEMIHOST leg Alex Bennée
2019-12-18 18:00   ` Alex Bennée
2019-12-18 19:36   ` Richard Henderson
2019-12-18 18:00 ` [PATCH v1 2/4] target/arm: only update pc after semihosting completes Alex Bennée
2019-12-18 18:00   ` Alex Bennée
2019-12-18 19:45   ` Richard Henderson
2019-12-18 18:00 ` [PATCH v1 3/4] semihosting: add qemu_semihosting_console_inc for SYS_READC Alex Bennée
2019-12-18 18:00   ` Alex Bennée
2019-12-18 20:16   ` Richard Henderson
2019-12-19 11:14     ` Alex Bennée [this message]
2019-12-19 11:14       ` Alex Bennée
2019-12-18 18:00 ` [PATCH v1 4/4] tests/tcg: add a dumb-as-bricks semihosting console test Alex Bennée
2019-12-18 18:00   ` Alex Bennée
2019-12-18 20:20   ` Richard Henderson
2019-12-18 22:12 ` [PATCH v1 0/4] semihosting read console support Keith Packard

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87v9qcefeu.fsf@linaro.org \
    --to=alex.bennee@linaro.org \
    --cc=keithp@keithp.com \
    --cc=laurent@vivier.eu \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=richard.henderson@linaro.org \
    --cc=riku.voipio@iki.fi \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.