|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v2 2/3] x86/hpet: Don't enable legacy replacement mode unconditionally
On Fri, Mar 26, 2021 at 06:59:46PM +0000, Andrew Cooper wrote:
> From: Jan Beulich <jbeulich@xxxxxxxx>
>
> Commit e1de4c196a2e ("x86/timer: Fix boot on Intel systems using ITSSPRC
> static PIT clock gating") was reported to cause boot failures on certain
> AMD Ryzen systems.
>
> Refine the fix to do nothing in the default case, and only attempt to
> configure legacy replacement mode if IRQ0 is found to not be working.
>
> In addition, introduce a "hpet" command line option so this heuristic
> can be overridden. Since it makes little sense to introduce just
> "hpet=legacy-replacement", also allow for a boolean argument as well as
> "broadcast" to replace the separate "hpetbroadcast" option.
>
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
> Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Reviewed-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
> ---
> CC: Jan Beulich <JBeulich@xxxxxxxx>
> CC: Roger Pau Monné <roger.pau@xxxxxxxxxx>
> CC: Wei Liu <wl@xxxxxxx>
> CC: Ian Jackson <iwj@xxxxxxxxxxxxxx>
> CC: Marek Marczykowski-Górecki <marmarek@xxxxxxxxxxxxxxxxxxxxxx>
> CC: Frédéric Pierret <frederic.pierret@xxxxxxxxxxxx>
>
> v2:
> * Reinstate missing hunk from Jan's original patch.
> * Fix up "8254 PIT".
> * Drop "goto retry".
>
> For 4.15: Attempt to unbreak AMD Ryzen 1800X systems.
> ---
> docs/misc/xen-command-line.pandoc | 33 +++++++++++++++++++++++++++
> xen/arch/x86/hpet.c | 48
> +++++++++++++++++++++++++--------------
> xen/arch/x86/io_apic.c | 27 ++++++++++++++++++++++
> xen/include/asm-x86/hpet.h | 1 +
> 4 files changed, 92 insertions(+), 17 deletions(-)
>
> diff --git a/docs/misc/xen-command-line.pandoc
> b/docs/misc/xen-command-line.pandoc
> index a0601ff838..a4bd3f12c5 100644
> --- a/docs/misc/xen-command-line.pandoc
> +++ b/docs/misc/xen-command-line.pandoc
> @@ -1274,9 +1274,42 @@ supported. See docs/misc/arm/big.LITTLE.txt for more
> information.
> When the hmp-unsafe option is disabled (default), CPUs that are not
> identical to the boot CPU will be parked and not used by Xen.
>
> +### hpet
> + = List of [ <bool> | broadcast=<bool> | legacy-replacement=<bool> ]
> +
> + Applicability: x86
> +
> +Controls Xen's use of the system's High Precision Event Timer. By default,
> +Xen will use an HPET when available and not subject to errata. Use of the
> +HPET can be disabled by specifying `hpet=0`.
> +
> + * The `broadcast` boolean is disabled by default, but forces Xen to keep
> + using the broadcast for CPUs in deep C-states even when an RTC interrupt
> is
> + enabled. This then also affects raising of the RTC interrupt.
> +
> + * The `legacy-replacement` boolean allows for control over whether Legacy
> + Replacement mode is enabled.
> +
> + Legacy Replacement mode is intended for hardware which does not have an
> + 8254 PIT, and allows the HPET to be configured into a compatible mode.
> + Intel chipsets from Skylake/ApolloLake onwards can turn the PIT off for
> + power saving reasons, and there is no platform-agnostic mechanism for
> + discovering this.
> +
> + By default, Xen will not change hardware configuration, unless the PIT
> + appears to be absent, at which point Xen will try to enable Legacy
> + Replacement mode before falling back to pre-IO-APIC interrupt routing
> + options.
> +
> + This behaviour can be inhibited by specifying `legacy-replacement=0`.
> + Alternatively, this mode can be enabled unconditionally (if available) by
> + specifying `legacy-replacement=1`.
> +
> ### hpetbroadcast (x86)
> > `= <boolean>`
>
> +Deprecated alternative of `hpet=broadcast`.
> +
> ### hvm_debug (x86)
> > `= <integer>`
>
> diff --git a/xen/arch/x86/hpet.c b/xen/arch/x86/hpet.c
> index c1d04f184f..bfa75f135a 100644
> --- a/xen/arch/x86/hpet.c
> +++ b/xen/arch/x86/hpet.c
> @@ -52,6 +52,8 @@ static unsigned int __read_mostly num_hpets_used;
> DEFINE_PER_CPU(struct hpet_event_channel *, cpu_bc_channel);
>
> unsigned long __initdata hpet_address;
> +int8_t __initdata opt_hpet_legacy_replacement = -1;
> +static bool __initdata opt_hpet = true;
> u8 __initdata hpet_blockid;
> u8 __initdata hpet_flags;
>
> @@ -63,6 +65,32 @@ u8 __initdata hpet_flags;
> static bool __initdata force_hpet_broadcast;
> boolean_param("hpetbroadcast", force_hpet_broadcast);
>
> +static int __init parse_hpet_param(const char *s)
> +{
> + const char *ss;
> + int val, rc = 0;
> +
> + do {
> + ss = strchr(s, ',');
> + if ( !ss )
> + ss = strchr(s, '\0');
> +
> + if ( (val = parse_bool(s, ss)) >= 0 )
> + opt_hpet = val;
> + else if ( (val = parse_boolean("broadcast", s, ss)) >= 0 )
> + force_hpet_broadcast = val;
> + else if ( (val = parse_boolean("legacy-replacement", s, ss)) >= 0 )
> + opt_hpet_legacy_replacement = val;
> + else
> + rc = -EINVAL;
> +
> + s = ss + 1;
> + } while ( *ss );
> +
> + return rc;
> +}
> +custom_param("hpet", parse_hpet_param);
> +
> /*
> * Calculate a multiplication factor for scaled math, which is used to
> convert
> * nanoseconds based values to clock ticks:
> @@ -820,12 +848,9 @@ u64 __init hpet_setup(void)
> unsigned int hpet_id, hpet_period;
> unsigned int last, rem;
>
> - if ( hpet_rate )
> + if ( hpet_rate || !hpet_address || !opt_hpet )
> return hpet_rate;
>
> - if ( hpet_address == 0 )
> - return 0;
> -
> set_fixmap_nocache(FIX_HPET_BASE, hpet_address);
>
> hpet_id = hpet_read32(HPET_ID);
> @@ -852,19 +877,8 @@ u64 __init hpet_setup(void)
> if ( (rem * 2) > hpet_period )
> hpet_rate++;
>
> - /*
> - * Intel chipsets from Skylake/ApolloLake onwards can statically clock
> - * gate the 8259 PIT. This option is enabled by default in slightly
> later
> - * systems, as turning the PIT off is a prerequisite to entering the C11
> - * power saving state.
> - *
> - * Xen currently depends on the legacy timer interrupt being active while
> - * IRQ routing is configured.
> - *
> - * Reconfigure the HPET into legacy mode to re-establish the timer
> - * interrupt.
> - */
> - hpet_enable_legacy_replacement_mode();
> + if ( opt_hpet_legacy_replacement > 0 )
> + hpet_enable_legacy_replacement_mode();
>
> return hpet_rate;
> }
> diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c
> index e93265f379..3f131a81fb 100644
> --- a/xen/arch/x86/io_apic.c
> +++ b/xen/arch/x86/io_apic.c
> @@ -29,6 +29,8 @@
> #include <xen/acpi.h>
> #include <xen/keyhandler.h>
> #include <xen/softirq.h>
> +
> +#include <asm/hpet.h>
> #include <asm/mc146818rtc.h>
> #include <asm/smp.h>
> #include <asm/desc.h>
> @@ -1930,6 +1932,31 @@ static void __init check_timer(void)
> local_irq_restore(flags);
> return;
> }
> +
> + /*
> + * Intel chipsets from Skylake/ApolloLake onwards can statically
> clock
> + * gate the 8254 PIT. This option is enabled by default in slightly
> + * later systems, as turning the PIT off is a prerequisite to
> entering
> + * the C11 power saving state.
> + *
> + * Xen currently depends on the legacy timer interrupt being active
> + * while IRQ routing is configured.
> + *
> + * If the user hasn't made an explicit choice, attempt to reconfigure
> + * the HPET into legacy mode to re-establish the timer interrupt.
> + */
> + if ( opt_hpet_legacy_replacement < 0 &&
> + hpet_enable_legacy_replacement_mode() )
> + {
> + printk(XENLOG_ERR "..no 8254 timer found - trying HPET Legacy
> Replacement Mode\n");
> +
> + if ( timer_irq_works() )
> + {
> + local_irq_restore(flags);
Is there any point in undoing the legacy replacement here, as I
understand it it's only required for the routing check?
Should we also prevent any attempts from using the PIT as a
timecounter in x86/time.c as a result of having the HPET in legacy
replacement mode?
AFAICT init_pit will already assert whether the PIT counters work, so
maybe there's no need for adding an extra check on whether legacy
replacement is enabled.
Thanks, Roger.
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |