|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH 04/13] cpufreq: Add Hardware P-State (HWP) driver
On Fri, May 28, 2021 at 2:35 AM Jan Beulich <jbeulich@xxxxxxxx> wrote:
>
> On 27.05.2021 20:50, Jason Andryuk wrote:
> > On Wed, May 26, 2021 at 11:00 AM Jan Beulich <jbeulich@xxxxxxxx> wrote:
> >>
> >> On 03.05.2021 21:28, Jason Andryuk wrote:
> >>> + hwp_verbose("HWP: FAST_IA32_HWP_REQUEST %ssupported\n",
> >>> + eax & CPUID6_EAX_FAST_HWP_MSR ? "" : "not ");
> >>> + if ( eax & CPUID6_EAX_FAST_HWP_MSR )
> >>> + {
> >>> + if ( rdmsr_safe(MSR_FAST_UNCORE_MSRS_CAPABILITY, val) )
> >>> + hwp_err("error
> >>> rdmsr_safe(MSR_FAST_UNCORE_MSRS_CAPABILITY)\n");
> >>> +
> >>> + hwp_verbose("HWP: MSR_FAST_UNCORE_MSRS_CAPABILITY: %016lx\n",
> >>> val);
> >>
> >> Missing "else" above here?
> >
> > Are unbalanced braces acceptable or must they be balanced? Is this
> > acceptable:
> > if ()
> > one;
> > else {
> > two;
> > three;
> > }
>
> Yes, it is. But I don't see how the question relates to my comment.
> All that needs to go in the else's body is the hwp_verbose().
'val' shouldn't be used to set features when the rdmsr fails, so the
following code needs to be within the else. Unless you want to rely
on a failed rdmsr returning 0.
> >>> +static void hdc_set_pkg_hdc_ctl(bool val)
> >>> +{
> >>> + uint64_t msr;
> >>> +
> >>> + if ( rdmsr_safe(MSR_IA32_PKG_HDC_CTL, msr) )
> >>> + {
> >>> + hwp_err("error rdmsr_safe(MSR_IA32_PKG_HDC_CTL)\n");
> >>
> >> I'm not convinced of the need of having such log messages after
> >> failed rdmsr/wrmsr, but I'm definitely against them getting logged
> >> unconditionally. In verbose mode, maybe.
> >
> > We should not fail the rdmsr if our earlier cpuid check passed. So in
> > that respect these messages can be removed. The benefit here is that
> > you can see which MSR failed. If you relied on extable_fixup, you
> > would have to cross reference manually. How will administors know if
> > hwp isn't working properly there are no messages?
>
> This same question would go for various other MSR accesses which
> might fail, but which aren't accompanied by an explicit log message.
> I wouldn't mind a single summary message reporting if e.g. HWP
> setup failed. More detailed analysis of such would be more of a
> developer's than an administrator's job then anyway.
>
> > For HWP in general, the SDM says to check CPUID for the availability
> > of MSRs. Therefore rdmsr/wrmsr shouldn't fail. During development, I
> > saw wrmsr failures when with "Valid Maximum" and other "Valid" bits
> > set. I think that was because I hadn't set up the Package Request
> > MSR. That has been fixed by not using those bits. Anyway,
> > rdmsr/wrmsr shouldn't fail, so how much code should be put into
> > checking for those failures which shouldn't happen?
>
> If there's any risk of accesses causing a fault, using *msr_safe()
> is of course the right choice. Beyond that you will need to consider
> what the consequences are. Sadly this needs doing on every single
> case individually. See "Handling unexpected conditions" section of
> ./CODING_STYLE for guidelines (even if the specific constructs
> aren't in use here).
Using *msr_safe(), I think the worst case is the users can't set HWP
in the way they want. So power/performance may not be what the users
wanted, but Xen won't crash. The hardware will throttle itself if
needed for self-protection, so that should be okay as well.
> >>> +static void hdc_set_pm_ctl1(bool val)
> >>> +{
> >>> + uint64_t msr;
> >>> +
> >>> + if ( rdmsr_safe(MSR_IA32_PM_CTL1, msr) )
> >>> + {
> >>> + hwp_err("error rdmsr_safe(MSR_IA32_PM_CTL1)\n");
> >>> +
> >>> + return;
> >>> + }
> >>> +
> >>> + msr = val ? IA32_PM_CTL1_HDC_Allow_Block : 0;
> >>
> >> Same here then, and ...
> >>
> >>> +static void hwp_fast_uncore_msrs_ctl(bool val)
> >>> +{
> >>> + uint64_t msr;
> >>> +
> >>> + if ( rdmsr_safe(MSR_FAST_UNCORE_MSRS_CTL, msr) )
> >>> + hwp_err("error rdmsr_safe(MSR_FAST_UNCORE_MSRS_CTL)\n");
> >>> +
> >>> + msr = val;
> >>
> >> ... here (where you imply bit 0 instead of using a proper
> >> constant).
> >>
> >> Also for all three functions I'm not convinced their names are
> >> in good sync with their parameters being boolean.
> >
> > Would you prefer something named closer to the bit names like:
> > hdc_set_pkg_hdc_ctl -> hdc_set_pkg_enable
> > hdc_set_pm_ctl1 -> hdc_set_allow_block
> > hwp_fast_uncore_msrs_ctl -> hwp_fast_request_enable
>
> My primary request is for function name, purpose, and parameter(s)
> to be in line. So e.g. if you left the parameters as boolean, then
> I think your suggested name changes make sense. Alternatively you
> could make the functions e.g. be full register updating ones, with
> suitable parameters, which could be a mask-to-set and mask-to-clear.
I'm going to use the replacement names while keeping the boolean
argument. Those MSRs only have single bits defined today, so
functions with boolean parameters are simpler.
> >>> +static void hwp_read_capabilities(void *info)
> >>> +{
> >>> + struct cpufreq_policy *policy = info;
> >>> + struct hwp_drv_data *data = hwp_drv_data[policy->cpu];
> >>> +
> >>> + if ( rdmsr_safe(MSR_IA32_HWP_CAPABILITIES, data->hwp_caps) )
> >>> + {
> >>> + hwp_err("CPU%u: error rdmsr_safe(MSR_IA32_HWP_CAPABILITIES)\n",
> >>> + policy->cpu);
> >>> +
> >>> + return;
> >>> + }
> >>> +
> >>> + if ( rdmsr_safe(MSR_IA32_HWP_REQUEST, data->curr_req.raw) )
> >>> + {
> >>> + hwp_err("CPU%u: error rdmsr_safe(MSR_IA32_HWP_REQUEST)\n",
> >>> policy->cpu);
> >>> +
> >>> + return;
> >>> + }
> >>> +}
> >>
> >> This function doesn't indicate failure to its caller(s), so am I
> >> to understand that failure to read either ofthe MSRs is actually
> >> benign to the driver?
> >
> > They really shouldn't fail since the CPUID check passed during
> > initialization. If you can't read/write MSRs, something is broken and
> > the driver cannot function. The machine would still run, but HWP
> > would be uncontrollable. How much care should be given to
> > "impossible" situations?
>
> See above. The main point is to avoid crashing. In the specific
> case here I think you could simply drop both the log messages and
> the early return, assuming the caller can deal fine with the zero
> value(s) that rdmsr_safe() will substitute for the MSR value(s).
> Bailing early, otoh, calls for handing back an error indicator
> imo.
I changed it to have failure set curr_req.raw = -1. Then
cpufreq_driver.init returns -ENODEV in that case.
> >>> + policy->governor = &hwp_cpufreq_governor;
> >>> +
> >>> + data = xzalloc(typeof(*data));
> >>
> >> Commonly we specify the type explicitly in such cases, rather than using
> >> typeof(). I will admit though that I'm not entirely certain which one's
> >> better. But consistency across the code base is perhaps preferable for
> >> the time being.
> >
> > I thought typeof(*data) is always preferable since it will always be
> > the matching type. I can change it, but I feel like it's a step
> > backwards.
>
> There's exactly one similar use in the entire code base. The original
> idea with xmalloc() was that one would explicitly specify the intended
> type, such that without looking elsewhere one can see what exactly is
> to be allocated. One could further rely on the compiler warning if
> there was a disagreement between declaration and assignment.
Oh, okay. Thanks for the explanation of xmalloc().
> >>> + if ( feature_hwp_energy_perf )
> >>> + data->energy_perf = 0x80;
> >>> + else
> >>> + data->energy_perf = 7;
> >>
> >> Where's this 7 coming from? (You do mention the 0x80 at least in the
> >> description.)
> >
> > When HWP energy performance preference is unavailable, it falls back
> > to IA32_ENERGY_PERF_BIAS with a 0-15 range. Per the SDM Vol3 14.3.4,
> > "A value of 7 roughly translates into a hint to balance performance
> > with energy consumption." I will add a comment.
>
> Actually, as per a comment on a later patch, I'm instead expecting
> you to add a #define, the name of which will serve as comment.
Yes, sounds good.
Regards,
Jason
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |