All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jan Beulich <jbeulich@suse.com>
To: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: "Roger Pau Monné" <roger.pau@citrix.com>, "Wei Liu" <wl@xen.org>,
	"Aaron Janse" <aaron@ajanse.me>,
	"Jason Andryuk" <jandryuk@gmail.com>,
	"Ondrej Balaz" <blami@blami.net>,
	"Tamas K Lengyel" <tamas@tklengyel.com>,
	"Marek Marczykowski-Górecki" <marmarek@invisiblethingslab.com>,
	Xen-devel <xen-devel@lists.xenproject.org>
Subject: Re: [PATCH] x86/timer: Fix boot on Intel systems using ITSSPRC static PIT clock gating
Date: Thu, 7 Jan 2021 14:53:11 +0100	[thread overview]
Message-ID: <6be85030-11aa-4143-b202-48a086bb5595@suse.com> (raw)
In-Reply-To: <20210107010625.5993-1-andrew.cooper3@citrix.com>

On 07.01.2021 02:06, Andrew Cooper wrote:
> Slightly RFC.  On older platforms this does generate some spurious PIC
> interrupts during boot, but they're benign.  I was hoping to have time to fix
> those too, but I'm getting an increasing number of requests to post this
> patch.

We still will want to try to suppress those by the release of 4.15,
and ideally even before we backport this one.

> @@ -793,6 +793,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 &&

Add parentheses here?

> +         !((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 cache
> +         * the "last write to cmp", as a hidden register.
> +         *
> +         * The semantics on generating a periodic interrupt is:
> +         *   cmp += "last value written to the cmp register"
> +         * which will reload a new period.
> +         *
> +         * Normally, writes to cmp update the main comparator as well as being
> +         * cached for the reload value.  However, under these semantics, the
> +         * HPET main counter needs resetting to 0 to be able to configure the
> +         * period correctly.
> +         *
> +         * Instead, HPET_TN_SETVAL is a self-clearing control bit which we can
> +         * use for periodic timers to mean that the second write to the
> +         * comparator updates only the "last written" cache, 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));

As you say, documentation is poor here. In fact the wording in the
HPET spec talks about updating of the "accumulator" instead;
perhaps just an unhelpful use of a different term. (Respective
Linux code has a comment indicating this is needed on a specific
AMD chipset only.)

It would seem more natural to me if things were explained a little
differently: Writes to the comparator with SETVAL clear always
update the "last written" value, i.e. the increment to be used
once the main counter equals the comparator. Writes with SETVAL set
update the comparator itself. (Assuming that's how it really is, of
course, but that's what I infer from the doc available.)

Linux additionally puts udelay(1) between the two writes. Do you
think we're fine without such, on all platforms?

> +        /* Restart the main counter, and legacy mode. */
> +        hpet_write32(hpet_cfg | HPET_CFG_ENABLE | HPET_CFG_LEGACY, HPET_CFG);

This isn't necessarily "restart" - you may start the counter for
the first time. Hence in the comment maybe "(Re)start ..."?

As to the spurious IRQs, does it perhaps matter at which point
CFG_LEGACY gets set? We could try setting it when clearing
CFG_ENABLE further up, or we could also try two separate writes
each setting just one of the bits. (At least I can't deduce
from the spec that we ought to be prepared to observe spurious
IRQs here.)

Jan


  reply	other threads:[~2021-01-07 13:53 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-07  1:06 [PATCH] x86/timer: Fix boot on Intel systems using ITSSPRC static PIT clock gating Andrew Cooper
2021-01-07 13:53 ` Jan Beulich [this message]
2021-01-26 17:31   ` Andrew Cooper
2021-01-27  9:28     ` Jan Beulich
2021-01-27 11:36       ` Andrew Cooper
2021-01-08 14:30 ` Jason Andryuk

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6be85030-11aa-4143-b202-48a086bb5595@suse.com \
    --to=jbeulich@suse.com \
    --cc=aaron@ajanse.me \
    --cc=andrew.cooper3@citrix.com \
    --cc=blami@blami.net \
    --cc=jandryuk@gmail.com \
    --cc=marmarek@invisiblethingslab.com \
    --cc=roger.pau@citrix.com \
    --cc=tamas@tklengyel.com \
    --cc=wl@xen.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.