@@ -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 (x86)
+ = 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
+ 8025 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>`
@@ -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:
@@ -852,19 +880,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;
}
@@ -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>
@@ -1922,14 +1924,38 @@ static void __init check_timer(void)
vector, apic1, pin1, apic2, pin2);
if (pin1 != -1) {
+ bool hpet_changed = false;
+
/*
* Ok, does IRQ0 through the IOAPIC work?
*/
unmask_IO_APIC_irq(irq_to_desc(0));
+ retry_ioapic_pin:
if (timer_irq_works()) {
local_irq_restore(flags);
return;
}
+
+ /*
+ * 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.
+ *
+ * If the user hasn't made an explicit option, attempt to reconfigure
+ * the HPET into legacy mode to re-establish the timer interrupt.
+ */
+ if ( opt_hpet_legacy_replacement < 0 &&
+ !hpet_changed && hpet_enable_legacy_replacement_mode() )
+ {
+ printk(XENLOG_ERR "..no 8254 timer found - trying HPET Legacy Replacement Mode\n");
+ hpet_changed = true;
+ goto retry_ioapic_pin;
+ }
+
clear_IO_APIC_pin(apic1, pin1);
printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to "
"IO-APIC\n");
@@ -53,6 +53,7 @@
extern unsigned long hpet_address;
extern u8 hpet_blockid;
extern u8 hpet_flags;
+extern int8_t opt_hpet_legacy_replacement;
/*
* Detect and initialise HPET hardware: return counter update frequency.