Re: [PATCH v2 1/2] arm/hvf: Optimize and simplify WFI handling
On 02.12.20 02:52, Peter Collingbourne wrote: On Tue, Dec 1, 2020 at 5:39 PM Alexander Graf wrote: On 02.12.20 02:32, Peter Collingbourne wrote: On Tue, Dec 1, 2020 at 3:24 PM Alexander Graf wrote: On 01.12.20 22:00, Peter Collingbourne wrote: Sleep on WFx until the VTIMER is due but allow ourselves to be woken up on IPI. Signed-off-by: Peter Collingbourne --- v2: - simplify locking further - wait indefinitely on disabled or masked timers accel/hvf/hvf-cpus.c | 5 +- include/sysemu/hvf_int.h | 3 +- target/arm/hvf/hvf.c | 116 ++- 3 files changed, 43 insertions(+), 81 deletions(-) diff --git a/accel/hvf/hvf-cpus.c b/accel/hvf/hvf-cpus.c index 4360f64671..b2c8fb57f6 100644 --- a/accel/hvf/hvf-cpus.c +++ b/accel/hvf/hvf-cpus.c @@ -344,9 +344,8 @@ static int hvf_init_vcpu(CPUState *cpu) sigact.sa_handler = dummy_signal; sigaction(SIG_IPI, , NULL); -pthread_sigmask(SIG_BLOCK, NULL, ); -sigdelset(, SIG_IPI); -pthread_sigmask(SIG_SETMASK, , NULL); +pthread_sigmask(SIG_BLOCK, NULL, >hvf->unblock_ipi_mask); +sigdelset(>hvf->unblock_ipi_mask, SIG_IPI); #ifdef __aarch64__ r = hv_vcpu_create(>hvf->fd, (hv_vcpu_exit_t **)>hvf->exit, NULL); diff --git a/include/sysemu/hvf_int.h b/include/sysemu/hvf_int.h index c56baa3ae8..13adf6ea77 100644 --- a/include/sysemu/hvf_int.h +++ b/include/sysemu/hvf_int.h @@ -62,8 +62,7 @@ extern HVFState *hvf_state; struct hvf_vcpu_state { uint64_t fd; void *exit; -struct timespec ts; -bool sleeping; +sigset_t unblock_ipi_mask; }; void assert_hvf_ok(hv_return_t ret); diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index 8fe10966d2..3321d48aa2 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -2,6 +2,7 @@ * QEMU Hypervisor.framework support for Apple Silicon * Copyright 2020 Alexander Graf + * Copyright 2020 Google LLC * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. @@ -18,6 +19,7 @@ #include "sysemu/hw_accel.h" #include +#include #include "exec/address-spaces.h" #include "hw/irq.h" @@ -320,18 +322,8 @@ int hvf_arch_init_vcpu(CPUState *cpu) void hvf_kick_vcpu_thread(CPUState *cpu) { -if (cpu->hvf->sleeping) { -/* - * When sleeping, make sure we always send signals. Also, clear the - * timespec, so that an IPI that arrives between setting hvf->sleeping - * and the nanosleep syscall still aborts the sleep. - */ -cpu->thread_kicked = false; -cpu->hvf->ts = (struct timespec){ }; -cpus_kick_thread(cpu); -} else { -hv_vcpus_exit(>hvf->fd, 1); -} +cpus_kick_thread(cpu); +hv_vcpus_exit(>hvf->fd, 1); } static int hvf_inject_interrupts(CPUState *cpu) @@ -349,6 +341,18 @@ static int hvf_inject_interrupts(CPUState *cpu) return 0; } +static void hvf_wait_for_ipi(CPUState *cpu, struct timespec *ts) +{ +/* + * Use pselect to sleep so that other threads can IPI us while we're + * sleeping. + */ +qatomic_mb_set(>thread_kicked, false); +qemu_mutex_unlock_iothread(); +pselect(0, 0, 0, 0, ts, >hvf->unblock_ipi_mask); +qemu_mutex_lock_iothread(); +} + int hvf_vcpu_exec(CPUState *cpu) { ARMCPU *arm_cpu = ARM_CPU(cpu); @@ -357,15 +361,11 @@ int hvf_vcpu_exec(CPUState *cpu) hv_return_t r; int ret = 0; -qemu_mutex_unlock_iothread(); - do { bool advance_pc = false; -qemu_mutex_lock_iothread(); current_cpu = cpu; qemu_wait_io_event_common(cpu); -qemu_mutex_unlock_iothread(); flush_cpu_state(cpu); @@ -374,10 +374,10 @@ int hvf_vcpu_exec(CPUState *cpu) } if (cpu->halted) { -qemu_mutex_lock_iothread(); return EXCP_HLT; } +qemu_mutex_unlock_iothread(); assert_hvf_ok(hv_vcpu_run(cpu->hvf->fd)); /* handle VMEXIT */ @@ -385,15 +385,14 @@ int hvf_vcpu_exec(CPUState *cpu) uint64_t syndrome = hvf_exit->exception.syndrome; uint32_t ec = syn_get_ec(syndrome); +qemu_mutex_lock_iothread(); switch (exit_reason) { case HV_EXIT_REASON_EXCEPTION: /* This is the main one, handle below. */ break; case HV_EXIT_REASON_VTIMER_ACTIVATED: -qemu_mutex_lock_iothread(); current_cpu = cpu; qemu_set_irq(arm_cpu->gt_timer_outputs[GTIMER_VIRT], 1); -qemu_mutex_unlock_iothread(); continue; case HV_EXIT_REASON_CANCELED: /* we got kicked, no exit to process */ @@ -413,7 +412,6 @@ int hvf_vcpu_exec(CPUState *cpu) uint32_t srt = (syndrome >> 16) & 0x1f;
Re: [PATCH v2 1/2] arm/hvf: Optimize and simplify WFI handling
On Tue, Dec 1, 2020 at 5:54 PM Alexander Graf wrote: > > > On 02.12.20 02:52, Peter Collingbourne wrote: > > On Tue, Dec 1, 2020 at 5:39 PM Alexander Graf wrote: > >> > >> On 02.12.20 02:32, Peter Collingbourne wrote: > >>> On Tue, Dec 1, 2020 at 3:24 PM Alexander Graf wrote: > On 01.12.20 22:00, Peter Collingbourne wrote: > > Sleep on WFx until the VTIMER is due but allow ourselves to be woken > > up on IPI. > > > > Signed-off-by: Peter Collingbourne > > --- > > v2: > > - simplify locking further > > - wait indefinitely on disabled or masked timers > > > > accel/hvf/hvf-cpus.c | 5 +- > > include/sysemu/hvf_int.h | 3 +- > > target/arm/hvf/hvf.c | 116 > > ++- > > 3 files changed, 43 insertions(+), 81 deletions(-) > > > > diff --git a/accel/hvf/hvf-cpus.c b/accel/hvf/hvf-cpus.c > > index 4360f64671..b2c8fb57f6 100644 > > --- a/accel/hvf/hvf-cpus.c > > +++ b/accel/hvf/hvf-cpus.c > > @@ -344,9 +344,8 @@ static int hvf_init_vcpu(CPUState *cpu) > > sigact.sa_handler = dummy_signal; > > sigaction(SIG_IPI, , NULL); > > > > -pthread_sigmask(SIG_BLOCK, NULL, ); > > -sigdelset(, SIG_IPI); > > -pthread_sigmask(SIG_SETMASK, , NULL); > > +pthread_sigmask(SIG_BLOCK, NULL, >hvf->unblock_ipi_mask); > > +sigdelset(>hvf->unblock_ipi_mask, SIG_IPI); > > > > #ifdef __aarch64__ > > r = hv_vcpu_create(>hvf->fd, (hv_vcpu_exit_t > > **)>hvf->exit, NULL); > > diff --git a/include/sysemu/hvf_int.h b/include/sysemu/hvf_int.h > > index c56baa3ae8..13adf6ea77 100644 > > --- a/include/sysemu/hvf_int.h > > +++ b/include/sysemu/hvf_int.h > > @@ -62,8 +62,7 @@ extern HVFState *hvf_state; > > struct hvf_vcpu_state { > > uint64_t fd; > > void *exit; > > -struct timespec ts; > > -bool sleeping; > > +sigset_t unblock_ipi_mask; > > }; > > > > void assert_hvf_ok(hv_return_t ret); > > diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c > > index 8fe10966d2..3321d48aa2 100644 > > --- a/target/arm/hvf/hvf.c > > +++ b/target/arm/hvf/hvf.c > > @@ -2,6 +2,7 @@ > > * QEMU Hypervisor.framework support for Apple Silicon > > > > * Copyright 2020 Alexander Graf > > + * Copyright 2020 Google LLC > > * > > * This work is licensed under the terms of the GNU GPL, version 2 > > or later. > > * See the COPYING file in the top-level directory. > > @@ -18,6 +19,7 @@ > > #include "sysemu/hw_accel.h" > > > > #include > > +#include > > > > #include "exec/address-spaces.h" > > #include "hw/irq.h" > > @@ -320,18 +322,8 @@ int hvf_arch_init_vcpu(CPUState *cpu) > > > > void hvf_kick_vcpu_thread(CPUState *cpu) > > { > > -if (cpu->hvf->sleeping) { > > -/* > > - * When sleeping, make sure we always send signals. Also, > > clear the > > - * timespec, so that an IPI that arrives between setting > > hvf->sleeping > > - * and the nanosleep syscall still aborts the sleep. > > - */ > > -cpu->thread_kicked = false; > > -cpu->hvf->ts = (struct timespec){ }; > > -cpus_kick_thread(cpu); > > -} else { > > -hv_vcpus_exit(>hvf->fd, 1); > > -} > > +cpus_kick_thread(cpu); > > +hv_vcpus_exit(>hvf->fd, 1); > > } > > > > static int hvf_inject_interrupts(CPUState *cpu) > > @@ -349,6 +341,18 @@ static int hvf_inject_interrupts(CPUState *cpu) > > return 0; > > } > > > > +static void hvf_wait_for_ipi(CPUState *cpu, struct timespec *ts) > > +{ > > +/* > > + * Use pselect to sleep so that other threads can IPI us while > > we're > > + * sleeping. > > + */ > > +qatomic_mb_set(>thread_kicked, false); > > +qemu_mutex_unlock_iothread(); > > +pselect(0, 0, 0, 0, ts, >hvf->unblock_ipi_mask); > > +qemu_mutex_lock_iothread(); > > +} > > + > > int hvf_vcpu_exec(CPUState *cpu) > > { > > ARMCPU *arm_cpu = ARM_CPU(cpu); > > @@ -357,15 +361,11 @@ int hvf_vcpu_exec(CPUState *cpu) > > hv_return_t r; > > int ret = 0; > > > > -qemu_mutex_unlock_iothread(); > > - > > do { > > bool advance_pc = false; > > > > -qemu_mutex_lock_iothread(); > > current_cpu = cpu; > > qemu_wait_io_event_common(cpu); > > -qemu_mutex_unlock_iothread(); > > > > flush_cpu_state(cpu); > > > > @@ -374,10 +374,10 @@ int hvf_vcpu_exec(CPUState *cpu) > > } > >
Re: [PATCH v2 1/2] arm/hvf: Optimize and simplify WFI handling
On Tue, Dec 1, 2020 at 5:39 PM Alexander Graf wrote: > > > On 02.12.20 02:32, Peter Collingbourne wrote: > > On Tue, Dec 1, 2020 at 3:24 PM Alexander Graf wrote: > >> > >> On 01.12.20 22:00, Peter Collingbourne wrote: > >>> Sleep on WFx until the VTIMER is due but allow ourselves to be woken > >>> up on IPI. > >>> > >>> Signed-off-by: Peter Collingbourne > >>> --- > >>> v2: > >>> - simplify locking further > >>> - wait indefinitely on disabled or masked timers > >>> > >>>accel/hvf/hvf-cpus.c | 5 +- > >>>include/sysemu/hvf_int.h | 3 +- > >>>target/arm/hvf/hvf.c | 116 ++- > >>>3 files changed, 43 insertions(+), 81 deletions(-) > >>> > >>> diff --git a/accel/hvf/hvf-cpus.c b/accel/hvf/hvf-cpus.c > >>> index 4360f64671..b2c8fb57f6 100644 > >>> --- a/accel/hvf/hvf-cpus.c > >>> +++ b/accel/hvf/hvf-cpus.c > >>> @@ -344,9 +344,8 @@ static int hvf_init_vcpu(CPUState *cpu) > >>>sigact.sa_handler = dummy_signal; > >>>sigaction(SIG_IPI, , NULL); > >>> > >>> -pthread_sigmask(SIG_BLOCK, NULL, ); > >>> -sigdelset(, SIG_IPI); > >>> -pthread_sigmask(SIG_SETMASK, , NULL); > >>> +pthread_sigmask(SIG_BLOCK, NULL, >hvf->unblock_ipi_mask); > >>> +sigdelset(>hvf->unblock_ipi_mask, SIG_IPI); > >>> > >>>#ifdef __aarch64__ > >>>r = hv_vcpu_create(>hvf->fd, (hv_vcpu_exit_t > >>> **)>hvf->exit, NULL); > >>> diff --git a/include/sysemu/hvf_int.h b/include/sysemu/hvf_int.h > >>> index c56baa3ae8..13adf6ea77 100644 > >>> --- a/include/sysemu/hvf_int.h > >>> +++ b/include/sysemu/hvf_int.h > >>> @@ -62,8 +62,7 @@ extern HVFState *hvf_state; > >>>struct hvf_vcpu_state { > >>>uint64_t fd; > >>>void *exit; > >>> -struct timespec ts; > >>> -bool sleeping; > >>> +sigset_t unblock_ipi_mask; > >>>}; > >>> > >>>void assert_hvf_ok(hv_return_t ret); > >>> diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c > >>> index 8fe10966d2..3321d48aa2 100644 > >>> --- a/target/arm/hvf/hvf.c > >>> +++ b/target/arm/hvf/hvf.c > >>> @@ -2,6 +2,7 @@ > >>> * QEMU Hypervisor.framework support for Apple Silicon > >>> > >>> * Copyright 2020 Alexander Graf > >>> + * Copyright 2020 Google LLC > >>> * > >>> * This work is licensed under the terms of the GNU GPL, version 2 or > >>> later. > >>> * See the COPYING file in the top-level directory. > >>> @@ -18,6 +19,7 @@ > >>>#include "sysemu/hw_accel.h" > >>> > >>>#include > >>> +#include > >>> > >>>#include "exec/address-spaces.h" > >>>#include "hw/irq.h" > >>> @@ -320,18 +322,8 @@ int hvf_arch_init_vcpu(CPUState *cpu) > >>> > >>>void hvf_kick_vcpu_thread(CPUState *cpu) > >>>{ > >>> -if (cpu->hvf->sleeping) { > >>> -/* > >>> - * When sleeping, make sure we always send signals. Also, clear > >>> the > >>> - * timespec, so that an IPI that arrives between setting > >>> hvf->sleeping > >>> - * and the nanosleep syscall still aborts the sleep. > >>> - */ > >>> -cpu->thread_kicked = false; > >>> -cpu->hvf->ts = (struct timespec){ }; > >>> -cpus_kick_thread(cpu); > >>> -} else { > >>> -hv_vcpus_exit(>hvf->fd, 1); > >>> -} > >>> +cpus_kick_thread(cpu); > >>> +hv_vcpus_exit(>hvf->fd, 1); > >>>} > >>> > >>>static int hvf_inject_interrupts(CPUState *cpu) > >>> @@ -349,6 +341,18 @@ static int hvf_inject_interrupts(CPUState *cpu) > >>>return 0; > >>>} > >>> > >>> +static void hvf_wait_for_ipi(CPUState *cpu, struct timespec *ts) > >>> +{ > >>> +/* > >>> + * Use pselect to sleep so that other threads can IPI us while we're > >>> + * sleeping. > >>> + */ > >>> +qatomic_mb_set(>thread_kicked, false); > >>> +qemu_mutex_unlock_iothread(); > >>> +pselect(0, 0, 0, 0, ts, >hvf->unblock_ipi_mask); > >>> +qemu_mutex_lock_iothread(); > >>> +} > >>> + > >>>int hvf_vcpu_exec(CPUState *cpu) > >>>{ > >>>ARMCPU *arm_cpu = ARM_CPU(cpu); > >>> @@ -357,15 +361,11 @@ int hvf_vcpu_exec(CPUState *cpu) > >>>hv_return_t r; > >>>int ret = 0; > >>> > >>> -qemu_mutex_unlock_iothread(); > >>> - > >>>do { > >>>bool advance_pc = false; > >>> > >>> -qemu_mutex_lock_iothread(); > >>>current_cpu = cpu; > >>>qemu_wait_io_event_common(cpu); > >>> -qemu_mutex_unlock_iothread(); > >>> > >>>flush_cpu_state(cpu); > >>> > >>> @@ -374,10 +374,10 @@ int hvf_vcpu_exec(CPUState *cpu) > >>>} > >>> > >>>if (cpu->halted) { > >>> -qemu_mutex_lock_iothread(); > >>>return EXCP_HLT; > >>>} > >>> > >>> +qemu_mutex_unlock_iothread(); > >>>assert_hvf_ok(hv_vcpu_run(cpu->hvf->fd)); > >>> > >>>/* handle VMEXIT */ > >>> @@ -385,15 +385,14 @@ int hvf_vcpu_exec(CPUState *cpu) > >>>uint64_t syndrome = hvf_exit->exception.syndrome; >
Re: [PATCH v2 1/2] arm/hvf: Optimize and simplify WFI handling
On 02.12.20 02:32, Peter Collingbourne wrote: On Tue, Dec 1, 2020 at 3:24 PM Alexander Graf wrote: On 01.12.20 22:00, Peter Collingbourne wrote: Sleep on WFx until the VTIMER is due but allow ourselves to be woken up on IPI. Signed-off-by: Peter Collingbourne --- v2: - simplify locking further - wait indefinitely on disabled or masked timers accel/hvf/hvf-cpus.c | 5 +- include/sysemu/hvf_int.h | 3 +- target/arm/hvf/hvf.c | 116 ++- 3 files changed, 43 insertions(+), 81 deletions(-) diff --git a/accel/hvf/hvf-cpus.c b/accel/hvf/hvf-cpus.c index 4360f64671..b2c8fb57f6 100644 --- a/accel/hvf/hvf-cpus.c +++ b/accel/hvf/hvf-cpus.c @@ -344,9 +344,8 @@ static int hvf_init_vcpu(CPUState *cpu) sigact.sa_handler = dummy_signal; sigaction(SIG_IPI, , NULL); -pthread_sigmask(SIG_BLOCK, NULL, ); -sigdelset(, SIG_IPI); -pthread_sigmask(SIG_SETMASK, , NULL); +pthread_sigmask(SIG_BLOCK, NULL, >hvf->unblock_ipi_mask); +sigdelset(>hvf->unblock_ipi_mask, SIG_IPI); #ifdef __aarch64__ r = hv_vcpu_create(>hvf->fd, (hv_vcpu_exit_t **)>hvf->exit, NULL); diff --git a/include/sysemu/hvf_int.h b/include/sysemu/hvf_int.h index c56baa3ae8..13adf6ea77 100644 --- a/include/sysemu/hvf_int.h +++ b/include/sysemu/hvf_int.h @@ -62,8 +62,7 @@ extern HVFState *hvf_state; struct hvf_vcpu_state { uint64_t fd; void *exit; -struct timespec ts; -bool sleeping; +sigset_t unblock_ipi_mask; }; void assert_hvf_ok(hv_return_t ret); diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index 8fe10966d2..3321d48aa2 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -2,6 +2,7 @@ * QEMU Hypervisor.framework support for Apple Silicon * Copyright 2020 Alexander Graf + * Copyright 2020 Google LLC * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. @@ -18,6 +19,7 @@ #include "sysemu/hw_accel.h" #include +#include #include "exec/address-spaces.h" #include "hw/irq.h" @@ -320,18 +322,8 @@ int hvf_arch_init_vcpu(CPUState *cpu) void hvf_kick_vcpu_thread(CPUState *cpu) { -if (cpu->hvf->sleeping) { -/* - * When sleeping, make sure we always send signals. Also, clear the - * timespec, so that an IPI that arrives between setting hvf->sleeping - * and the nanosleep syscall still aborts the sleep. - */ -cpu->thread_kicked = false; -cpu->hvf->ts = (struct timespec){ }; -cpus_kick_thread(cpu); -} else { -hv_vcpus_exit(>hvf->fd, 1); -} +cpus_kick_thread(cpu); +hv_vcpus_exit(>hvf->fd, 1); } static int hvf_inject_interrupts(CPUState *cpu) @@ -349,6 +341,18 @@ static int hvf_inject_interrupts(CPUState *cpu) return 0; } +static void hvf_wait_for_ipi(CPUState *cpu, struct timespec *ts) +{ +/* + * Use pselect to sleep so that other threads can IPI us while we're + * sleeping. + */ +qatomic_mb_set(>thread_kicked, false); +qemu_mutex_unlock_iothread(); +pselect(0, 0, 0, 0, ts, >hvf->unblock_ipi_mask); +qemu_mutex_lock_iothread(); +} + int hvf_vcpu_exec(CPUState *cpu) { ARMCPU *arm_cpu = ARM_CPU(cpu); @@ -357,15 +361,11 @@ int hvf_vcpu_exec(CPUState *cpu) hv_return_t r; int ret = 0; -qemu_mutex_unlock_iothread(); - do { bool advance_pc = false; -qemu_mutex_lock_iothread(); current_cpu = cpu; qemu_wait_io_event_common(cpu); -qemu_mutex_unlock_iothread(); flush_cpu_state(cpu); @@ -374,10 +374,10 @@ int hvf_vcpu_exec(CPUState *cpu) } if (cpu->halted) { -qemu_mutex_lock_iothread(); return EXCP_HLT; } +qemu_mutex_unlock_iothread(); assert_hvf_ok(hv_vcpu_run(cpu->hvf->fd)); /* handle VMEXIT */ @@ -385,15 +385,14 @@ int hvf_vcpu_exec(CPUState *cpu) uint64_t syndrome = hvf_exit->exception.syndrome; uint32_t ec = syn_get_ec(syndrome); +qemu_mutex_lock_iothread(); switch (exit_reason) { case HV_EXIT_REASON_EXCEPTION: /* This is the main one, handle below. */ break; case HV_EXIT_REASON_VTIMER_ACTIVATED: -qemu_mutex_lock_iothread(); current_cpu = cpu; qemu_set_irq(arm_cpu->gt_timer_outputs[GTIMER_VIRT], 1); -qemu_mutex_unlock_iothread(); continue; case HV_EXIT_REASON_CANCELED: /* we got kicked, no exit to process */ @@ -413,7 +412,6 @@ int hvf_vcpu_exec(CPUState *cpu) uint32_t srt = (syndrome >> 16) & 0x1f; uint64_t val = 0; -qemu_mutex_lock_iothread(); current_cpu = cpu; DPRINTF("data abort: [pc=0x%llx va=0x%016llx
Re: [PATCH v2 1/2] arm/hvf: Optimize and simplify WFI handling
On Tue, Dec 1, 2020 at 3:24 PM Alexander Graf wrote: > > > On 01.12.20 22:00, Peter Collingbourne wrote: > > Sleep on WFx until the VTIMER is due but allow ourselves to be woken > > up on IPI. > > > > Signed-off-by: Peter Collingbourne > > --- > > v2: > > - simplify locking further > > - wait indefinitely on disabled or masked timers > > > > accel/hvf/hvf-cpus.c | 5 +- > > include/sysemu/hvf_int.h | 3 +- > > target/arm/hvf/hvf.c | 116 ++- > > 3 files changed, 43 insertions(+), 81 deletions(-) > > > > diff --git a/accel/hvf/hvf-cpus.c b/accel/hvf/hvf-cpus.c > > index 4360f64671..b2c8fb57f6 100644 > > --- a/accel/hvf/hvf-cpus.c > > +++ b/accel/hvf/hvf-cpus.c > > @@ -344,9 +344,8 @@ static int hvf_init_vcpu(CPUState *cpu) > > sigact.sa_handler = dummy_signal; > > sigaction(SIG_IPI, , NULL); > > > > -pthread_sigmask(SIG_BLOCK, NULL, ); > > -sigdelset(, SIG_IPI); > > -pthread_sigmask(SIG_SETMASK, , NULL); > > +pthread_sigmask(SIG_BLOCK, NULL, >hvf->unblock_ipi_mask); > > +sigdelset(>hvf->unblock_ipi_mask, SIG_IPI); > > > > #ifdef __aarch64__ > > r = hv_vcpu_create(>hvf->fd, (hv_vcpu_exit_t **)>hvf->exit, > > NULL); > > diff --git a/include/sysemu/hvf_int.h b/include/sysemu/hvf_int.h > > index c56baa3ae8..13adf6ea77 100644 > > --- a/include/sysemu/hvf_int.h > > +++ b/include/sysemu/hvf_int.h > > @@ -62,8 +62,7 @@ extern HVFState *hvf_state; > > struct hvf_vcpu_state { > > uint64_t fd; > > void *exit; > > -struct timespec ts; > > -bool sleeping; > > +sigset_t unblock_ipi_mask; > > }; > > > > void assert_hvf_ok(hv_return_t ret); > > diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c > > index 8fe10966d2..3321d48aa2 100644 > > --- a/target/arm/hvf/hvf.c > > +++ b/target/arm/hvf/hvf.c > > @@ -2,6 +2,7 @@ > >* QEMU Hypervisor.framework support for Apple Silicon > > > >* Copyright 2020 Alexander Graf > > + * Copyright 2020 Google LLC > >* > >* This work is licensed under the terms of the GNU GPL, version 2 or > > later. > >* See the COPYING file in the top-level directory. > > @@ -18,6 +19,7 @@ > > #include "sysemu/hw_accel.h" > > > > #include > > +#include > > > > #include "exec/address-spaces.h" > > #include "hw/irq.h" > > @@ -320,18 +322,8 @@ int hvf_arch_init_vcpu(CPUState *cpu) > > > > void hvf_kick_vcpu_thread(CPUState *cpu) > > { > > -if (cpu->hvf->sleeping) { > > -/* > > - * When sleeping, make sure we always send signals. Also, clear the > > - * timespec, so that an IPI that arrives between setting > > hvf->sleeping > > - * and the nanosleep syscall still aborts the sleep. > > - */ > > -cpu->thread_kicked = false; > > -cpu->hvf->ts = (struct timespec){ }; > > -cpus_kick_thread(cpu); > > -} else { > > -hv_vcpus_exit(>hvf->fd, 1); > > -} > > +cpus_kick_thread(cpu); > > +hv_vcpus_exit(>hvf->fd, 1); > > } > > > > static int hvf_inject_interrupts(CPUState *cpu) > > @@ -349,6 +341,18 @@ static int hvf_inject_interrupts(CPUState *cpu) > > return 0; > > } > > > > +static void hvf_wait_for_ipi(CPUState *cpu, struct timespec *ts) > > +{ > > +/* > > + * Use pselect to sleep so that other threads can IPI us while we're > > + * sleeping. > > + */ > > +qatomic_mb_set(>thread_kicked, false); > > +qemu_mutex_unlock_iothread(); > > +pselect(0, 0, 0, 0, ts, >hvf->unblock_ipi_mask); > > +qemu_mutex_lock_iothread(); > > +} > > + > > int hvf_vcpu_exec(CPUState *cpu) > > { > > ARMCPU *arm_cpu = ARM_CPU(cpu); > > @@ -357,15 +361,11 @@ int hvf_vcpu_exec(CPUState *cpu) > > hv_return_t r; > > int ret = 0; > > > > -qemu_mutex_unlock_iothread(); > > - > > do { > > bool advance_pc = false; > > > > -qemu_mutex_lock_iothread(); > > current_cpu = cpu; > > qemu_wait_io_event_common(cpu); > > -qemu_mutex_unlock_iothread(); > > > > flush_cpu_state(cpu); > > > > @@ -374,10 +374,10 @@ int hvf_vcpu_exec(CPUState *cpu) > > } > > > > if (cpu->halted) { > > -qemu_mutex_lock_iothread(); > > return EXCP_HLT; > > } > > > > +qemu_mutex_unlock_iothread(); > > assert_hvf_ok(hv_vcpu_run(cpu->hvf->fd)); > > > > /* handle VMEXIT */ > > @@ -385,15 +385,14 @@ int hvf_vcpu_exec(CPUState *cpu) > > uint64_t syndrome = hvf_exit->exception.syndrome; > > uint32_t ec = syn_get_ec(syndrome); > > > > +qemu_mutex_lock_iothread(); > > switch (exit_reason) { > > case HV_EXIT_REASON_EXCEPTION: > > /* This is the main one, handle below. */ > > break; > > case HV_EXIT_REASON_VTIMER_ACTIVATED: > > -qemu_mutex_lock_iothread(); > > current_cpu = cpu; > >
Re: [PATCH v2 1/2] arm/hvf: Optimize and simplify WFI handling
On 01.12.20 22:00, Peter Collingbourne wrote: Sleep on WFx until the VTIMER is due but allow ourselves to be woken up on IPI. Signed-off-by: Peter Collingbourne --- v2: - simplify locking further - wait indefinitely on disabled or masked timers accel/hvf/hvf-cpus.c | 5 +- include/sysemu/hvf_int.h | 3 +- target/arm/hvf/hvf.c | 116 ++- 3 files changed, 43 insertions(+), 81 deletions(-) diff --git a/accel/hvf/hvf-cpus.c b/accel/hvf/hvf-cpus.c index 4360f64671..b2c8fb57f6 100644 --- a/accel/hvf/hvf-cpus.c +++ b/accel/hvf/hvf-cpus.c @@ -344,9 +344,8 @@ static int hvf_init_vcpu(CPUState *cpu) sigact.sa_handler = dummy_signal; sigaction(SIG_IPI, , NULL); -pthread_sigmask(SIG_BLOCK, NULL, ); -sigdelset(, SIG_IPI); -pthread_sigmask(SIG_SETMASK, , NULL); +pthread_sigmask(SIG_BLOCK, NULL, >hvf->unblock_ipi_mask); +sigdelset(>hvf->unblock_ipi_mask, SIG_IPI); #ifdef __aarch64__ r = hv_vcpu_create(>hvf->fd, (hv_vcpu_exit_t **)>hvf->exit, NULL); diff --git a/include/sysemu/hvf_int.h b/include/sysemu/hvf_int.h index c56baa3ae8..13adf6ea77 100644 --- a/include/sysemu/hvf_int.h +++ b/include/sysemu/hvf_int.h @@ -62,8 +62,7 @@ extern HVFState *hvf_state; struct hvf_vcpu_state { uint64_t fd; void *exit; -struct timespec ts; -bool sleeping; +sigset_t unblock_ipi_mask; }; void assert_hvf_ok(hv_return_t ret); diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index 8fe10966d2..3321d48aa2 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -2,6 +2,7 @@ * QEMU Hypervisor.framework support for Apple Silicon * Copyright 2020 Alexander Graf + * Copyright 2020 Google LLC * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. @@ -18,6 +19,7 @@ #include "sysemu/hw_accel.h" #include +#include #include "exec/address-spaces.h" #include "hw/irq.h" @@ -320,18 +322,8 @@ int hvf_arch_init_vcpu(CPUState *cpu) void hvf_kick_vcpu_thread(CPUState *cpu) { -if (cpu->hvf->sleeping) { -/* - * When sleeping, make sure we always send signals. Also, clear the - * timespec, so that an IPI that arrives between setting hvf->sleeping - * and the nanosleep syscall still aborts the sleep. - */ -cpu->thread_kicked = false; -cpu->hvf->ts = (struct timespec){ }; -cpus_kick_thread(cpu); -} else { -hv_vcpus_exit(>hvf->fd, 1); -} +cpus_kick_thread(cpu); +hv_vcpus_exit(>hvf->fd, 1); } static int hvf_inject_interrupts(CPUState *cpu) @@ -349,6 +341,18 @@ static int hvf_inject_interrupts(CPUState *cpu) return 0; } +static void hvf_wait_for_ipi(CPUState *cpu, struct timespec *ts) +{ +/* + * Use pselect to sleep so that other threads can IPI us while we're + * sleeping. + */ +qatomic_mb_set(>thread_kicked, false); +qemu_mutex_unlock_iothread(); +pselect(0, 0, 0, 0, ts, >hvf->unblock_ipi_mask); +qemu_mutex_lock_iothread(); +} + int hvf_vcpu_exec(CPUState *cpu) { ARMCPU *arm_cpu = ARM_CPU(cpu); @@ -357,15 +361,11 @@ int hvf_vcpu_exec(CPUState *cpu) hv_return_t r; int ret = 0; -qemu_mutex_unlock_iothread(); - do { bool advance_pc = false; -qemu_mutex_lock_iothread(); current_cpu = cpu; qemu_wait_io_event_common(cpu); -qemu_mutex_unlock_iothread(); flush_cpu_state(cpu); @@ -374,10 +374,10 @@ int hvf_vcpu_exec(CPUState *cpu) } if (cpu->halted) { -qemu_mutex_lock_iothread(); return EXCP_HLT; } +qemu_mutex_unlock_iothread(); assert_hvf_ok(hv_vcpu_run(cpu->hvf->fd)); /* handle VMEXIT */ @@ -385,15 +385,14 @@ int hvf_vcpu_exec(CPUState *cpu) uint64_t syndrome = hvf_exit->exception.syndrome; uint32_t ec = syn_get_ec(syndrome); +qemu_mutex_lock_iothread(); switch (exit_reason) { case HV_EXIT_REASON_EXCEPTION: /* This is the main one, handle below. */ break; case HV_EXIT_REASON_VTIMER_ACTIVATED: -qemu_mutex_lock_iothread(); current_cpu = cpu; qemu_set_irq(arm_cpu->gt_timer_outputs[GTIMER_VIRT], 1); -qemu_mutex_unlock_iothread(); continue; case HV_EXIT_REASON_CANCELED: /* we got kicked, no exit to process */ @@ -413,7 +412,6 @@ int hvf_vcpu_exec(CPUState *cpu) uint32_t srt = (syndrome >> 16) & 0x1f; uint64_t val = 0; -qemu_mutex_lock_iothread(); current_cpu = cpu; DPRINTF("data abort: [pc=0x%llx va=0x%016llx pa=0x%016llx isv=%x " @@ -446,8 +444,6 @@ int hvf_vcpu_exec(CPUState *cpu) hvf_set_reg(cpu,
[PATCH v2 1/2] arm/hvf: Optimize and simplify WFI handling
Sleep on WFx until the VTIMER is due but allow ourselves to be woken up on IPI. Signed-off-by: Peter Collingbourne --- v2: - simplify locking further - wait indefinitely on disabled or masked timers accel/hvf/hvf-cpus.c | 5 +- include/sysemu/hvf_int.h | 3 +- target/arm/hvf/hvf.c | 116 ++- 3 files changed, 43 insertions(+), 81 deletions(-) diff --git a/accel/hvf/hvf-cpus.c b/accel/hvf/hvf-cpus.c index 4360f64671..b2c8fb57f6 100644 --- a/accel/hvf/hvf-cpus.c +++ b/accel/hvf/hvf-cpus.c @@ -344,9 +344,8 @@ static int hvf_init_vcpu(CPUState *cpu) sigact.sa_handler = dummy_signal; sigaction(SIG_IPI, , NULL); -pthread_sigmask(SIG_BLOCK, NULL, ); -sigdelset(, SIG_IPI); -pthread_sigmask(SIG_SETMASK, , NULL); +pthread_sigmask(SIG_BLOCK, NULL, >hvf->unblock_ipi_mask); +sigdelset(>hvf->unblock_ipi_mask, SIG_IPI); #ifdef __aarch64__ r = hv_vcpu_create(>hvf->fd, (hv_vcpu_exit_t **)>hvf->exit, NULL); diff --git a/include/sysemu/hvf_int.h b/include/sysemu/hvf_int.h index c56baa3ae8..13adf6ea77 100644 --- a/include/sysemu/hvf_int.h +++ b/include/sysemu/hvf_int.h @@ -62,8 +62,7 @@ extern HVFState *hvf_state; struct hvf_vcpu_state { uint64_t fd; void *exit; -struct timespec ts; -bool sleeping; +sigset_t unblock_ipi_mask; }; void assert_hvf_ok(hv_return_t ret); diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index 8fe10966d2..3321d48aa2 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -2,6 +2,7 @@ * QEMU Hypervisor.framework support for Apple Silicon * Copyright 2020 Alexander Graf + * Copyright 2020 Google LLC * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. @@ -18,6 +19,7 @@ #include "sysemu/hw_accel.h" #include +#include #include "exec/address-spaces.h" #include "hw/irq.h" @@ -320,18 +322,8 @@ int hvf_arch_init_vcpu(CPUState *cpu) void hvf_kick_vcpu_thread(CPUState *cpu) { -if (cpu->hvf->sleeping) { -/* - * When sleeping, make sure we always send signals. Also, clear the - * timespec, so that an IPI that arrives between setting hvf->sleeping - * and the nanosleep syscall still aborts the sleep. - */ -cpu->thread_kicked = false; -cpu->hvf->ts = (struct timespec){ }; -cpus_kick_thread(cpu); -} else { -hv_vcpus_exit(>hvf->fd, 1); -} +cpus_kick_thread(cpu); +hv_vcpus_exit(>hvf->fd, 1); } static int hvf_inject_interrupts(CPUState *cpu) @@ -349,6 +341,18 @@ static int hvf_inject_interrupts(CPUState *cpu) return 0; } +static void hvf_wait_for_ipi(CPUState *cpu, struct timespec *ts) +{ +/* + * Use pselect to sleep so that other threads can IPI us while we're + * sleeping. + */ +qatomic_mb_set(>thread_kicked, false); +qemu_mutex_unlock_iothread(); +pselect(0, 0, 0, 0, ts, >hvf->unblock_ipi_mask); +qemu_mutex_lock_iothread(); +} + int hvf_vcpu_exec(CPUState *cpu) { ARMCPU *arm_cpu = ARM_CPU(cpu); @@ -357,15 +361,11 @@ int hvf_vcpu_exec(CPUState *cpu) hv_return_t r; int ret = 0; -qemu_mutex_unlock_iothread(); - do { bool advance_pc = false; -qemu_mutex_lock_iothread(); current_cpu = cpu; qemu_wait_io_event_common(cpu); -qemu_mutex_unlock_iothread(); flush_cpu_state(cpu); @@ -374,10 +374,10 @@ int hvf_vcpu_exec(CPUState *cpu) } if (cpu->halted) { -qemu_mutex_lock_iothread(); return EXCP_HLT; } +qemu_mutex_unlock_iothread(); assert_hvf_ok(hv_vcpu_run(cpu->hvf->fd)); /* handle VMEXIT */ @@ -385,15 +385,14 @@ int hvf_vcpu_exec(CPUState *cpu) uint64_t syndrome = hvf_exit->exception.syndrome; uint32_t ec = syn_get_ec(syndrome); +qemu_mutex_lock_iothread(); switch (exit_reason) { case HV_EXIT_REASON_EXCEPTION: /* This is the main one, handle below. */ break; case HV_EXIT_REASON_VTIMER_ACTIVATED: -qemu_mutex_lock_iothread(); current_cpu = cpu; qemu_set_irq(arm_cpu->gt_timer_outputs[GTIMER_VIRT], 1); -qemu_mutex_unlock_iothread(); continue; case HV_EXIT_REASON_CANCELED: /* we got kicked, no exit to process */ @@ -413,7 +412,6 @@ int hvf_vcpu_exec(CPUState *cpu) uint32_t srt = (syndrome >> 16) & 0x1f; uint64_t val = 0; -qemu_mutex_lock_iothread(); current_cpu = cpu; DPRINTF("data abort: [pc=0x%llx va=0x%016llx pa=0x%016llx isv=%x " @@ -446,8 +444,6 @@ int hvf_vcpu_exec(CPUState *cpu) hvf_set_reg(cpu, srt, val); } -qemu_mutex_unlock_iothread(); - advance_pc = true; break; } @@ -493,68