Re: [kvm-unit-tests PATCH v2 07/23] arm/arm64: Add support for timer initialization through ACPI

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

 



On Fri, May 06, 2022 at 09:55:49PM +0100, Nikos Nikoleris wrote:
> For systems with ACPI support, we can discover timers through the ACPI
> GTDT table. This change implements the code to discover timers through
> the GTDT and adds ACPI support in timer_save_state. This change
> retains the default behavior; we check if a valid DT is provided, if
> not, we try to discover timers using ACPI.
> 
> Signed-off-by: Nikos Nikoleris <nikos.nikoleris@xxxxxxx>
> ---
>  arm/Makefile.common |  1 +
>  lib/arm/asm/timer.h |  2 ++
>  lib/acpi.h          | 18 +++++++++++
>  lib/arm/setup.c     | 39 ------------------------
>  lib/arm/timer.c     | 73 +++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 94 insertions(+), 39 deletions(-)
>  create mode 100644 lib/arm/timer.c
> 
> diff --git a/arm/Makefile.common b/arm/Makefile.common
> index 8e9b3bb..5be42c0 100644
> --- a/arm/Makefile.common
> +++ b/arm/Makefile.common
> @@ -53,6 +53,7 @@ cflatobjs += lib/arm/psci.o
>  cflatobjs += lib/arm/smp.o
>  cflatobjs += lib/arm/delay.o
>  cflatobjs += lib/arm/gic.o lib/arm/gic-v2.o lib/arm/gic-v3.o
> +cflatobjs += lib/arm/timer.o
>  
>  OBJDIRS += lib/arm
>  
> diff --git a/lib/arm/asm/timer.h b/lib/arm/asm/timer.h
> index f75cc67..aaf839f 100644
> --- a/lib/arm/asm/timer.h
> +++ b/lib/arm/asm/timer.h
> @@ -27,5 +27,7 @@ extern struct timer_state __timer_state;
>  #define TIMER_PTIMER_IRQ (__timer_state.ptimer.irq)
>  #define TIMER_VTIMER_IRQ (__timer_state.vtimer.irq)
>  
> +void timer_save_state(void);
> +
>  #endif /* !__ASSEMBLY__ */
>  #endif /* _ASMARM_TIMER_H_ */
> diff --git a/lib/acpi.h b/lib/acpi.h
> index 5213299..297ad87 100644
> --- a/lib/acpi.h
> +++ b/lib/acpi.h
> @@ -17,6 +17,7 @@
>  #define FACP_SIGNATURE ACPI_SIGNATURE('F','A','C','P')
>  #define FACS_SIGNATURE ACPI_SIGNATURE('F','A','C','S')
>  #define SPCR_SIGNATURE ACPI_SIGNATURE('S','P','C','R')
> +#define GTDT_SIGNATURE ACPI_SIGNATURE('G','T','D','T')
>  
>  
>  #define ACPI_SIGNATURE_8BYTE(c1, c2, c3, c4, c5, c6, c7, c8) \
> @@ -172,6 +173,23 @@ struct spcr_descriptor {
>      u32 reserved2;
>  } __attribute__ ((packed));
>  
> +struct acpi_table_gtdt {
> +    ACPI_TABLE_HEADER_DEF   /* ACPI common table header */
> +    u64 counter_block_addresss;
> +    u32 reserved;
> +    u32 secure_el1_interrupt;
> +    u32 secure_el1_flags;
> +    u32 non_secure_el1_interrupt;
> +    u32 non_secure_el1_flags;
> +    u32 virtual_timer_interrupt;
> +    u32 virtual_timer_flags;
> +    u32 non_secure_el2_interrupt;
> +    u32 non_secure_el2_flags;
> +    u64 counter_read_block_address;
> +    u32 platform_timer_count;
> +    u32 platform_timer_offset;
> +} __attribute__ ((packed));
> +
>  void set_efi_rsdp(struct rsdp_descriptor *rsdp);
>  void* find_acpi_table_addr(u32 sig);
>  
> diff --git a/lib/arm/setup.c b/lib/arm/setup.c
> index bcdf0d7..1572c64 100644
> --- a/lib/arm/setup.c
> +++ b/lib/arm/setup.c
> @@ -35,8 +35,6 @@
>  
>  extern unsigned long etext;
>  
> -struct timer_state __timer_state;
> -
>  char *initrd;
>  u32 initrd_size;
>  
> @@ -199,43 +197,6 @@ static void mem_init(phys_addr_t freemem_start)
>  	page_alloc_ops_enable();
>  }
>  
> -static void timer_save_state(void)
> -{
> -	const struct fdt_property *prop;
> -	const void *fdt = dt_fdt();
> -	int node, len;
> -	u32 *data;
> -
> -	node = fdt_node_offset_by_compatible(fdt, -1, "arm,armv8-timer");
> -	assert(node >= 0 || node == -FDT_ERR_NOTFOUND);
> -
> -	if (node == -FDT_ERR_NOTFOUND) {
> -		__timer_state.ptimer.irq = -1;
> -		__timer_state.vtimer.irq = -1;
> -		return;
> -	}
> -
> -	/*
> -	 * From Linux devicetree timer binding documentation
> -	 *
> -	 * interrupts <type irq flags>:
> -	 *	secure timer irq
> -	 *	non-secure timer irq		(ptimer)
> -	 *	virtual timer irq		(vtimer)
> -	 *	hypervisor timer irq
> -	 */
> -	prop = fdt_get_property(fdt, node, "interrupts", &len);
> -	assert(prop && len == (4 * 3 * sizeof(u32)));
> -
> -	data = (u32 *)prop->data;
> -	assert(fdt32_to_cpu(data[3]) == 1 /* PPI */);
> -	__timer_state.ptimer.irq = fdt32_to_cpu(data[4]);
> -	__timer_state.ptimer.irq_flags = fdt32_to_cpu(data[5]);
> -	assert(fdt32_to_cpu(data[6]) == 1 /* PPI */);
> -	__timer_state.vtimer.irq = fdt32_to_cpu(data[7]);
> -	__timer_state.vtimer.irq_flags = fdt32_to_cpu(data[8]);
> -}
> -
>  void setup(const void *fdt, phys_addr_t freemem_start)
>  {
>  	void *freemem;
> diff --git a/lib/arm/timer.c b/lib/arm/timer.c
> new file mode 100644
> index 0000000..eceabdf
> --- /dev/null
> +++ b/lib/arm/timer.c
> @@ -0,0 +1,73 @@
> +/*
> + * Initialize timers.
> + *
> + * Copyright (C) 2022, Arm Ltd., Nikos Nikoleris <nikos.nikoleris@xxxxxxx>
> + * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@xxxxxxxxxx>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.
> + */
> +#include <libcflat.h>
> +#include <asm/timer.h>

nit: I usually prefer an order like this for #includes

#include <lib-include1, usually libcflat.h>  
#include <lib-include2>
...
#include <sublib-include1, libfdt/* and linux/*>
#include <sublib-include2>
...
#include <asm-include1>
#include <asm-include2>

> +
> +#include <acpi.h>
> +#include <devicetree.h>
> +#include <libfdt/libfdt.h>
> +
> +struct timer_state __timer_state;
> +
> +static void timer_save_state_fdt(void)
> +{
> +	const struct fdt_property *prop;
> +	const void *fdt = dt_fdt();
> +	int node, len;
> +	u32 *data;
> +
> +	node = fdt_node_offset_by_compatible(fdt, -1, "arm,armv8-timer");
> +	assert(node >= 0 || node == -FDT_ERR_NOTFOUND);
> +
> +	if (node == -FDT_ERR_NOTFOUND) {
> +		__timer_state.ptimer.irq = -1;
> +		__timer_state.vtimer.irq = -1;
> +		return;
> +	}
> +
> +	/*
> +	 * From Linux devicetree timer binding documentation
> +	 *
> +	 * interrupts <type irq flags>:
> +	 *	secure timer irq
> +	 *	non-secure timer irq		(ptimer)
> +	 *	virtual timer irq		(vtimer)
> +	 *	hypervisor timer irq
> +	 */
> +	prop = fdt_get_property(fdt, node, "interrupts", &len);
> +	assert(prop && len == (4 * 3 * sizeof(u32)));
> +
> +	data = (u32 *)prop->data;
> +	assert(fdt32_to_cpu(data[3]) == 1 /* PPI */);
> +	__timer_state.ptimer.irq = fdt32_to_cpu(data[4]);
> +	__timer_state.ptimer.irq_flags = fdt32_to_cpu(data[5]);
> +	assert(fdt32_to_cpu(data[6]) == 1 /* PPI */);
> +	__timer_state.vtimer.irq = fdt32_to_cpu(data[7]);
> +	__timer_state.vtimer.irq_flags = fdt32_to_cpu(data[8]);
> +}
> +
> +static void timer_save_state_acpi(void)
> +{
> +	struct acpi_table_gtdt *gtdt = find_acpi_table_addr(GTDT_SIGNATURE);
> +
> +	assert_msg(gtdt, "Unable to find ACPI GTDT");
> +	__timer_state.ptimer.irq = gtdt->non_secure_el1_interrupt;
> +	__timer_state.ptimer.irq_flags = gtdt->non_secure_el1_flags;
> +
> +	__timer_state.vtimer.irq = gtdt->virtual_timer_interrupt;
> +	__timer_state.vtimer.irq_flags = gtdt->virtual_timer_flags;
> +}
> +
> +void timer_save_state(void)
> +{
> +	if (dt_available())
> +		timer_save_state_fdt();
> +	else
> +		timer_save_state_acpi();
> +}
> -- 
> 2.25.1
>

Reviewed-by: Andrew Jones <drjones@xxxxxxxxxx>

Thanks,
drew




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux