Re: [RFC PATCH v2 11/34] x86/msr: Remove calling native_{read,write}_msr{,_safe}() in pmu_msr_{read,write}()

Mi, Dapeng
2025-04-24T06:26:05Z

On 4/22/2025 4:21 PM, Xin Li (Intel) wrote:
> hpa found that pmu_msr_write() is actually a completely pointless
> function [1]: all it does is shuffle some arguments, then calls
> pmu_msr_chk_emulated() and if it returns true AND the emulated flag
> is clear then does *exactly the same thing* that the calling code
> would have done if pmu_msr_write() itself had returned true. And
> pmu_msr_read() does the equivalent stupidity.
>
> Remove the calls to native_{read,write}_msr{,_safe}() within
> pmu_msr_{read,write}(). Instead reuse the existing calling code
> that decides whether to call native_{read,write}_msr{,_safe}() based
> on the return value from pmu_msr_{read,write}(). Consequently,
> eliminate the need to pass an error pointer to pmu_msr_{read,write}().
>
> While at it, refactor pmu_msr_write() to take the MSR value as a u64
> argument, replacing the current dual u32 arguments, because the dual
> u32 arguments were only used to call native_write_msr{,_safe}(), which
> has now been removed.
>
> [1]: https://lore.kernel.org/lkml/0ec48b84-d158-47c6-b14c-3563fd14bcc4@zytor.com/
>
> Suggested-by: H. Peter Anvin (Intel) <hpa@zytor.com>
> Sign-off-by: Xin Li (Intel) <xin@zytor.com>
> ---
> arch/x86/xen/enlighten_pv.c | 6 +++++-
> arch/x86/xen/pmu.c | 27 ++++-----------------------
> arch/x86/xen/xen-ops.h | 4 ++--
> 3 files changed, 11 insertions(+), 26 deletions(-)
>
> diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
> index 9fbe187aff00..1418758b57ff 100644
> --- a/arch/x86/xen/enlighten_pv.c
> +++ b/arch/x86/xen/enlighten_pv.c
> @@ -1132,6 +1132,8 @@ static void set_seg(unsigned int which, unsigned int low, unsigned int high,
> static void xen_do_write_msr(unsigned int msr, unsigned int low,
> unsigned int high, int *err)
> {
> + u64 val;
> +
> switch (msr) {
> case MSR_FS_BASE:
> set_seg(SEGBASE_FS, low, high, err);
> @@ -1158,7 +1160,9 @@ static void xen_do_write_msr(unsigned int msr, unsigned int low,
> break;
>
> default:
> - if (!pmu_msr_write(msr, low, high, err)) {
> + val = (u64)high << 32 | low;
> +
> + if (!pmu_msr_write(msr, val)) {
> if (err)
> *err = native_write_msr_safe(msr, low, high);
> else
> diff --git a/arch/x86/xen/pmu.c b/arch/x86/xen/pmu.c
> index 9c1682af620a..95caae97a394 100644
> --- a/arch/x86/xen/pmu.c
> +++ b/arch/x86/xen/pmu.c
> @@ -313,37 +313,18 @@ static bool pmu_msr_chk_emulated(unsigned int msr, uint64_t *val, bool is_read,
> return true;
> }
>
> -bool pmu_msr_read(unsigned int msr, uint64_t *val, int *err)
> +bool pmu_msr_read(u32 msr, u64 *val)

The function name is some kind of misleading right now. With the change,
this function only read PMU MSR's value if it's emulated, otherwise it
won't really read PMU MSR. How about changing the name to
"pmu_emulated_msr_read" or something similar?

> {
> bool emulated;
>
> - if (!pmu_msr_chk_emulated(msr, val, true, &emulated))
> - return false;
> -
> - if (!emulated) {
> - *val = err ? native_read_msr_safe(msr, err)
> - : native_read_msr(msr);
> - }
> -
> - return true;
> + return pmu_msr_chk_emulated(msr, val, true, &emulated) && emulated;
> }
>
> -bool pmu_msr_write(unsigned int msr, uint32_t low, uint32_t high, int *err)
> +bool pmu_msr_write(u32 msr, u64 val)

ditto.

> {
> - uint64_t val = ((uint64_t)high << 32) | low;
> bool emulated;
>
> - if (!pmu_msr_chk_emulated(msr, &val, false, &emulated))
> - return false;
> -
> - if (!emulated) {
> - if (err)
> - *err = native_write_msr_safe(msr, low, high);
> - else
> - native_write_msr(msr, low, high);
> - }
> -
> - return true;
> + return pmu_msr_chk_emulated(msr, &val, false, &emulated) && emulated;
> }
>
> static u64 xen_amd_read_pmc(int counter)
> diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
> index dc886c3cc24d..a1875e10be31 100644
> --- a/arch/x86/xen/xen-ops.h
> +++ b/arch/x86/xen/xen-ops.h
> @@ -271,8 +271,8 @@ void xen_pmu_finish(int cpu);
> static inline void xen_pmu_init(int cpu) {}
> static inline void xen_pmu_finish(int cpu) {}
> #endif
> -bool pmu_msr_read(unsigned int msr, uint64_t *val, int *err);
> -bool pmu_msr_write(unsigned int msr, uint32_t low, uint32_t high, int *err);
> +bool pmu_msr_read(u32 msr, u64 *val);

The prototype of pmu_msr_read() has been changed, but why there is no
corresponding change in its caller (xen_do_read_msr())?

> +bool pmu_msr_write(u32 msr, u64 val);
> int pmu_apic_update(uint32_t reg);
> u64 xen_read_pmc(int counter);
>