On 9 February 2017 at 17:09, Alex Bennée <alex.ben...@linaro.org> wrote:
> The arm_reset_cpu/set_cpu_on/set_cpu_off() functions do their work
> asynchronously in the target vCPUs context. As a result we need to
> ensure the SRC_SCR reset bits correctly report the reset status at the
> right time. To do this we defer the clearing of the bit with an async
> job which will run after the work queued by ARM powerctl functions.
>
> Signed-off-by: Alex Bennée <alex.ben...@linaro.org>
> ---
>  hw/misc/imx6_src.c | 58 
> +++++++++++++++++++++++++++++++++++++++++++++---------
>  1 file changed, 49 insertions(+), 9 deletions(-)
>
> diff --git a/hw/misc/imx6_src.c b/hw/misc/imx6_src.c
> index 55b817b8d7..f7c1d94a3e 100644
> --- a/hw/misc/imx6_src.c
> +++ b/hw/misc/imx6_src.c
> @@ -14,6 +14,7 @@
>  #include "qemu/bitops.h"
>  #include "qemu/log.h"
>  #include "arm-powerctl.h"
> +#include "qom/cpu.h"
>
>  #ifndef DEBUG_IMX6_SRC
>  #define DEBUG_IMX6_SRC 0
> @@ -113,6 +114,45 @@ static uint64_t imx6_src_read(void *opaque, hwaddr 
> offset, unsigned size)
>      return value;
>  }
>
> +
> +/* The reset is asynchronous so we need to defer clearing the reset
> + * bit until the work is completed.
> + */
> +
> +struct src_scr_reset_info {

Struct names should be CamelCase.

> +    IMX6SRCState *s;
> +    unsigned long reset_bit;

Unsigned long ? That's always a bit of a red flag because it's
variable in size from host to host. I think you want "int".

> +};
> +
> +static void imx6_clear_reset_bit(CPUState *cpu, run_on_cpu_data data)
> +{
> +    struct src_scr_reset_info *ri = data.host_ptr;
> +    IMX6SRCState *s = ri->s;
> +
> +    assert(qemu_mutex_iothread_locked());
> +
> +    s->regs[SRC_SCR] = deposit32(s->regs[SRC_SCR], ri->reset_bit, 1, 0);
> +    DPRINTF("reg[%s] <= 0x%" PRIx32 "\n",
> +            imx6_src_reg_name(SRC_SCR), s->regs[SRC_SCR]);
> +
> +    g_free(ri);
> +}
> +
> +static void imx6_defer_clear_reset_bit(int cpuid,
> +                                       IMX6SRCState *s,
> +                                       unsigned long reset_shift)
> +{
> +    struct src_scr_reset_info *ri;
> +
> +    ri = g_malloc(sizeof(struct src_scr_reset_info));
> +    ri->s = s;
> +    ri->reset_bit = reset_shift;
> +
> +    async_run_on_cpu(arm_get_cpu_by_id(cpuid), imx6_clear_reset_bit,
> +                     RUN_ON_CPU_HOST_PTR(ri));
> +}

What happens if we do a system reset between calling this
and the async hook running? Do all the outstanding async
run hooks guarantee to run first?

I guess a malloc-and-free is OK since the guest isn't going to be
bouncing CPUs through reset very often, though it's a bit ugly to
see in device code.

Otherwise this looks OK.

thanks
-- PMM

Reply via email to