arm/arm64: Add ITS tests
Subsystems (3)
v4 cover arm/arm64: Add ITS tests
This series is a revival of an RFC series sent in Dec 2016 [1]. Given the amount of code and the lack of traction at that time, I haven't respinned until now. However a recent bug found related to the ITS migration convinced me that this work may deserve to be respinned and enhanced.
Tests exercise main ITS commands and also test migration. With the migration framework, we are able to trigger the migration from guest and that is very practical actually.
What is particular with the ITS programming is that most of the commands are passed through queues and there is real error handling. Invalid commands are just ignored and that is not really tester friendly.
The series can be fount at:
https://github.com/eauger/kut/tree/its-v4
Best Regards
Eric
History:
v3 -> v4:
- addressed comments from Drew and Zenghui
- added "page_alloc: Introduce get_order()"
- removed "arm: gic: Provide per-IRQ helper functions"
- ITS files moved to lib64
- and many more, see individual logs
v2 -> v3:
- fix 32b compilation
- take into account Drew's comments (see individual diff logs)
v1 -> v2:
- took into account Zenghui's comments
- collect R-b's from Thomas
References:
[1] [kvm-unit-tests RFC 00/15] arm/arm64: add ITS framework
https://lists.gnu.org/archive/html/qemu-devel/2016-12/msg00575.html
Execution:
x For other ITS tests:
./run_tests.sh -g its
x non migration tests can be launched invidually. For instance:
./arm-run arm/gic.flat -smp 8 -append 'its-trigger'
Eric Auger (13):
libcflat: Add other size defines
page_alloc: Introduce get_order()
arm/arm64: gic: Introduce setup_irq() helper arm/arm64: gicv3: Add some re-distributor defines arm/arm64: gicv3: Set the LPI config and pending tables arm/arm64: ITS: Introspection tests
arm/arm64: ITS: its_enable_defaults
arm/arm64: ITS: Device and collection Initialization arm/arm64: ITS: Commands
arm/arm64: ITS: INT functional tests
arm/run: Allow Migration tests
arm/arm64: ITS: migration tests
arm/arm64: ITS: pending table migration test
arm/Makefile.arm64 | 1 + arm/Makefile.common | 2 +- arm/gic.c | 469 +++++++++++++++++++++++++++++++++++-- arm/run | 2 +- arm/unittests.cfg | 38 +++ lib/alloc_page.c | 7 +- lib/alloc_page.h | 1 + lib/arm/asm/gic-v3-its.h | 39 +++ lib/arm/asm/gic-v3.h | 32 +++ lib/arm/gic-v3.c | 76 ++++++ lib/arm/gic.c | 34 ++- lib/arm/io.c | 28 +++ lib/arm64/asm/gic-v3-its.h | 172 ++++++++++++++ lib/arm64/gic-v3-its-cmd.c | 463 ++++++++++++++++++++++++++++++++++++ lib/arm64/gic-v3-its.c | 172 ++++++++++++++ lib/libcflat.h | 3 + 16 files changed, 1510 insertions(+), 29 deletions(-) create mode 100644 lib/arm/asm/gic-v3-its.h create mode 100644 lib/arm64/asm/gic-v3-its.h create mode 100644 lib/arm64/gic-v3-its-cmd.c create mode 100644 lib/arm64/gic-v3-its.c
Signature · 1 line
2.20.1
PATCH v4 1/13 libcflat: Add other size defines
Introduce additional SZ_256, SZ_8K, SZ_16K macros that will be used by ITS tests.
--- lib/libcflat.h | 3 +++ 1 file changed, 3 insertions(+)
lib/libcflat.h +3 -0
@@ -36,7 +36,10 @@#define ALIGN (x, a) __ALIGN((x), (a))#define IS_ALIGNED (x, a) (((x) & ((typeof(x))(a) - 1)) == 0) +#define SZ_256 (1 << 8)#define SZ_4K (1 << 12) +#define SZ_8K (1 << 13) +#define SZ_16K (1 << 14)#define SZ_64K (1 << 16)#define SZ_2M (1 << 21)#define SZ_1G (1 << 30)
Signature · 1 line
2.20.1
PATCH v4 2/13 page_alloc: Introduce get_order()
In reply to Eric AugerCompute the power of 2 order of a size. Use it inpage_memalign. Other users are looming.
--- lib/alloc_page.c | 7 ++++++- lib/alloc_page.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-)
lib/alloc_page.c +6 -1
@@ -155,7 +155,7 @@ static void *page_memalign(size_t alignment, size_t size)if (!size)return NULL ; - order =is_power_of_2 (n) ?fls (n) :fls (n) +1 ; + order =get_order (n);return alloc_pages (order); }
@@ -175,3 +175,8 @@ void page_alloc_ops_enable(void) { alloc_ops = &page_alloc_ops; } + +int get_order (size_t size) +{ +return is_power_of_2 (size) ?fls (size) :fls (size) +1 ; +}
lib/alloc_page.h +1 -0
@@ -15,5 +15,6 @@ void *alloc_pages(unsigned long order);void free_page (void *page);void free_pages (void *mem,unsigned long size);void free_pages_by_order (void *mem,unsigned long order); +int get_order (size_t size);#endif
Signature · 1 line
2.20.1
PATCH v4 3/13 arm/arm64: gic: Introduce setup_irq() helper
In reply to Eric Augeripi_enable() code would be reusable for other interrupts than IPI. Let's rename it setup_irq() and pass an interrupt handler pointer.
---
v2 -> v3:
- do not export setup_irq anymore
--- arm/gic.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-)
arm/gic.c +7 -13
@@ -34,6 +34,7 @@ static struct gic *gic;static int acked[NR_CPUS ], spurious[NR_CPUS ];static int bad_sender[NR_CPUS ], bad_irq[NR_CPUS ];static cpumask_t ready; +typedef void (*handler_t)(struct pt_regs *regs __unused);static void nr_cpu_check (int nr) {
@@ -215,20 +216,20 @@ static void ipi_test_smp(void)report_prefix_pop (); } -static void ipi_enable (void ) +static void setup_irq (handler_t handler) {gic_enable_defaults ();#ifdef __arm__ -install_exception_handler (EXCPTN_IRQ , ipi_handler); +install_exception_handler (EXCPTN_IRQ , handler);#else -install_irq_handler (EL1H_IRQ , ipi_handler); +install_irq_handler (EL1H_IRQ , handler);#endif local_irq_enable (); }static void ipi_send (void ) { -ipi_enable (); +setup_irq (ipi_handler);wait_on_ready ();ipi_test_self ();ipi_test_smp ();
@@ -238,7 +239,7 @@ static void ipi_send(void)static void ipi_recv (void ) { -ipi_enable (); +setup_irq (ipi_handler);cpumask_set_cpu (smp_processor_id (), &ready);while (1 )wfi ();
@@ -295,14 +296,7 @@ static void ipi_clear_active_handler(struct pt_regs *regs __unused)static void run_active_clear_test (void ) {report_prefix_push ("active" ); -gic_enable_defaults (); -#ifdef __arm__ -install_exception_handler (EXCPTN_IRQ , ipi_clear_active_handler); -#else -install_irq_handler (EL1H_IRQ , ipi_clear_active_handler); -#endif -local_irq_enable (); - +setup_irq (ipi_clear_active_handler);ipi_test_self ();report_prefix_pop (); }
Signature · 6 lines
2.20.1 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Re: [kvm-unit-tests PATCH v4 03/13] arm/arm64: gic: Introduce setup_irq() helper
Quoted 19 lines · Eric Auger
ipi_enable()code would be reusable for other interrupts than IPI. Let's rename itsetup_irq()and pass an interrupt handler pointer.Signed-off-by Eric Auger <[email protected]>---
v2 -> v3:
- do not exportsetup_irqanymore--- arm/gic.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-)arm/gic.c +0
-0
arm/gic.c static struct gic *gic; · line 37
Quoted 4 lines
arm/gic.c +1
-0@@ -34,6 +34,7 @@ static struct gic *gic;static int acked[NR_CPUS ], spurious[NR_CPUS ];static int bad_sender[NR_CPUS ], bad_irq[NR_CPUS ];static cpumask_t ready; +typedef void (*handler_t)(struct pt_regs *regs __unused);
This is just irq_handler_fn, which is already defined in processor.h. We don't need the __unused, not since 6b07148d06b1 ("Replace -Wextra with a saner list of warning flags").
Quoted 56 lines
arm/gic.c +6
-13static void nr_cpu_check (int nr) {@@ -215,20 +216,20 @@ static void ipi_test_smp(void)report_prefix_pop (); } -static void ipi_enable (void ) +static void setup_irq (handler_t handler) {gic_enable_defaults ();#ifdef __arm__ -install_exception_handler (EXCPTN_IRQ , ipi_handler); +install_exception_handler (EXCPTN_IRQ , handler);#else -install_irq_handler (EL1H_IRQ , ipi_handler); +install_irq_handler (EL1H_IRQ , handler);#endif local_irq_enable (); }static void ipi_send (void ) { -ipi_enable (); +setup_irq (ipi_handler);wait_on_ready ();ipi_test_self ();ipi_test_smp ();@@ -238,7 +239,7 @@ static void ipi_send(void)static void ipi_recv (void ) { -ipi_enable (); +setup_irq (ipi_handler);cpumask_set_cpu (smp_processor_id (), &ready);while (1 )wfi ();@@ -295,14 +296,7 @@ static void ipi_clear_active_handler(struct pt_regs *regs __unused)static void run_active_clear_test (void ) {report_prefix_push ("active" ); -gic_enable_defaults (); -#ifdef __arm__ -install_exception_handler (EXCPTN_IRQ , ipi_clear_active_handler); -#else -install_irq_handler (EL1H_IRQ , ipi_clear_active_handler); -#endif -local_irq_enable (); - +setup_irq (ipi_clear_active_handler);ipi_test_self ();report_prefix_pop (); }Signature · 1 line
2.20.1
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Re: [kvm-unit-tests PATCH v4 03/13] arm/arm64: gic: Introduce setup_irq() helper
Hi Drew,
Quoted 15 lines · Andrew Jones
Quoted 14 lines · Eric Auger
ipi_enable()code would be reusable for other interrupts than IPI. Let's rename itsetup_irq()and pass an interrupt handler pointer.Signed-off-by Eric Auger <[email protected]>---
v2 -> v3:
- do not exportsetup_irqanymore--- arm/gic.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-)
Quoted 13 lines
arm/gic.c static struct gic *gic; · line 37
Quoted 9 lines
arm/gic.c +1
-0@@ -34,6 +34,7 @@ static struct gic *gic;static int acked[NR_CPUS ], spurious[NR_CPUS ];static int bad_sender[NR_CPUS ], bad_irq[NR_CPUS ];static cpumask_t ready; +typedef void (*handler_t)(struct pt_regs *regs __unused);This is just
irq_handler_fn, which is already defined inprocessor.h. We don't need the__unused, not since6b07148d06b1("Replace -Wextra with a saner list of warning flags").
Shall I duplicate it into ./lib/arm/asm/processor.h as well?
Thanks
Eric
Quoted 57 lines
Quoted 57 lines
arm/gic.c +6
-13static void nr_cpu_check (int nr) {@@ -215,20 +216,20 @@ static void ipi_test_smp(void)report_prefix_pop (); } -static void ipi_enable (void ) +static void setup_irq (handler_t handler) {gic_enable_defaults ();#ifdef __arm__ -install_exception_handler (EXCPTN_IRQ , ipi_handler); +install_exception_handler (EXCPTN_IRQ , handler);#else -install_irq_handler (EL1H_IRQ , ipi_handler); +install_irq_handler (EL1H_IRQ , handler);#endif local_irq_enable (); }static void ipi_send (void ) { -ipi_enable (); +setup_irq (ipi_handler);wait_on_ready ();ipi_test_self ();ipi_test_smp ();@@ -238,7 +239,7 @@ static void ipi_send(void)static void ipi_recv (void ) { -ipi_enable (); +setup_irq (ipi_handler);cpumask_set_cpu (smp_processor_id (), &ready);while (1 )wfi ();@@ -295,14 +296,7 @@ static void ipi_clear_active_handler(struct pt_regs *regs __unused)static void run_active_clear_test (void ) {report_prefix_push ("active" ); -gic_enable_defaults (); -#ifdef __arm__ -install_exception_handler (EXCPTN_IRQ , ipi_clear_active_handler); -#else -install_irq_handler (EL1H_IRQ , ipi_clear_active_handler); -#endif -local_irq_enable (); - +setup_irq (ipi_clear_active_handler);ipi_test_self ();report_prefix_pop (); }Signature · 1 line
2.20.1
Re: [kvm-unit-tests PATCH v4 03/13] arm/arm64: gic: Introduce setup_irq() helper
Quoted 30 lines · Auger Eric
Hi Drew,
Quoted 15 lines · Andrew Jones
Quoted 14 lines · Eric Auger
ipi_enable()code would be reusable for other interrupts than IPI. Let's rename itsetup_irq()and pass an interrupt handler pointer.Signed-off-by Eric Auger <[email protected]>---
v2 -> v3:
- do not exportsetup_irqanymore--- arm/gic.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-)Quoted 13 lines
arm/gic.c static struct gic *gic; · line 37
Quoted 9 lines
arm/gic.c +1
-0@@ -34,6 +34,7 @@ static struct gic *gic;static int acked[NR_CPUS ], spurious[NR_CPUS ];static int bad_sender[NR_CPUS ], bad_irq[NR_CPUS ];static cpumask_t ready; +typedef void (*handler_t)(struct pt_regs *regs __unused);This is just
irq_handler_fn, which is already defined inprocessor.h. We don't need the__unused, not since6b07148d06b1("Replace -Wextra with a saner list of warning flags").
Quoted 1 line
Shall I duplicate it into
./lib/arm/asm/processor.has well?
Yes, please do
Thanks,
drew
Quoted 53 lines
Thanks
Eric
Quoted 49 lines
Quoted 49 lines
arm/gic.c +5
-12static void nr_cpu_check (int nr) {@@ -215,20 +216,20 @@ static void ipi_test_smp(void)report_prefix_pop (); } -static void ipi_enable (void ) +static void setup_irq (handler_t handler) {gic_enable_defaults ();#ifdef __arm__ -install_exception_handler (EXCPTN_IRQ , ipi_handler); +install_exception_handler (EXCPTN_IRQ , handler);#else -install_irq_handler (EL1H_IRQ , ipi_handler); +install_irq_handler (EL1H_IRQ , handler);#endif local_irq_enable (); }static void ipi_send (void ) { -ipi_enable (); +setup_irq (ipi_handler);wait_on_ready ();ipi_test_self ();ipi_test_smp ();@@ -238,7 +239,7 @@ static void ipi_send(void)static void ipi_recv (void ) { -ipi_enable (); +setup_irq (ipi_handler);cpumask_set_cpu (smp_processor_id (), &ready);while (1 )wfi ();@@ -295,14 +296,7 @@ static void ipi_clear_active_handler(struct pt_regs *regs __unused)static void run_active_clear_test (void ) {report_prefix_push ("active" ); -gic_enable_defaults (); -#ifdef __arm__ -install_exception_handler (EXCPTN_IRQ , ipi_clear_active_handler); -#else -install_irq_handler (EL1H_IRQ , ipi_clear_active_handler); -#endif -local_irq_enable ();
Quoted 10 lines
Quoted 8 lines
Quoted 8 lines
arm/gic.c +1
-1- +setup_irq (ipi_clear_active_handler);ipi_test_self ();report_prefix_pop (); }Signature · 1 line
2.20.1
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v4 4/13 arm/arm64: gicv3: Add some re-distributor defines
In reply to Eric AugerPROPBASER, PENDBASE and GICR_CTRL will be used for LPI management.
---
v3 -> v4:
- replace some spaces by tabs and added Zenghui's R-b
--- lib/arm/asm/gic-v3.h | 6 ++++++ 1 file changed, 6 insertions(+)
lib/arm/asm/gic-v3.h +6 -0
@@ -18,6 +18,7 @@* We expect to be run in Non-secure mode, thus we define the * group1 enable bits with respect to that view. */ +#define GICD_CTLR 0x0000#define GICD_CTLR_RWP (1U << 31)#define GICD_CTLR_ARE_NS (1U << 4)#define GICD_CTLR_ENABLE_G1A (1U << 1)
@@ -38,6 +39,11 @@#define GICR_ICACTIVER0 GICD_ICACTIVER#define GICR_IPRIORITYR0 GICD_IPRIORITYR +#define GICR_PROPBASER 0x0070 +#define GICR_PENDBASER 0x0078 +#define GICR_CTLR GICD_CTLR +#define GICR_CTLR_ENABLE_LPIS (1UL << 0) +#define ICC_SGI1R_AFFINITY_1_SHIFT 16#define ICC_SGI1R_AFFINITY_2_SHIFT 32#define ICC_SGI1R_AFFINITY_3_SHIFT 48
Signature · 6 lines
2.20.1 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v4 5/13 arm/arm64: gicv3: Set the LPI config and pending tables
In reply to Eric AugerAllocate the LPI configuration and per re-distributor pending table. Set redistributor's PROPBASER and PENDBASER. The LPIs are enabled by default in the config table.
Also introduce a helper routine that allows to set the pending table bit for a given LPI.
---
v2 -> v3:
- Move the helpers in lib/arm/gic-v3.c and prefix them with "gicv3_" and add _lpi prefix too
v1 -> v2:
- remove memory attributes
--- lib/arm/asm/gic-v3.h | 16 +++++++++++ lib/arm/gic-v3.c | 64 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+)
lib/arm/asm/gic-v3.h +16 -0
@@ -50,6 +50,16 @@#define MPIDR_TO_SGI_AFFINITY (cluster_id, level) \ (MPIDR_AFFINITY_LEVEL(cluster_id, level) << ICC_SGI1R_AFFINITY_## level ## _SHIFT) +#define GICR_PROPBASER_IDBITS_MASK (0x1f) + +#define GICR_PENDBASER_PTZ BIT_ULL(62) + +#define LPI_PROP_GROUP1 (1 << 1) +#define LPI_PROP_ENABLED (1 << 0) +#define LPI_PROP_DEFAULT_PRIO 0xa0 +#define LPI_PROP_DEFAULT (LPI_PROP_DEFAULT_PRIO | LPI_PROP_GROUP1 | \ + LPI_PROP_ENABLED) +#include <asm/arch_gicv3.h> #ifndef __ASSEMBLY__
@@ -66,6 +76,8 @@ struct gicv3_data {void *dist_base;void *redist_bases[GICV3_NR_REDISTS ];void *redist_base[NR_CPUS ]; +void *lpi_prop; +void *lpi_pend[NR_CPUS ];unsigned int irq_nr; };extern struct gicv3_data gicv3_data;
@@ -82,6 +94,10 @@ extern void gicv3_write_eoir(u32 irqstat);extern void gicv3_ipi_send_single (int irq,int cpu);extern void gicv3_ipi_send_mask (int irq,const cpumask_t *dest);extern void gicv3_set_redist_base (size_t stride); +extern void gicv3_lpi_set_config (int n,u8 val); +extern u8 gicv3_lpi_get_config (int n); +extern void gicv3_lpi_set_pending_table_bit (int rdist,int n,bool set); +extern void gicv3_lpi_alloc_tables (void );static inline void gicv3_do_wait_for_rwp (void *base) {
lib/arm/gic-v3.c +64 -0
73 lines not on this page · raw message
Signature · 1 line
2.20.1
PATCH v4 6/13 arm/arm64: ITS: Introspection tests
In reply to Eric AugerDetect the presence of an ITS as part of the GICv3 init routine, initialize its base address and read few registers the IIDR, the TYPER to store its dimensioning parameters. Parse the BASER registers. As part of the init sequence we also init all the requested tables.
This is our first ITS test, belonging to a new "its" group.
---
v3 -> v4:
- fixed some typos, refine trace msgs
- move its files to lib/arm64 instead of lib/arm
- create lib/arm/asm/gic-v3-its.h containing stubs
- rework gic_get_dt_bases
- rework baser parsing
- move table allocation to init routine
- use get_order()
v2 -> v3:
- updated dates and changed author
- squash "arm/arm64: ITS: Test BASER" into this patch but removes setup_baser which will be introduced later.
- only compile on aarch64
- restrict the new test to aarch64
v1 -> v2:
- clean GITS_TYPER macros and unused fields in typer struct
- remove memory attribute related macros
- remove everything related to memory attributes
- s/dev_baser/coll_baser/ in report_info
- add extra line
- removed index filed in its_baser
--- arm/Makefile.arm64 | 1 + arm/gic.c | 44 ++++++++++++++++ arm/unittests.cfg | 7 +++ lib/arm/asm/gic-v3-its.h | 23 +++++++++ lib/arm/gic.c | 34 +++++++++++-- lib/arm64/asm/gic-v3-its.h | 92 +++++++++++++++++++++++++++++++++ lib/arm64/gic-v3-its.c | 102 +++++++++++++++++++++++++++++++++++++ 7 files changed, 298 insertions(+), 5 deletions(-) create mode 100644 lib/arm/asm/gic-v3-its.h create mode 100644 lib/arm64/asm/gic-v3-its.h create mode 100644 lib/arm64/gic-v3-its.c
arm/Makefile.arm64 +1 -0
@@ -19,6 +19,7 @@ endef cstart.o = $(TEST_DIR)/cstart64.o cflatobjs += lib/arm64/processor.o cflatobjs += lib/arm64/spinlock.o +cflatobjs += lib/arm64/gic-v3-its.o OBJDIRS += lib/arm64
arm/gic.c +44 -0
62 lines not on this page · raw message
arm/unittests.cfg +7 -0
@@ -122,6 +122,13 @@ smp = $MAX_SMP extra_params = -machine gic-version=3 -append 'active' groups = gic +[its-introspection] +file = gic.flat +smp = $MAX_SMP +extra_params = -machine gic-version=3 -append 'its-introspection' +groups = its +arch = arm64 + # Test PSCI emulation [psci] file = psci.flat
lib/arm/asm/gic-v3-its.h new file +23 -0
@@ -0,0 +1,23 @@ +/* +* ITS 32-bit stubs +* +* Copyright (C) 2020, Red Hat Inc, Eric Auger <[email protected]> +* +* This work is licensed under the terms of the GNU LGPL, version 2. +*/ + +#ifndef _ASMARM_GICv3_ITS +#define _ASMARM_GICv3_ITS + +/* dummy its_data struct to allow gic_get_dt_bases() call */ +struct its_data { +void *base; +}; + +static inline void its_init (void ) {} +static inline void test_its_introspection (void ) +{ +report_abort ("not supported on 32-bit" ); +} + +#endif /* _ASMARM_GICv3_ITS */
lib/arm/gic.c +29 -5
@@ -6,9 +6,11 @@#include <devicetree.h> #include <asm/gic.h> #include <asm/io.h> +#include <asm/gic-v3-its.h> struct gicv2_data gicv2_data;struct gicv3_data gicv3_data; +struct its_data its_data;struct gic_common_ops {void (*enable_defaults)(void );
@@ -44,12 +46,13 @@ static const struct gic_common_ops gicv3_common_ops = {* Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt */ static bool -gic_get_dt_bases (const char *compatible,void **base1,void **base2) +gic_get_dt_bases (const char *compatible,void **base1,void **base2,void **base3) {struct dt_pbus_reg reg; -struct dt_device gic; +struct dt_device gic, its;struct dt_bus bus; -int node, ret, i; +int node, subnode, ret, i, len; +const void *fdt =dt_fdt ();dt_bus_init_defaults (&bus);dt_device_init (&gic, &bus,NULL );
@@ -74,19 +77,39 @@ gic_get_dt_bases(const char *compatible, void **base1, void **base2) base2[i] =ioremap (reg.addr, reg.size); } +if (!base3) { +assert (!strcmp (compatible,"arm,cortex-a15-gic" )); +return true; + } + +assert (!strcmp (compatible,"arm,gic-v3" )); + +dt_for_each_subnode (node, subnode) { +const struct fdt_property *prop; + + prop =fdt_get_property (fdt, subnode,"compatible" , &len); +if (!strcmp ((char *)prop->data,"arm,gic-v3-its" )) { +dt_device_bind_node (&its, subnode); + ret =dt_pbus_translate (&its,0 , ®); +assert (ret ==0 ); + *base3 =ioremap (reg.addr, reg.size); +break ; + } + } +return true; }int gicv2_init (void ) {return gic_get_dt_bases ("arm,cortex-a15-gic" , - &gicv2_data.dist_base, &gicv2_data.cpu_base); + &gicv2_data.dist_base, &gicv2_data.cpu_base,NULL ); }int gicv3_init (void ) {return gic_get_dt_bases ("arm,gic-v3" , &gicv3_data.dist_base, - &gicv3_data.redist_bases[0 ]); + &gicv3_data.redist_bases[0 ], &its_data.base); }int gic_version (void )
@@ -104,6 +127,7 @@ int gic_init(void) gic_common_ops = &gicv2_common_ops; else if (gicv3_init()) gic_common_ops = &gicv3_common_ops; +its_init ();return gic_version (); }
lib/arm64/asm/gic-v3-its.h new file +92 -0
92 lines not on this page · raw message
lib/arm64/gic-v3-its.c new file +102 -0
102 lines not on this page · raw message
Signature · 1 line
2.20.1
Re: [kvm-unit-tests PATCH v4 06/13] arm/arm64: ITS: Introspection tests
Quoted 163 lines · Eric Auger
Detect the presence of an ITS as part of the GICv3 init routine, initialize its base address and read few registers the IIDR, the TYPER to store its dimensioning parameters. Parse the BASER registers. As part of the init sequence we also init all the requested tables.
This is our first ITS test, belonging to a new "its" group.
Signed-off-by Eric Auger <[email protected]>---
v3 -> v4:
- fixed some typos, refine trace msgs
- move its files to lib/arm64 instead of lib/arm
- createlib/arm/asm/gic-v3-its.hcontaining stubs
- reworkgic_get_dt_bases
- rework baser parsing
- move table allocation to init routine
- useget_order()v2 -> v3:
- updated dates and changed author
- squash "arm/arm64: ITS: Test BASER" into this patch but removessetup_baserwhich will be introduced later.
- only compile on aarch64
- restrict the new test to aarch64v1 -> v2:
- cleanGITS_TYPERmacros and unused fields in typer struct
- remove memory attribute related macros
- remove everything related to memory attributes
- s/dev_baser/coll_baser/ inreport_info
- add extra line
- removed index filed inits_baser--- arm/Makefile.arm64 | 1 + arm/gic.c | 44 ++++++++++++++++ arm/unittests.cfg | 7 +++ lib/arm/asm/gic-v3-its.h | 23 +++++++++ lib/arm/gic.c | 34 +++++++++++-- lib/arm64/asm/gic-v3-its.h | 92 +++++++++++++++++++++++++++++++++ lib/arm64/gic-v3-its.c | 102 +++++++++++++++++++++++++++++++++++++ 7 files changed, 298 insertions(+), 5 deletions(-) create mode 100644 lib/arm/asm/gic-v3-its.h create mode 100644 lib/arm64/asm/gic-v3-its.h create mode 100644 lib/arm64/gic-v3-its.carm/Makefile.arm64 +1
-0@@ -19,6 +19,7 @@ endef cstart.o = $(TEST_DIR)/cstart64.o cflatobjs += lib/arm64/processor.o cflatobjs += lib/arm64/spinlock.o +cflatobjs += lib/arm64/gic-v3-its.o OBJDIRS += lib/arm64arm/gic.c +44
-0@@ -16,6 +16,7 @@#include <asm/processor.h> #include <asm/delay.h> #include <asm/gic.h> +#include <asm/gic-v3-its.h> #include <asm/smp.h> #include <asm/barrier.h> #include <asm/io.h> @@ -518,6 +519,45 @@ static void gic_test_mmio(void)test_targets (nr_irqs); } +#if defined(__aarch64__) + +static void test_its_introspection (void ) +{ +struct its_baser *dev_baser = &its_data.device_baser; +struct its_baser *coll_baser = &its_data.coll_baser; +struct its_typer *typer = &its_data.typer; + +if (!gicv3_its_base ()) { +report_skip ("No ITS, skip ..." ); +return ; + } + +/* IIDR */ +report (test_readonly_32 (gicv3_its_base () +GITS_IIDR , false), +"GITS_IIDR is read-only" ), + +/* TYPER */ +report (test_readonly_32 (gicv3_its_base () +GITS_TYPER , false), +"GITS_TYPER is read-only" ); + +report (typer->phys_lpi,"ITS supports physical LPIs" ); +report_info ("vLPI support: %s" , typer->virt_lpi ?"yes" :"no" ); +report_info ("ITT entry size = 0x%x" , typer->ite_size); +report_info ("Bit Count: EventID=%d DeviceId=%d CollId=%d" , + typer->eventid_bits, typer->deviceid_bits, + typer->collid_bits); +report (typer->eventid_bits && typer->deviceid_bits && + typer->collid_bits,"ID spaces" ); +report_info ("Target address format %s" , + typer->pta ?"Redist base address" :"PE #" ); + +report (dev_baser && coll_baser,"detect device and collection BASER" ); +report_info ("device table entry_size = 0x%x" , dev_baser->esz); +report_info ("collection table entry_size = 0x%x" , coll_baser->esz); +} + +#endif +int main (int argc,char **argv) {if (!gic_init ()) {@@ -549,6 +589,10 @@ int main(int argc, char **argv)report_prefix_push (argv[1 ]);gic_test_mmio ();report_prefix_pop (); + }else if (strcmp (argv[1 ],"its-introspection" ) ==0 ) { +report_prefix_push (argv[1 ]); +test_its_introspection (); +report_prefix_pop (); }else {report_abort ("Unknown subtest '%s'" , argv[1 ]); }arm/unittests.cfg +7
-0@@ -122,6 +122,13 @@ smp = $MAX_SMP extra_params = -machine gic-version=3 -append 'active' groups = gic +[its-introspection] +file = gic.flat +smp = $MAX_SMP +extra_params = -machine gic-version=3 -append 'its-introspection' +groups = its +arch = arm64 + # Test PSCI emulation [psci] file = psci.flatlib/arm/asm/gic-v3-its.h new file +10
-0@@ -0,0 +1,23 @@ +/* +* ITS 32-bit stubs +* +* Copyright (C) 2020, Red Hat Inc, Eric Auger <[email protected]> +* +* This work is licensed under the terms of the GNU LGPL, version 2. +*/ + +#ifndef _ASMARM_GICv3_ITS +#define _ASMARM_GICv3_ITS
lib/arm/asm/gic-v3-its.h line 20
Quoted 10 lines
lib/arm/asm/gic-v3-its.h new file +10
-0+ +/* dummy its_data struct to allow gic_get_dt_bases() call */ +struct its_data { +void *base; +}; + +static inline void its_init (void ) {} +static inline void test_its_introspection (void ) +{ +report_abort ("not supported on 32-bit" );
I suggested report_abort() in this function when it was in arm/gic.c, but we don't want report_* functions in the library code, nor do we want functions named test_*. This test_* stub should go back to arm/gic.c, where it can be empty, because the 32-bit its_init() stub here could get an assert_msg("not supported on 32-bit") instead.
Quoted 245 lines
lib/arm/asm/gic-v3-its.h new file +3
-0+} + +#endif /* _ASMARM_GICv3_ITS */ lib/arm/gic.c +29
-5@@ -6,9 +6,11 @@#include <devicetree.h> #include <asm/gic.h> #include <asm/io.h> +#include <asm/gic-v3-its.h> struct gicv2_data gicv2_data;struct gicv3_data gicv3_data; +struct its_data its_data;struct gic_common_ops {void (*enable_defaults)(void );@@ -44,12 +46,13 @@ static const struct gic_common_ops gicv3_common_ops = {* Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt */ static bool -gic_get_dt_bases (const char *compatible,void **base1,void **base2) +gic_get_dt_bases (const char *compatible,void **base1,void **base2,void **base3) {struct dt_pbus_reg reg; -struct dt_device gic; +struct dt_device gic, its;struct dt_bus bus; -int node, ret, i; +int node, subnode, ret, i, len; +const void *fdt =dt_fdt ();dt_bus_init_defaults (&bus);dt_device_init (&gic, &bus,NULL );@@ -74,19 +77,39 @@ gic_get_dt_bases(const char *compatible, void **base1, void **base2) base2[i] =ioremap (reg.addr, reg.size); } +if (!base3) { +assert (!strcmp (compatible,"arm,cortex-a15-gic" )); +return true; + } + +assert (!strcmp (compatible,"arm,gic-v3" )); + +dt_for_each_subnode (node, subnode) { +const struct fdt_property *prop; + + prop =fdt_get_property (fdt, subnode,"compatible" , &len); +if (!strcmp ((char *)prop->data,"arm,gic-v3-its" )) { +dt_device_bind_node (&its, subnode); + ret =dt_pbus_translate (&its,0 , ®); +assert (ret ==0 ); + *base3 =ioremap (reg.addr, reg.size); +break ; + } + } +return true; }int gicv2_init (void ) {return gic_get_dt_bases ("arm,cortex-a15-gic" , - &gicv2_data.dist_base, &gicv2_data.cpu_base); + &gicv2_data.dist_base, &gicv2_data.cpu_base,NULL ); }int gicv3_init (void ) {return gic_get_dt_bases ("arm,gic-v3" , &gicv3_data.dist_base, - &gicv3_data.redist_bases[0 ]); + &gicv3_data.redist_bases[0 ], &its_data.base); }int gic_version (void )@@ -104,6 +127,7 @@ int gic_init(void) gic_common_ops = &gicv2_common_ops; else if (gicv3_init()) gic_common_ops = &gicv3_common_ops; +its_init ();return gic_version (); }lib/arm64/asm/gic-v3-its.h new file +92
-0@@ -0,0 +1,92 @@ +/* +* All ITS* defines are lifted from include/linux/irqchip/arm-gic-v3.h +* +* Copyright (C) 2020, Red Hat Inc, Eric Auger <[email protected]> +* +* This work is licensed under the terms of the GNU LGPL, version 2. +*/ +#ifndef _ASMARM64_GIC_V3_ITS_H_ +#define _ASMARM64_GIC_V3_ITS_H_ + +struct its_typer { +unsigned int ite_size; +unsigned int eventid_bits; +unsigned int deviceid_bits; +unsigned int collid_bits; +bool pta; +bool phys_lpi; +bool virt_lpi; +}; + +struct its_baser { +int index; +size_t psz; +int esz; +bool indirect; +phys_addr_t table_addr; +}; + +#define GITS_BASER_NR_REGS 8 + +struct its_data { +void *base; +struct its_typer typer; +struct its_baser device_baser; +struct its_baser coll_baser; +struct its_cmd_block *cmd_base; +struct its_cmd_block *cmd_write; +}; + +extern struct its_data its_data; + +#define gicv3_its_base () (its_data.base) + +#define GITS_CTLR 0x0000 +#define GITS_IIDR 0x0004 +#define GITS_TYPER 0x0008 +#define GITS_CBASER 0x0080 +#define GITS_CWRITER 0x0088 +#define GITS_CREADR 0x0090 +#define GITS_BASER 0x0100 + +#define GITS_TYPER_PLPIS BIT(0) +#define GITS_TYPER_VLPIS BIT(1) +#define GITS_TYPER_ITT_ENTRY_SIZE GENMASK_ULL(7, 4) +#define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT 4 +#define GITS_TYPER_IDBITS GENMASK_ULL(8, 12) +#define GITS_TYPER_IDBITS_SHIFT 8 +#define GITS_TYPER_DEVBITS GENMASK_ULL(13, 17) +#define GITS_TYPER_DEVBITS_SHIFT 13 +#define GITS_TYPER_PTA BIT(19) +#define GITS_TYPER_CIDBITS GENMASK_ULL(32, 35) +#define GITS_TYPER_CIDBITS_SHIFT 32 +#define GITS_TYPER_CIL BIT(36) + +#define GITS_CTLR_ENABLE (1U << 0) + +#define GITS_CBASER_VALID (1UL << 63) + +#define GITS_BASER_VALID BIT(63) +#define GITS_BASER_INDIRECT BIT(62) +#define GITS_BASER_TYPE_SHIFT (56) +#define GITS_BASER_TYPE (r) (((r) >> GITS_BASER_TYPE_SHIFT) & 7) +#define GITS_BASER_ENTRY_SIZE_SHIFT (48) +#define GITS_BASER_ENTRY_SIZE (r) ((((r) >> GITS_BASER_ENTRY_SIZE_SHIFT) & 0x1f) + 1) +#define GITS_BASER_PAGE_SIZE_SHIFT (8) +#define GITS_BASER_PAGE_SIZE_4K (0UL << GITS_BASER_PAGE_SIZE_SHIFT) +#define GITS_BASER_PAGE_SIZE_16K (1UL << GITS_BASER_PAGE_SIZE_SHIFT) +#define GITS_BASER_PAGE_SIZE_64K (2UL << GITS_BASER_PAGE_SIZE_SHIFT) +#define GITS_BASER_PAGE_SIZE_MASK (3UL << GITS_BASER_PAGE_SIZE_SHIFT) +#define GITS_BASER_PAGES_MAX 256 +#define GITS_BASER_PAGES_SHIFT (0) +#define GITS_BASER_NR_PAGES (r) (((r) & 0xff) + 1) +#define GITS_BASER_PHYS_ADDR_MASK 0xFFFFFFFFF000 +#define GITS_BASER_TYPE_NONE 0 +#define GITS_BASER_TYPE_DEVICE 1 +#define GITS_BASER_TYPE_COLLECTION 4 + +extern void its_parse_typer (void ); +extern void its_init (void ); +extern int its_baser_lookup (int i,struct its_baser *baser); + +#endif /* _ASMARM64_GIC_V3_ITS_H_ */ lib/arm64/gic-v3-its.c new file +55
-0@@ -0,0 +1,102 @@ +/* +* Copyright (C) 2020, Red Hat Inc, Eric Auger <[email protected]> +* +* This work is licensed under the terms of the GNU LGPL, version 2. +*/ +#include <asm/gic.h> +#include <alloc_page.h> +#include <asm/gic-v3-its.h> + +void its_parse_typer (void ) +{ +u64 typer =readq (gicv3_its_base () +GITS_TYPER ); +struct its_typer *t = &its_data.typer; + + t->ite_size = ((typer &GITS_TYPER_ITT_ENTRY_SIZE ) >>GITS_TYPER_ITT_ENTRY_SIZE_SHIFT ) +1 ; + t->pta = typer &GITS_TYPER_PTA ; + t->eventid_bits = ((typer &GITS_TYPER_IDBITS ) >>GITS_TYPER_IDBITS_SHIFT ) +1 ; + t->deviceid_bits = ((typer &GITS_TYPER_DEVBITS ) >>GITS_TYPER_DEVBITS_SHIFT ) +1 ; + +if (typer &GITS_TYPER_CIL ) + t->collid_bits = ((typer &GITS_TYPER_CIDBITS ) >>GITS_TYPER_CIDBITS_SHIFT ) +1 ; +else + t->collid_bits =16 ; + + t->virt_lpi = typer &GITS_TYPER_VLPIS ; + t->phys_lpi = typer &GITS_TYPER_PLPIS ; +} + +int its_baser_lookup (int type,struct its_baser *baser) +{ +int i; + +for (i =0 ; i <GITS_BASER_NR_REGS ; i++) { +void *reg_addr =gicv3_its_base () +GITS_BASER + i *8 ; +u64 val =readq (reg_addr); + +if (GITS_BASER_TYPE (val) == type) { +assert ((val &GITS_BASER_PAGE_SIZE_MASK ) ==GITS_BASER_PAGE_SIZE_64K ); + baser->esz =GITS_BASER_ENTRY_SIZE (val); + baser->indirect = val &GITS_BASER_INDIRECT ; + baser->index = i; +return 0 ; + } + } +return -1 ; +} + +/* +* Allocate the BASER table (a single page of size @baser->psz) +* and set the BASER valid +*/ +static void its_baser_alloc_table (struct its_baser *baser,size_t size) +{ +unsigned long order =get_order (size >>PAGE_SHIFT ); +void *reg_addr =gicv3_its_base () +GITS_BASER + baser->index *8 ;
lib/arm64/gic-v3-its.c line 65
Quoted 10 lines
lib/arm64/gic-v3-its.c new file +10
-0+u64 val =readq (reg_addr); + + baser->table_addr = (u64 )virt_to_phys (alloc_pages (order)); + + val |= (u64 )baser->table_addr |GITS_BASER_VALID ; + +writeq (val, reg_addr); +} + +/**
nit: this isn't a kernel-doc comment, one * is enough
Quoted 40 lines
lib/arm64/gic-v3-its.c new file +37
-0+* init_cmd_queue - Allocate the command queue and initialize +* CBASER, CWRITER +*/ +static void its_cmd_queue_init (void ) +{ +unsigned long order =get_order (SZ_64K >>PAGE_SHIFT ); +u64 cbaser; + + its_data.cmd_base = (void *)virt_to_phys (alloc_pages (order)); + + cbaser = ((u64 )its_data.cmd_base | (SZ_64K /SZ_4K -1 ) |GITS_CBASER_VALID ); + +writeq (cbaser, its_data.base +GITS_CBASER ); + + its_data.cmd_write = its_data.cmd_base; +writeq (0 , its_data.base +GITS_CWRITER ); +} + +void its_init (void ) +{ +if (!its_data.base) +return ; + +its_parse_typer (); + +assert (!its_baser_lookup (GITS_BASER_TYPE_DEVICE , &its_data.device_baser)); +assert (!its_baser_lookup (GITS_BASER_TYPE_COLLECTION , &its_data.coll_baser)); + +its_baser_alloc_table (&its_data.device_baser,SZ_64K ); +its_baser_alloc_table (&its_data.coll_baser,SZ_64K ); + +/* Allocate LPI config and pending tables */ +gicv3_lpi_alloc_tables (); + +its_cmd_queue_init (); +} +Signature · 1 line
2.20.1
Thanks,
drew
Re: [kvm-unit-tests PATCH v4 06/13] arm/arm64: ITS: Introspection tests
Hi,
Quoted 172 lines · Andrew Jones
Quoted 171 lines · Eric Auger
Detect the presence of an ITS as part of the GICv3 init routine, initialize its base address and read few registers the IIDR, the TYPER to store its dimensioning parameters. Parse the BASER registers. As part of the init sequence we also init all the requested tables.
This is our first ITS test, belonging to a new "its" group.
Signed-off-by Eric Auger <[email protected]>---
v3 -> v4:
- fixed some typos, refine trace msgs
- move its files to lib/arm64 instead of lib/arm
- createlib/arm/asm/gic-v3-its.hcontaining stubs
- reworkgic_get_dt_bases
- rework baser parsing
- move table allocation to init routine
- useget_order()v2 -> v3:
- updated dates and changed author
- squash "arm/arm64: ITS: Test BASER" into this patch but removessetup_baserwhich will be introduced later.
- only compile on aarch64
- restrict the new test to aarch64v1 -> v2:
- cleanGITS_TYPERmacros and unused fields in typer struct
- remove memory attribute related macros
- remove everything related to memory attributes
- s/dev_baser/coll_baser/ inreport_info
- add extra line
- removed index filed inits_baser--- arm/Makefile.arm64 | 1 + arm/gic.c | 44 ++++++++++++++++ arm/unittests.cfg | 7 +++ lib/arm/asm/gic-v3-its.h | 23 +++++++++ lib/arm/gic.c | 34 +++++++++++-- lib/arm64/asm/gic-v3-its.h | 92 +++++++++++++++++++++++++++++++++ lib/arm64/gic-v3-its.c | 102 +++++++++++++++++++++++++++++++++++++ 7 files changed, 298 insertions(+), 5 deletions(-) create mode 100644 lib/arm/asm/gic-v3-its.h create mode 100644 lib/arm64/asm/gic-v3-its.h create mode 100644 lib/arm64/gic-v3-its.carm/Makefile.arm64 +1
-0@@ -19,6 +19,7 @@ endef cstart.o = $(TEST_DIR)/cstart64.o cflatobjs += lib/arm64/processor.o cflatobjs += lib/arm64/spinlock.o +cflatobjs += lib/arm64/gic-v3-its.o OBJDIRS += lib/arm64arm/gic.c +44
-0@@ -16,6 +16,7 @@#include <asm/processor.h> #include <asm/delay.h> #include <asm/gic.h> +#include <asm/gic-v3-its.h> #include <asm/smp.h> #include <asm/barrier.h> #include <asm/io.h> @@ -518,6 +519,45 @@ static void gic_test_mmio(void)test_targets (nr_irqs); } +#if defined(__aarch64__) + +static void test_its_introspection (void ) +{ +struct its_baser *dev_baser = &its_data.device_baser; +struct its_baser *coll_baser = &its_data.coll_baser; +struct its_typer *typer = &its_data.typer; + +if (!gicv3_its_base ()) { +report_skip ("No ITS, skip ..." ); +return ; + } + +/* IIDR */ +report (test_readonly_32 (gicv3_its_base () +GITS_IIDR , false), +"GITS_IIDR is read-only" ), + +/* TYPER */ +report (test_readonly_32 (gicv3_its_base () +GITS_TYPER , false), +"GITS_TYPER is read-only" ); + +report (typer->phys_lpi,"ITS supports physical LPIs" ); +report_info ("vLPI support: %s" , typer->virt_lpi ?"yes" :"no" ); +report_info ("ITT entry size = 0x%x" , typer->ite_size); +report_info ("Bit Count: EventID=%d DeviceId=%d CollId=%d" , + typer->eventid_bits, typer->deviceid_bits, + typer->collid_bits); +report (typer->eventid_bits && typer->deviceid_bits && + typer->collid_bits,"ID spaces" ); +report_info ("Target address format %s" , + typer->pta ?"Redist base address" :"PE #" ); + +report (dev_baser && coll_baser,"detect device and collection BASER" ); +report_info ("device table entry_size = 0x%x" , dev_baser->esz); +report_info ("collection table entry_size = 0x%x" , coll_baser->esz); +} + +#endif +int main (int argc,char **argv) {if (!gic_init ()) {@@ -549,6 +589,10 @@ int main(int argc, char **argv)report_prefix_push (argv[1 ]);gic_test_mmio ();report_prefix_pop (); + }else if (strcmp (argv[1 ],"its-introspection" ) ==0 ) { +report_prefix_push (argv[1 ]); +test_its_introspection (); +report_prefix_pop (); }else {report_abort ("Unknown subtest '%s'" , argv[1 ]); }arm/unittests.cfg +7
-0@@ -122,6 +122,13 @@ smp = $MAX_SMP extra_params = -machine gic-version=3 -append 'active' groups = gic +[its-introspection] +file = gic.flat +smp = $MAX_SMP +extra_params = -machine gic-version=3 -append 'its-introspection' +groups = its +arch = arm64 + # Test PSCI emulation [psci] file = psci.flatlib/arm/asm/gic-v3-its.h new file +18
-0@@ -0,0 +1,23 @@ +/* +* ITS 32-bit stubs +* +* Copyright (C) 2020, Red Hat Inc, Eric Auger <[email protected]> +* +* This work is licensed under the terms of the GNU LGPL, version 2. +*/ + +#ifndef _ASMARM_GICv3_ITS +#define _ASMARM_GICv3_ITS + +/* dummy its_data struct to allow gic_get_dt_bases() call */ +struct its_data { +void *base; +}; + +static inline void its_init (void ) {} +static inline void test_its_introspection (void )
Quoted 8 lines
lib/arm/asm/gic-v3-its.h line 20
Quoted 2 lines
lib/arm/asm/gic-v3-its.h new file +2
-0+{ +report_abort ("not supported on 32-bit" );I suggested
report_abort()in this function when it was inarm/gic.c, but we don't want report_* functions in the library code, nor do we want functions named test_*. This test_* stub should go back toarm/gic.c, where it can be empty, because the 32-bitits_init()stub here could get anassert_msg("not supported on 32-bit")instead.
OK I did not get your comment.
Thanks
Eric
Quoted 303 lines
Quoted 246 lines
lib/arm/asm/gic-v3-its.h new file +3
-0+} + +#endif /* _ASMARM_GICv3_ITS */ lib/arm/gic.c +29
-5@@ -6,9 +6,11 @@#include <devicetree.h> #include <asm/gic.h> #include <asm/io.h> +#include <asm/gic-v3-its.h> struct gicv2_data gicv2_data;struct gicv3_data gicv3_data; +struct its_data its_data;struct gic_common_ops {void (*enable_defaults)(void );@@ -44,12 +46,13 @@ static const struct gic_common_ops gicv3_common_ops = {* Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt */ static bool -gic_get_dt_bases (const char *compatible,void **base1,void **base2) +gic_get_dt_bases (const char *compatible,void **base1,void **base2,void **base3) {struct dt_pbus_reg reg; -struct dt_device gic; +struct dt_device gic, its;struct dt_bus bus; -int node, ret, i; +int node, subnode, ret, i, len; +const void *fdt =dt_fdt ();dt_bus_init_defaults (&bus);dt_device_init (&gic, &bus,NULL );@@ -74,19 +77,39 @@ gic_get_dt_bases(const char *compatible, void **base1, void **base2) base2[i] =ioremap (reg.addr, reg.size); } +if (!base3) { +assert (!strcmp (compatible,"arm,cortex-a15-gic" )); +return true; + } + +assert (!strcmp (compatible,"arm,gic-v3" )); + +dt_for_each_subnode (node, subnode) { +const struct fdt_property *prop; + + prop =fdt_get_property (fdt, subnode,"compatible" , &len); +if (!strcmp ((char *)prop->data,"arm,gic-v3-its" )) { +dt_device_bind_node (&its, subnode); + ret =dt_pbus_translate (&its,0 , ®); +assert (ret ==0 ); + *base3 =ioremap (reg.addr, reg.size); +break ; + } + } +return true; }int gicv2_init (void ) {return gic_get_dt_bases ("arm,cortex-a15-gic" , - &gicv2_data.dist_base, &gicv2_data.cpu_base); + &gicv2_data.dist_base, &gicv2_data.cpu_base,NULL ); }int gicv3_init (void ) {return gic_get_dt_bases ("arm,gic-v3" , &gicv3_data.dist_base, - &gicv3_data.redist_bases[0 ]); + &gicv3_data.redist_bases[0 ], &its_data.base); }int gic_version (void )@@ -104,6 +127,7 @@ int gic_init(void) gic_common_ops = &gicv2_common_ops; else if (gicv3_init()) gic_common_ops = &gicv3_common_ops; +its_init ();return gic_version (); }lib/arm64/asm/gic-v3-its.h new file +92
-0@@ -0,0 +1,92 @@ +/* +* All ITS* defines are lifted from include/linux/irqchip/arm-gic-v3.h +* +* Copyright (C) 2020, Red Hat Inc, Eric Auger <[email protected]> +* +* This work is licensed under the terms of the GNU LGPL, version 2. +*/ +#ifndef _ASMARM64_GIC_V3_ITS_H_ +#define _ASMARM64_GIC_V3_ITS_H_ + +struct its_typer { +unsigned int ite_size; +unsigned int eventid_bits; +unsigned int deviceid_bits; +unsigned int collid_bits; +bool pta; +bool phys_lpi; +bool virt_lpi; +}; + +struct its_baser { +int index; +size_t psz; +int esz; +bool indirect; +phys_addr_t table_addr; +}; + +#define GITS_BASER_NR_REGS 8 + +struct its_data { +void *base; +struct its_typer typer; +struct its_baser device_baser; +struct its_baser coll_baser; +struct its_cmd_block *cmd_base; +struct its_cmd_block *cmd_write; +}; + +extern struct its_data its_data; + +#define gicv3_its_base () (its_data.base) + +#define GITS_CTLR 0x0000 +#define GITS_IIDR 0x0004 +#define GITS_TYPER 0x0008 +#define GITS_CBASER 0x0080 +#define GITS_CWRITER 0x0088 +#define GITS_CREADR 0x0090 +#define GITS_BASER 0x0100 + +#define GITS_TYPER_PLPIS BIT(0) +#define GITS_TYPER_VLPIS BIT(1) +#define GITS_TYPER_ITT_ENTRY_SIZE GENMASK_ULL(7, 4) +#define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT 4 +#define GITS_TYPER_IDBITS GENMASK_ULL(8, 12) +#define GITS_TYPER_IDBITS_SHIFT 8 +#define GITS_TYPER_DEVBITS GENMASK_ULL(13, 17) +#define GITS_TYPER_DEVBITS_SHIFT 13 +#define GITS_TYPER_PTA BIT(19) +#define GITS_TYPER_CIDBITS GENMASK_ULL(32, 35) +#define GITS_TYPER_CIDBITS_SHIFT 32 +#define GITS_TYPER_CIL BIT(36) + +#define GITS_CTLR_ENABLE (1U << 0) + +#define GITS_CBASER_VALID (1UL << 63) + +#define GITS_BASER_VALID BIT(63) +#define GITS_BASER_INDIRECT BIT(62) +#define GITS_BASER_TYPE_SHIFT (56) +#define GITS_BASER_TYPE (r) (((r) >> GITS_BASER_TYPE_SHIFT) & 7) +#define GITS_BASER_ENTRY_SIZE_SHIFT (48) +#define GITS_BASER_ENTRY_SIZE (r) ((((r) >> GITS_BASER_ENTRY_SIZE_SHIFT) & 0x1f) + 1) +#define GITS_BASER_PAGE_SIZE_SHIFT (8) +#define GITS_BASER_PAGE_SIZE_4K (0UL << GITS_BASER_PAGE_SIZE_SHIFT) +#define GITS_BASER_PAGE_SIZE_16K (1UL << GITS_BASER_PAGE_SIZE_SHIFT) +#define GITS_BASER_PAGE_SIZE_64K (2UL << GITS_BASER_PAGE_SIZE_SHIFT) +#define GITS_BASER_PAGE_SIZE_MASK (3UL << GITS_BASER_PAGE_SIZE_SHIFT) +#define GITS_BASER_PAGES_MAX 256 +#define GITS_BASER_PAGES_SHIFT (0) +#define GITS_BASER_NR_PAGES (r) (((r) & 0xff) + 1) +#define GITS_BASER_PHYS_ADDR_MASK 0xFFFFFFFFF000 +#define GITS_BASER_TYPE_NONE 0 +#define GITS_BASER_TYPE_DEVICE 1 +#define GITS_BASER_TYPE_COLLECTION 4 + +extern void its_parse_typer (void ); +extern void its_init (void ); +extern int its_baser_lookup (int i,struct its_baser *baser); + +#endif /* _ASMARM64_GIC_V3_ITS_H_ */ lib/arm64/gic-v3-its.c new file +55
-0@@ -0,0 +1,102 @@ +/* +* Copyright (C) 2020, Red Hat Inc, Eric Auger <[email protected]> +* +* This work is licensed under the terms of the GNU LGPL, version 2. +*/ +#include <asm/gic.h> +#include <alloc_page.h> +#include <asm/gic-v3-its.h> + +void its_parse_typer (void ) +{ +u64 typer =readq (gicv3_its_base () +GITS_TYPER ); +struct its_typer *t = &its_data.typer; + + t->ite_size = ((typer &GITS_TYPER_ITT_ENTRY_SIZE ) >>GITS_TYPER_ITT_ENTRY_SIZE_SHIFT ) +1 ; + t->pta = typer &GITS_TYPER_PTA ; + t->eventid_bits = ((typer &GITS_TYPER_IDBITS ) >>GITS_TYPER_IDBITS_SHIFT ) +1 ; + t->deviceid_bits = ((typer &GITS_TYPER_DEVBITS ) >>GITS_TYPER_DEVBITS_SHIFT ) +1 ; + +if (typer &GITS_TYPER_CIL ) + t->collid_bits = ((typer &GITS_TYPER_CIDBITS ) >>GITS_TYPER_CIDBITS_SHIFT ) +1 ; +else + t->collid_bits =16 ; + + t->virt_lpi = typer &GITS_TYPER_VLPIS ; + t->phys_lpi = typer &GITS_TYPER_PLPIS ; +} + +int its_baser_lookup (int type,struct its_baser *baser) +{ +int i; + +for (i =0 ; i <GITS_BASER_NR_REGS ; i++) { +void *reg_addr =gicv3_its_base () +GITS_BASER + i *8 ; +u64 val =readq (reg_addr); + +if (GITS_BASER_TYPE (val) == type) { +assert ((val &GITS_BASER_PAGE_SIZE_MASK ) ==GITS_BASER_PAGE_SIZE_64K ); + baser->esz =GITS_BASER_ENTRY_SIZE (val); + baser->indirect = val &GITS_BASER_INDIRECT ; + baser->index = i; +return 0 ; + } + } +return -1 ; +} + +/* +* Allocate the BASER table (a single page of size @baser->psz) +* and set the BASER valid +*/ +static void its_baser_alloc_table (struct its_baser *baser,size_t size) +{ +unsigned long order =get_order (size >>PAGE_SHIFT ); +void *reg_addr =gicv3_its_base () +GITS_BASER + baser->index *8 ;lib/arm64/gic-v3-its.c line 65
Quoted 10 lines
lib/arm64/gic-v3-its.c new file +10
-0+u64 val =readq (reg_addr); + + baser->table_addr = (u64 )virt_to_phys (alloc_pages (order)); + + val |= (u64 )baser->table_addr |GITS_BASER_VALID ; + +writeq (val, reg_addr); +} + +/** nit: this isn't a kernel-doc comment, one * is enough
Quoted 40 lines
lib/arm64/gic-v3-its.c new file +37
-0+* init_cmd_queue - Allocate the command queue and initialize +* CBASER, CWRITER +*/ +static void its_cmd_queue_init (void ) +{ +unsigned long order =get_order (SZ_64K >>PAGE_SHIFT ); +u64 cbaser; + + its_data.cmd_base = (void *)virt_to_phys (alloc_pages (order)); + + cbaser = ((u64 )its_data.cmd_base | (SZ_64K /SZ_4K -1 ) |GITS_CBASER_VALID ); + +writeq (cbaser, its_data.base +GITS_CBASER ); + + its_data.cmd_write = its_data.cmd_base; +writeq (0 , its_data.base +GITS_CWRITER ); +} + +void its_init (void ) +{ +if (!its_data.base) +return ; + +its_parse_typer (); + +assert (!its_baser_lookup (GITS_BASER_TYPE_DEVICE , &its_data.device_baser)); +assert (!its_baser_lookup (GITS_BASER_TYPE_COLLECTION , &its_data.coll_baser)); + +its_baser_alloc_table (&its_data.device_baser,SZ_64K ); +its_baser_alloc_table (&its_data.coll_baser,SZ_64K ); + +/* Allocate LPI config and pending tables */ +gicv3_lpi_alloc_tables (); + +its_cmd_queue_init (); +} +Signature · 1 line
2.20.1Thanks,
drew
PATCH v4 7/13 arm/arm64: ITS: its_enable_defaults
In reply to Eric Augerits_enable_defaults() enable LPIs at distributor level and ITS level.
gicv3_enable_defaults must be called before.
---
v3 -> v4:
- use GITS_BASER_INDIRECT & GITS_BASER_VALID in its_setup_baser()
- don't parse BASERs again in its_enable_defaults
- rename its_setup_baser into its_baser_alloc_table
- All allocations moved to the init function
- squashed "arm/arm64: gicv3: Enable/Disable LPIs at re-distributor level" into this patch
- introduce gicv3_lpi_rdist_enable and gicv3_lpi_rdist_disable
- pend and prop table bases stored as virt addresses
- move some init functions from enable() to its_init
- removed GICR_PROPBASER_IDBITS_MASK
- introduced LPI_OFFSET
- lpi_prop becomes u8 *
- gicv3_lpi_set_config/get_config became macro
- renamed gicv3_lpi_set_pending_table_bit into gicv3_lpi_set_clr_pending
v2 -> v3:
- introduce its_setup_baser in this patch
- squash "arm/arm64: ITS: Init the command queue" in this patch.
--- lib/arm/asm/gic-v3.h | 28 +++++++++++------ lib/arm/gic-v3.c | 64 ++++++++++++++++++++++---------------- lib/arm64/asm/gic-v3-its.h | 1 + lib/arm64/gic-v3-its.c | 16 ++++++++-- 4 files changed, 71 insertions(+), 38 deletions(-)
lib/arm/asm/gic-v3.h +19 -9
@@ -50,15 +50,16 @@#define MPIDR_TO_SGI_AFFINITY (cluster_id, level) \ (MPIDR_AFFINITY_LEVEL(cluster_id, level) << ICC_SGI1R_AFFINITY_## level ## _SHIFT) -#define GICR_PROPBASER_IDBITS_MASK (0x1f) +#define GICR_PENDBASER_PTZ BIT_ULL(62) -#define GICR_PENDBASER_PTZ BIT_ULL(62) +#define LPI_PROP_GROUP1 (1 << 1) +#define LPI_PROP_ENABLED (1 << 0) +#define LPI_PROP_DEFAULT_PRIO 0xa0 +#define LPI_PROP_DEFAULT (LPI_PROP_DEFAULT_PRIO | LPI_PROP_GROUP1 | LPI_PROP_ENABLED) -#define LPI_PROP_GROUP1 (1 << 1) -#define LPI_PROP_ENABLED (1 << 0) -#define LPI_PROP_DEFAULT_PRIO 0xa0 -#define LPI_PROP_DEFAULT (LPI_PROP_DEFAULT_PRIO | LPI_PROP_GROUP1 | \ - LPI_PROP_ENABLED) +#define LPI_ID_BASE 8192 +#define LPI (lpi) ((lpi) + LPI_ID_BASE) +#define LPI_OFFSET (intid) ((intid) - LPI_ID_BASE)#include <asm/arch_gicv3.h>
@@ -76,7 +77,7 @@ struct gicv3_data {void *dist_base;void *redist_bases[GICV3_NR_REDISTS ];void *redist_base[NR_CPUS ]; -void *lpi_prop; +u8 *lpi_prop;void *lpi_pend[NR_CPUS ];unsigned int irq_nr; };
@@ -96,8 +97,10 @@ extern void gicv3_ipi_send_mask(int irq, const cpumask_t *dest);extern void gicv3_set_redist_base (size_t stride);extern void gicv3_lpi_set_config (int n,u8 val);extern u8 gicv3_lpi_get_config (int n); -extern void gicv3_lpi_set_pending_table_bit (int rdist,int n,bool set); +extern void gicv3_lpi_set_clr_pending (int rdist,int n,bool set);extern void gicv3_lpi_alloc_tables (void ); +extern void gicv3_lpi_rdist_enable (int redist); +extern void gicv3_lpi_rdist_disable (int redist);static inline void gicv3_do_wait_for_rwp (void *base) {
@@ -143,5 +146,12 @@ static inline u64 mpidr_uncompress(u32 compressed)return mpidr; } +#define gicv3_lpi_set_config (intid, value) ({ \ + gicv3_data.lpi_prop[LPI_OFFSET(intid)] = value; \ +}) + +#define gicv3_lpi_get_config (intid) (gicv3_data.lpi_prop[LPI_OFFSET(intid)]) + +#endif /* !__ASSEMBLY__ */ #endif /* _ASMARM_GIC_V3_H_ */
lib/arm/gic-v3.c +38 -26
92 lines not on this page · raw message
lib/arm64/asm/gic-v3-its.h +1 -0
@@ -88,5 +88,6 @@ extern struct its_data its_data;extern void its_parse_typer (void );extern void its_init (void );extern int its_baser_lookup (int i,struct its_baser *baser); +extern void its_enable_defaults (void );#endif /* _ASMARM64_GIC_V3_ITS_H_ */
lib/arm64/gic-v3-its.c +13 -3
@@ -94,9 +94,19 @@ void its_init(void)its_baser_alloc_table (&its_data.device_baser,SZ_64K );its_baser_alloc_table (&its_data.coll_baser,SZ_64K ); -/* Allocate LPI config and pending tables */ -gicv3_lpi_alloc_tables (); -its_cmd_queue_init (); } +/* must be called after gicv3_enable_defaults */ +void its_enable_defaults (void ) +{ +int i; + +/* Allocate LPI config and pending tables */ +gicv3_lpi_alloc_tables (); + +for (i =0 ; i < nr_cpus; i++) +gicv3_lpi_rdist_enable (i); + +writel (GITS_CTLR_ENABLE , its_data.base +GITS_CTLR ); +}
Signature · 1 line
2.20.1
Re: [kvm-unit-tests PATCH v4 07/13] arm/arm64: ITS: its_enable_defaults
Quoted 46 lines · Eric Auger
its_enable_defaults()enable LPIs at distributor level and ITS level.
gicv3_enable_defaultsmust be called before.Signed-off-by Eric Auger <[email protected]>---
v3 -> v4:
- useGITS_BASER_INDIRECT&GITS_BASER_VALIDinits_setup_baser()
- don't parse BASERs again inits_enable_defaults
- renameits_setup_baserintoits_baser_alloc_table
- All allocations moved to the init function
- squashed "arm/arm64: gicv3: Enable/Disable LPIs at re-distributor level" into this patch
- introducegicv3_lpi_rdist_enableandgicv3_lpi_rdist_disable
- pend and prop table bases stored as virt addresses
- move some init functions fromenable()toits_init
- removedGICR_PROPBASER_IDBITS_MASK
- introducedLPI_OFFSET
-lpi_propbecomes u8 *
- gicv3_lpi_set_config/get_config became macro
- renamedgicv3_lpi_set_pending_table_bitintogicv3_lpi_set_clr_pendingv2 -> v3:
- introduceits_setup_baserin this patch
- squash "arm/arm64: ITS: Init the command queue" in this patch.--- lib/arm/asm/gic-v3.h | 28 +++++++++++------ lib/arm/gic-v3.c | 64 ++++++++++++++++++++++---------------- lib/arm64/asm/gic-v3-its.h | 1 + lib/arm64/gic-v3-its.c | 16 ++++++++-- 4 files changed, 71 insertions(+), 38 deletions(-)lib/arm/asm/gic-v3.h +1
-2@@ -50,15 +50,16 @@#define MPIDR_TO_SGI_AFFINITY (cluster_id, level) \ (MPIDR_AFFINITY_LEVEL(cluster_id, level) << ICC_SGI1R_AFFINITY_## level ## _SHIFT) -#define GICR_PROPBASER_IDBITS_MASK (0x1f) +#define GICR_PENDBASER_PTZ BIT_ULL(62) -#define GICR_PENDBASER_PTZ BIT_ULL(62)
lib/arm/asm/gic-v3.h line 61
Quoted 10 lines
lib/arm/asm/gic-v3.h +4
-5+#define LPI_PROP_GROUP1 (1 << 1) +#define LPI_PROP_ENABLED (1 << 0) +#define LPI_PROP_DEFAULT_PRIO 0xa0 +#define LPI_PROP_DEFAULT (LPI_PROP_DEFAULT_PRIO | LPI_PROP_GROUP1 | LPI_PROP_ENABLED) -#define LPI_PROP_GROUP1 (1 << 1) -#define LPI_PROP_ENABLED (1 << 0) -#define LPI_PROP_DEFAULT_PRIO 0xa0 -#define LPI_PROP_DEFAULT (LPI_PROP_DEFAULT_PRIO | LPI_PROP_GROUP1 | \ - LPI_PROP_ENABLED)
This reformatting should be squashed into 5/13.
Quoted 45 lines
lib/arm/asm/gic-v3.h +14
-2+#define LPI_ID_BASE 8192 +#define LPI (lpi) ((lpi) + LPI_ID_BASE) +#define LPI_OFFSET (intid) ((intid) - LPI_ID_BASE)#include <asm/arch_gicv3.h> @@ -76,7 +77,7 @@ struct gicv3_data {void *dist_base;void *redist_bases[GICV3_NR_REDISTS ];void *redist_base[NR_CPUS ]; -void *lpi_prop; +u8 *lpi_prop;void *lpi_pend[NR_CPUS ];unsigned int irq_nr; };@@ -96,8 +97,10 @@ extern void gicv3_ipi_send_mask(int irq, const cpumask_t *dest);extern void gicv3_set_redist_base (size_t stride);extern void gicv3_lpi_set_config (int n,u8 val);extern u8 gicv3_lpi_get_config (int n); -extern void gicv3_lpi_set_pending_table_bit (int rdist,int n,bool set); +extern void gicv3_lpi_set_clr_pending (int rdist,int n,bool set);extern void gicv3_lpi_alloc_tables (void ); +extern void gicv3_lpi_rdist_enable (int redist); +extern void gicv3_lpi_rdist_disable (int redist);static inline void gicv3_do_wait_for_rwp (void *base) {@@ -143,5 +146,12 @@ static inline u64 mpidr_uncompress(u32 compressed)return mpidr; } +#define gicv3_lpi_set_config (intid, value) ({ \ + gicv3_data.lpi_prop[LPI_OFFSET(intid)] = value; \ +}) + +#define gicv3_lpi_get_config (intid) (gicv3_data.lpi_prop[LPI_OFFSET(intid)]) + +#endif /* !__ASSEMBLY__ */ #endif /* _ASMARM_GIC_V3_H_ */ lib/arm/gic-v3.c +0
-0
lib/arm/gic-v3.c void gicv3_ipi_send_single(int irq, int cpu) · line 154
Quoted 6 lines
lib/arm/gic-v3.c +2
-1@@ -150,7 +150,14 @@ void gicv3_ipi_send_single(int irq, int cpu) }#if defined(__aarch64__) -/* alloc_lpi_tables: Allocate LPI config and pending tables */ + +/**
*
lib/arm/gic-v3.c void gicv3_ipi_send_single(int irq, int cpu) · line 159
Quoted 5 lines
lib/arm/gic-v3.c +5
-0+* alloc_lpi_tables - Allocate LPI config and pending tables +* and set PROPBASER (shared by all rdistributors) and per +* redistributor PENDBASER. +* +* gicv3_set_redist_base() must be called before
How about asserting gicv3_redist_base() isn't NULL?
Quoted 125 lines
lib/arm/gic-v3.c +31
-25+*/ void gicv3_lpi_alloc_tables (void ) {unsigned long n =SZ_64K >>PAGE_SHIFT ;@@ -161,13 +168,9 @@ void gicv3_lpi_alloc_tables(void) gicv3_data.lpi_prop =alloc_pages (order);/* ID bits = 13, ie. up to 14b LPI INTID */ - prop_val = (u64 )virt_to_phys (gicv3_data.lpi_prop) |13 ; + prop_val = (u64)(virt_to_phys (gicv3_data.lpi_prop)) |13 ; -/* -* Allocate pending tables for each redistributor -* and set PROPBASER and PENDBASER -*/ -for_each_present_cpu (cpu) { +for (cpu =0 ; cpu < nr_cpus; cpu++) {u64 pend_val;void *ptr;@@ -176,30 +179,14 @@ void gicv3_lpi_alloc_tables(void)writeq (prop_val, ptr +GICR_PROPBASER ); gicv3_data.lpi_pend[cpu] =alloc_pages (order); - - pend_val = (u64 )virt_to_phys (gicv3_data.lpi_pend[cpu]); - + pend_val = (u64)(virt_to_phys (gicv3_data.lpi_pend[cpu]));writeq (pend_val, ptr +GICR_PENDBASER ); } } -void gicv3_lpi_set_config (int n,u8 value) +void gicv3_lpi_set_clr_pending (int rdist,int n,bool set) { -u8 *entry = (u8 *)(gicv3_data.lpi_prop + (n -8192 )); - - *entry = value; -} - -u8 gicv3_lpi_get_config (int n) -{ -u8 *entry = (u8 *)(gicv3_data.lpi_prop + (n -8192 )); - -return *entry; -} - -void gicv3_lpi_set_pending_table_bit (int rdist,int n,bool set) -{ -u8 *ptr =phys_to_virt ((phys_addr_t )gicv3_data.lpi_pend[rdist]); +u8 *ptr = gicv3_data.lpi_pend[rdist];u8 mask =1 << (n %8 ), byte; ptr += (n /8 );@@ -210,4 +197,29 @@ void gicv3_lpi_set_pending_table_bit(int rdist, int n, bool set) byte &= ~mask; *ptr = byte; } + +static void gicv3_lpi_rdist_ctrl (u32 redist,bool set) +{ +void *ptr; +u64 val; + +assert (redist < nr_cpus); + + ptr = gicv3_data.redist_base[redist]; + val =readl (ptr +GICR_CTLR ); +if (set) + val |=GICR_CTLR_ENABLE_LPIS ; +else + val &= ~GICR_CTLR_ENABLE_LPIS ; +writel (val, ptr +GICR_CTLR ); +} + +void gicv3_lpi_rdist_enable (int redist) +{ +gicv3_lpi_rdist_ctrl (redist, true); +} +void gicv3_lpi_rdist_disable (int redist) +{ +gicv3_lpi_rdist_ctrl (redist, false); +}#endif /* __aarch64__ */ lib/arm64/asm/gic-v3-its.h +1
-0@@ -88,5 +88,6 @@ extern struct its_data its_data;extern void its_parse_typer (void );extern void its_init (void );extern int its_baser_lookup (int i,struct its_baser *baser); +extern void its_enable_defaults (void );#endif /* _ASMARM64_GIC_V3_ITS_H_ */ lib/arm64/gic-v3-its.c +13
-3@@ -94,9 +94,19 @@ void its_init(void)its_baser_alloc_table (&its_data.device_baser,SZ_64K );its_baser_alloc_table (&its_data.coll_baser,SZ_64K ); -/* Allocate LPI config and pending tables */ -gicv3_lpi_alloc_tables (); -its_cmd_queue_init (); } +/* must be called after gicv3_enable_defaults */ +void its_enable_defaults (void ) +{ +int i; + +/* Allocate LPI config and pending tables */ +gicv3_lpi_alloc_tables (); + +for (i =0 ; i < nr_cpus; i++) +gicv3_lpi_rdist_enable (i); + +writel (GITS_CTLR_ENABLE , its_data.base +GITS_CTLR ); +}Signature · 1 line
2.20.1
Re: [kvm-unit-tests PATCH v4 07/13] arm/arm64: ITS: its_enable_defaults
In reply to Eric AugerQuoted 119 lines · Eric Auger
its_enable_defaults()enable LPIs at distributor level and ITS level.
gicv3_enable_defaultsmust be called before.Signed-off-by Eric Auger <[email protected]>---
v3 -> v4:
- useGITS_BASER_INDIRECT&GITS_BASER_VALIDinits_setup_baser()
- don't parse BASERs again inits_enable_defaults
- renameits_setup_baserintoits_baser_alloc_table
- All allocations moved to the init function
- squashed "arm/arm64: gicv3: Enable/Disable LPIs at re-distributor level" into this patch
- introducegicv3_lpi_rdist_enableandgicv3_lpi_rdist_disable
- pend and prop table bases stored as virt addresses
- move some init functions fromenable()toits_init
- removedGICR_PROPBASER_IDBITS_MASK
- introducedLPI_OFFSET
-lpi_propbecomes u8 *
- gicv3_lpi_set_config/get_config became macro
- renamedgicv3_lpi_set_pending_table_bitintogicv3_lpi_set_clr_pendingv2 -> v3:
- introduceits_setup_baserin this patch
- squash "arm/arm64: ITS: Init the command queue" in this patch.--- lib/arm/asm/gic-v3.h | 28 +++++++++++------ lib/arm/gic-v3.c | 64 ++++++++++++++++++++++---------------- lib/arm64/asm/gic-v3-its.h | 1 + lib/arm64/gic-v3-its.c | 16 ++++++++-- 4 files changed, 71 insertions(+), 38 deletions(-)lib/arm/asm/gic-v3.h +19
-9@@ -50,15 +50,16 @@#define MPIDR_TO_SGI_AFFINITY (cluster_id, level) \ (MPIDR_AFFINITY_LEVEL(cluster_id, level) << ICC_SGI1R_AFFINITY_## level ## _SHIFT) -#define GICR_PROPBASER_IDBITS_MASK (0x1f) +#define GICR_PENDBASER_PTZ BIT_ULL(62) -#define GICR_PENDBASER_PTZ BIT_ULL(62) +#define LPI_PROP_GROUP1 (1 << 1) +#define LPI_PROP_ENABLED (1 << 0) +#define LPI_PROP_DEFAULT_PRIO 0xa0 +#define LPI_PROP_DEFAULT (LPI_PROP_DEFAULT_PRIO | LPI_PROP_GROUP1 | LPI_PROP_ENABLED) -#define LPI_PROP_GROUP1 (1 << 1) -#define LPI_PROP_ENABLED (1 << 0) -#define LPI_PROP_DEFAULT_PRIO 0xa0 -#define LPI_PROP_DEFAULT (LPI_PROP_DEFAULT_PRIO | LPI_PROP_GROUP1 | \ - LPI_PROP_ENABLED) +#define LPI_ID_BASE 8192 +#define LPI (lpi) ((lpi) + LPI_ID_BASE) +#define LPI_OFFSET (intid) ((intid) - LPI_ID_BASE)#include <asm/arch_gicv3.h> @@ -76,7 +77,7 @@ struct gicv3_data {void *dist_base;void *redist_bases[GICV3_NR_REDISTS ];void *redist_base[NR_CPUS ]; -void *lpi_prop; +u8 *lpi_prop;void *lpi_pend[NR_CPUS ];unsigned int irq_nr; };@@ -96,8 +97,10 @@ extern void gicv3_ipi_send_mask(int irq, const cpumask_t *dest);extern void gicv3_set_redist_base (size_t stride);extern void gicv3_lpi_set_config (int n,u8 val);extern u8 gicv3_lpi_get_config (int n); -extern void gicv3_lpi_set_pending_table_bit (int rdist,int n,bool set); +extern void gicv3_lpi_set_clr_pending (int rdist,int n,bool set);extern void gicv3_lpi_alloc_tables (void ); +extern void gicv3_lpi_rdist_enable (int redist); +extern void gicv3_lpi_rdist_disable (int redist);static inline void gicv3_do_wait_for_rwp (void *base) {@@ -143,5 +146,12 @@ static inline u64 mpidr_uncompress(u32 compressed)return mpidr; } +#define gicv3_lpi_set_config (intid, value) ({ \ + gicv3_data.lpi_prop[LPI_OFFSET(intid)] = value; \ +}) + +#define gicv3_lpi_get_config (intid) (gicv3_data.lpi_prop[LPI_OFFSET(intid)]) + +#endif /* !__ASSEMBLY__ */ #endif /* _ASMARM_GIC_V3_H_ */ lib/arm/gic-v3.c +8
-1@@ -150,7 +150,14 @@ void gicv3_ipi_send_single(int irq, int cpu) }#if defined(__aarch64__) -/* alloc_lpi_tables: Allocate LPI config and pending tables */ + +/** +* alloc_lpi_tables - Allocate LPI config and pending tables +* and set PROPBASER (shared by all rdistributors) and per +* redistributor PENDBASER. +* +* gicv3_set_redist_base() must be called before +*/ void gicv3_lpi_alloc_tables (void ) {unsigned long n =SZ_64K >>PAGE_SHIFT ;@@ -161,13 +168,9 @@ void gicv3_lpi_alloc_tables(void) gicv3_data.lpi_prop =alloc_pages (order);
lib/arm/gic-v3.c void gicv3_lpi_alloc_tables(void) · line 173
Quoted 10 lines
lib/arm/gic-v3.c +2
-6/* ID bits = 13, ie. up to 14b LPI INTID */ - prop_val = (u64 )virt_to_phys (gicv3_data.lpi_prop) |13 ; + prop_val = (u64)(virt_to_phys (gicv3_data.lpi_prop)) |13 ; -/* -* Allocate pending tables for each redistributor -* and set PROPBASER and PENDBASER -*/ -for_each_present_cpu (cpu) { +for (cpu =0 ; cpu < nr_cpus; cpu++) {
You don't mention this change in the changelog. What's wrong with using for_each_present_cpu() here?
Quoted 24 lines
lib/arm/gic-v3.c +2
-10u64 pend_val;void *ptr;@@ -176,30 +179,14 @@ void gicv3_lpi_alloc_tables(void)writeq (prop_val, ptr +GICR_PROPBASER ); gicv3_data.lpi_pend[cpu] =alloc_pages (order); - - pend_val = (u64 )virt_to_phys (gicv3_data.lpi_pend[cpu]); - + pend_val = (u64)(virt_to_phys (gicv3_data.lpi_pend[cpu]));writeq (pend_val, ptr +GICR_PENDBASER ); } } -void gicv3_lpi_set_config (int n,u8 value) +void gicv3_lpi_set_clr_pending (int rdist,int n,bool set) { -u8 *entry = (u8 *)(gicv3_data.lpi_prop + (n -8192 )); - - *entry = value; -} - -u8 gicv3_lpi_get_config (int n)
lib/arm/gic-v3.c void gicv3_lpi_alloc_tables(void) · line 189
Quoted 10 lines
lib/arm/gic-v3.c +1
-9-{ -u8 *entry = (u8 *)(gicv3_data.lpi_prop + (n -8192 )); - -return *entry; -} - -void gicv3_lpi_set_pending_table_bit (int rdist,int n,bool set) -{ -u8 *ptr =phys_to_virt ((phys_addr_t )gicv3_data.lpi_pend[rdist]); +u8 *ptr = gicv3_data.lpi_pend[rdist];
Alot of the changes above and in this patch in general look like cleanups that should have been squashed into the patches that introduced the lines in the first place.
Quoted 74 lines
lib/arm/gic-v3.c +25
-0u8 mask =1 << (n %8 ), byte; ptr += (n /8 );@@ -210,4 +197,29 @@ void gicv3_lpi_set_pending_table_bit(int rdist, int n, bool set) byte &= ~mask; *ptr = byte; } + +static void gicv3_lpi_rdist_ctrl (u32 redist,bool set) +{ +void *ptr; +u64 val; + +assert (redist < nr_cpus); + + ptr = gicv3_data.redist_base[redist]; + val =readl (ptr +GICR_CTLR ); +if (set) + val |=GICR_CTLR_ENABLE_LPIS ; +else + val &= ~GICR_CTLR_ENABLE_LPIS ; +writel (val, ptr +GICR_CTLR ); +} + +void gicv3_lpi_rdist_enable (int redist) +{ +gicv3_lpi_rdist_ctrl (redist, true); +} +void gicv3_lpi_rdist_disable (int redist) +{ +gicv3_lpi_rdist_ctrl (redist, false); +}#endif /* __aarch64__ */ lib/arm64/asm/gic-v3-its.h +1
-0@@ -88,5 +88,6 @@ extern struct its_data its_data;extern void its_parse_typer (void );extern void its_init (void );extern int its_baser_lookup (int i,struct its_baser *baser); +extern void its_enable_defaults (void );#endif /* _ASMARM64_GIC_V3_ITS_H_ */ lib/arm64/gic-v3-its.c +13
-3@@ -94,9 +94,19 @@ void its_init(void)its_baser_alloc_table (&its_data.device_baser,SZ_64K );its_baser_alloc_table (&its_data.coll_baser,SZ_64K ); -/* Allocate LPI config and pending tables */ -gicv3_lpi_alloc_tables (); -its_cmd_queue_init (); } +/* must be called after gicv3_enable_defaults */ +void its_enable_defaults (void ) +{ +int i; + +/* Allocate LPI config and pending tables */ +gicv3_lpi_alloc_tables (); + +for (i =0 ; i < nr_cpus; i++) +gicv3_lpi_rdist_enable (i); + +writel (GITS_CTLR_ENABLE , its_data.base +GITS_CTLR ); +}Signature · 1 line
2.20.1
Thanks,
drew
Re: [kvm-unit-tests PATCH v4 07/13] arm/arm64: ITS: its_enable_defaults
Hi Drew,
Quoted 124 lines · Andrew Jones
Quoted 123 lines · Eric Auger
its_enable_defaults()enable LPIs at distributor level and ITS level.
gicv3_enable_defaultsmust be called before.Signed-off-by Eric Auger <[email protected]>---
v3 -> v4:
- useGITS_BASER_INDIRECT&GITS_BASER_VALIDinits_setup_baser()
- don't parse BASERs again inits_enable_defaults
- renameits_setup_baserintoits_baser_alloc_table
- All allocations moved to the init function
- squashed "arm/arm64: gicv3: Enable/Disable LPIs at re-distributor level" into this patch
- introducegicv3_lpi_rdist_enableandgicv3_lpi_rdist_disable
- pend and prop table bases stored as virt addresses
- move some init functions fromenable()toits_init
- removedGICR_PROPBASER_IDBITS_MASK
- introducedLPI_OFFSET
-lpi_propbecomes u8 *
- gicv3_lpi_set_config/get_config became macro
- renamedgicv3_lpi_set_pending_table_bitintogicv3_lpi_set_clr_pendingv2 -> v3:
- introduceits_setup_baserin this patch
- squash "arm/arm64: ITS: Init the command queue" in this patch.--- lib/arm/asm/gic-v3.h | 28 +++++++++++------ lib/arm/gic-v3.c | 64 ++++++++++++++++++++++---------------- lib/arm64/asm/gic-v3-its.h | 1 + lib/arm64/gic-v3-its.c | 16 ++++++++-- 4 files changed, 71 insertions(+), 38 deletions(-)lib/arm/asm/gic-v3.h +19
-9@@ -50,15 +50,16 @@#define MPIDR_TO_SGI_AFFINITY (cluster_id, level) \ (MPIDR_AFFINITY_LEVEL(cluster_id, level) << ICC_SGI1R_AFFINITY_## level ## _SHIFT) -#define GICR_PROPBASER_IDBITS_MASK (0x1f) +#define GICR_PENDBASER_PTZ BIT_ULL(62) -#define GICR_PENDBASER_PTZ BIT_ULL(62) +#define LPI_PROP_GROUP1 (1 << 1) +#define LPI_PROP_ENABLED (1 << 0) +#define LPI_PROP_DEFAULT_PRIO 0xa0 +#define LPI_PROP_DEFAULT (LPI_PROP_DEFAULT_PRIO | LPI_PROP_GROUP1 | LPI_PROP_ENABLED) -#define LPI_PROP_GROUP1 (1 << 1) -#define LPI_PROP_ENABLED (1 << 0) -#define LPI_PROP_DEFAULT_PRIO 0xa0 -#define LPI_PROP_DEFAULT (LPI_PROP_DEFAULT_PRIO | LPI_PROP_GROUP1 | \ - LPI_PROP_ENABLED) +#define LPI_ID_BASE 8192 +#define LPI (lpi) ((lpi) + LPI_ID_BASE) +#define LPI_OFFSET (intid) ((intid) - LPI_ID_BASE)#include <asm/arch_gicv3.h> @@ -76,7 +77,7 @@ struct gicv3_data {void *dist_base;void *redist_bases[GICV3_NR_REDISTS ];void *redist_base[NR_CPUS ]; -void *lpi_prop; +u8 *lpi_prop;void *lpi_pend[NR_CPUS ];unsigned int irq_nr; };@@ -96,8 +97,10 @@ extern void gicv3_ipi_send_mask(int irq, const cpumask_t *dest);extern void gicv3_set_redist_base (size_t stride);extern void gicv3_lpi_set_config (int n,u8 val);extern u8 gicv3_lpi_get_config (int n); -extern void gicv3_lpi_set_pending_table_bit (int rdist,int n,bool set); +extern void gicv3_lpi_set_clr_pending (int rdist,int n,bool set);extern void gicv3_lpi_alloc_tables (void ); +extern void gicv3_lpi_rdist_enable (int redist); +extern void gicv3_lpi_rdist_disable (int redist);static inline void gicv3_do_wait_for_rwp (void *base) {@@ -143,5 +146,12 @@ static inline u64 mpidr_uncompress(u32 compressed)return mpidr; } +#define gicv3_lpi_set_config (intid, value) ({ \ + gicv3_data.lpi_prop[LPI_OFFSET(intid)] = value; \ +}) + +#define gicv3_lpi_get_config (intid) (gicv3_data.lpi_prop[LPI_OFFSET(intid)]) + +#endif /* !__ASSEMBLY__ */ #endif /* _ASMARM_GIC_V3_H_ */ lib/arm/gic-v3.c +9
-2@@ -150,7 +150,14 @@ void gicv3_ipi_send_single(int irq, int cpu) }#if defined(__aarch64__) -/* alloc_lpi_tables: Allocate LPI config and pending tables */ + +/** +* alloc_lpi_tables - Allocate LPI config and pending tables +* and set PROPBASER (shared by all rdistributors) and per +* redistributor PENDBASER. +* +* gicv3_set_redist_base() must be called before +*/ void gicv3_lpi_alloc_tables (void ) {unsigned long n =SZ_64K >>PAGE_SHIFT ;@@ -161,13 +168,9 @@ void gicv3_lpi_alloc_tables(void) gicv3_data.lpi_prop =alloc_pages (order);/* ID bits = 13, ie. up to 14b LPI INTID */ - prop_val = (u64 )virt_to_phys (gicv3_data.lpi_prop) |13 ; + prop_val = (u64)(virt_to_phys (gicv3_data.lpi_prop)) |13 ;
Quoted 8 lines
lib/arm/gic-v3.c void gicv3_lpi_alloc_tables(void) · line 173
Quoted 6 lines
lib/arm/gic-v3.c +1
-5-/* -* Allocate pending tables for each redistributor -* and set PROPBASER and PENDBASER -*/ -for_each_present_cpu (cpu) { +for (cpu =0 ; cpu < nr_cpus; cpu++) {You don't mention this change in the changelog.
Hey, you can see the changelog is pretty long already & accurate. But you're right I missed that one and listing those changes too would have avoided me to put those changes in that patch.
What's wrong with
Quoted 1 line
using
for_each_present_cpu()here?
As you encouraged me to move the alloc into the it, I tried to do so but then discovered this was feasible for such kind of issue. At init time, CPUs have nott booted yet.
Quoted 31 lines
Quoted 31 lines
lib/arm/gic-v3.c +2
-16u64 pend_val;void *ptr;@@ -176,30 +179,14 @@ void gicv3_lpi_alloc_tables(void)writeq (prop_val, ptr +GICR_PROPBASER ); gicv3_data.lpi_pend[cpu] =alloc_pages (order); - - pend_val = (u64 )virt_to_phys (gicv3_data.lpi_pend[cpu]); - + pend_val = (u64)(virt_to_phys (gicv3_data.lpi_pend[cpu]));writeq (pend_val, ptr +GICR_PENDBASER ); } } -void gicv3_lpi_set_config (int n,u8 value) +void gicv3_lpi_set_clr_pending (int rdist,int n,bool set) { -u8 *entry = (u8 *)(gicv3_data.lpi_prop + (n -8192 )); - - *entry = value; -} - -u8 gicv3_lpi_get_config (int n) -{ -u8 *entry = (u8 *)(gicv3_data.lpi_prop + (n -8192 )); - -return *entry; -} -
Quoted 8 lines
lib/arm/gic-v3.c void gicv3_lpi_alloc_tables(void) · line 189
Quoted 4 lines
lib/arm/gic-v3.c +1
-3-void gicv3_lpi_set_pending_table_bit (int rdist,int n,bool set) -{ -u8 *ptr =phys_to_virt ((phys_addr_t )gicv3_data.lpi_pend[rdist]); +u8 *ptr = gicv3_data.lpi_pend[rdist];Alot of the changes above and in this patch in general look like cleanups that should have been squashed into the patches that introduced the lines in the first place.
Yes you're right. I forgot to move those changes back to previous patch. I will do
Thanks
Eric
Quoted 70 lines
Quoted 70 lines
lib/arm/gic-v3.c +25
-0u8 mask =1 << (n %8 ), byte; ptr += (n /8 );@@ -210,4 +197,29 @@ void gicv3_lpi_set_pending_table_bit(int rdist, int n, bool set) byte &= ~mask; *ptr = byte; } + +static void gicv3_lpi_rdist_ctrl (u32 redist,bool set) +{ +void *ptr; +u64 val; + +assert (redist < nr_cpus); + + ptr = gicv3_data.redist_base[redist]; + val =readl (ptr +GICR_CTLR ); +if (set) + val |=GICR_CTLR_ENABLE_LPIS ; +else + val &= ~GICR_CTLR_ENABLE_LPIS ; +writel (val, ptr +GICR_CTLR ); +} + +void gicv3_lpi_rdist_enable (int redist) +{ +gicv3_lpi_rdist_ctrl (redist, true); +} +void gicv3_lpi_rdist_disable (int redist) +{ +gicv3_lpi_rdist_ctrl (redist, false); +}#endif /* __aarch64__ */ lib/arm64/asm/gic-v3-its.h +1
-0@@ -88,5 +88,6 @@ extern struct its_data its_data;extern void its_parse_typer (void );extern void its_init (void );extern int its_baser_lookup (int i,struct its_baser *baser); +extern void its_enable_defaults (void );#endif /* _ASMARM64_GIC_V3_ITS_H_ */ lib/arm64/gic-v3-its.c +11
-3@@ -94,9 +94,19 @@ void its_init(void)its_baser_alloc_table (&its_data.device_baser,SZ_64K );its_baser_alloc_table (&its_data.coll_baser,SZ_64K ); -/* Allocate LPI config and pending tables */ -gicv3_lpi_alloc_tables (); -its_cmd_queue_init (); } +/* must be called after gicv3_enable_defaults */ +void its_enable_defaults (void ) +{ +int i; + +/* Allocate LPI config and pending tables */ +gicv3_lpi_alloc_tables (); + +for (i =0 ; i < nr_cpus; i++) +gicv3_lpi_rdist_enable (i); +
Quoted 10 lines
Quoted 5 lines
lib/arm64/gic-v3-its.c +2
-0+writel (GITS_CTLR_ENABLE , its_data.base +GITS_CTLR ); +}Signature · 1 line
2.20.1Thanks,
drew
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Re: [kvm-unit-tests PATCH v4 07/13] arm/arm64: ITS: its_enable_defaults
Quoted 8 lines · Auger Eric
Quoted 4 lines
lib/arm/gic-v3.c void gicv3_lpi_alloc_tables(void) · line 173
Quoted 2 lines
lib/arm/gic-v3.c +1
-1-for_each_present_cpu (cpu) { +for (cpu =0 ; cpu < nr_cpus; cpu++) {You don't mention this change in the changelog.
Hey, you can see the changelog is pretty long already & accurate. But you're right I missed that one and listing those changes too would have avoided me to put those changes in that patch.
Quoted 5 lines
What's wrong with
Quoted 1 line
using
for_each_present_cpu()here?As you encouraged me to move the alloc into the it, I tried to do so but then discovered this was feasible for such kind of issue. At init time, CPUs have nott booted yet.
They may not have booted, but for_each_present_cpu() should still work because the present mask is initialized at setup() time before the unit test even starts.
Thanks,
drew
PATCH v4 8/13 arm/arm64: ITS: Device and collection Initialization
In reply to Eric AugerIntroduce an helper functions to register
- a new device, characterized by its device id and the max number of event IDs that dimension its ITT (Interrupt Translation Table). The function allocates the ITT.
- a new collection, characterized by its ID and the target processing engine (PE).
---
v3 -> v4:
- remove unused its_baser variable from its_create_device()
- use get_order()
- device->itt becomes a GVA instead of GPA
v2 -> v3:
- s/report_abort/assert
v1 -> v2:
- s/nb_/nr_
--- lib/arm64/asm/gic-v3-its.h | 19 +++++++++++++++++++ lib/arm64/gic-v3-its.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+)
lib/arm64/asm/gic-v3-its.h +19 -0
@@ -27,6 +27,19 @@ struct its_baser { };#define GITS_BASER_NR_REGS 8 +#define GITS_MAX_DEVICES 8 +#define GITS_MAX_COLLECTIONS 8 + +struct its_device { +u32 device_id;/* device ID */ +u32 nr_ites;/* Max Interrupt Translation Entries */ +void *itt;/* Interrupt Translation Table GVA */ +}; + +struct its_collection { +u64 target_address; +u16 col_id; +};struct its_data {void *base;
@@ -35,6 +48,10 @@ struct its_data {struct its_baser coll_baser;struct its_cmd_block *cmd_base;struct its_cmd_block *cmd_write; +struct its_device devices[GITS_MAX_DEVICES ]; +u32 nr_devices;/* Allocated Devices */ +struct its_collection collections[GITS_MAX_COLLECTIONS ]; +u32 nr_collections;/* Allocated Collections */ };extern struct its_data its_data;
@@ -89,5 +106,7 @@ extern void its_parse_typer(void);extern void its_init (void );extern int its_baser_lookup (int i,struct its_baser *baser);extern void its_enable_defaults (void ); +extern struct its_device *its_create_device (u32 dev_id,int nr_ites); +extern struct its_collection *its_create_collection (u32 col_id,u32 target_pe);#endif /* _ASMARM64_GIC_V3_ITS_H_ */
lib/arm64/gic-v3-its.c +38 -0
@@ -110,3 +110,41 @@ void its_enable_defaults(void)writel (GITS_CTLR_ENABLE , its_data.base +GITS_CTLR ); } + +struct its_device *its_create_device (u32 device_id,int nr_ites) +{ +struct its_device *new; +unsigned long n; + +assert (its_data.nr_devices <GITS_MAX_DEVICES ); + + new = &its_data.devices[its_data.nr_devices]; + + new->device_id = device_id; + new->nr_ites = nr_ites; + + n = (its_data.typer.ite_size * nr_ites) >>PAGE_SHIFT ; + new->itt =alloc_pages (get_order (n)); + + its_data.nr_devices++; +return new; +} + +struct its_collection *its_create_collection (u32 col_id,u32 pe) +{ +struct its_collection *new; + +assert (its_data.nr_collections <GITS_MAX_COLLECTIONS ); + + new = &its_data.collections[its_data.nr_collections]; + + new->col_id = col_id; + +if (its_data.typer.pta) + new->target_address = (u64 )gicv3_data.redist_base[pe]; +else + new->target_address = pe <<16 ; + + its_data.nr_collections++; +return new; +}
Signature · 1 line
2.20.1
PATCH v4 9/13 arm/arm64: ITS: Commands
In reply to Eric AugerImplement main ITS commands. The code is largely inherited from the ITS driver.
---
v3 -> v4:
- device's itt now is a VGA
- pass verbose to choose whether we shall print the cmd
- use printf instead of report_info
v2 -> v3:
- do not use report() anymore
- assert if cmd_write exceeds the queue capacity
v1 -> v2:
- removed its_print_cmd_state
--- arm/Makefile.arm64 | 2 +- lib/arm64/asm/gic-v3-its.h | 57 +++++ lib/arm64/gic-v3-its-cmd.c | 463 +++++++++++++++++++++++++++++++++++++ 3 files changed, 521 insertions(+), 1 deletion(-) create mode 100644 lib/arm64/gic-v3-its-cmd.c
arm/Makefile.arm64 +1 -1
@@ -19,7 +19,7 @@ endef cstart.o = $(TEST_DIR)/cstart64.o cflatobjs += lib/arm64/processor.o cflatobjs += lib/arm64/spinlock.o -cflatobjs += lib/arm64/gic-v3-its.o +cflatobjs += lib/arm64/gic-v3-its.o lib/arm64/gic-v3-its-cmd.o OBJDIRS += lib/arm64
lib/arm64/asm/gic-v3-its.h +57 -0
67 lines not on this page · raw message
lib/arm64/gic-v3-its-cmd.c new file +463 -0
463 lines not on this page · raw message
Signature · 1 line
2.20.1
PATCH v4 10/13 arm/arm64: ITS: INT functional tests
In reply to Eric AugerTriggers LPIs through the INT command.
the test checks the LPI hits the right CPU and triggers the right LPI intid, ie. the translation is correct.
Updates to the config table also are tested, along with inv and invall commands.
---
v3 -> v4:
- assert in lpi_handler if the interrupt is not an LPI
- remove check_lpi_stats from its_prerequisites()
v2 -> v3:
- add comments
- keep the report_skip in case there aren't 4 vcpus to be able to run other tests in the its category.
- fix the prefix pop
- move its_event and its_stats to arm/gic.c
--- arm/gic.c | 221 +++++++++++++++++++++++++++++++++++++-- arm/unittests.cfg | 7 ++ lib/arm/asm/gic-v3-its.h | 9 +- 3 files changed, 223 insertions(+), 14 deletions(-)
arm/gic.c +210 -11
@@ -160,6 +160,84 @@ static void ipi_handler(struct pt_regs *regs __unused) } } +static void setup_irq (handler_t handler) +{ +gic_enable_defaults (); +#ifdef __arm__ +install_exception_handler (EXCPTN_IRQ , handler); +#else +install_irq_handler (EL1H_IRQ , handler); +#endif +local_irq_enable (); +} + +#if defined(__aarch64__) +struct its_event { +int cpu_id; +int lpi_id; +}; + +struct its_stats { +struct its_event expected; +struct its_event observed; +}; + +static struct its_stats lpi_stats; + +static void lpi_handler(struct pt_regs *regs __unused) +{ +u32 irqstat =gic_read_iar (); +int irqnr =gic_iar_irqnr (irqstat); + +gic_write_eoir (irqstat); +assert (irqnr >=8192 ); +smp_rmb ();/* pairs with wmb in lpi_stats_expect */ + lpi_stats.observed.cpu_id =smp_processor_id (); + lpi_stats.observed.lpi_id = irqnr; +smp_wmb ();/* pairs with rmb in check_lpi_stats */ +} + +static void lpi_stats_expect (int exp_cpu_id,int exp_lpi_id) +{ + lpi_stats.expected.cpu_id = exp_cpu_id; + lpi_stats.expected.lpi_id = exp_lpi_id; + lpi_stats.observed.cpu_id =-1 ; + lpi_stats.observed.lpi_id =-1 ; +smp_wmb ();/* pairs with rmb in handler */ +} + +static void check_lpi_stats (const char *msg) +{ +bool pass = false; +mdelay (100 ); +smp_rmb ();/* pairs with wmb in lpi_handler */ +if (lpi_stats.observed.cpu_id != lpi_stats.expected.cpu_id || + lpi_stats.observed.lpi_id != lpi_stats.expected.lpi_id) { +if (lpi_stats.observed.cpu_id ==-1 && + lpi_stats.observed.lpi_id ==-1 ) { +report_info ("No LPI received whereas (cpuid=%d, intid=%d) " +"was expected" , lpi_stats.expected.cpu_id, + lpi_stats.expected.lpi_id); + }else { +report_info ("Unexpected LPI (cpuid=%d, intid=%d)" , + lpi_stats.observed.cpu_id, + lpi_stats.observed.lpi_id); + } + }else { + pass = true; + } +report (pass,"%s" , msg); +} + +static void secondary_lpi_test (void ) +{ +setup_irq (lpi_handler); +cpumask_set_cpu (smp_processor_id (), &ready); +while (1 ) +wfi (); +} +#endif +static void gicv2_ipi_send_self (void ) {writel (2 <<24 |IPI_IRQ ,gicv2_dist_base () +GICD_SGIR );
@@ -217,17 +295,6 @@ static void ipi_test_smp(void)report_prefix_pop (); } -static void setup_irq (handler_t handler) -{ -gic_enable_defaults (); -#ifdef __arm__ -install_exception_handler (EXCPTN_IRQ , handler); -#else -install_irq_handler (EL1H_IRQ , handler); -#endif -local_irq_enable (); -} -static void ipi_send (void ) {setup_irq (ipi_handler);
@@ -556,6 +623,134 @@ static void test_its_introspection(void)report_info ("collection table entry_size = 0x%x" , coll_baser->esz); } +static int its_prerequisites (int nb_cpus) +{ +int cpu; + +if (!gicv3_its_base ()) { +report_skip ("No ITS, skip ..." ); +return -1 ; + } + +if (nr_cpus < nb_cpus) { +report_skip ("Test requires at least %d vcpus" , nb_cpus); +return -1 ; + } + +stats_reset (); + +setup_irq (lpi_handler); + +for_each_present_cpu (cpu) { +if (cpu ==0 ) +continue ; +smp_boot_secondary (cpu, secondary_lpi_test); + } +wait_on_ready (); + +its_enable_defaults (); + +return 0 ; +} + +static void test_its_trigger (void ) +{ +struct its_collection *col3, *col2; +struct its_device *dev2, *dev7; + +if (its_prerequisites (4 )) +return ; + + dev2 =its_create_device (2 /* dev id */ ,8 /* nb_ites */ ); + dev7 =its_create_device (7 /* dev id */ ,8 /* nb_ites */ ); + + col3 =its_create_collection (3 /* col id */ ,3 /* target PE */ ); + col2 =its_create_collection (2 /* col id */ ,2 /* target PE */ ); + +gicv3_lpi_set_config (8195 ,LPI_PROP_DEFAULT ); +gicv3_lpi_set_config (8196 ,LPI_PROP_DEFAULT ); + +its_send_invall (col2); +its_send_invall (col3); + +report_prefix_push ("int" ); +/* +* dev=2, eventid=20 -> lpi= 8195, col=3 +* dev=7, eventid=255 -> lpi= 8196, col=2 +* Trigger dev2, eventid=20 and dev7, eventid=255 +* Check both LPIs hit +*/ + +its_send_mapd (dev2, true); +its_send_mapd (dev7, true); + +its_send_mapc (col3, true); +its_send_mapc (col2, true); + +its_send_mapti (dev2,8195 /* lpi id */ ,20 /* event id */ , col3); +its_send_mapti (dev7,8196 /* lpi id */ ,255 /* event id */ , col2); + +lpi_stats_expect (3 ,8195 ); +its_send_int (dev2,20 ); +check_lpi_stats ("dev=2, eventid=20 -> lpi= 8195, col=3" ); + +lpi_stats_expect (2 ,8196 ); +its_send_int (dev7,255 ); +check_lpi_stats ("dev=7, eventid=255 -> lpi= 8196, col=2" ); + +report_prefix_pop (); + +report_prefix_push ("inv/invall" ); + +/* +* disable 8195, check dev2/eventid=20 does not trigger the +* corresponding LPI +*/ +gicv3_lpi_set_config (8195 ,LPI_PROP_DEFAULT & ~LPI_PROP_ENABLED ); +its_send_inv (dev2,20 ); + +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev2,20 ); +check_lpi_stats ("dev2/eventid=20 does not trigger any LPI" ); + +/* +* re-enable the LPI but willingly do not call invall +* so the change in config is not taken into account. +* The LPI should not hit +*/ +gicv3_lpi_set_config (8195 ,LPI_PROP_DEFAULT ); +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev2,20 ); +check_lpi_stats ("dev2/eventid=20 still does not trigger any LPI" ); + +/* Now call the invall and check the LPI hits */ +its_send_invall (col3); +lpi_stats_expect (3 ,8195 ); +its_send_int (dev2,20 ); +check_lpi_stats ("dev2/eventid=20 now triggers an LPI" ); + +report_prefix_pop (); + +report_prefix_push ("mapd valid=false" ); +/* +* Unmap device 2 and check the eventid 20 formerly +* attached to it does not hit anymore +*/ + +its_send_mapd (dev2, false); +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev2,20 ); +check_lpi_stats ("no LPI after device unmap" ); +report_prefix_pop (); + +/* Unmap the collection this time and check no LPI does hit */ +report_prefix_push ("mapc valid=false" ); +its_send_mapc (col2, false); +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev7,255 ); +check_lpi_stats ("no LPI after collection unmap" ); +report_prefix_pop (); +}#endif int main (int argc,char **argv)
@@ -589,6 +784,10 @@ int main(int argc, char **argv)report_prefix_push (argv[1 ]);gic_test_mmio ();report_prefix_pop (); + }else if (!strcmp (argv[1 ],"its-trigger" )) { +report_prefix_push (argv[1 ]); +test_its_trigger (); +report_prefix_pop (); }else if (strcmp (argv[1 ],"its-introspection" ) ==0 ) {report_prefix_push (argv[1 ]);test_its_introspection ();
arm/unittests.cfg +7 -0
@@ -129,6 +129,13 @@ extra_params = -machine gic-version=3 -append 'its-introspection' groups = its arch = arm64 +[its-trigger] +file = gic.flat +smp = $MAX_SMP +extra_params = -machine gic-version=3 -append 'its-trigger' +groups = its +arch = arm64 + # Test PSCI emulation [psci] file = psci.flat
lib/arm/asm/gic-v3-its.h +6 -3
@@ -5,9 +5,8 @@* * This work is licensed under the terms of the GNU LGPL, version 2. */ - -#ifndef _ASMARM_GICv3_ITS -#define _ASMARM_GICv3_ITS +#ifndef _ASMARM_GIC_V3_ITS_H_ +#define _ASMARM_GIC_V3_ITS_H_/* dummy its_data struct to allow gic_get_dt_bases() call */ struct its_data {
@@ -19,5 +18,9 @@ static inline void test_its_introspection(void) {report_abort ("not supported on 32-bit" ); } +static inline void test_its_trigger (void ) +{ +report_abort ("not supported on 32-bit" ); +}#endif /* _ASMARM_GICv3_ITS */
Signature · 1 line
2.20.1
Re: [kvm-unit-tests PATCH v4 10/13] arm/arm64: ITS: INT functional tests
On Mon, Mar 09, 2020 at 11:24:17AM +0100, Eric Auger wrote:
...
lib/arm/asm/gic-v3-its.h line 9
Quoted 13 lines
lib/arm/asm/gic-v3-its.h +2
-3@@ -5,9 +5,8 @@* * This work is licensed under the terms of the GNU LGPL, version 2. */ - -#ifndef _ASMARM_GICv3_ITS -#define _ASMARM_GICv3_ITS +#ifndef _ASMARM_GIC_V3_ITS_H_ +#define _ASMARM_GIC_V3_ITS_H_
Another fix to squash into the patch where the lines are introduced.
lib/arm/asm/gic-v3-its.h static inline void test_its_introspection(void) · line 23
Quoted 10 lines
lib/arm/asm/gic-v3-its.h +3
-0/* dummy its_data struct to allow gic_get_dt_bases() call */ struct its_data {@@ -19,5 +18,9 @@ static inline void test_its_introspection(void) {report_abort ("not supported on 32-bit" ); } +static inline void test_its_trigger (void ) +{ +report_abort ("not supported on 32-bit" );
As mentioned before, we don't want test_* and report_* functions in the library code.
lib/arm/asm/gic-v3-its.h static inline void test_its_introspection(void) · line 26
Quoted 3 lines
lib/arm/asm/gic-v3-its.h +1
-0+}#endif /* _ASMARM_GICv3_ITS */
Forgot to change _ASMARM_GICv3_ITS here.
Quoted 3 lines
Signature · 1 line
2.20.1
Thanks,
drew
PATCH v4 11/13 arm/run: Allow Migration tests
In reply to Eric AugerLet's link getchar.o to use puts and getchar from the tests.
Then allow tests belonging to the migration group to trigger the migration from the test code by putting "migrate" into the uart. Then the code can wait for the migration completion by using getchar().
The __getchar implement is minimalist as it just reads the data register. It is just meant to read the single character emitted at the end of the migration by the runner script.
It is not meant to read more data (FIFOs are not enabled).
---
v3 -> v4:
- remove space around Elvis operator
- rename ___getchar into do_getchar
v2 -> v3:
- take the lock
- assert if more than 16 chars
- removed Thomas' R-b
--- arm/Makefile.common | 2 +- arm/run | 2 +- lib/arm/io.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-)
arm/Makefile.common +1 -1
@@ -32,7 +32,7 @@ CFLAGS += -I $(SRCDIR)/lib -I $(SRCDIR)/lib/libfdt -I lib asm-offsets = lib/$(ARCH)/asm-offsets.h include $(SRCDIR)/scripts/asm-offsets.mak -cflatobjs += lib/util.o +cflatobjs += lib/util.o lib/getchar.o cflatobjs += lib/alloc_phys.o cflatobjs += lib/alloc_page.o cflatobjs += lib/vmalloc.o
arm/run +1 -1
@@ -61,6 +61,6 @@ fi M+=",accel=$ACCEL" command="$qemu -nodefaults $M -cpu $processor $chr_testdev $pci_testdev" command+=" -display none -serial stdio -kernel" -command="$(timeout_cmd) $command" +command="$(migration_cmd) $(timeout_cmd) $command" run_qemu $command "$@"
lib/arm/io.c +28 -0
@@ -87,6 +87,34 @@ void puts(const char *s)spin_unlock (&uart_lock); } +static int do_getchar (void ) +{ +int c; + +spin_lock (&uart_lock); + c =readb (uart0_base); +spin_unlock (&uart_lock); + +return c ?:-1 ; +} + +/* +* Minimalist implementation for migration completion detection. +* Without FIFOs enabled on the QEMU UART device we just read +* the data register: we cannot read more than 16 characters. +*/ +int __getchar (void ) +{ +int c =do_getchar (); +static int count; + +if (c !=-1 ) + ++count; + +assert (count <16 ); + +return c; +}/* * Defining halt to take 'code' as an argument guarantees that it will
Signature · 1 line
2.20.1
PATCH v4 12/13 arm/arm64: ITS: migration tests
In reply to Eric AugerThis test maps LPIs (populates the device table, the collection table, interrupt translation tables, configuration table), migrates and make sure the translation is correct on the destination.
---
v3 -> v4:
- assert in its_get_device/collection if the id is not found
--- arm/gic.c | 58 ++++++++++++++++++++++++++++++++++---- arm/unittests.cfg | 8 ++++++ lib/arm/asm/gic-v3-its.h | 4 +++ lib/arm64/asm/gic-v3-its.h | 3 ++ lib/arm64/gic-v3-its.c | 22 +++++++++++++++ 5 files changed, 89 insertions(+), 6 deletions(-)
arm/gic.c +52 -6
@@ -653,13 +653,19 @@ static int its_prerequisites(int nb_cpus)return 0 ; } -static void test_its_trigger (void ) +/* +* Setup the configuration for those mappings: +* dev_id=2 event=20 -> vcpu 3, intid=8195 +* dev_id=7 event=255 -> vcpu 2, intid=8196 +* LPIs ready to hit +*/ +static int its_setup1 (void ) {struct its_collection *col3, *col2;struct its_device *dev2, *dev7;if (its_prerequisites (4 )) -return ; +return -1 ; dev2 =its_create_device (2 /* dev id */ ,8 /* nb_ites */ ); dev7 =its_create_device (7 /* dev id */ ,8 /* nb_ites */ );
@@ -673,14 +679,10 @@ static void test_its_trigger(void)its_send_invall (col2);its_send_invall (col3); -report_prefix_push ("int" );/* * dev=2, eventid=20 -> lpi= 8195, col=3 * dev=7, eventid=255 -> lpi= 8196, col=2 -* Trigger dev2, eventid=20 and dev7, eventid=255 -* Check both LPIs hit */ -its_send_mapd (dev2, true);its_send_mapd (dev7, true);
@@ -689,6 +691,23 @@ static void test_its_trigger(void)its_send_mapti (dev2,8195 /* lpi id */ ,20 /* event id */ , col3);its_send_mapti (dev7,8196 /* lpi id */ ,255 /* event id */ , col2); +return 0 ; +} + +static void test_its_trigger (void ) +{ +struct its_collection *col3, *col2; +struct its_device *dev2, *dev7; + +if (its_setup1 ()) +return ; + + col3 =its_get_collection (3 ); + col2 =its_get_collection (2 ); + dev2 =its_get_device (2 ); + dev7 =its_get_device (7 ); + +report_prefix_push ("int" );lpi_stats_expect (3 ,8195 );its_send_int (dev2,20 );
@@ -751,6 +770,29 @@ static void test_its_trigger(void)check_lpi_stats ("no LPI after collection unmap" ); report_prefix_pop(); } + +static void test_its_migration (void ) +{ +struct its_device *dev2, *dev7; + +if (its_setup1 ()) +return ; + + dev2 =its_get_device (2 ); + dev7 =its_get_device (7 ); + +puts ("Now migrate the VM, then press a key to continue...\n" ); + (void )getchar (); +report_info ("Migration complete" ); + +lpi_stats_expect (3 ,8195 ); +its_send_int (dev2,20 ); +check_lpi_stats ("dev2/eventid=20 triggers LPI 8195 en PE #3 after migration" ); + +lpi_stats_expect (2 ,8196 ); +its_send_int (dev7,255 ); +check_lpi_stats ("dev7/eventid=255 triggers LPI 8196 on PE #2 after migration" ); +}#endif int main (int argc,char **argv)
@@ -788,6 +830,10 @@ int main(int argc, char **argv)report_prefix_push (argv[1 ]);test_its_trigger ();report_prefix_pop (); + }else if (!strcmp (argv[1 ],"its-migration" )) { +report_prefix_push (argv[1 ]); +test_its_migration (); +report_prefix_pop (); }else if (strcmp (argv[1 ],"its-introspection" ) ==0 ) {report_prefix_push (argv[1 ]);test_its_introspection ();
arm/unittests.cfg +8 -0
@@ -136,6 +136,14 @@ extra_params = -machine gic-version=3 -append 'its-trigger' groups = its arch = arm64 +[its-migration] +file = gic.flat +smp = $MAX_SMP +accel = kvm +extra_params = -machine gic-version=3 -append 'its-migration' +groups = its migration +arch = arm64 + # Test PSCI emulation [psci] file = psci.flat
lib/arm/asm/gic-v3-its.h +4 -0
@@ -22,5 +22,9 @@ static inline void test_its_trigger(void) {report_abort ("not supported on 32-bit" ); } +static inline void test_its_migration (void ) +{ +report_abort ("not supported on 32-bit" ); +}#endif /* _ASMARM_GICv3_ITS */
lib/arm64/asm/gic-v3-its.h +3 -0
@@ -166,4 +166,7 @@ extern void __its_send_sync(struct its_collection *col, bool verbose);#define its_send_movi_nv (dev, col, id) __its_send_movi(dev, col, id, false)#define its_send_sync_nv (col) __its_send_sync(col, false) +extern struct its_device *its_get_device (u32 id); +extern struct its_collection *its_get_collection (u32 id); +#endif /* _ASMARM64_GIC_V3_ITS_H_ */
lib/arm64/gic-v3-its.c +22 -0
@@ -148,3 +148,25 @@ struct its_collection *its_create_collection(u32 col_id, u32 pe) its_data.nr_collections++;return new; } + +struct its_device *its_get_device (u32 id) +{ +int i; + +for (i =0 ; i <GITS_MAX_DEVICES ; i++) { +if (its_data.devices[i].device_id == id) +return &its_data.devices[i]; + } +assert (0 ); +} + +struct its_collection *its_get_collection (u32 id) +{ +int i; + +for (i =0 ; i <GITS_MAX_COLLECTIONS ; i++) { +if (its_data.collections[i].col_id == id) +return &its_data.collections[i]; + } +assert (0 ); +}
Signature · 1 line
2.20.1
PATCH v4 13/13 arm/arm64: ITS: pending table migration test
In reply to Eric AugerAdd two new migration tests. One testing the migration of a topology where collection were unmapped. The second test checks the migration of the pending table.
---
v3 -> v4:
- do not talk about odd/even CPUs, use pe0 and pe1
- comment the delay
v2 -> v3:
- tests belong to both its and migration groups
- use LPI(i)
- gicv3_lpi_set_pending_table_bit renamed into gicv3_lpi_set_clr_pending
--- arm/gic.c | 144 +++++++++++++++++++++++++++++++++++++++ arm/unittests.cfg | 16 +++++ lib/arm/asm/gic-v3-its.h | 9 +++ 3 files changed, 169 insertions(+)
arm/gic.c +144 -0
@@ -194,6 +194,7 @@ static void lpi_handler(struct pt_regs *regs __unused)smp_rmb ();/* pairs with wmb in lpi_stats_expect */ lpi_stats.observed.cpu_id =smp_processor_id (); lpi_stats.observed.lpi_id = irqnr; + acked[lpi_stats.observed.cpu_id]++;smp_wmb ();/* pairs with rmb in check_lpi_stats */ }
@@ -236,6 +237,22 @@ static void secondary_lpi_test(void)while (1 ) wfi(); } + +static void check_lpi_hits (int *expected,const char *msg) +{ +bool pass = true; +int i; + +for (i =0 ; i < nr_cpus; i++) { +if (acked[i] != expected[i]) { +report_info ("expected %d LPIs on PE #%d, %d observed" , + expected[i], i, acked[i]); + pass = false; +break ; + } + } +report (pass,"%s" , msg); +}#endif static void gicv2_ipi_send_self (void )
@@ -653,6 +670,17 @@ static int its_prerequisites(int nb_cpus)return 0 ; } +static void set_lpi (struct its_device *dev,u32 eventid,u32 physid, +struct its_collection *col) +{ +assert (dev && col); + +its_send_mapti (dev, physid, eventid, col); + +gicv3_lpi_set_config (physid,LPI_PROP_DEFAULT ); +its_send_invall (col); +} +/* * Setup the configuration for those mappings: * dev_id=2 event=20 -> vcpu 3, intid=8195
@@ -793,6 +821,114 @@ static void test_its_migration(void)its_send_int (dev7,255 );check_lpi_stats ("dev7/eventid=255 triggers LPI 8196 on PE #2 after migration" ); } + +static void test_migrate_unmapped_collection (void ) +{ +struct its_collection *col; +struct its_device *dev2, *dev7; +int pe0 = nr_cpus -1 ; +u8 config; + +if (its_setup1 ()) +return ; + + col =its_create_collection (pe0, pe0); + dev2 =its_get_device (2 ); + dev7 =its_get_device (7 ); + +/* MAPTI with the collection unmapped */ +set_lpi (dev2,0 ,8192 , col); + +puts ("Now migrate the VM, then press a key to continue...\n" ); + (void )getchar (); +report_info ("Migration complete" ); + +/* on the destination, map the collection */ +its_send_mapc (col, true); + +lpi_stats_expect (2 ,8196 ); +its_send_int (dev7,255 ); +check_lpi_stats ("dev7/eventid= 255 triggered LPI 8196 on PE #2" ); + + config =gicv3_lpi_get_config (8192 ); +report (config ==LPI_PROP_DEFAULT , +"Config of LPI 8192 was properly migrated" ); + +lpi_stats_expect (pe0,8192 ); +its_send_int (dev2,0 ); +check_lpi_stats ("dev2/eventid = 0 triggered LPI 8192 on PE0" ); + +/* unmap the collection */ +its_send_mapc (col, false); + +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev2,0 ); +check_lpi_stats ("no LPI triggered after collection unmapping" ); +} + +static void test_its_pending_migration (void ) +{ +struct its_device *dev; +struct its_collection *collection[2 ]; +int *expected =malloc (nr_cpus *sizeof (int )); +int pe0 = nr_cpus -1 , pe1 = nr_cpus -2 ; +u64 pendbaser; +void *ptr; +int i; + +if (its_prerequisites (4 )) +return ; + + dev =its_create_device (2 /* dev id */ ,8 /* nb_ites */ ); +its_send_mapd (dev, true); + + collection[0 ] =its_create_collection (pe0, pe0); + collection[1 ] =its_create_collection (pe1, pe1); +its_send_mapc (collection[0 ], true); +its_send_mapc (collection[1 ], true); + +/* disable lpi at redist level */ +gicv3_lpi_rdist_disable (pe0); +gicv3_lpi_rdist_disable (pe1); + +/* lpis are interleaved inbetween the 2 PEs */ +for (i =0 ; i <256 ; i++) { +struct its_collection *col = i %2 ? collection[0 ] : + collection[1 ]; +int vcpu = col->target_address >>16 ; + +its_send_mapti (dev,LPI (i), i, col); +gicv3_lpi_set_config (LPI (i),LPI_PROP_DEFAULT ); +gicv3_lpi_set_clr_pending (vcpu,LPI (i), true); + } +its_send_invall (collection[0 ]); +its_send_invall (collection[1 ]); + +/* Set the PTZ bit on each pendbaser */ + + expected[pe0] =128 ; + expected[pe1] =128 ; + + ptr = gicv3_data.redist_base[pe0] +GICR_PENDBASER ; + pendbaser =readq (ptr); +writeq (pendbaser & ~GICR_PENDBASER_PTZ , ptr); + + ptr = gicv3_data.redist_base[pe1] +GICR_PENDBASER ; + pendbaser =readq (ptr); +writeq (pendbaser & ~GICR_PENDBASER_PTZ , ptr); + +gicv3_lpi_rdist_enable (pe0); +gicv3_lpi_rdist_enable (pe1); + +puts ("Now migrate the VM, then press a key to continue...\n" ); + (void )getchar (); +report_info ("Migration complete" ); + +/* let's wait for the 256 LPIs to be handled */ +mdelay (1000 ); + +check_lpi_hits (expected,"128 LPIs on both PE0 and PE1 after migration" ); +}#endif int main (int argc,char **argv)
@@ -834,6 +970,14 @@ int main(int argc, char **argv)report_prefix_push (argv[1 ]);test_its_migration ();report_prefix_pop (); + }else if (!strcmp (argv[1 ],"its-pending-migration" )) { +report_prefix_push (argv[1 ]); +test_its_pending_migration (); +report_prefix_pop (); + }else if (!strcmp (argv[1 ],"its-migrate-unmapped-collection" )) { +report_prefix_push (argv[1 ]); +test_migrate_unmapped_collection (); +report_prefix_pop (); }else if (strcmp (argv[1 ],"its-introspection" ) ==0 ) {report_prefix_push (argv[1 ]);test_its_introspection ();
arm/unittests.cfg +16 -0
@@ -144,6 +144,22 @@ extra_params = -machine gic-version=3 -append 'its-migration' groups = its migration arch = arm64 +[its-pending-migration] +file = gic.flat +smp = $MAX_SMP +accel = kvm +extra_params = -machine gic-version=3 -append 'its-pending-migration' +groups = its migration +arch = arm64 + +[its-migrate-unmapped-collection] +file = gic.flat +smp = $MAX_SMP +accel = kvm +extra_params = -machine gic-version=3 -append 'its-migrate-unmapped-collection' +groups = its migration +arch = arm64 + # Test PSCI emulation [psci] file = psci.flat
lib/arm/asm/gic-v3-its.h +9 -0
@@ -26,5 +26,14 @@ static inline void test_its_migration(void) {report_abort ("not supported on 32-bit" ); } +static inline void test_its_pending_migration (void ) +{ +report_abort ("not supported on 32-bit" ); +} +static inline void test_migrate_unmapped_collection (void ) +{ +report_abort ("not supported on 32-bit" ); +} +#endif /* _ASMARM_GICv3_ITS */
Signature · 6 lines
2.20.1 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Quoted 77 lines · Eric Auger
This series is a revival of an RFC series sent in Dec 2016 [1]. Given the amount of code and the lack of traction at that time, I haven't respinned until now. However a recent bug found related to the ITS migration convinced me that this work may deserve to be respinned and enhanced.
Tests exercise main ITS commands and also test migration. With the migration framework, we are able to trigger the migration from guest and that is very practical actually.
What is particular with the ITS programming is that most of the commands are passed through queues and there is real error handling. Invalid commands are just ignored and that is not really tester friendly.
The series can be fount at:
https://github.com/eauger/kut/tree/its-v4Best Regards
Eric
History:
v3 -> v4:
- addressed comments from Drew and Zenghui
- added "page_alloc: Introduceget_order()"
- removed "arm: gic: Provide per-IRQ helper functions"
- ITS files moved to lib64
- and many more, see individual logsv2 -> v3:
- fix 32b compilation
- take into account Drew's comments (see individual diff logs)v1 -> v2:
- took into account Zenghui's comments
- collect R-b's from ThomasReferences:
[1] [kvm-unit-tests RFC 00/15] arm/arm64: add ITS frameworkhttps://lists.gnu.org/archive/html/qemu-devel/2016-12/msg00575.htmlExecution:
x For other ITS tests:
./run_tests.sh -g itsx non migration tests can be launched invidually. For instance:
./arm-run arm/gic.flat -smp 8 -append 'its-trigger'Eric Auger (13):
libcflat: Add other size defines
page_alloc: Introduceget_order()
arm/arm64: gic: Introducesetup_irq()helper arm/arm64: gicv3: Add some re-distributor defines arm/arm64: gicv3: Set the LPI config and pending tables arm/arm64: ITS: Introspection tests
arm/arm64: ITS:its_enable_defaults
arm/arm64: ITS: Device and collection Initialization arm/arm64: ITS: Commands
arm/arm64: ITS: INT functional tests
arm/run: Allow Migration tests
arm/arm64: ITS: migration tests
arm/arm64: ITS: pending table migration testarm/Makefile.arm64 | 1 + arm/Makefile.common | 2 +- arm/gic.c | 469 +++++++++++++++++++++++++++++++++++-- arm/run | 2 +- arm/unittests.cfg | 38 +++ lib/alloc_page.c | 7 +- lib/alloc_page.h | 1 + lib/arm/asm/gic-v3-its.h | 39 +++ lib/arm/asm/gic-v3.h | 32 +++ lib/arm/gic-v3.c | 76 ++++++ lib/arm/gic.c | 34 ++- lib/arm/io.c | 28 +++ lib/arm64/asm/gic-v3-its.h | 172 ++++++++++++++
Quoted 13 lines
lib/arm64/gic-v3-its-cmd.c | 463 ++++++++++++++++++++++++++++++++++++ lib/arm64/gic-v3-its.c | 172 ++++++++++++++ lib/libcflat.h | 3 + 16 files changed, 1510 insertions(+), 29 deletions(-) create mode 100644 lib/arm/asm/gic-v3-its.h create mode 100644 lib/arm64/asm/gic-v3-its.h create mode 100644 lib/arm64/gic-v3-its-cmd.c create mode 100644 lib/arm64/gic-v3-its.cSignature · 1 line
2.20.1
This looks pretty good to me. It just needs some resquashing cleanups. Does Andre plan to review? I've only been reviewing with respect to the framework, not ITS. If no other reviews are expected, then I'll queue the next version.
Thanks,
drew
Quoted 4 lines · Andrew Jones
This looks pretty good to me. It just needs some resquashing cleanups. Does Andre plan to review? I've only been reviewing with respect to the framework, not ITS. If no other reviews are expected, then I'll queue the next version.
Oops, sorry Zenghui, I forgot to ask if you'll be reviewing again as well.
Thanks,
drew
Zenghui Yu
reviewerQuoted 8 lines · Andrew Jones
Quoted 4 lines · Andrew Jones
This looks pretty good to me. It just needs some resquashing cleanups. Does Andre plan to review? I've only been reviewing with respect to the framework, not ITS. If no other reviews are expected, then I'll queue the next version.
Oops, sorry Zenghui, I forgot to ask if you'll be reviewing again as well.
I'd like to have a look again this week if time permits :-). Thanks for reminding me.
Zenghui
Hi Zenghui,
Quoted 7 lines · Zenghui Yu
Quoted 6 lines · Andrew Jones
Quoted 4 lines · Andrew Jones
This looks pretty good to me. It just needs some resquashing cleanups. Does Andre plan to review? I've only been reviewing with respect to the framework, not ITS. If no other reviews are expected, then I'll queue the next version.
Quoted 5 lines
Quoted 2 lines
Oops, sorry Zenghui, I forgot to ask if you'll be reviewing again as well.
I'd like to have a look again this week if time permits :-). Thanks for reminding me.
I have just sent:
[kvm-unit-tests PATCH v5 00/13] arm/arm64: Add ITS tests
where I took last Drew's comments
Thanks
Eric
Quoted 4 lines
Zenghui