[kvm-unit-tests PATCH 3/7] riscv: Add ACPI support for timer frequency discovery

Andrew Jones andrew.jones at linux.dev
Wed Sep 30 02:43:46 PDT 2026


On Thu, Sep 24, 2026 at 11:39:41AM +0800, Xiang W wrote:
> When a DT is not provided, read the system time base frequency from
> the RHCT instead of aborting in timer_get_frequency().
> 
> RHCT Time Base Frequency is the ACPI equivalent of the DT
> /cpus timebase-frequency property and is the same for all harts.
> Keep DT as the preferred path when one is available.
> 
> Signed-off-by: Xiang W <wangxiang at iscas.ac.cn>
> ---
>  lib/acpi.h        |  9 +++++++++
>  lib/riscv/timer.c | 37 +++++++++++++++++++++++++------------
>  2 files changed, 34 insertions(+), 12 deletions(-)
> 
> diff --git a/lib/acpi.h b/lib/acpi.h
> index a905807d..2597e8ce 100644
> --- a/lib/acpi.h
> +++ b/lib/acpi.h
> @@ -20,6 +20,7 @@
>  #define MADT_SIGNATURE ACPI_SIGNATURE('A','P','I','C')
>  #define SPCR_SIGNATURE ACPI_SIGNATURE('S','P','C','R')
>  #define GTDT_SIGNATURE ACPI_SIGNATURE('G','T','D','T')
> +#define RHCT_SIGNATURE ACPI_SIGNATURE('R','H','C','T')
>  
>  #define ACPI_SIGNATURE_8BYTE(c1, c2, c3, c4, c5, c6, c7, c8) \
>  	(((uint64_t)(ACPI_SIGNATURE(c1, c2, c3, c4))) |	     \
> @@ -328,6 +329,14 @@ struct acpi_table_gtdt {
>  	u32 virtual_el2_timer_flags;
>  };
>  
> +struct acpi_table_rhct {
> +	ACPI_TABLE_HEADER_DEF
> +	u32 flags;
> +	u64 timebase_frequency;
> +	u32 node_count;
> +	u32 node_offset;
> +};
> +
>  /* Reset to default packing */
>  #pragma pack()
>  
> diff --git a/lib/riscv/timer.c b/lib/riscv/timer.c
> index 18063b7e..2a18f0e0 100644
> --- a/lib/riscv/timer.c
> +++ b/lib/riscv/timer.c
> @@ -13,24 +13,37 @@
>  #include <asm/smp.h>
>  #include <asm/timer.h>
>  
> +#ifdef CONFIG_EFI
> +#include <acpi.h>
> +#endif
> +
>  void timer_get_frequency(void)
>  {
> -	const struct fdt_property *prop;
> -	u32 *data;
> -	int cpus, len;
> -
> -	assert_msg(dt_available(), "ACPI not yet supported");
> +	if (dt_available()) {
> +		const struct fdt_property *prop;
> +		u32 *data;
> +		int cpus, len;
>  
> -	const void *fdt = dt_fdt();
> +		const void *fdt = dt_fdt();

This should be put above 'u32 *data'

>  
> -	cpus = fdt_path_offset(fdt, "/cpus");
> -	assert(cpus >= 0);
> +		cpus = fdt_path_offset(fdt, "/cpus");
> +		assert(cpus >= 0);
>  
> -	prop = fdt_get_property(fdt, cpus, "timebase-frequency", &len);
> -	assert(prop != NULL && len == 4);
> +		prop = fdt_get_property(fdt, cpus, "timebase-frequency", &len);
> +		assert(prop != NULL && len == 4);
>  
> -	data = (u32 *)prop->data;
> -	timebase_frequency = fdt32_to_cpu(*data);
> +		data = (u32 *)prop->data;
> +		timebase_frequency = fdt32_to_cpu(*data);
> +	} else {
> +#ifdef CONFIG_EFI
> +		struct acpi_table_rhct *rhct;

Need a blank line here, or just do the find call on the same line.

> +		rhct = find_acpi_table_addr(RHCT_SIGNATURE);
> +		assert_msg(rhct, "Cannot find ACPI RHCT");
> +		timebase_frequency = rhct->timebase_frequency;
> +#else
> +		assert_msg(false, "ACPI not available");
> +#endif
> +	}
>  }
>  
>  void timer_start(unsigned long duration_us)
> -- 
> 2.47.3
>

Thanks,
drew



More information about the kvm-riscv mailing list