Message ID | 20230316103236.37102-1-roger.pau@citrix.com (mailing list archive) |
---|---|
State | Superseded, archived |
Headers | show |
Series | [v3] acpi/processor: fix evaluating _PDC method when running as Xen dom0 | expand |
On 16.03.2023 11:32, Roger Pau Monne wrote: > --- a/arch/x86/include/asm/xen/hypervisor.h > +++ b/arch/x86/include/asm/xen/hypervisor.h > @@ -63,4 +63,14 @@ void __init xen_pvh_init(struct boot_params *boot_params); > void __init mem_map_via_hcall(struct boot_params *boot_params_p); > #endif > > +#ifdef CONFIG_XEN_DOM0 Shouldn't you also check CONFIG_X86 here, seeing the condition for when pcpu.c would be built? Additionally CONFIG_ACPI may want checking, which - taken together - would amount to checking CONFIG_XEN_ACPI. (For which in turn I find odd that it will also be engaged when !DOM0.) > @@ -381,3 +383,20 @@ static int __init xen_pcpu_init(void) > return ret; > } > arch_initcall(xen_pcpu_init); > + > +bool __init xen_processor_present(uint32_t acpi_id) > +{ > + struct pcpu *pcpu; > + bool online = false; > + > + mutex_lock(&xen_pcpu_lock); > + list_for_each_entry(pcpu, &xen_pcpus, list) > + if (pcpu->acpi_id == acpi_id) { > + online = pcpu->flags & XEN_PCPU_FLAGS_ONLINE; > + break; > + } > + > + mutex_unlock(&xen_pcpu_lock); > + > + return online; > +} Since it is neither natural nor obvious that this function takes an ACPI ID as input (could in particular also be an APIC ID), would that perhaps better be expressed in its name? Jan
On Thu, Mar 16, 2023 at 11:45:47AM +0100, Jan Beulich wrote: > On 16.03.2023 11:32, Roger Pau Monne wrote: > > --- a/arch/x86/include/asm/xen/hypervisor.h > > +++ b/arch/x86/include/asm/xen/hypervisor.h > > @@ -63,4 +63,14 @@ void __init xen_pvh_init(struct boot_params *boot_params); > > void __init mem_map_via_hcall(struct boot_params *boot_params_p); > > #endif > > > > +#ifdef CONFIG_XEN_DOM0 > > Shouldn't you also check CONFIG_X86 here, seeing the condition for when > pcpu.c would be built? It's in a x86 specific header, so that's enough I think? (note the path of the header) > Additionally CONFIG_ACPI may want checking, which > - taken together - would amount to checking CONFIG_XEN_ACPI. (For which > in turn I find odd that it will also be engaged when !DOM0.) Hm, is it worth making the acpi_id field in struct pcpu or helper conditional to CONFIG_ACPI? It's just data fetched from Xen so it doesn't depend on any of the ACPI functionality in Linux. IMO I don't think it's worth the extra ifdefs. > > @@ -381,3 +383,20 @@ static int __init xen_pcpu_init(void) > > return ret; > > } > > arch_initcall(xen_pcpu_init); > > + > > +bool __init xen_processor_present(uint32_t acpi_id) > > +{ > > + struct pcpu *pcpu; > > + bool online = false; > > + > > + mutex_lock(&xen_pcpu_lock); > > + list_for_each_entry(pcpu, &xen_pcpus, list) > > + if (pcpu->acpi_id == acpi_id) { > > + online = pcpu->flags & XEN_PCPU_FLAGS_ONLINE; > > + break; > > + } > > + > > + mutex_unlock(&xen_pcpu_lock); > > + > > + return online; > > +} > > Since it is neither natural nor obvious that this function takes an > ACPI ID as input (could in particular also be an APIC ID), would that > perhaps better be expressed in its name? I did wonder the same, but convinced myself that the parameter name being `acpi_id` was enough of a hint that the function takes an ACPI ID. Thanks, Roger.
On 16.03.2023 12:00, Roger Pau Monné wrote: > On Thu, Mar 16, 2023 at 11:45:47AM +0100, Jan Beulich wrote: >> On 16.03.2023 11:32, Roger Pau Monne wrote: >>> --- a/arch/x86/include/asm/xen/hypervisor.h >>> +++ b/arch/x86/include/asm/xen/hypervisor.h >>> @@ -63,4 +63,14 @@ void __init xen_pvh_init(struct boot_params *boot_params); >>> void __init mem_map_via_hcall(struct boot_params *boot_params_p); >>> #endif >>> >>> +#ifdef CONFIG_XEN_DOM0 >> >> Shouldn't you also check CONFIG_X86 here, seeing the condition for when >> pcpu.c would be built? > > It's in a x86 specific header, so that's enough I think? (note the > path of the header) Oh, of course I should have paid attention - I'm sorry. (Then again it's not really logical to live in an arch-dependent header, as the same would be needed elsewhere with ACPI.) >> Additionally CONFIG_ACPI may want checking, which >> - taken together - would amount to checking CONFIG_XEN_ACPI. (For which >> in turn I find odd that it will also be engaged when !DOM0.) > > Hm, is it worth making the acpi_id field in struct pcpu or helper > conditional to CONFIG_ACPI? It's just data fetched from Xen so it > doesn't depend on any of the ACPI functionality in Linux. > > IMO I don't think it's worth the extra ifdefs. I didn't mean to suggest #ifdef for the new struct field. But the helper is of no use without ACPI. Jan
diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/xen/hypervisor.h index 5fc35f889cd1..f14e39bce2cb 100644 --- a/arch/x86/include/asm/xen/hypervisor.h +++ b/arch/x86/include/asm/xen/hypervisor.h @@ -63,4 +63,14 @@ void __init xen_pvh_init(struct boot_params *boot_params); void __init mem_map_via_hcall(struct boot_params *boot_params_p); #endif +#ifdef CONFIG_XEN_DOM0 +bool __init xen_processor_present(uint32_t acpi_id); +#else +static inline bool xen_processor_present(uint32_t acpi_id) +{ + BUG(); + return false; +} +#endif + #endif /* _ASM_X86_XEN_HYPERVISOR_H */ diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 8c3f82c9fff3..18fb04523f93 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -14,6 +14,8 @@ #include <linux/acpi.h> #include <acpi/processor.h> +#include <xen/xen.h> + #include "internal.h" static bool __init processor_physically_present(acpi_handle handle) @@ -47,6 +49,15 @@ static bool __init processor_physically_present(acpi_handle handle) return false; } + if (xen_initial_domain()) + /* + * When running as a Xen dom0 the number of processors Linux + * sees can be different from the real number of processors on + * the system, and we still need to execute _PDC for all of + * them. + */ + return xen_processor_present(acpi_id); + type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0; cpuid = acpi_get_cpuid(handle, type, acpi_id); diff --git a/drivers/xen/pcpu.c b/drivers/xen/pcpu.c index fd3a644b0855..51df5f036419 100644 --- a/drivers/xen/pcpu.c +++ b/drivers/xen/pcpu.c @@ -58,6 +58,7 @@ struct pcpu { struct list_head list; struct device dev; uint32_t cpu_id; + uint32_t acpi_id; uint32_t flags; }; @@ -249,6 +250,7 @@ static struct pcpu *create_and_register_pcpu(struct xenpf_pcpuinfo *info) INIT_LIST_HEAD(&pcpu->list); pcpu->cpu_id = info->xen_cpuid; + pcpu->acpi_id = info->acpi_id; pcpu->flags = info->flags; /* Need hold on xen_pcpu_lock before pcpu list manipulations */ @@ -381,3 +383,20 @@ static int __init xen_pcpu_init(void) return ret; } arch_initcall(xen_pcpu_init); + +bool __init xen_processor_present(uint32_t acpi_id) +{ + struct pcpu *pcpu; + bool online = false; + + mutex_lock(&xen_pcpu_lock); + list_for_each_entry(pcpu, &xen_pcpus, list) + if (pcpu->acpi_id == acpi_id) { + online = pcpu->flags & XEN_PCPU_FLAGS_ONLINE; + break; + } + + mutex_unlock(&xen_pcpu_lock); + + return online; +}
In ACPI systems, the OS can direct power management, as opposed to the firmware. This OS-directed Power Management is called OSPM. Part of telling the firmware that the OS going to direct power management is making ACPI "_PDC" (Processor Driver Capabilities) calls. These _PDC methods must be evaluated for every processor object. If these _PDC calls are not completed for every processor it can lead to inconsistency and later failures in things like the CPU frequency driver. In a Xen system, the dom0 kernel is responsible for system-wide power management. The dom0 kernel is in charge of OSPM. However, the number of CPUs available to dom0 can be different than the number of CPUs physically present on the system. This leads to a problem: the dom0 kernel needs to evaluate _PDC for all the processors, but it can't always see them. In dom0 kernels, ignore the existing ACPI method for determining if a processor is physically present because it might not be accurate. Instead, ask the hypervisor for this information. Fix this by introducing a custom function to use when running as Xen dom0 in order to check whether a processor object matches a CPU that's online. Such checking is done using the existing information fetched by the Xen pCPU subsystem, extending it to also store the ACPI ID. This ensures that _PDC method gets evaluated for all physically online CPUs, regardless of the number of CPUs made available to dom0. Fixes: 5d554a7bb064 ('ACPI: processor: add internal processor_physically_present()') Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> --- Changes since v2: - Extend and use the existing pcpu functionality. Changes since v1: - Reword commit message. --- arch/x86/include/asm/xen/hypervisor.h | 10 ++++++++++ drivers/acpi/processor_pdc.c | 11 +++++++++++ drivers/xen/pcpu.c | 19 +++++++++++++++++++ 3 files changed, 40 insertions(+)