Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backported patches for computers without legacy PIT #6

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions SOURCES/backport-83736c567d.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
From 83736c567d6b64dbce98f251ca72e7870f556421 Mon Sep 17 00:00:00 2001
From: Andrew Cooper <[email protected]>
Date: Tue, 29 Dec 2020 17:51:23 +0000
Subject: [PATCH] x86/hpet: Fix return value of hpet_setup()
MIME-Version: 1.0
Content-Type: text/plain; charset=utf8
Content-Transfer-Encoding: 8bit

hpet_setup() is idempotent if the rate has already been calculated, and
returns the cached value. However, this only works correctly when the return
statements are identical.

Use a sensibly named local variable, rather than a dead one with a bad name.

Fixes: a60bb68219 ("x86/time: reduce rounding errors in calculations")
Signed-off-by: Andrew Cooper <[email protected]>
Reviewed-by: Roger Pau Monné <[email protected]>
---
xen/arch/x86/hpet.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/xen/arch/x86/hpet.c b/xen/arch/x86/hpet.c
index a55e68e6f7..e6fab8acd8 100644
--- a/xen/arch/x86/hpet.c
+++ b/xen/arch/x86/hpet.c
@@ -743,7 +743,7 @@ u64 __init hpet_setup(void)
{
static u64 __initdata hpet_rate;
u32 hpet_id, hpet_period;
- unsigned int last;
+ unsigned int last, rem;

if ( hpet_rate )
return hpet_rate;
@@ -773,9 +773,11 @@ u64 __init hpet_setup(void)
hpet_resume(hpet_boot_cfg);

hpet_rate = 1000000000000000ULL; /* 10^15 */
- (void)do_div(hpet_rate, hpet_period);
+ rem = do_div(hpet_rate, hpet_period);
+ if ( (rem * 2) > hpet_period )
+ hpet_rate++;

return hpet_rate;
}

void hpet_resume(u32 *boot_cfg)
--
2.20.1

122 changes: 122 additions & 0 deletions SOURCES/backport-e1de4c196a2eb4fd5063c30a2e115adf144bdeef.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
From e1de4c196a2eb4fd5063c30a2e115adf144bdeef Mon Sep 17 00:00:00 2001
From: Andrew Cooper <[email protected]>
Date: Thu, 6 Aug 2020 13:00:07 +0100
Subject: [PATCH] x86/timer: Fix boot on Intel systems using ITSSPRC static PIT
clock gating

Recent Intel client devices have disabled the legacy PIT for powersaving
reasons, breaking compatibility with a traditional IBM PC. Xen depends on a
legacy timer interrupt to check that the IO-APIC/PIC routing is configured
correctly, and fails to boot with:

(XEN) *******************************
(XEN) Panic on CPU 0:
(XEN) IO-APIC + timer doesn't work! Boot with apic_verbosity=debug and send report. Then try booting with the `noapic` option
(XEN) *******************************

While this setting can be undone by Xen, the details of how to differ by
chipset, and would be very short sighted for battery based devices. See bit 2
"8254 Static Clock Gating Enable" in:

https://edc.intel.com/content/www/us/en/design/products-and-solutions/processors-and-chipsets/comet-lake-u/intel-400-series-chipset-on-package-platform-controller-hub-register-database/itss-power-reduction-control-itssprc-offset-3300/

All impacted systems have an HPET, but there is no indication of the absence
of PIT functionality, nor a suitable way to probe for its absence. As a short
term fix, reconfigure the HPET into legacy replacement mode. A better
longterm fix would be to avoid the reliance on the timer interrupt entirely.

Signed-off-by: Andrew Cooper <[email protected]>
Tested-by: Jason Andryuk <[email protected]>
Acked-by: Jan Beulich <[email protected]>
---
xen/arch/x86/hpet.c | 67 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 66 insertions(+), 1 deletion(-)

