Re: [PATCH v2 1/2] arm/hvf: Optimize and simplify WFI handling

2020-12-01 Thread Alexander Graf



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

2020-12-01 Thread Peter Collingbourne
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

2020-12-01 Thread Peter Collingbourne
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

2020-12-01 Thread Alexander Graf



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

2020-12-01 Thread Peter Collingbourne
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

2020-12-01 Thread Alexander Graf



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

2020-12-01 Thread Peter Collingbourne via
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