+ Nicholas M (Forgot to include the text in the prev mail, please ignore that)
On Thu, Apr 17, 2025 at 04:49:03PM +0530, Gautam Menghani wrote: > Currently, on a P10 KVM guest, the mitigations seen in the output of > "lscpu" command are different from the host. The reason for this > behaviour is that when the KVM guest makes the "h_get_cpu_characteristics" > hcall, QEMU does not consider the data it received from the host via the > KVM_PPC_GET_CPU_CHAR ioctl, and just uses the values present in > spapr->eff.caps[], which in turn just contain the default values set in > spapr_machine_class_init(). > > Fix this behaviour by making sure that h_get_cpu_characteristics() > returns the data received from the KVM ioctl for a KVM guest. > > Perf impact: > With null syscall benchmark[1], ~45% improvement is observed. > > 1. Vanilla QEMU > $ ./null_syscall > 132.19 ns 456.54 cycles > > 2. With this patch > $ ./null_syscall > 91.18 ns 314.57 cycles > > [1]: https://ozlabs.org/~anton/junkcode/null_syscall.c > > Signed-off-by: Gautam Menghani <gau...@linux.ibm.com> > --- > v1 -> v2: > Handle the case where KVM_PPC_GET_CPU_CHAR ioctl fails > > hw/ppc/spapr_hcall.c | 6 ++++++ > include/hw/ppc/spapr.h | 1 + > target/ppc/kvm.c | 13 ++++++++++--- > 3 files changed, 17 insertions(+), 3 deletions(-) > > diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c > index 5e1d020e3d..d6db1bdab8 100644 > --- a/hw/ppc/spapr_hcall.c > +++ b/hw/ppc/spapr_hcall.c > @@ -1402,6 +1402,12 @@ static target_ulong > h_get_cpu_characteristics(PowerPCCPU *cpu, > uint8_t count_cache_flush_assist = spapr_get_cap(spapr, > SPAPR_CAP_CCF_ASSIST); > > + if (kvm_enabled() && spapr->chars.character) { > + args[0] = spapr->chars.character; > + args[1] = spapr->chars.behaviour; > + return H_SUCCESS; > + } > + > switch (safe_cache) { > case SPAPR_CAP_WORKAROUND: > characteristics |= H_CPU_CHAR_L1D_FLUSH_ORI30; > diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h > index af4aa1cb0f..c41da8cb82 100644 > --- a/include/hw/ppc/spapr.h > +++ b/include/hw/ppc/spapr.h > @@ -280,6 +280,7 @@ struct SpaprMachineState { > Error *fwnmi_migration_blocker; > > SpaprWatchdog wds[WDT_MAX_WATCHDOGS]; > + struct kvm_ppc_cpu_char chars; > }; > > #define H_SUCCESS 0 > diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c > index 3efc28f18b..fec7bcc347 100644 > --- a/target/ppc/kvm.c > +++ b/target/ppc/kvm.c > @@ -2499,7 +2499,8 @@ bool kvmppc_has_cap_xive(void) > > static void kvmppc_get_cpu_characteristics(KVMState *s) > { > - struct kvm_ppc_cpu_char c; > + SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); > + struct kvm_ppc_cpu_char c = {0}; > int ret; > > /* Assume broken */ > @@ -2509,18 +2510,24 @@ static void kvmppc_get_cpu_characteristics(KVMState > *s) > > ret = kvm_vm_check_extension(s, KVM_CAP_PPC_GET_CPU_CHAR); > if (!ret) { > - return; > + goto err; > } > ret = kvm_vm_ioctl(s, KVM_PPC_GET_CPU_CHAR, &c); > if (ret < 0) { > - return; > + goto err; > } > > + spapr->chars = c; > cap_ppc_safe_cache = parse_cap_ppc_safe_cache(c); > cap_ppc_safe_bounds_check = parse_cap_ppc_safe_bounds_check(c); > cap_ppc_safe_indirect_branch = parse_cap_ppc_safe_indirect_branch(c); > cap_ppc_count_cache_flush_assist = > parse_cap_ppc_count_cache_flush_assist(c); > + > + return; > + > +err: > + memset(&(spapr->chars), 0, sizeof(struct kvm_ppc_cpu_char)); > } > > int kvmppc_get_cap_safe_cache(void) > -- > 2.49.0 >