qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Philippe Mathieu-Daudé" <philmd@redhat.com>
To: Niek Linnenbank <nieklinnenbank@gmail.com>
Cc: Peter Maydell <peter.maydell@linaro.org>,
	qemu-arm <qemu-arm@nongnu.org>,
	QEMU Developers <qemu-devel@nongnu.org>,
	Laurent Vivier <laurent@vivier.eu>
Subject: Re: [PATCH v3 12/17] hw/arm/allwinner: add RTC device support
Date: Sat, 18 Jan 2020 16:05:29 +0100	[thread overview]
Message-ID: <128940fd-eda9-8151-eb4f-4d29c2c1d72a@redhat.com> (raw)
In-Reply-To: <CAPan3WrkQVb7VhJRYZET_BjEWEOYow-28ft2+4=G-9SNUDm6WA@mail.gmail.com>

Hi Niek,

On 1/14/20 11:57 PM, Niek Linnenbank wrote:
> On Tue, Jan 14, 2020 at 11:52 PM Niek Linnenbank 
> <nieklinnenbank@gmail.com <mailto:nieklinnenbank@gmail.com>> wrote:
> 
>     Hi Philippe,
> 
>     On Mon, Jan 13, 2020 at 11:57 PM Philippe Mathieu-Daudé
>     <philmd@redhat.com <mailto:philmd@redhat.com>> wrote:
> 
>         On 1/8/20 9:00 PM, Niek Linnenbank wrote:
>          > Allwinner System-on-Chips usually contain a Real Time Clock (RTC)
>          > for non-volatile system date and time keeping. This commit
>         adds a generic
>          > Allwinner RTC device that supports the RTC devices found in
>         Allwinner SoC
>          > family sun4i (A10), sun7i (A20) and sun6i and newer (A31,
>         H2+, H3, etc).
[...]
>          > +static uint64_t allwinner_rtc_read(void *opaque, hwaddr offset,
>          > +                                   unsigned size)
>          > +{
>          > +    AwRtcState *s = AW_RTC(opaque);
>          > +    const AwRtcClass *c = AW_RTC_GET_CLASS(s);
>          > +    uint64_t val = 0;
>          > +
>          > +    if (offset >= AW_RTC_REGS_MAXADDR) {
>          > +        qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds
>         offset 0x%04x\n",
>          > +                      __func__, (uint32_t)offset);
>          > +        return 0;
>          > +    }
>          > +
>          > +    if (!c->regmap[offset]) {
>          > +            qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid
>         register 0x%04x\n",
>          > +                          __func__, (uint32_t)offset);
>          > +        return 0;
>          > +    }
>          > +
>          > +    switch (c->regmap[offset]) {
>          > +    case REG_LOSC:       /* Low Oscillator Control */
>          > +        val = s->regs[REG_LOSC];
>          > +        s->regs[REG_LOSC] &= ~(REG_LOSC_YMD | REG_LOSC_HMS);
>          > +        break;
>          > +    case REG_YYMMDD:     /* RTC Year-Month-Day */
>          > +    case REG_HHMMSS:     /* RTC Hour-Minute-Second */
>          > +    case REG_GP0:        /* General Purpose Register 0 */
>          > +    case REG_GP1:        /* General Purpose Register 1 */
>          > +    case REG_GP2:        /* General Purpose Register 2 */
>          > +    case REG_GP3:        /* General Purpose Register 3 */
>          > +        val = s->regs[c->regmap[offset]];
>          > +        break;
>          > +    default:
>          > +        if (!c->read(s, offset)) {
>          > +            qemu_log_mask(LOG_UNIMP, "%s: unimplemented
>         register 0x%04x\n",
>          > +                          __func__, (uint32_t)offset);
>          > +        }
>          > +        val = s->regs[c->regmap[offset]];
>          > +        break;
>          > +    }
>          > +
>          > +    trace_allwinner_rtc_read(offset, val);
>          > +    return val;
>          > +}
>          > +
>          > +static void allwinner_rtc_write(void *opaque, hwaddr offset,
>          > +                                uint64_t val, unsigned size)
>          > +{
>          > +    AwRtcState *s = AW_RTC(opaque);
>          > +    const AwRtcClass *c = AW_RTC_GET_CLASS(s);
>          > +
>          > +    if (offset >= AW_RTC_REGS_MAXADDR) {
>          > +        qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds
>         offset 0x%04x\n",
>          > +                      __func__, (uint32_t)offset);
>          > +        return;
>          > +    }
>          > +
>          > +    if (!c->regmap[offset]) {
>          > +            qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid
>         register 0x%04x\n",
>          > +                          __func__, (uint32_t)offset);
>          > +        return;
>          > +    }
>          > +
>          > +    trace_allwinner_rtc_write(offset, val);
>          > +
>          > +    switch (c->regmap[offset]) {
>          > +    case REG_YYMMDD:     /* RTC Year-Month-Day */
>          > +        s->regs[REG_YYMMDD] = val;
>          > +        s->regs[REG_LOSC]  |= REG_LOSC_YMD;
>          > +        break;
>          > +    case REG_HHMMSS:     /* RTC Hour-Minute-Second */
>          > +        s->regs[REG_HHMMSS] = val;
>          > +        s->regs[REG_LOSC]  |= REG_LOSC_HMS;
>          > +        break;
>          > +    case REG_GP0:        /* General Purpose Register 0 */
>          > +    case REG_GP1:        /* General Purpose Register 1 */
>          > +    case REG_GP2:        /* General Purpose Register 2 */
>          > +    case REG_GP3:        /* General Purpose Register 3 */
>          > +        s->regs[c->regmap[offset]] = val;
>          > +        break;
>          > +    default:
>          > +        if (!c->write(s, offset, val)) {
>          > +            qemu_log_mask(LOG_UNIMP, "%s: unimplemented
>         register 0x%04x\n",
>          > +                          __func__, (uint32_t)offset);
>          > +        }
>          > +        break;
>          > +    }
>          > +}
>          > +
>          > +static const MemoryRegionOps allwinner_rtc_ops = {
>          > +    .read = allwinner_rtc_read,
>          > +    .write = allwinner_rtc_write,
>          > +    .endianness = DEVICE_NATIVE_ENDIAN,
>          > +    .valid = {
>          > +        .min_access_size = 4,
>          > +        .max_access_size = 4,
>          > +    },
>          > +    .impl.min_access_size = 4,
>          > +};
>          > +
>          > +static void allwinner_rtc_reset(DeviceState *dev)
>          > +{
>          > +    AwRtcState *s = AW_RTC(dev);
>          > +    const AwRtcClass *c = AW_RTC_GET_CLASS(dev);
>          > +    struct tm now;
>          > +
>          > +    /* Clear registers */
>          > +    memset(s->regs, 0, sizeof(s->regs));
>          > +
>          > +    /* Get current datetime */
>          > +    qemu_get_timedate(&now, 0);
>          > +
>          > +    /* Set RTC with current datetime */
>          > +    s->regs[REG_YYMMDD] =  ((now.tm_year - c->year_offset)
>         << 16) |
>          > +                           ((now.tm_mon + 1) << 8) |
>          > +                             now.tm_mday;
>          > +    s->regs[REG_HHMMSS] = (((now.tm_wday + 6) % 7) << 29) |
>          > +                              (now.tm_hour << 16) |
>          > +                              (now.tm_min << 8) |
>          > +                               now.tm_sec;
> 
>         This doesn't look correct.
> 
>           From H3 Datasheet (Rev1.2):
>             4.8.3.4. RTC YY-MM-DD Register (Default Value: 0x00000000)
>             4.8.3.5. RTC HH-MM-SS Register (Default Value: 0x00000000)
> 
> 
>     I don't yet fully understand what you mean. Could you please explain
>     a bit more what should be changed?

I was thinking about:

- Start a VM on Monday at 12:34

- Pause the VM on Tuesday at 12:34
   rtc_time=Tuesday,12:34

- [Eventually savevm/migrate/loadvm]
   rtc_time=Tuesday,12:34

- Resume the VM on Wednesday 12:34
   (time should be Tuesday at 12:34)
   so rtc_time=Tuesday,12:34

- Check time on Thursday at 12:33
   (time should be Wednesday at 12:33)
   rtc_time=Wednesday,12:34

- Reset the VM on Thursday at 12:34
   (time was Wednesday at 12:34)

- Check time on Thursday at 12:35
   (time should be Wednesday at 12:35)

However due to reset() calling qemu_get_timedate(), the rtc_time will be 
Thursday at 12:35 instead of Wednesday.

I don't know how the hardware keep these 2*32-bit safe when powered off.

Laurent Vivier posted a patch where he uses a block backend for his 
machine NVRAM (used by RTC). This seems to me the clever way to do this:
https://www.mail-archive.com/qemu-devel@nongnu.org/msg666837.html

I'd use a block of 8 bytes for your RTC.
If we start a machine without rtc block backend, the 2*32-bit are 
initialized as zero as the datasheet. If we provide a block, the machine 
will power-on from that stored time.

You might want to look at the global -rtc command line option:

   -rtc
   [base=utc|localtime|datetime][,clock=host|rt|vm][,driftfix=none|slew]
         Specify base as "utc" or "localtime" to let the RTC start
         at the current UTC or local time, respectively. "localtime"
         is required for correct date in MS-DOS or Windows. To start
         at a specific point in time, provide datetime in the format
         "2006-06-17T16:01:21" or "2006-06-17". The default base is
         UTC.

But it might be specific to the MC146818 RTC.

>     For filling the YYMMDD and HHMMSS register fields, I simply looked
>     at the 4.8.3.4 and 4.8.3.5 sections
>     and filled it with the time retrieved from qemu_get_timedate. The
>     shifts are done so the values are set in the proper bits.
>     If I read it with the hwclock -r command under Linux, this reads out OK.
>     On NetBSD, this works as well, except for the base year mismatch
>     which I explained above.
> 
> 
>         I'm not sure what is the proper to model this, maybe set this
>         value in
>         init()? If we suspend a machine, migrate it, and resume it, what
>         RTC are
>         we expecting?
> 
> I forgot to reply on this one.
> 
> I have not used migration very often, but I did manage to test it a 
> couple of times
> using the 'migrate' command on the Qemu monitor console before I 
> submitted each
> new version of the patch series. My expectation would be that the RTC 
> time is suspended
> along with all the other state of the machine such as memory, I/O 
> devices etc. So that would mean
> the time is 'frozen' until resumed. I think that is what we currently 
> have here.
> 
> Do you think that is correct or should it work differently?

Yes, this is the behavior I'd expect. Maybe other would disagree.



  reply	other threads:[~2020-01-18 15:06 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-08 20:00 [PATCH v3 00/17] Add Allwinner H3 SoC and Orange Pi PC Machine Niek Linnenbank
2020-01-08 20:00 ` [PATCH v3 01/17] hw/arm: add Allwinner H3 System-on-Chip Niek Linnenbank
2020-01-08 23:13   ` Philippe Mathieu-Daudé
2020-01-11 20:45     ` Niek Linnenbank
2020-01-08 20:00 ` [PATCH v3 02/17] hw/arm: add Xunlong Orange Pi PC machine Niek Linnenbank
2020-01-08 22:44   ` Philippe Mathieu-Daudé
2020-01-10 21:20     ` Niek Linnenbank
2020-01-08 20:00 ` [PATCH v3 03/17] hw/arm/allwinner-h3: add Clock Control Unit Niek Linnenbank
2020-01-13 19:18   ` Niek Linnenbank
2020-01-18 15:37     ` Philippe Mathieu-Daudé
2020-01-18 23:28       ` Niek Linnenbank
2020-01-08 20:00 ` [PATCH v3 04/17] hw/arm/allwinner-h3: add USB host controller Niek Linnenbank
2020-01-08 20:00 ` [PATCH v3 05/17] hw/arm/allwinner-h3: add System Control module Niek Linnenbank
2020-01-08 20:00 ` [PATCH v3 06/17] hw/arm/allwinner: add CPU Configuration module Niek Linnenbank
2020-01-13 23:14   ` Philippe Mathieu-Daudé
2020-01-14 23:04     ` Niek Linnenbank
2020-01-18  9:06       ` Philippe Mathieu-Daudé
2020-01-18 22:17         ` Niek Linnenbank
2020-01-08 20:00 ` [PATCH v3 07/17] hw/arm/allwinner: add Security Identifier device Niek Linnenbank
2020-01-18 15:25   ` Philippe Mathieu-Daudé
2020-01-20 17:59     ` Corey Minyard
2020-02-02 21:27       ` Niek Linnenbank
2020-02-03 13:10         ` Corey Minyard
2020-02-06 21:09           ` Niek Linnenbank
2020-02-12 21:31             ` Niek Linnenbank
2020-02-12 22:47               ` Philippe Mathieu-Daudé
2020-02-17 19:34                 ` Niek Linnenbank
2020-01-08 20:00 ` [PATCH v3 08/17] hw/arm/allwinner: add SD/MMC host controller Niek Linnenbank
2020-01-18 15:39   ` Philippe Mathieu-Daudé
2020-01-08 20:00 ` [PATCH v3 09/17] hw/arm/allwinner-h3: add EMAC ethernet device Niek Linnenbank
2020-01-18 15:17   ` Philippe Mathieu-Daudé
2020-01-08 20:00 ` [PATCH v3 10/17] hw/arm/allwinner-h3: add Boot ROM support Niek Linnenbank
2020-01-13 23:28   ` Philippe Mathieu-Daudé
2020-01-14 23:10     ` Niek Linnenbank
2020-01-18  9:09       ` Philippe Mathieu-Daudé
2020-01-18 22:28         ` Niek Linnenbank
2020-01-08 20:00 ` [PATCH v3 11/17] hw/arm/allwinner-h3: add SDRAM controller device Niek Linnenbank
2020-01-18 15:22   ` Philippe Mathieu-Daudé
2020-01-08 20:00 ` [PATCH v3 12/17] hw/arm/allwinner: add RTC device support Niek Linnenbank
2020-01-13 22:57   ` Philippe Mathieu-Daudé
2020-01-14 22:52     ` Niek Linnenbank
2020-01-14 22:57       ` Niek Linnenbank
2020-01-18 15:05         ` Philippe Mathieu-Daudé [this message]
2020-01-18 22:52           ` Niek Linnenbank
2020-01-08 20:00 ` [PATCH v3 13/17] tests/boot_linux_console: Add a quick test for the OrangePi PC board Niek Linnenbank
2020-01-18 11:22   ` Philippe Mathieu-Daudé
2020-01-18 23:04     ` Niek Linnenbank
2020-01-08 20:00 ` [PATCH v3 14/17] tests/boot_linux_console: Add initrd test for the Orange Pi " Niek Linnenbank
2020-01-08 20:00 ` [PATCH v3 15/17] tests/boot_linux_console: Add a SD card test for the OrangePi " Niek Linnenbank
2020-01-08 20:00 ` [PATCH v3 16/17] tests/boot_linux_console: Add a SLOW test booting Ubuntu on OrangePi PC Niek Linnenbank
2020-01-08 20:00 ` [PATCH v3 17/17] docs: add Orange Pi PC document Niek Linnenbank
2020-01-18  9:37   ` Philippe Mathieu-Daudé
2020-01-18 22:38     ` Niek Linnenbank

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=128940fd-eda9-8151-eb4f-4d29c2c1d72a@redhat.com \
    --to=philmd@redhat.com \
    --cc=laurent@vivier.eu \
    --cc=nieklinnenbank@gmail.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).