diff --git a/xen/arch/x86/hpet.c b/xen/arch/x86/hpet.c
index e6fab8acd8..1ff005fb4a 100644
--- a/xen/arch/x86/hpet.c
+++ b/xen/arch/x86/hpet.c
@@ -742,7 +742,7 @@ static u32 *hpet_boot_cfg;
u64 __init hpet_setup(void)
{
static u64 __initdata hpet_rate;
- u32 hpet_id, hpet_period;
+ unsigned int hpet_id, hpet_period, hpet_cfg;
unsigned int last, rem;

if ( hpet_rate )
@@ -777,6 +777,71 @@ 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.
+ */
+ if ( hpet_id & HPET_ID_LEGSUP &&
+ !((hpet_cfg = hpet_read32(HPET_CFG)) & HPET_CFG_LEGACY) )
+ {
+ unsigned int c0_cfg, ticks, count;
+
+ /* Stop the main counter. */
+ hpet_write32(hpet_cfg & ~HPET_CFG_ENABLE, HPET_CFG);
+
+ /* Reconfigure channel 0 to be 32bit periodic. */
+ c0_cfg = hpet_read32(HPET_Tn_CFG(0));
+ c0_cfg |= (HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL |
+ HPET_TN_32BIT);
+ hpet_write32(c0_cfg, HPET_Tn_CFG(0));
+
+ /*
+ * The exact period doesn't have to match a legacy PIT. All we need
+ * is an interrupt queued up via the IO-APIC to check routing.
+ *
+ * Use HZ as the frequency.
+ */
+ ticks = ((SECONDS(1) / HZ) * div_sc(hpet_rate, SECONDS(1), 32)) >> 32;
+
+ count = hpet_read32(HPET_COUNTER);
+
+ /*
+ * HPET_TN_SETVAL above is atrociously documented in the spec.
+ *
+ * Periodic HPET channels have a main comparator register, and
+ * separate "accumulator" register. Despite being named accumulator
+ * in the spec, this is not an accurate description of its behaviour
+ * or purpose.
+ *
+ * Each time an interrupt is generated, the "accumulator" register is
+ * re-added to the comparator set up the new period.
+ *
+ * Normally, writes to the CMP register update both registers.
+ * However, under these semantics, it is impossible to set up a
+ * periodic timer correctly without the main HPET counter being at 0.
+ *
+ * Instead, HPET_TN_SETVAL is a self-clearing control bit which we can
+ * use for periodic timers to mean that the second write to CMP
+ * updates the accumulator only, and not the absolute comparator
+ * value.
+ *
+ * This lets us set a period when the main counter isn't at 0.
+ */
+ hpet_write32(count + ticks, HPET_Tn_CMP(0));
+ hpet_write32(ticks, HPET_Tn_CMP(0));
+
+ /* Restart the main counter, and legacy mode. */
+ hpet_write32(hpet_cfg | HPET_CFG_ENABLE | HPET_CFG_LEGACY, HPET_CFG);
+ }
+
return hpet_rate;
}

--
2.20.1

2 changes: 2 additions & 0 deletions SPECS/xen.spec
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ Patch214: backport-758fae24d7b9.patch
Patch215: backport-e373bc1bdc59.patch
Patch216: backport-b7c333016e3d.patch
Patch217: xsa360.patch
Patch218: backport-83736c567d.patch
Patch219: backport-e1de4c196a2eb4fd5063c30a2e115adf144bdeef.patch

Provides: gitsha(https://code.citrite.net/rest/archive/latest/projects/XSU/repos/xen/archive?at=RELEASE-4.13.1&prefix=xen-4.13.1&format=tar.gz#/xen-4.13.1.tar.gz) = 6278553325a9f76d37811923221b21db3882e017
Provides: gitsha(ssh://[email protected]/xs/xen.pg.git) = 70d4b5941e4fa18d059d0f62cb3bbf5dab7a7946
Expand Down