From ee4336f9470b74f4dd3493d1fdbd61ff13005f9d Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 26 Apr 2024 13:29:11 +0100 Subject: hw/arm/sbsa-ref: Force CPU generic timer to 62.5MHz MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently QEMU CPUs always run with a generic timer counter frequency of 62.5MHz, but ARMv8.6 CPUs will run at 1GHz. For older versions of the TF-A firmware that sbsa-ref runs, the frequency of the generic timer is hardcoded into the firmware, and so if the CPU actually has a different frequency then timers in the guest will be set incorrectly. The default frequency used by the 'max' CPU is about to change, so make the sbsa-ref board force the CPU frequency to the value which the firmware expects. Newer versions of TF-A will read the frequency from the CPU's CNTFRQ_EL0 register: https://github.com/ARM-software/arm-trusted-firmware/commit/4c77fac98dac0bebc63798aae9101ac865b87148 so in the longer term we could make this board use the 1GHz frequency. We will need to make sure we update the binaries used by our avocado test Aarch64SbsarefMachine.test_sbsaref_alpine_linux_max_pauth_impdef before we can do that. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Marcin Juszkiewicz Message-id: 20240426122913.3427983-3-peter.maydell@linaro.org --- hw/arm/sbsa-ref.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'hw/arm/sbsa-ref.c') diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c index f5709d6c14..36f6f717b4 100644 --- a/hw/arm/sbsa-ref.c +++ b/hw/arm/sbsa-ref.c @@ -60,6 +60,19 @@ #define NUM_SMMU_IRQS 4 #define NUM_SATA_PORTS 6 +/* + * Generic timer frequency in Hz (which drives both the CPU generic timers + * and the SBSA watchdog-timer). Older versions of the TF-A firmware + * typically used with sbsa-ref (including the binaries in our Avocado test + * Aarch64SbsarefMachine.test_sbsaref_alpine_linux_max_pauth_impdef + * assume it is this value. + * + * TODO: this value is not architecturally correct for an Armv8.6 or + * better CPU, so we should move to 1GHz once the TF-A fix above has + * made it into a release and into our Avocado test. + */ +#define SBSA_GTIMER_HZ 62500000 + enum { SBSA_FLASH, SBSA_MEM, @@ -767,6 +780,8 @@ static void sbsa_ref_init(MachineState *machine) &error_abort); } + object_property_set_int(cpuobj, "cntfrq", SBSA_GTIMER_HZ, &error_abort); + object_property_set_link(cpuobj, "memory", OBJECT(sysmem), &error_abort); -- cgit 1.4.1 From 88c756bc9e5d38b6e46e631b9875ae954a319ed9 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 26 Apr 2024 13:29:12 +0100 Subject: hw/watchdog/sbsa_gwdt: Make watchdog timer frequency a QOM property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the sbsa_gdwt watchdog device hardcodes its frequency at 62.5MHz. In real hardware, this watchdog is supposed to be driven from the system counter, which also drives the CPU generic timers. Newer CPU types (in particular from Armv8.6) should have a CPU generic timer frequency of 1GHz, so we can't leave the watchdog on the old QEMU default of 62.5GHz. Make the frequency a QOM property so it can be set by the board, and have our only board that uses this device set that frequency to the same value it sets the CPU frequency. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Message-id: 20240426122913.3427983-4-peter.maydell@linaro.org --- hw/arm/sbsa-ref.c | 1 + hw/watchdog/sbsa_gwdt.c | 15 ++++++++++++++- include/hw/watchdog/sbsa_gwdt.h | 3 +-- 3 files changed, 16 insertions(+), 3 deletions(-) (limited to 'hw/arm/sbsa-ref.c') diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c index 36f6f717b4..57c337fd92 100644 --- a/hw/arm/sbsa-ref.c +++ b/hw/arm/sbsa-ref.c @@ -543,6 +543,7 @@ static void create_wdt(const SBSAMachineState *sms) SysBusDevice *s = SYS_BUS_DEVICE(dev); int irq = sbsa_ref_irqmap[SBSA_GWDT_WS0]; + qdev_prop_set_uint64(dev, "clock-frequency", SBSA_GTIMER_HZ); sysbus_realize_and_unref(s, &error_fatal); sysbus_mmio_map(s, 0, rbase); sysbus_mmio_map(s, 1, cbase); diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c index 96895d7636..d437535cc6 100644 --- a/hw/watchdog/sbsa_gwdt.c +++ b/hw/watchdog/sbsa_gwdt.c @@ -18,6 +18,7 @@ #include "qemu/osdep.h" #include "sysemu/reset.h" #include "sysemu/watchdog.h" +#include "hw/qdev-properties.h" #include "hw/watchdog/sbsa_gwdt.h" #include "qemu/timer.h" #include "migration/vmstate.h" @@ -109,7 +110,7 @@ static void sbsa_gwdt_update_timer(SBSA_GWDTState *s, WdtRefreshType rtype) timeout = s->woru; timeout <<= 32; timeout |= s->worl; - timeout = muldiv64(timeout, NANOSECONDS_PER_SECOND, SBSA_TIMER_FREQ); + timeout = muldiv64(timeout, NANOSECONDS_PER_SECOND, s->freq); timeout += qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); if ((rtype == EXPLICIT_REFRESH) || ((rtype == TIMEOUT_REFRESH) && @@ -261,6 +262,17 @@ static void wdt_sbsa_gwdt_realize(DeviceState *dev, Error **errp) dev); } +static Property wdt_sbsa_gwdt_props[] = { + /* + * Timer frequency in Hz. This must match the frequency used by + * the CPU's generic timer. Default 62.5Hz matches QEMU's legacy + * CPU timer frequency default. + */ + DEFINE_PROP_UINT64("clock-frequency", struct SBSA_GWDTState, freq, + 62500000), + DEFINE_PROP_END_OF_LIST(), +}; + static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -271,6 +283,7 @@ static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, void *data) set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories); dc->vmsd = &vmstate_sbsa_gwdt; dc->desc = "SBSA-compliant generic watchdog device"; + device_class_set_props(dc, wdt_sbsa_gwdt_props); } static const TypeInfo wdt_sbsa_gwdt_info = { diff --git a/include/hw/watchdog/sbsa_gwdt.h b/include/hw/watchdog/sbsa_gwdt.h index 70b137de30..4bdc6c6fdb 100644 --- a/include/hw/watchdog/sbsa_gwdt.h +++ b/include/hw/watchdog/sbsa_gwdt.h @@ -55,8 +55,6 @@ #define SBSA_GWDT_RMMIO_SIZE 0x1000 #define SBSA_GWDT_CMMIO_SIZE 0x1000 -#define SBSA_TIMER_FREQ 62500000 /* Hz */ - typedef struct SBSA_GWDTState { /* */ SysBusDevice parent_obj; @@ -67,6 +65,7 @@ typedef struct SBSA_GWDTState { qemu_irq irq; QEMUTimer *timer; + uint64_t freq; uint32_t id; uint32_t wcs; -- cgit 1.4.1