[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH for-4.22 3/5] x86/vRTC: support century field


  • To: Jan Beulich <jbeulich@xxxxxxxx>
  • From: Roger Pau Monné <roger.pau@xxxxxxxxxx>
  • Date: Wed, 13 May 2026 17:14:51 +0200
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=citrix.com; dmarc=pass action=none header.from=citrix.com; dkim=pass header.d=citrix.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=JS6+p+Wyd2ELQaZoR3bXxMQfYe/VVjWierr1tPs2DB0=; b=ZyhC9iIHp3FnTa+3k65pfw2o/ZvFKueE1H+OZLNHFPPFgxNRFgHhjqk9+tPIaC0Q1csL597m2AxsUeULbXQWEgjrlRJ6NuVsKMyfcTZ8Tl7yVFYizSgyUB2x31nSFTU69L9FLM6pthwwl1wrxIqdSDy03xoJCWUCrV+ruQazvL0WguSM8O7OTo3E/8jNcE3NdUsgkpjbs9zmk/ATe4HPOBWE13qdp67nJJbMBrCcVLpX2+9VMBNW/7BGajv6LiQzH6Sr2EigrVLmjpDUAf0Mmej3FU6WoM2kX6bf9novDfR3LMDASjgEYMEqfsjq25Y6j1lwCGkt1cZUGNRnm+Kkiw==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=ZPF/NNeKZQ7NcuLroFraTqdt+nziH1u7brCJ94qGTtf2GeaOraeb6OOOr7AAqQjF7hVkjYikgTAJpqbUFiVYSmo3SI8cmXkyW8vEN8weB+1LiBapAgGAGYsmnjMMhmh/USUSnzlaYtBvPWTInlZkSDaC+rv7/jWrEsmnSoJ0NkByREwdaUESw85A7no1zmABB/6c8OBuLWLET3zY3FkG3KIOXli3ZR9jR6UN3kJUDptqSJRsWNq5x1EJNlVLLVv8G9SHcp5hFIzxeLM3ac1mgTviu30qRjUl5XN+FJczCEgxokDzT5ydCunt+aAjEklJRyjyLWLxEHBkWWTokqtp1Q==
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=citrix.com header.i="@citrix.com" header.h="From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck"
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=citrix.com;
  • Cc: "xen-devel@xxxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxxx>, Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Teddy Astie <teddy.astie@xxxxxxxxxx>, Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
  • Delivery-date: Wed, 13 May 2026 15:15:06 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

