Skip to content

Commit

Permalink
x86/HPET: don't enable legacy replacement mode unconditionally
Browse files Browse the repository at this point in the history
Commit e1de4c1 ("x86/timer: Fix boot on Intel systems using ITSSPRC
static PIT clock gating") was reported to cause boot failures on certain
AMD Ryzen systems. Until we can figure out what the actual issue there
is, skip this new part of HPET setup by default. Introduce a "hpet"
command line option to allow enabling this on hardware where it's really
needed for Xen to boot successfully (i.e. where the PIT doesn't drive
the timer interrupt).

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@suse.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Ian Jackson <iwj@xenproject.org>
Release-Acked-by: Ian Jackson <iwj@xenproject.org>
(cherry picked from commit e680cc4)
  • Loading branch information
jbeulich authored and ijackson-citrix committed Mar 26, 2021
1 parent b712639 commit 7fa14f3
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 6 deletions.
17 changes: 17 additions & 0 deletions docs/misc/xen-command-line.pandoc
Original file line number Diff line number Diff line change
Expand Up @@ -1274,9 +1274,26 @@ 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 (x86)
> `= List of [ <boolean> | broadcast | legacy-replacement ]`

> Default : `true`, `no-broadcast`, 'no-legacy-replacement`

Controls Xen's use of the system's High Precision Event Timer. The boolean
allows to turn off use altogether.

`broadcast` forces Xen to keep using the broadcast for CPUs in deep C-states
even when an RTC interrupt got enabled.

`legacy-replacement` is intended to be used on platforms where the timer
interrupt doesn't get raised by the legacy PIT. This then also affects
raising of the RTC interrupt.

### hpetbroadcast (x86)
> `= <boolean>`

Deprecated alternative of `hpet=broadcast`.

### hvm_debug (x86)
> `= <integer>`

Expand Down
37 changes: 31 additions & 6 deletions xen/arch/x86/hpet.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
static bool __initdata opt_hpet = true;
static bool __initdata opt_legacy_replacement;
u8 __initdata hpet_blockid;
u8 __initdata hpet_flags;

Expand All @@ -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_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:
Expand Down Expand Up @@ -761,12 +789,9 @@ u64 __init hpet_setup(void)
unsigned int hpet_id, hpet_period, hpet_cfg;
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);
Expand Down Expand Up @@ -803,9 +828,9 @@ u64 __init hpet_setup(void)
* IRQ routing is configured.
*
* Reconfigure the HPET into legacy mode to re-establish the timer
* interrupt.
* interrupt, if available and if so requested.
*/
if ( hpet_id & HPET_ID_LEGSUP &&
if ( opt_legacy_replacement && (hpet_id & HPET_ID_LEGSUP) &&
!((hpet_cfg = hpet_read32(HPET_CFG)) & HPET_CFG_LEGACY) )
{
unsigned int c0_cfg, ticks, count;
Expand Down

0 comments on commit 7fa14f3

Please sign in to comment.