diff mbox series

[qemu] ppc/kvm: Skip writing DPDES back when in run time state

Message ID 20190923084110.34643-1-aik@ozlabs.ru
State New
Headers show
Series [qemu] ppc/kvm: Skip writing DPDES back when in run time state | expand

Commit Message

Alexey Kardashevskiy Sept. 23, 2019, 8:41 a.m. UTC
On POWER8 systems the Directed Privileged Door-bell Exception State
register (DPDES) stores doorbell pending status, one bit per a thread
of a core, set by "msgsndp" instruction. The register is shared among
threads of the same core and KVM on POWER9 emulates it in a similar way
(POWER9 does not have DPDES).

DPDES is shared but QEMU assumes all SPRs are per thread so the only safe
way to write DPDES back to VCPU before running a guest is doing so
while all threads are pulled out of the guest so DPDES cannot change.
There is only one situation when this condition is met: incoming migration
when all threads are stopped. Otherwise any QEMU HMP/QMP command causing
kvm_arch_put_registers() (for example printing registers or dumping memory)
can clobber DPDES in a race with other vcpu threads.

This changes DPDES handling so it is not written to KVM at runtime.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
 target/ppc/kvm.c                | 5 +++++
 target/ppc/translate_init.inc.c | 9 ++++-----
 2 files changed, 9 insertions(+), 5 deletions(-)

Comments

David Gibson Sept. 24, 2019, 1:18 p.m. UTC | #1
On Mon, Sep 23, 2019 at 06:41:10PM +1000, Alexey Kardashevskiy wrote:
> On POWER8 systems the Directed Privileged Door-bell Exception State
> register (DPDES) stores doorbell pending status, one bit per a thread
> of a core, set by "msgsndp" instruction. The register is shared among
> threads of the same core and KVM on POWER9 emulates it in a similar way
> (POWER9 does not have DPDES).
> 
> DPDES is shared but QEMU assumes all SPRs are per thread so the only safe
> way to write DPDES back to VCPU before running a guest is doing so
> while all threads are pulled out of the guest so DPDES cannot change.
> There is only one situation when this condition is met: incoming migration
> when all threads are stopped. Otherwise any QEMU HMP/QMP command causing
> kvm_arch_put_registers() (for example printing registers or dumping memory)
> can clobber DPDES in a race with other vcpu threads.
> 
> This changes DPDES handling so it is not written to KVM at runtime.
> 
> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>

Applied to ppc-for-4.2, thanks.

> ---
>  target/ppc/kvm.c                | 5 +++++
>  target/ppc/translate_init.inc.c | 9 ++++-----
>  2 files changed, 9 insertions(+), 5 deletions(-)
> 
> diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
> index 8c5b1f25cc95..820724cc7d15 100644
> --- a/target/ppc/kvm.c
> +++ b/target/ppc/kvm.c
> @@ -993,6 +993,10 @@ int kvm_arch_put_registers(CPUState *cs, int level)
>          }
>  
>          kvm_set_one_reg(cs, KVM_REG_PPC_TB_OFFSET, &env->tb_env->tb_offset);
> +
> +        if (level > KVM_PUT_RUNTIME_STATE) {
> +            kvm_put_one_spr(cs, KVM_REG_PPC_DPDES, SPR_DPDES);
> +        }
>  #endif /* TARGET_PPC64 */
>      }
>  
> @@ -1297,6 +1301,7 @@ int kvm_arch_get_registers(CPUState *cs)
>          }
>  
>          kvm_get_one_reg(cs, KVM_REG_PPC_TB_OFFSET, &env->tb_env->tb_offset);
> +        kvm_get_one_spr(cs, KVM_REG_PPC_DPDES, SPR_DPDES);
>  #endif
>      }
>  
> diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
> index 0fb11c7ac6da..ba726dec4d00 100644
> --- a/target/ppc/translate_init.inc.c
> +++ b/target/ppc/translate_init.inc.c
> @@ -8200,11 +8200,10 @@ static void gen_spr_power8_dpdes(CPUPPCState *env)
>  {
>  #if !defined(CONFIG_USER_ONLY)
>      /* Directed Privileged Door-bell Exception State, used for IPI */
> -    spr_register_kvm_hv(env, SPR_DPDES, "DPDES",
> -                        SPR_NOACCESS, SPR_NOACCESS,
> -                        &spr_read_generic, SPR_NOACCESS,
> -                        &spr_read_generic, &spr_write_generic,
> -                        KVM_REG_PPC_DPDES, 0x00000000);
> +    spr_register(env, SPR_DPDES, "DPDES",
> +                 SPR_NOACCESS, SPR_NOACCESS,
> +                 &spr_read_generic, SPR_NOACCESS,
> +                 0x00000000);
>  #endif
>  }
>
diff mbox series

Patch

diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 8c5b1f25cc95..820724cc7d15 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -993,6 +993,10 @@  int kvm_arch_put_registers(CPUState *cs, int level)
         }
 
         kvm_set_one_reg(cs, KVM_REG_PPC_TB_OFFSET, &env->tb_env->tb_offset);
+
+        if (level > KVM_PUT_RUNTIME_STATE) {
+            kvm_put_one_spr(cs, KVM_REG_PPC_DPDES, SPR_DPDES);
+        }
 #endif /* TARGET_PPC64 */
     }
 
@@ -1297,6 +1301,7 @@  int kvm_arch_get_registers(CPUState *cs)
         }
 
         kvm_get_one_reg(cs, KVM_REG_PPC_TB_OFFSET, &env->tb_env->tb_offset);
+        kvm_get_one_spr(cs, KVM_REG_PPC_DPDES, SPR_DPDES);
 #endif
     }
 
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index 0fb11c7ac6da..ba726dec4d00 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -8200,11 +8200,10 @@  static void gen_spr_power8_dpdes(CPUPPCState *env)
 {
 #if !defined(CONFIG_USER_ONLY)
     /* Directed Privileged Door-bell Exception State, used for IPI */
-    spr_register_kvm_hv(env, SPR_DPDES, "DPDES",
-                        SPR_NOACCESS, SPR_NOACCESS,
-                        &spr_read_generic, SPR_NOACCESS,
-                        &spr_read_generic, &spr_write_generic,
-                        KVM_REG_PPC_DPDES, 0x00000000);
+    spr_register(env, SPR_DPDES, "DPDES",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, SPR_NOACCESS,
+                 0x00000000);
 #endif
 }