On Wed, May 13, 2026 at 04:58:57PM +0200, Jan Beulich wrote:
> On 13.05.2026 16:24, Roger Pau Monné wrote:
> > On Tue, May 12, 2026 at 04:59:35PM +0200, Jan Beulich wrote:
> >> Both ROMBIOS and SeaBIOS (with CONFIG_QEMU=y, as we build it) blindly
> >> assume availability of this field (at its conventional index 0x32); OVMF
> >> at least has code to inspect FADT. Hence we ought to have supported it
> >> virtually forever.
> >>
> >> As the index is beyond RTC_CMOS_SIZE, leverage the padding field in
> >> struct hvm_hw_rtc to hold its value. Update the field only when involved
> >> values are valid BCD century specifiers. Otherwise (for VMs migrated in
> >> from an older hypervisor) leave handling to the DM.
> >>
> >> This makes the Linux rtc-cmos driver report y3k compatibility.
> >>
> >> While extending xen-hvmctx.c:dump_rtc() also add RTC offset there.
> >>
> >> Fixes: 4ca161214355 ("[HVM] Move RTC emulation into the hypervisor")
> >> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
> >> ---
> >> Am I overly paranoid with the checking of the field, considering that
> >> Xen 3.x post-dates year 2000 and hence all firmware nowadays usable guests
> >> have ever run with should have been aware of the field? Or am I, quite the
> >> opposite, still not strict enough?
> >>
> >> I can't help the impression that this introduces a latency issue for
> >> the 2nd of gmtime()'s while() loops: We now allow years up into the 99th
> >> century, i.e. over 8000 years away from 1970. 8000 years are very roughly
> >> 2^^38 seconds, making for (again very roughly) 5 million iterations there.
> >> Did I get my math wrong, or do we need a prereq change to (vastly) reduce
> >> the number of iterations of that loop (e.g. along the lines of the other
> >> one, first going in 400 year steps)?
> > 
> > Hm, maybe we need to add some XTF testing for the RTC?  I'm slightly
> > worried how much time this could take, and since those calls are
> > serialized on the s->lock I wonder whether enough parallel accesses
> > from the guest could manage to trigger the watchdog?
> 
> I'm not really up to making an XTF test, I guess. However, as you look to
> share my concern, I'll add a prereq patch adjusting gmtime().
> 
> >> --- a/tools/libacpi/static_tables.c
> >> +++ b/tools/libacpi/static_tables.c
> >> @@ -33,6 +33,8 @@ struct acpi_20_facs Facs = {
> >>  #define ACPI_PM_TMR_BLK_BIT_WIDTH           0x20
> >>  #define ACPI_PM_TMR_BLK_BIT_OFFSET          0x00
> >>  
> >> +#define CMOS_CENTURY 0x32 /* Conventional index used also without ACPI */
> > 
> > IMO this define (together with the RTC_CENTURY one below) need to be
> > in a public header so it can be consumed by both the hypervisor and
> > the toolstack.  Having two separate defines, one for the hypervisor,
> > and another for the toolstack will just create confusion.
> 
> I first thought I'd do it like this, but (a) this isn't a value Xen
> defines (hence the comments in both places) and (b) I'm not entirely
> happy with such a(n) (ab)use of the public headers (yes, we have other
> such examples there, which I also don't really like).

Yeah, it's not great, but it's better than having the same value
defined in two different files, and having to keep them in-sync for
the CMOS century field to work correctly?

> >> --- a/xen/arch/x86/hvm/rtc.c
> >> +++ b/xen/arch/x86/hvm/rtc.c
> >> @@ -47,6 +47,12 @@
> >>  #define epoch_year     1900
> >>  #define get_year(x)    ((x) + epoch_year)
> >>  
> >> +static inline bool is_century(unsigned int x)
> >> +{
> >> +    /* Constant below should match epoch_year above, just as BCD value. */
> >> +    return x >= 0x19 && (x & 0xf) < 10 && (x >> 4) < 10;
> >> +}
> >> +
> >>  enum rtc_mode {
> >>     rtc_mode_no_ack,
> >>     rtc_mode_strict
> >> @@ -482,16 +488,32 @@ static int rtc_ioport_write(void *opaque
> >>          data &= 0x7f;
> >>          s->hw.cmos_index = data;
> >>          spin_unlock(&s->lock);
> >> +        /* RTC_CENTURY always forwarded to DM. */
> >>          return (data < RTC_CMOS_SIZE);
> >>      }
> >>  
> >> -    if ( s->hw.cmos_index >= RTC_CMOS_SIZE )
> >> +    switch ( s->hw.cmos_index )
> >>      {
> >> +    case 0 ... RTC_CMOS_SIZE - 1:
> >> +        orig = s->hw.cmos_data[s->hw.cmos_index];
> >> +        break;
> >> +
> >> +    case RTC_CENTURY:
> >> +        orig = s->hw.century;
> >> +        if ( !is_century(orig) || !is_century(data) )
> > 
> > Is a real RTC strict in such a way, ie: will it refuse to set the
> > century value to < 19 (0x19)?  For example QEMU seems to be way more
> > relaxed, and allow any century value.
> 
> I can switch to rejecting merely 0. Unlike centuries in the future, it
> didn't look very useful to me to permit anything below 19. Please clarify
> which way you prefer it.

QEMU seems to tolerate everything, so I lean towards tolerating
everything that's not 0.  That's solely based on what QEMU does, which
I think it's likely to be (quite) widely tested.

> >> @@ -515,7 +538,10 @@ static int rtc_ioport_write(void *opaque
> >>              /* Fetch the current time and update just this field. */
> >>              s->current_tm = gmtime(get_localtime(d));
> >>              rtc_copy_date(s);
> >> -            s->hw.cmos_data[s->hw.cmos_index] = data;
> >> +            if ( s->hw.cmos_index != RTC_CENTURY )
> >> +                s->hw.cmos_data[s->hw.cmos_index] = data;
> >> +            else
> >> +                s->hw.century = data;
> >>              rtc_set_time(s);
> >>          }
> >>          alarm_timer_update(s);
> > 
> > Don't you need to adjust the tail return of rtc_ioport_write() (below
> > the context here) to return 0 when s->hw.cmos_index == RTC_CENTURY, so
> > the set value is also propagated to the DM, and not only the index?
> 
> I don't think so. The case of us not handling RTC_CENTURY is dealt with
> earlier in the function. Whereas when we handle the field, we don't want
> to forward (like for all the other RTC fields).

Right, so then you also want to adjust the top part of
rtc_ioport_write() to not propagate the write to the 0x70 IO port when
data is RTC_CENTURY?  Otherwise you propagate the write to port 0x70,
but not the read/write to port 0x71?

Thanks, Roger.



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.