arm/arm64: Add ITS tests
Subsystems (3)
v2 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.
This series includes Andre's patch: "arm: gic: Provide per-IRQ helper functions" [2]
test_migrate_unmapped_collection is currently failing with upstream kernel. See [3].
The series can be fount at:
https://github.com/eauger/kut/tree/its-v2
Best Regards
Eric
History:
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
[2] [kvm-unit-tests PATCH 00/17] arm: gic: Test SPIs and interrupt groups
https://patchwork.kernel.org/cover/11234975/
[3] [PATCH] KVM: arm/arm64: vgic-its: Fix restoration of unmappedxi
collections (https://lkml.org/lkml/2019/12/13/205)
Execution:
x For ITS migration testing use:
./run_tests.sh -g migration (blocks on TCG)
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'
Andre Przywara (1):
arm: gic: Provide per-IRQ helper functions
Eric Auger (15):
libcflat: Add other size defines
arm/arm64: gic: Introduce setup_irq() helper arm/arm64: gicv3: Add some re-distributor defines arm/arm64: ITS: Introspection tests
arm/arm64: ITS: Test BASER
arm/arm64: ITS: Set the LPI config and pending tables arm/arm64: ITS: Init the command queue
arm/arm64: ITS: Enable/Disable LPIs at re-distributor level 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.common | 3 +- arm/gic.c | 446 ++++++++++++++++++++++++++++++++++-- arm/run | 2 +- arm/unittests.cfg | 39 ++++ lib/arm/asm/gic-v3-its.h | 177 +++++++++++++++ lib/arm/asm/gic-v3.h | 20 ++ lib/arm/asm/gic.h | 12 + lib/arm/gic-v3-its-cmd.c | 453 +++++++++++++++++++++++++++++++++++++ lib/arm/gic-v3-its.c | 327 ++++++++++++++++++++++++++ lib/arm/gic.c | 132 ++++++++++- lib/arm/io.c | 13 ++ lib/arm64/asm/gic-v3-its.h | 1 + lib/libcflat.h | 3 + 13 files changed, 1600 insertions(+), 28 deletions(-) create mode 100644 lib/arm/asm/gic-v3-its.h create mode 100644 lib/arm/gic-v3-its-cmd.c create mode 100644 lib/arm/gic-v3-its.c create mode 100644 lib/arm64/asm/gic-v3-its.h
Signature · 1 line
2.20.1
PATCH v2 1/16 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 v2 2/16 arm: gic: Provide per-IRQ helper functions
In reply to Eric AugerFrom: Andre Przywara <[email protected]>
A common theme when accessing per-IRQ parameters in the GIC distributor is to set fields of a certain bit width in a range of MMIO registers. Examples are the enabled status (one bit per IRQ), the level/edge configuration (2 bits per IRQ) or the priority (8 bits per IRQ).
Add a generic helper function which is able to mask and set the respective number of bits, given the IRQ number and the MMIO offset. Provide wrappers using this function to easily allow configuring an IRQ.
For now assume that private IRQ numbers always refer to the current CPU. In a GICv2 accessing the "other" private IRQs is not easily doable (the registers are banked per CPU on the same MMIO address), so we impose the same limitation on GICv3, even though those registers are not banked there anymore.
---
initialize reg
--- lib/arm/asm/gic-v3.h | 2 + lib/arm/asm/gic.h | 8 ++++ lib/arm/gic.c | 90 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+)
lib/arm/asm/gic-v3.h +2 -0
@@ -23,6 +23,8 @@#define GICD_CTLR_ENABLE_G1A (1U << 1)#define GICD_CTLR_ENABLE_G1 (1U << 0) +#define GICD_IROUTER 0x6000 +/* Re-Distributor registers, offsets from RD_base */ #define GICR_TYPER 0x0008
lib/arm/asm/gic.h +8 -0
@@ -74,5 +74,13 @@ extern void gic_write_eoir(u32 irqstat);extern void gic_ipi_send_single (int irq,int cpu);extern void gic_ipi_send_mask (int irq,const cpumask_t *dest); +void gic_set_irq_bit (int irq,int offset); +void gic_enable_irq (int irq); +void gic_disable_irq (int irq); +void gic_set_irq_priority (int irq,u8 prio); +void gic_set_irq_target (int irq,int cpu); +void gic_set_irq_group (int irq,int group); +int gic_get_irq_group (int irq); +#endif /* !__ASSEMBLY__ */ #endif /* _ASMARM_GIC_H_ */
lib/arm/gic.c +90 -0
93 lines not on this page · raw message
Signature · 6 lines
2.20.1 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v2 3/16 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. We also export it to use it in other tests such as the PMU's one.
--- arm/gic.c | 24 +++--------------------- lib/arm/asm/gic.h | 3 +++ lib/arm/gic.c | 11 +++++++++++ 3 files changed, 17 insertions(+), 21 deletions(-)
arm/gic.c +3 -21
@@ -215,20 +215,9 @@ static void ipi_test_smp(void)report_prefix_pop (); } -static void ipi_enable (void ) -{ -gic_enable_defaults (); -#ifdef __arm__ -install_exception_handler (EXCPTN_IRQ , ipi_handler); -#else -install_irq_handler (EL1H_IRQ , ipi_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 +227,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 +284,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 (); }
lib/arm/asm/gic.h +3 -0
@@ -82,5 +82,8 @@ void gic_set_irq_target(int irq, int cpu);void gic_set_irq_group (int irq,int group);int gic_get_irq_group (int irq); +typedef void (*handler_t)(struct pt_regs *regs __unused); +extern void setup_irq (handler_t handler); +#endif /* !__ASSEMBLY__ */ #endif /* _ASMARM_GIC_H_ */
lib/arm/gic.c +11 -0
@@ -236,3 +236,14 @@ int gic_get_irq_group(int irq) {return gic_masked_irq_bits (irq,GICD_IGROUPR ,1 ,0 ,ACCESS_READ ); } + +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 (); +}
Signature · 6 lines
2.20.1 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Re: [kvm-unit-tests PATCH v2 03/16] arm/arm64: gic: Introduce setup_irq() helper
Quoted 98 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. We also export it to use it in other tests such as the PMU's one.Signed-off-by Eric Auger <[email protected]>--- arm/gic.c | 24 +++--------------------- lib/arm/asm/gic.h | 3 +++ lib/arm/gic.c | 11 +++++++++++ 3 files changed, 17 insertions(+), 21 deletions(-)arm/gic.c +3
-21@@ -215,20 +215,9 @@ static void ipi_test_smp(void)report_prefix_pop (); } -static void ipi_enable (void ) -{ -gic_enable_defaults (); -#ifdef __arm__ -install_exception_handler (EXCPTN_IRQ , ipi_handler); -#else -install_irq_handler (EL1H_IRQ , ipi_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 +227,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 +284,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 (); }lib/arm/asm/gic.h +3
-0@@ -82,5 +82,8 @@ void gic_set_irq_target(int irq, int cpu);void gic_set_irq_group (int irq,int group);int gic_get_irq_group (int irq); +typedef void (*handler_t)(struct pt_regs *regs __unused); +extern void setup_irq (handler_t handler); +#endif /* !__ASSEMBLY__ */ #endif /* _ASMARM_GIC_H_ */ lib/arm/gic.c +11
-0@@ -236,3 +236,14 @@ int gic_get_irq_group(int irq) {return gic_masked_irq_bits (irq,GICD_IGROUPR ,1 ,0 ,ACCESS_READ ); } + +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 (); +}Signature · 1 line
2.20.1
I'd rather not add this function to the common code, at least not without calling it something with 'defaults' in the name. Also I'd prefer unit tests to call local_irq_enable()/disable() themselves. I think it's fine to implement this in arm/gic.c and duplicate it in arm/pmu.c, if needed.
Thanks,
drew
PATCH v2 4/16 arm/arm64: gicv3: Add some re-distributor defines
In reply to Eric AugerPROPBASER, PENDBASE and GICR_CTRL will be used for LPI management.
--- 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)
@@ -36,6 +37,11 @@#define GICR_ICENABLER0 GICD_ICENABLER#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 v2 5/16 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.
This is our first ITS test, belonging to a new "its" group.
---
v1 -> v2:
- clean GITS_TYPER macros and unused fields in typer struct
- remove memory attribute related macros
--- arm/Makefile.common | 1 + arm/gic.c | 34 ++++++++++++++++ arm/unittests.cfg | 6 +++ lib/arm/asm/gic-v3-its.h | 81 ++++++++++++++++++++++++++++++++++++++ lib/arm/asm/gic.h | 1 + lib/arm/gic-v3-its.c | 39 ++++++++++++++++++ lib/arm/gic.c | 31 ++++++++++++--- lib/arm64/asm/gic-v3-its.h | 1 + 8 files changed, 189 insertions(+), 5 deletions(-) create mode 100644 lib/arm/asm/gic-v3-its.h create mode 100644 lib/arm/gic-v3-its.c create mode 100644 lib/arm64/asm/gic-v3-its.h
arm/Makefile.common +1 -0
@@ -52,6 +52,7 @@ cflatobjs += lib/arm/psci.o cflatobjs += lib/arm/smp.o cflatobjs += lib/arm/delay.o cflatobjs += lib/arm/gic.o lib/arm/gic-v2.o lib/arm/gic-v3.o +cflatobjs += lib/arm/gic-v3-its.o OBJDIRS += lib/arm
arm/gic.c +34 -0
@@ -506,6 +506,36 @@ static void gic_test_mmio(void)test_targets (nr_irqs); } +static void test_its_introspection (void ) +{ +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 (!typer->hw_collections,"collections only in ext memory" ); +report_info ("Target address format %s" , + typer->pta ?"Redist basse address" :"PE #" ); +} +int main (int argc,char **argv) {if (!gic_init ()) {
@@ -537,6 +567,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 +6 -0
@@ -122,6 +122,12 @@ 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 + # Test PSCI emulation [psci] file = psci.flat
lib/arm/asm/gic-v3-its.h new file +81 -0
81 lines not on this page · raw message
lib/arm/asm/gic.h +1 -0
@@ -40,6 +40,7 @@#include <asm/gic-v2.h> #include <asm/gic-v3.h> +#include <asm/gic-v3-its.h> #define PPI (irq) ((irq) + 16)#define SPI (irq) ((irq) + GIC_FIRST_SPI)
lib/arm/gic-v3-its.c new file +39 -0
@@ -0,0 +1,39 @@ +/* +* Copyright (C) 2016, Red Hat Inc, Eric Auger <[email protected]> +* +* This work is licensed under the terms of the GNU LGPL, version 2. +*/ +#include <asm/gic.h> + +struct its_data its_data; + +void its_parse_typer (void ) +{ +u64 typer =readq (gicv3_its_base () +GITS_TYPER ); + + its_data.typer.ite_size = ((typer &GITS_TYPER_ITT_ENTRY_SIZE ) >> +GITS_TYPER_ITT_ENTRY_SIZE_SHIFT ) +1 ; + its_data.typer.pta = typer &GITS_TYPER_PTA ; + its_data.typer.eventid_bits = ((typer &GITS_TYPER_IDBITS ) >> +GITS_TYPER_IDBITS_SHIFT ) +1 ; + its_data.typer.deviceid_bits = ((typer &GITS_TYPER_DEVBITS ) >> +GITS_TYPER_DEVBITS_SHIFT ) +1 ; + +if (typer &GITS_TYPER_CIL ) + its_data.typer.collid_bits = ((typer &GITS_TYPER_CIDBITS ) >> +GITS_TYPER_CIDBITS_SHIFT ) +1 ; +else + its_data.typer.collid_bits =16 ; + + its_data.typer.virt_lpi = typer &GITS_TYPER_VLPIS ; + its_data.typer.phys_lpi = typer &GITS_TYPER_PLPIS ; +} + +void its_init (void ) +{ +if (!its_data.base) +return ; + +its_parse_typer (); +} +
lib/arm/gic.c +26 -5
@@ -6,6 +6,7 @@#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;
@@ -44,12 +45,14 @@ 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,36 @@ gic_get_dt_bases(const char *compatible, void **base1, void **base2) base2[i] =ioremap (reg.addr, reg.size); } +if (base3 && !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 +124,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 +1 -0
@@ -0,0 +1 @@ +#include "../../arm/asm/gic-v3-its.h"
Signature · 6 lines
2.20.1 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Re: [kvm-unit-tests PATCH v2 05/16] arm/arm64: ITS: Introspection tests
Quoted 114 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.
This is our first ITS test, belonging to a new "its" group.
Signed-off-by Eric Auger <[email protected]>---
v1 -> v2:
- cleanGITS_TYPERmacros and unused fields in typer struct
- remove memory attribute related macros--- arm/Makefile.common | 1 + arm/gic.c | 34 ++++++++++++++++ arm/unittests.cfg | 6 +++ lib/arm/asm/gic-v3-its.h | 81 ++++++++++++++++++++++++++++++++++++++ lib/arm/asm/gic.h | 1 + lib/arm/gic-v3-its.c | 39 ++++++++++++++++++ lib/arm/gic.c | 31 ++++++++++++--- lib/arm64/asm/gic-v3-its.h | 1 + 8 files changed, 189 insertions(+), 5 deletions(-) create mode 100644 lib/arm/asm/gic-v3-its.h create mode 100644 lib/arm/gic-v3-its.c create mode 100644 lib/arm64/asm/gic-v3-its.harm/Makefile.common +1
-0@@ -52,6 +52,7 @@ cflatobjs += lib/arm/psci.o cflatobjs += lib/arm/smp.o cflatobjs += lib/arm/delay.o cflatobjs += lib/arm/gic.o lib/arm/gic-v2.o lib/arm/gic-v3.o +cflatobjs += lib/arm/gic-v3-its.o OBJDIRS += lib/armarm/gic.c +34
-0@@ -506,6 +506,36 @@ static void gic_test_mmio(void)test_targets (nr_irqs); } +static void test_its_introspection (void ) +{ +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 (!typer->hw_collections,"collections only in ext memory" ); +report_info ("Target address format %s" , + typer->pta ?"Redist basse address" :"PE #" ); +} +int main (int argc,char **argv) {if (!gic_init ()) {@@ -537,6 +567,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 +6
-0@@ -122,6 +122,12 @@ 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 + # Test PSCI emulation [psci] file = psci.flatlib/arm/asm/gic-v3-its.h new file +0
-0
lib/arm/asm/gic-v3-its.h line 4
Quoted 4 lines
lib/arm/asm/gic-v3-its.h new file +4
-0@@ -0,0 +1,81 @@ +/* +* All ITS* defines are lifted from include/linux/irqchip/arm-gic-v3.h +* +* Copyright (C) 2016, Red Hat Inc, Andrew Jones <[email protected]>
I don't recall writing this file. Well, I guess it was four years ago, so I probably just forgot :-)
Quoted 95 lines
lib/arm/asm/gic-v3-its.h new file +77
-0+* +* This work is licensed under the terms of the GNU LGPL, version 2. +*/ +#ifndef _ASMARM_GIC_V3_ITS_H_ +#define _ASMARM_GIC_V3_ITS_H_ + +#ifndef __ASSEMBLY__ + +#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_NR_REGS 8 +#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 + +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_data { +void *base; +struct its_typer typer; +}; + +extern struct its_data its_data; + +#define gicv3_its_base () (its_data.base) + +extern void its_parse_typer (void ); +extern void its_init (void ); + +#endif /* !__ASSEMBLY__ */ +#endif /* _ASMARM_GIC_V3_ITS_H_ */ lib/arm/asm/gic.h +1
-0@@ -40,6 +40,7 @@#include <asm/gic-v2.h> #include <asm/gic-v3.h> +#include <asm/gic-v3-its.h> #define PPI (irq) ((irq) + 16)#define SPI (irq) ((irq) + GIC_FIRST_SPI)lib/arm/gic-v3-its.c new file +0
-0
lib/arm/gic-v3-its.c line 2
Quoted 2 lines
lib/arm/gic-v3-its.c new file +2
-0@@ -0,0 +1,39 @@ +/* +* Copyright (C) 2016, Red Hat Inc, Eric Auger <[email protected]>
2016? Time flies...
Quoted 124 lines
lib/arm/gic-v3-its.c new file +37
-0+* +* This work is licensed under the terms of the GNU LGPL, version 2. +*/ +#include <asm/gic.h> + +struct its_data its_data; + +void its_parse_typer (void ) +{ +u64 typer =readq (gicv3_its_base () +GITS_TYPER ); + + its_data.typer.ite_size = ((typer &GITS_TYPER_ITT_ENTRY_SIZE ) >> +GITS_TYPER_ITT_ENTRY_SIZE_SHIFT ) +1 ; + its_data.typer.pta = typer &GITS_TYPER_PTA ; + its_data.typer.eventid_bits = ((typer &GITS_TYPER_IDBITS ) >> +GITS_TYPER_IDBITS_SHIFT ) +1 ; + its_data.typer.deviceid_bits = ((typer &GITS_TYPER_DEVBITS ) >> +GITS_TYPER_DEVBITS_SHIFT ) +1 ; + +if (typer &GITS_TYPER_CIL ) + its_data.typer.collid_bits = ((typer &GITS_TYPER_CIDBITS ) >> +GITS_TYPER_CIDBITS_SHIFT ) +1 ; +else + its_data.typer.collid_bits =16 ; + + its_data.typer.virt_lpi = typer &GITS_TYPER_VLPIS ; + its_data.typer.phys_lpi = typer &GITS_TYPER_PLPIS ; +} + +void its_init (void ) +{ +if (!its_data.base) +return ; + +its_parse_typer (); +} +lib/arm/gic.c +26
-5@@ -6,6 +6,7 @@#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;@@ -44,12 +45,14 @@ 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,36 @@ gic_get_dt_bases(const char *compatible, void **base1, void **base2) base2[i] =ioremap (reg.addr, reg.size); } +if (base3 && !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 +124,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 +1
-0@@ -0,0 +1 @@ +#include "../../arm/asm/gic-v3-its.h" Signature · 1 line
2.20.1
Re: [kvm-unit-tests PATCH v2 05/16] arm/arm64: ITS: Introspection tests
In reply to Eric AugerOn Fri, Jan 10, 2020 at 03:54:01PM +0100, Eric Auger wrote:
...
Quoted 13 lines
lib/arm/gic.c +1
-0@@ -6,6 +6,7 @@#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;
lib/arm/gic.c static const struct gic_common_ops gicv3_common_ops = { · line 49
Quoted 6 lines
lib/arm/gic.c +2
-1@@ -44,12 +45,14 @@ 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)
Here's another place that I would prefer using our 120 chars. No need to put base3 on a new line.
Thanks,
drew
PATCH v2 6/16 arm/arm64: ITS: Test BASER
In reply to Eric AugerAdd helper routines to parse and set up BASER registers. Add a new test dedicated to BASER<n> accesses.
---
v2 -> v3:
- remove everything related to memory attributes
- s/dev_baser/coll_baser/ in report_info
- add extra line
- removed index filed in its_baser
--- arm/gic.c | 21 ++++++++++- arm/unittests.cfg | 6 +++ lib/arm/asm/gic-v3-its.h | 14 +++++++ lib/arm/gic-v3-its.c | 80 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 1 deletion(-)
arm/gic.c +20 -1
@@ -531,11 +531,26 @@ static void test_its_introspection(void) typer->collid_bits);report (typer->eventid_bits && typer->deviceid_bits && typer->collid_bits,"ID spaces" ); -report (!typer->hw_collections,"collections only in ext memory" );report_info ("Target address format %s" , typer->pta ?"Redist basse address" :"PE #" ); } +static void test_its_baser (void ) +{ +struct its_baser *dev_baser, *coll_baser; + +if (!gicv3_its_base ()) { +report_skip ("No ITS, skip ..." ); +return ; + } + + dev_baser =its_lookup_baser (GITS_BASER_TYPE_DEVICE ); + coll_baser =its_lookup_baser (GITS_BASER_TYPE_COLLECTION ); +report (dev_baser && coll_baser,"detect device and collection BASER" ); +report_info ("device baser entry_size = 0x%x" , dev_baser->esz); +report_info ("collection baser entry_size = 0x%x" , coll_baser->esz); +} +int main (int argc,char **argv) {if (!gic_init ()) {
@@ -571,6 +586,10 @@ int main(int argc, char **argv)report_prefix_push (argv[1 ]);test_its_introspection ();report_prefix_pop (); + }else if (strcmp (argv[1 ],"its-baser" ) ==0 ) { +report_prefix_push (argv[1 ]); +test_its_baser (); +report_prefix_pop (); }else {report_abort ("Unknown subtest '%s'" , argv[1 ]); }
arm/unittests.cfg +6 -0
@@ -128,6 +128,12 @@ smp = $MAX_SMP extra_params = -machine gic-version=3 -append 'its-introspection' groups = its +[its-baser] +file = gic.flat +smp = $MAX_SMP +extra_params = -machine gic-version=3 -append 'its-baser' +groups = its + # Test PSCI emulation [psci] file = psci.flat
lib/arm/asm/gic-v3-its.h +14 -0
@@ -65,9 +65,20 @@ struct its_typer {bool virt_lpi; }; +struct its_baser { +int type; +size_t psz; +int nr_pages; +bool indirect; +phys_addr_t table_addr; +bool valid; +int esz; +}; +struct its_data {void *base;struct its_typer typer; +struct its_baser baser[GITS_BASER_NR_REGS ]; };extern struct its_data its_data;
@@ -76,6 +87,9 @@ extern struct its_data its_data;extern void its_parse_typer (void );extern void its_init (void ); +extern int its_parse_baser (int i,struct its_baser *baser); +extern void its_setup_baser (int i,struct its_baser *baser); +extern struct its_baser *its_lookup_baser (int type);#endif /* !__ASSEMBLY__ */ #endif /* _ASMARM_GIC_V3_ITS_H_ */
lib/arm/gic-v3-its.c +80 -0
97 lines not on this page · raw message
Signature · 6 lines
2.20.1 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Re: [kvm-unit-tests PATCH v2 06/16] arm/arm64: ITS: Test BASER
Quoted 67 lines · Eric Auger
Add helper routines to parse and set up BASER registers. Add a new test dedicated to BASER<n> accesses.
Signed-off-by Eric Auger <[email protected]>---
v2 -> v3:
- remove everything related to memory attributes
- s/dev_baser/coll_baser/ inreport_info
- add extra line
- removed index filed inits_baser--- arm/gic.c | 21 ++++++++++- arm/unittests.cfg | 6 +++ lib/arm/asm/gic-v3-its.h | 14 +++++++ lib/arm/gic-v3-its.c | 80 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 1 deletion(-)arm/gic.c +20
-1@@ -531,11 +531,26 @@ static void test_its_introspection(void) typer->collid_bits);report (typer->eventid_bits && typer->deviceid_bits && typer->collid_bits,"ID spaces" ); -report (!typer->hw_collections,"collections only in ext memory" );report_info ("Target address format %s" , typer->pta ?"Redist basse address" :"PE #" ); } +static void test_its_baser (void ) +{ +struct its_baser *dev_baser, *coll_baser; + +if (!gicv3_its_base ()) { +report_skip ("No ITS, skip ..." ); +return ; + } + + dev_baser =its_lookup_baser (GITS_BASER_TYPE_DEVICE ); + coll_baser =its_lookup_baser (GITS_BASER_TYPE_COLLECTION ); +report (dev_baser && coll_baser,"detect device and collection BASER" ); +report_info ("device baser entry_size = 0x%x" , dev_baser->esz); +report_info ("collection baser entry_size = 0x%x" , coll_baser->esz); +} +int main (int argc,char **argv) {if (!gic_init ()) {@@ -571,6 +586,10 @@ int main(int argc, char **argv)report_prefix_push (argv[1 ]);test_its_introspection ();report_prefix_pop (); + }else if (strcmp (argv[1 ],"its-baser" ) ==0 ) { +report_prefix_push (argv[1 ]); +test_its_baser (); +report_prefix_pop (); }else {report_abort ("Unknown subtest '%s'" , argv[1 ]); }arm/unittests.cfg +0
-0
arm/unittests.cfg smp = $MAX_SMP · line 135
Quoted 8 lines
arm/unittests.cfg +5
-0@@ -128,6 +128,12 @@ smp = $MAX_SMP extra_params = -machine gic-version=3 -append 'its-introspection' groups = its +[its-baser] +file = gic.flat +smp = $MAX_SMP +extra_params = -machine gic-version=3 -append 'its-baser' +groups = its
Do these tests need to be run separately from the its-introspection tests for some reason? If not, then I'd combine them.
Thanks,
drew
Re: [kvm-unit-tests PATCH v2 06/16] arm/arm64: ITS: Test BASER
Hi,
Quoted 71 lines · Andrew Jones
Quoted 70 lines · Eric Auger
Add helper routines to parse and set up BASER registers. Add a new test dedicated to BASER<n> accesses.
Signed-off-by Eric Auger <[email protected]>---
v2 -> v3:
- remove everything related to memory attributes
- s/dev_baser/coll_baser/ inreport_info
- add extra line
- removed index filed inits_baser--- arm/gic.c | 21 ++++++++++- arm/unittests.cfg | 6 +++ lib/arm/asm/gic-v3-its.h | 14 +++++++ lib/arm/gic-v3-its.c | 80 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 1 deletion(-)arm/gic.c +20
-1@@ -531,11 +531,26 @@ static void test_its_introspection(void) typer->collid_bits);report (typer->eventid_bits && typer->deviceid_bits && typer->collid_bits,"ID spaces" ); -report (!typer->hw_collections,"collections only in ext memory" );report_info ("Target address format %s" , typer->pta ?"Redist basse address" :"PE #" ); } +static void test_its_baser (void ) +{ +struct its_baser *dev_baser, *coll_baser; + +if (!gicv3_its_base ()) { +report_skip ("No ITS, skip ..." ); +return ; + } + + dev_baser =its_lookup_baser (GITS_BASER_TYPE_DEVICE ); + coll_baser =its_lookup_baser (GITS_BASER_TYPE_COLLECTION ); +report (dev_baser && coll_baser,"detect device and collection BASER" ); +report_info ("device baser entry_size = 0x%x" , dev_baser->esz); +report_info ("collection baser entry_size = 0x%x" , coll_baser->esz); +} +int main (int argc,char **argv) {if (!gic_init ()) {@@ -571,6 +586,10 @@ int main(int argc, char **argv)report_prefix_push (argv[1 ]);test_its_introspection ();report_prefix_pop (); + }else if (strcmp (argv[1 ],"its-baser" ) ==0 ) { +report_prefix_push (argv[1 ]); +test_its_baser (); +report_prefix_pop (); }else {report_abort ("Unknown subtest '%s'" , argv[1 ]); }arm/unittests.cfg +0
-0@@ -128,6 +128,12 @@ smp = $MAX_SMP extra_params = -machine gic-version=3 -append 'its-introspection' groups = its
Quoted 8 lines
arm/unittests.cfg smp = $MAX_SMP · line 135
Quoted 5 lines
arm/unittests.cfg +5
-0+[its-baser] +file = gic.flat +smp = $MAX_SMP +extra_params = -machine gic-version=3 -append 'its-baser' +groups = itsDo these tests need to be run separately from the its-introspection tests for some reason? If not, then I'd combine them.
Not really. To me it is easier to debug and analyze when the fail though. I will merge both.
Thanks
Eric
Quoted 4 lines
Thanks,
drew
PATCH v2 7/16 arm/arm64: ITS: 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.
---
v1 -> v2:
- remove memory attributes
--- lib/arm/asm/gic-v3-its.h | 3 ++ lib/arm/asm/gic-v3.h | 12 ++++++++ lib/arm/gic-v3-its.c | 60 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+)
lib/arm/asm/gic-v3-its.h +3 -0
@@ -90,6 +90,9 @@ extern void its_init(void);extern int its_parse_baser (int i,struct its_baser *baser);extern void its_setup_baser (int i,struct its_baser *baser);extern struct its_baser *its_lookup_baser (int type); +extern void set_lpi_config (int n,u8 val); +extern u8 get_lpi_config (int n); +extern void set_pending_table_bit (int rdist,int n,bool set);#endif /* !__ASSEMBLY__ */ #endif /* _ASMARM_GIC_V3_ITS_H_ */
lib/arm/asm/gic-v3.h +12 -0
@@ -48,6 +48,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__
@@ -64,6 +74,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;
lib/arm/gic-v3-its.c +60 -0
63 lines not on this page · raw message
Signature · 1 line
2.20.1
Re: [kvm-unit-tests PATCH v2 07/16] arm/arm64: ITS: Set the LPI config and pending tables
Quoted 24 lines · Eric Auger
Allocate 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.
Signed-off-by Eric Auger <[email protected]>---
v1 -> v2:
- remove memory attributes--- lib/arm/asm/gic-v3-its.h | 3 ++ lib/arm/asm/gic-v3.h | 12 ++++++++ lib/arm/gic-v3-its.c | 60 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+)lib/arm/asm/gic-v3-its.h +0
-0
lib/arm/asm/gic-v3-its.h extern void its_init(void); · line 95
Quoted 6 lines
lib/arm/asm/gic-v3-its.h +3
-0@@ -90,6 +90,9 @@ extern void its_init(void);extern int its_parse_baser (int i,struct its_baser *baser);extern void its_setup_baser (int i,struct its_baser *baser);extern struct its_baser *its_lookup_baser (int type); +extern void set_lpi_config (int n,u8 val); +extern u8 get_lpi_config (int n); +extern void set_pending_table_bit (int rdist,int n,bool set);
Please prefix with 'its' or at least swap the 'lpi' and verb. E.g. lpi_set_config, its_set_pending_table_bit.
Quoted 42 lines
lib/arm/asm/gic-v3-its.h +0
-0#endif /* !__ASSEMBLY__ */ #endif /* _ASMARM_GIC_V3_ITS_H_ */ lib/arm/asm/gic-v3.h +12
-0@@ -48,6 +48,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__@@ -64,6 +74,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;lib/arm/gic-v3-its.c +1
-0@@ -117,3 +117,63 @@ void its_setup_baser(int i, struct its_baser *baser)writeq (val,gicv3_its_base () +GITS_BASER + i *8 ); } +inline void set_lpi_config (int n,u8 value)
lib/arm/gic-v3-its.c void its_setup_baser(int i, struct its_baser *baser) · line 130
Quoted 10 lines
lib/arm/gic-v3-its.c +10
-0+{ +u8 *entry = (u8 *)(gicv3_data.lpi_prop + (n -8192 )); + *entry = value; +} + +inline u8 get_lpi_config (int n) +{ +u8 *entry = (u8 *)(gicv3_data.lpi_prop + (n -8192 )); +return *entry; +}
Probably don't need the 'inline', but ok.
lib/arm/gic-v3-its.c void its_setup_baser(int i, struct its_baser *baser) · line 134
Quoted 4 lines
lib/arm/gic-v3-its.c +4
-0+ +/* alloc_lpi_tables: Allocate LPI config and pending tables */ +void alloc_lpi_tables (void ); +void alloc_lpi_tables (void )
Why not add this to the header (renamed to lpi_alloc_tables)? Or should this function be static?
Quoted 15 lines
lib/arm/gic-v3-its.c +15
-0+{ +unsigned long n =SZ_64K >>PAGE_SHIFT ; +unsigned long order =fls (n); +u64 prop_val; +int cpu; + + gicv3_data.lpi_prop = (void *)virt_to_phys (alloc_pages (order)); + +/* ID bits = 13, ie. up to 14b LPI INTID */ + prop_val = (u64 )gicv3_data.lpi_prop |13 ; + +/* +* Allocate pending tables for each redistributor +* and set PROPBASER and PENDBASER +*/
lib/arm/gic-v3-its.c void its_setup_baser(int i, struct its_baser *baser) · line 159
Quoted 10 lines
lib/arm/gic-v3-its.c +10
-0+for_each_present_cpu (cpu) { +u64 pend_val; +void *ptr; + + ptr = gicv3_data.redist_base[cpu]; + +writeq (prop_val, ptr +GICR_PROPBASER ); + + gicv3_data.lpi_pend[cpu] = + (void *)virt_to_phys (alloc_pages (order));
nit: I think these line brakes on = or worse than going over 80 chars. And, you don't need to worry about 80 chars anyway. See the README, we allow 120.
Quoted 23 lines
lib/arm/gic-v3-its.c +20
-0+ + pend_val = (u64 )gicv3_data.lpi_pend[cpu]; + +writeq (pend_val, ptr +GICR_PENDBASER ); + } +} + +void set_pending_table_bit (int rdist,int n,bool set) +{ +u8 *ptr =phys_to_virt ((phys_addr_t )gicv3_data.lpi_pend[rdist]); +u8 mask =1 << (n %8 ), byte; + + ptr += (n /8 ); + byte = *ptr; +if (set) + byte |= mask; +else + byte &= ~mask; + *ptr = byte; +}Signature · 1 line
2.20.1
Thanks,
drew
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v2 8/16 arm/arm64: ITS: Init the command queue
In reply to Eric AugerAllocate the command queue and initialize related registers:
CBASER, CREADR, CWRITER.
The command queue is 64kB. This aims at not bothing with fullness.
---
v2 -> v3:
- removed readr
--- lib/arm/asm/gic-v3-its.h | 6 ++++++ lib/arm/gic-v3-its.c | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+)
lib/arm/asm/gic-v3-its.h +6 -0
@@ -75,10 +75,16 @@ struct its_baser {int esz; }; +struct its_cmd_block { +u64 raw_cmd[4 ]; +}; +struct its_data {void *base;struct its_typer typer;struct its_baser baser[GITS_BASER_NR_REGS ]; +struct its_cmd_block *cmd_base; +struct its_cmd_block *cmd_write; };extern struct its_data its_data;
lib/arm/gic-v3-its.c +22 -0
@@ -177,3 +177,25 @@ void set_pending_table_bit(int rdist, int n, bool set) byte &= ~mask; *ptr = byte; } + +/** +* init_cmd_queue: Allocate the command queue and initialize +* CBASER, CREADR, CWRITER +*/ +void init_cmd_queue (void ); +void init_cmd_queue (void ) +{ +unsigned long n =SZ_64K >>PAGE_SHIFT ; +unsigned long order =fls (n); +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 ); +}
Signature · 1 line
2.20.1
Re: [kvm-unit-tests PATCH v2 08/16] arm/arm64: ITS: Init the command queue
Quoted 4 lines · Eric Auger
Allocate the command queue and initialize related registers:
CBASER, CREADR, CWRITER.The command queue is 64kB. This aims at not bothing with fullness.
I think these means that the goal isn't completeness? If so, please write "minimal implementation" or nothing, as all of kvm-unit-tests is a minimal implementation.
Quoted 17 lines
Signed-off-by Eric Auger <[email protected]>---
v2 -> v3:
- removed readr--- lib/arm/asm/gic-v3-its.h | 6 ++++++ lib/arm/gic-v3-its.c | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+)lib/arm/asm/gic-v3-its.h +0
-0
lib/arm/asm/gic-v3-its.h struct its_baser { · line 79
Quoted 5 lines
lib/arm/asm/gic-v3-its.h +2
-0@@ -75,10 +75,16 @@ struct its_baser {int esz; }; +struct its_cmd_block { +u64 raw_cmd[4 ];
Do we need these spaces (not even a tab) after the u64?
Quoted 16 lines
lib/arm/asm/gic-v3-its.h +4
-0+}; +struct its_data {void *base;struct its_typer typer;struct its_baser baser[GITS_BASER_NR_REGS ]; +struct its_cmd_block *cmd_base; +struct its_cmd_block *cmd_write; };extern struct its_data its_data;lib/arm/gic-v3-its.c +0
-0
lib/arm/gic-v3-its.c void set_pending_table_bit(int rdist, int n, bool set) · line 186
Quoted 10 lines
lib/arm/gic-v3-its.c +7
-0@@ -177,3 +177,25 @@ void set_pending_table_bit(int rdist, int n, bool set) byte &= ~mask; *ptr = byte; } + +/** +* init_cmd_queue: Allocate the command queue and initialize +* CBASER, CREADR, CWRITER +*/ +void init_cmd_queue (void ); +void init_cmd_queue (void )
its_cmd_queue_init
lib/arm/gic-v3-its.c void set_pending_table_bit(int rdist, int n, bool set) · line 195
Quoted 9 lines
lib/arm/gic-v3-its.c +9
-0+{ +unsigned long n =SZ_64K >>PAGE_SHIFT ; +unsigned long order =fls (n); +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 );
120 chars
Quoted 9 lines
lib/arm/gic-v3-its.c +6
-0+ +writeq (cbaser, its_data.base +GITS_CBASER ); + + its_data.cmd_write = its_data.cmd_base; +writeq (0 , its_data.base +GITS_CWRITER ); +}Signature · 1 line
2.20.1
Thanks,
drew
PATCH v2 9/16 arm/arm64: ITS: Enable/Disable LPIs at re-distributor level
In reply to Eric AugerThis helper function enables or disables the signaling of LPIs at redistributor level.
--- lib/arm/asm/gic-v3-its.h | 1 + lib/arm/gic-v3-its.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+)
lib/arm/asm/gic-v3-its.h +1 -0
@@ -99,6 +99,7 @@ extern struct its_baser *its_lookup_baser(int type);extern void set_lpi_config (int n,u8 val);extern u8 get_lpi_config (int n);extern void set_pending_table_bit (int rdist,int n,bool set); +extern void gicv3_rdist_ctrl_lpi (u32 redist,bool set);#endif /* !__ASSEMBLY__ */ #endif /* _ASMARM_GIC_V3_ITS_H_ */
lib/arm/gic-v3-its.c +18 -0
@@ -199,3 +199,21 @@ void init_cmd_queue(void) its_data.cmd_write = its_data.cmd_base;writeq (0 , its_data.base +GITS_CWRITER ); } + +void gicv3_rdist_ctrl_lpi (u32 redist,bool set) +{ +void *ptr; +u64 val; + +if (redist >= nr_cpus) +report_abort ("%s redist=%d >= cpu_count=%d\n" , + __func__, 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 ); +}
Signature · 1 line
2.20.1
Re: [kvm-unit-tests PATCH v2 09/16] arm/arm64: ITS: Enable/Disable LPIs at re-distributor level
Quoted 28 lines · Eric Auger
This helper function enables or disables the signaling of LPIs at redistributor level.
Signed-off-by Eric Auger <[email protected]>--- lib/arm/asm/gic-v3-its.h | 1 + lib/arm/gic-v3-its.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+)lib/arm/asm/gic-v3-its.h +1
-0@@ -99,6 +99,7 @@ extern struct its_baser *its_lookup_baser(int type);extern void set_lpi_config (int n,u8 val);extern u8 get_lpi_config (int n);extern void set_pending_table_bit (int rdist,int n,bool set); +extern void gicv3_rdist_ctrl_lpi (u32 redist,bool set);#endif /* !__ASSEMBLY__ */ #endif /* _ASMARM_GIC_V3_ITS_H_ */ lib/arm/gic-v3-its.c +0
-0@@ -199,3 +199,21 @@ void init_cmd_queue(void) its_data.cmd_write = its_data.cmd_base;writeq (0 , its_data.base +GITS_CWRITER );
lib/arm/gic-v3-its.c void init_cmd_queue(void) · line 210
Quoted 10 lines
lib/arm/gic-v3-its.c +9
-0} + +void gicv3_rdist_ctrl_lpi (u32 redist,bool set) +{ +void *ptr; +u64 val; + +if (redist >= nr_cpus) +report_abort ("%s redist=%d >= cpu_count=%d\n" , + __func__, redist, nr_cpus);
I'd use {} here because of the multiline call. But, we don't use the report API in common code. Well, apparently s390 has report calls in lib/s390x/interrupt.c, but I don't really agree with that. IMO, common code failures should always be unexpected and just assert/assert_msg.
Quoted 12 lines
lib/arm/gic-v3-its.c +9
-0+ + 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 ); +}Signature · 1 line
2.20.1
Also, you can squash this patch into whatever is going to make use of this new helper.
Thanks,
drew
PATCH v2 10/16 arm/arm64: ITS: its_enable_defaults
In reply to Eric Augerits_enable_defaults() is the top init function that allocates all the requested tables (device, collection, lpi config and pending tables), enable LPIs at distributor level and ITS level.
gicv3_enable_defaults must be called before.
--- lib/arm/asm/gic-v3-its.h | 1 + lib/arm/gic-v3-its.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+)
lib/arm/asm/gic-v3-its.h +1 -0
@@ -100,6 +100,7 @@ extern void set_lpi_config(int n, u8 val);extern u8 get_lpi_config (int n);extern void set_pending_table_bit (int rdist,int n,bool set);extern void gicv3_rdist_ctrl_lpi (u32 redist,bool set); +extern void its_enable_defaults (void );#endif /* !__ASSEMBLY__ */ #endif /* _ASMARM_GIC_V3_ITS_H_ */
lib/arm/gic-v3-its.c +40 -0
@@ -217,3 +217,43 @@ void gicv3_rdist_ctrl_lpi(u32 redist, bool set) val &= ~GICR_CTLR_ENABLE_LPIS ;writel (val, ptr +GICR_CTLR ); } + +void its_enable_defaults (void ) +{ +unsigned int i; + +its_parse_typer (); + +/* Allocate BASER tables (device and collection tables) */ +for (i =0 ; i <GITS_BASER_NR_REGS ; i++) { +struct its_baser *baser = &its_data.baser[i]; +int ret; + + ret =its_parse_baser (i, baser); +if (ret) +continue ; + +switch (baser->type) { +case GITS_BASER_TYPE_DEVICE : + baser->valid = true; +its_setup_baser (i, baser); +break ; +case GITS_BASER_TYPE_COLLECTION : + baser->valid = true; +its_setup_baser (i, baser); +break ; +default : +break ; + } + } + +/* Allocate LPI config and pending tables */ +alloc_lpi_tables (); + +init_cmd_queue (); + +for (i =0 ; i < nr_cpus; i++) +gicv3_rdist_ctrl_lpi (i, true); + +writel (GITS_CTLR_ENABLE , its_data.base +GITS_CTLR ); +}
Signature · 1 line
2.20.1
PATCH v2 11/16 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).
---
v2 -> v3:
- s/nb_/nr_
--- lib/arm/asm/gic-v3-its.h | 20 +++++++++++++++++ lib/arm/gic-v3-its.c | 46 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+)
lib/arm/asm/gic-v3-its.h +20 -0
@@ -55,6 +55,9 @@#define GITS_BASER_TYPE_DEVICE 1#define GITS_BASER_TYPE_COLLECTION 4 +#define GITS_MAX_DEVICES 8 +#define GITS_MAX_COLLECTIONS 8 +struct its_typer {unsigned int ite_size;unsigned int eventid_bits;
@@ -79,12 +82,27 @@ struct its_cmd_block {u64 raw_cmd[4 ]; }; +struct its_device { +u32 device_id;/* device ID */ +u32 nr_ites;/* Max Interrupt Translation Entries */ +void *itt;/* Interrupt Translation Table GPA */ +}; + +struct its_collection { +u64 target_address; +u16 col_id; +}; +struct its_data {void *base;struct its_typer typer;struct its_baser baser[GITS_BASER_NR_REGS ];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;
@@ -101,6 +119,8 @@ extern u8 get_lpi_config(int n);extern void set_pending_table_bit (int rdist,int n,bool set);extern void gicv3_rdist_ctrl_lpi (u32 redist,bool set);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 /* !__ASSEMBLY__ */ #endif /* _ASMARM_GIC_V3_ITS_H_ */
lib/arm/gic-v3-its.c +46 -0
49 lines not on this page · raw message
Signature · 1 line
2.20.1
Re: [kvm-unit-tests PATCH v2 11/16] arm/arm64: ITS: Device and collection Initialization
Quoted 127 lines · Eric Auger
Introduce 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).
Signed-off-by Eric Auger <[email protected]>---
v2 -> v3:
- s/nb_/nr_--- lib/arm/asm/gic-v3-its.h | 20 +++++++++++++++++ lib/arm/gic-v3-its.c | 46 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+)lib/arm/asm/gic-v3-its.h +20
-0@@ -55,6 +55,9 @@#define GITS_BASER_TYPE_DEVICE 1#define GITS_BASER_TYPE_COLLECTION 4 +#define GITS_MAX_DEVICES 8 +#define GITS_MAX_COLLECTIONS 8 +struct its_typer {unsigned int ite_size;unsigned int eventid_bits;@@ -79,12 +82,27 @@ struct its_cmd_block {u64 raw_cmd[4 ]; }; +struct its_device { +u32 device_id;/* device ID */ +u32 nr_ites;/* Max Interrupt Translation Entries */ +void *itt;/* Interrupt Translation Table GPA */ +}; + +struct its_collection { +u64 target_address; +u16 col_id; +}; +struct its_data {void *base;struct its_typer typer;struct its_baser baser[GITS_BASER_NR_REGS ];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;@@ -101,6 +119,8 @@ extern u8 get_lpi_config(int n);extern void set_pending_table_bit (int rdist,int n,bool set);extern void gicv3_rdist_ctrl_lpi (u32 redist,bool set);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 /* !__ASSEMBLY__ */ #endif /* _ASMARM_GIC_V3_ITS_H_ */ lib/arm/gic-v3-its.c +46
-0@@ -257,3 +257,49 @@ 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_baser *baser; +struct its_device *new; +unsigned long n, order; + +if (its_data.nr_devices >=GITS_MAX_DEVICES ) +report_abort ("%s redimension GITS_MAX_DEVICES" , __func__); + + baser =its_lookup_baser (GITS_BASER_TYPE_DEVICE ); +if (!baser) +return NULL ; + + 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 ; + order =is_power_of_2 (n) ?fls (n) :fls (n) +1 ; + new->itt = (void *)virt_to_phys (alloc_pages (order)); + + its_data.nr_devices++; +return new; +} + +struct its_collection *its_create_collection (u32 col_id,u32 pe) +{ +struct its_collection *new; + +if (its_data.nr_collections >=GITS_MAX_COLLECTIONS ) +report_abort ("%s redimension GITS_MAX_COLLECTIONS" , __func__); + + 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
Please replace the if (cond) report_abort(...)'s with assert_msg(cond, ...)'s.
Thanks,
drew
PATCH v2 12/16 arm/arm64: ITS: commands
In reply to Eric AugerImplement main ITS commands. The code is largely inherited from the ITS driver.
---
v1 -> v2:
- removed its_print_cmd_state
--- arm/Makefile.common | 2 +- lib/arm/asm/gic-v3-its.h | 35 +++ lib/arm/gic-v3-its-cmd.c | 453 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 489 insertions(+), 1 deletion(-) create mode 100644 lib/arm/gic-v3-its-cmd.c
arm/Makefile.common +1 -1
@@ -52,7 +52,7 @@ cflatobjs += lib/arm/psci.o cflatobjs += lib/arm/smp.o cflatobjs += lib/arm/delay.o cflatobjs += lib/arm/gic.o lib/arm/gic-v2.o lib/arm/gic-v3.o -cflatobjs += lib/arm/gic-v3-its.o +cflatobjs += lib/arm/gic-v3-its.o lib/arm/gic-v3-its-cmd.o OBJDIRS += lib/arm
lib/arm/asm/gic-v3-its.h +35 -0
@@ -58,6 +58,24 @@#define GITS_MAX_DEVICES 8#define GITS_MAX_COLLECTIONS 8 +/* +* ITS commands +*/ +#define GITS_CMD_MAPD 0x08 +#define GITS_CMD_MAPC 0x09 +#define GITS_CMD_MAPTI 0x0a +/* older GIC documentation used MAPVI for this command */ +#define GITS_CMD_MAPVI GITS_CMD_MAPTI +#define GITS_CMD_MAPI 0x0b +#define GITS_CMD_MOVI 0x01 +#define GITS_CMD_DISCARD 0x0f +#define GITS_CMD_INV 0x0c +#define GITS_CMD_MOVALL 0x0e +#define GITS_CMD_INVALL 0x0d +#define GITS_CMD_INT 0x03 +#define GITS_CMD_CLEAR 0x04 +#define GITS_CMD_SYNC 0x05 +struct its_typer {unsigned int ite_size;unsigned int eventid_bits;
@@ -122,5 +140,22 @@ 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); +extern void its_send_mapd (struct its_device *dev,int valid); +extern void its_send_mapc (struct its_collection *col,int valid); +extern void its_send_mapti (struct its_device *dev,u32 irq_id, +u32 event_id,struct its_collection *col); +extern void its_send_int (struct its_device *dev,u32 event_id); +extern void its_send_inv (struct its_device *dev,u32 event_id); +extern void its_send_discard (struct its_device *dev,u32 event_id); +extern void its_send_clear (struct its_device *dev,u32 event_id); +extern void its_send_invall (struct its_collection *col); +extern void its_send_movi (struct its_device *dev, +struct its_collection *col,u32 id); +extern void its_send_sync (struct its_collection *col); + +#define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1ULL << 0) +#define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1) +#define ITS_FLAGS_WORKAROUND_CAVIUM_23144 (1ULL << 2) +#endif /* !__ASSEMBLY__ */ #endif /* _ASMARM_GIC_V3_ITS_H_ */
lib/arm/gic-v3-its-cmd.c new file +453 -0
453 lines not on this page · raw message
Signature · 1 line
2.20.1
Re: [kvm-unit-tests PATCH v2 12/16] arm/arm64: ITS: commands
Quoted 87 lines · Eric Auger
Implement main ITS commands. The code is largely inherited from the ITS driver.
Signed-off-by Eric Auger <[email protected]>---
v1 -> v2:
- removedits_print_cmd_state--- arm/Makefile.common | 2 +- lib/arm/asm/gic-v3-its.h | 35 +++ lib/arm/gic-v3-its-cmd.c | 453 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 489 insertions(+), 1 deletion(-) create mode 100644 lib/arm/gic-v3-its-cmd.carm/Makefile.common +1
-1@@ -52,7 +52,7 @@ cflatobjs += lib/arm/psci.o cflatobjs += lib/arm/smp.o cflatobjs += lib/arm/delay.o cflatobjs += lib/arm/gic.o lib/arm/gic-v2.o lib/arm/gic-v3.o -cflatobjs += lib/arm/gic-v3-its.o +cflatobjs += lib/arm/gic-v3-its.o lib/arm/gic-v3-its-cmd.o OBJDIRS += lib/armlib/arm/asm/gic-v3-its.h +35
-0@@ -58,6 +58,24 @@#define GITS_MAX_DEVICES 8#define GITS_MAX_COLLECTIONS 8 +/* +* ITS commands +*/ +#define GITS_CMD_MAPD 0x08 +#define GITS_CMD_MAPC 0x09 +#define GITS_CMD_MAPTI 0x0a +/* older GIC documentation used MAPVI for this command */ +#define GITS_CMD_MAPVI GITS_CMD_MAPTI +#define GITS_CMD_MAPI 0x0b +#define GITS_CMD_MOVI 0x01 +#define GITS_CMD_DISCARD 0x0f +#define GITS_CMD_INV 0x0c +#define GITS_CMD_MOVALL 0x0e +#define GITS_CMD_INVALL 0x0d +#define GITS_CMD_INT 0x03 +#define GITS_CMD_CLEAR 0x04 +#define GITS_CMD_SYNC 0x05 +struct its_typer {unsigned int ite_size;unsigned int eventid_bits;@@ -122,5 +140,22 @@ 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); +extern void its_send_mapd (struct its_device *dev,int valid); +extern void its_send_mapc (struct its_collection *col,int valid); +extern void its_send_mapti (struct its_device *dev,u32 irq_id, +u32 event_id,struct its_collection *col); +extern void its_send_int (struct its_device *dev,u32 event_id); +extern void its_send_inv (struct its_device *dev,u32 event_id); +extern void its_send_discard (struct its_device *dev,u32 event_id); +extern void its_send_clear (struct its_device *dev,u32 event_id); +extern void its_send_invall (struct its_collection *col); +extern void its_send_movi (struct its_device *dev, +struct its_collection *col,u32 id); +extern void its_send_sync (struct its_collection *col); + +#define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1ULL << 0) +#define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1) +#define ITS_FLAGS_WORKAROUND_CAVIUM_23144 (1ULL << 2) +#endif /* !__ASSEMBLY__ */ #endif /* _ASMARM_GIC_V3_ITS_H_ */ lib/arm/gic-v3-its-cmd.c new file +0
-0
lib/arm/gic-v3-its-cmd.c line 2
Quoted 2 lines
lib/arm/gic-v3-its-cmd.c new file +2
-0@@ -0,0 +1,453 @@ +/* +* Copyright (C) 2016, Red Hat Inc, Eric Auger <[email protected]>
2016?
Quoted 122 lines
lib/arm/gic-v3-its-cmd.c new file +122
-0+* +* Most of the code is copy-pasted from: +* drivers/irqchip/irq-gic-v3-its.c +* This work is licensed under the terms of the GNU LGPL, version 2. +*/ +#include <asm/io.h> +#include <asm/gic.h> + +#define ITS_ITT_ALIGN SZ_256 + +static const char *const its_cmd_string[] = { + [GITS_CMD_MAPD ] ="MAPD" , + [GITS_CMD_MAPC ] ="MAPC" , + [GITS_CMD_MAPTI ] ="MAPTI" , + [GITS_CMD_MAPI ] ="MAPI" , + [GITS_CMD_MOVI ] ="MOVI" , + [GITS_CMD_DISCARD ] ="DISCARD" , + [GITS_CMD_INV ] ="INV" , + [GITS_CMD_MOVALL ] ="MOVALL" , + [GITS_CMD_INVALL ] ="INVALL" , + [GITS_CMD_INT ] ="INT" , + [GITS_CMD_CLEAR ] ="CLEAR" , + [GITS_CMD_SYNC ] ="SYNC" , +}; + +struct its_cmd_desc { +union { +struct { +struct its_device *dev; +u32 event_id; + } its_inv_cmd; + +struct { +struct its_device *dev; +u32 event_id; + } its_int_cmd; + +struct { +struct its_device *dev; +bool valid; + } its_mapd_cmd; + +struct { +struct its_collection *col; +bool valid; + } its_mapc_cmd; + +struct { +struct its_device *dev; +u32 phys_id; +u32 event_id; +u32 col_id; + } its_mapti_cmd; + +struct { +struct its_device *dev; +struct its_collection *col; +u32 event_id; + } its_movi_cmd; + +struct { +struct its_device *dev; +u32 event_id; + } its_discard_cmd; + +struct { +struct its_device *dev; +u32 event_id; + } its_clear_cmd; + +struct { +struct its_collection *col; + } its_invall_cmd; + +struct { +struct its_collection *col; + } its_sync_cmd; + }; +}; + +typedef void (*its_cmd_builder_t )(struct its_cmd_block *, +struct its_cmd_desc *); + +/* ITS COMMANDS */ + +static void its_encode_cmd (struct its_cmd_block *cmd,u8 cmd_nr) +{ + cmd->raw_cmd[0 ] &= ~0xffUL ; + cmd->raw_cmd[0 ] |= cmd_nr; +} + +static void its_encode_devid (struct its_cmd_block *cmd,u32 devid) +{ + cmd->raw_cmd[0 ] &=BIT_ULL (32 ) -1 ; + cmd->raw_cmd[0 ] |= ((u64 )devid) <<32 ; +} + +static void its_encode_event_id (struct its_cmd_block *cmd,u32 id) +{ + cmd->raw_cmd[1 ] &= ~0xffffffffUL ; + cmd->raw_cmd[1 ] |= id; +} + +static void its_encode_phys_id (struct its_cmd_block *cmd,u32 phys_id) +{ + cmd->raw_cmd[1 ] &=0xffffffffUL ; + cmd->raw_cmd[1 ] |= ((u64 )phys_id) <<32 ; +} + +static void its_encode_size (struct its_cmd_block *cmd,u8 size) +{ + cmd->raw_cmd[1 ] &= ~0x1fUL ; + cmd->raw_cmd[1 ] |= size &0x1f ; +} + +static void its_encode_itt (struct its_cmd_block *cmd,u64 itt_addr) +{ + cmd->raw_cmd[2 ] &= ~0xffffffffffffUL ; + cmd->raw_cmd[2 ] |= itt_addr &0xffffffffff00UL ; +} + +static void its_encode_valid (struct its_cmd_block *cmd,int valid)
lib/arm/gic-v3-its-cmd.c line 134
Quoted 10 lines
lib/arm/gic-v3-its-cmd.c new file +10
-0+{ + cmd->raw_cmd[2 ] &= ~(1UL <<63 ); + cmd->raw_cmd[2 ] |= ((u64 )!!valid) <<63 ; +} + +static void its_encode_target (struct its_cmd_block *cmd,u64 target_addr) +{ + cmd->raw_cmd[2 ] &= ~(0xfffffffffUL <<16 ); + cmd->raw_cmd[2 ] |= (target_addr & (0xffffffffUL <<16 )); +}
Did you trying compiling arm (as opposed to arm64)? I see this file and the other ITS files are added to arm/Makefile.common, but I'd expect this to be a problem here, since it's UL instead of ULL.
Quoted 21 lines
lib/arm/gic-v3-its-cmd.c new file +21
-0+ +static void its_encode_collection (struct its_cmd_block *cmd,u16 col) +{ + cmd->raw_cmd[2 ] &= ~0xffffUL ; + cmd->raw_cmd[2 ] |= col; +} + +static inline void its_fixup_cmd (struct its_cmd_block *cmd) +{ +/* Let's fixup BE commands */ + cmd->raw_cmd[0 ] =cpu_to_le64 (cmd->raw_cmd[0 ]); + cmd->raw_cmd[1 ] =cpu_to_le64 (cmd->raw_cmd[1 ]); + cmd->raw_cmd[2 ] =cpu_to_le64 (cmd->raw_cmd[2 ]); + cmd->raw_cmd[3 ] =cpu_to_le64 (cmd->raw_cmd[3 ]); +} + +static u64 its_cmd_ptr_to_offset (struct its_cmd_block *ptr) +{ +return (ptr - its_data.cmd_base) *sizeof (*ptr); +} +
lib/arm/gic-v3-its-cmd.c line 165
Quoted 10 lines
lib/arm/gic-v3-its-cmd.c new file +10
-0+static struct its_cmd_block *its_post_commands (void ) +{ +u64 wr =its_cmd_ptr_to_offset (its_data.cmd_write); + +writeq (wr, its_data.base +GITS_CWRITER ); +return its_data.cmd_write; +} + + +/* We just assume the queue is large enough */
Assert when the assuming is wrong?
Quoted 18 lines
lib/arm/gic-v3-its-cmd.c new file +18
-0+static struct its_cmd_block *its_allocate_entry (void ) +{ +struct its_cmd_block *cmd; + + cmd = its_data.cmd_write++; +return cmd; +} + +static void its_wait_for_range_completion (struct its_cmd_block *from, +struct its_cmd_block *to) +{ +u64 rd_idx, from_idx, to_idx; +u32 count =1000000 ;/* 1s! */ + + from_idx =its_cmd_ptr_to_offset (from); + to_idx =its_cmd_ptr_to_offset (to); +while (1 ) { + rd_idx =readq (its_data.base +GITS_CREADR );
lib/arm/gic-v3-its-cmd.c line 193
Quoted 10 lines
lib/arm/gic-v3-its-cmd.c new file +10
-0+if (rd_idx >= to_idx || rd_idx < from_idx) +break ; + + count--; +if (!count) { +unsigned int cmd_id = from->raw_cmd[0 ] &0xFF ; + +report (false,"%s timeout!" , + cmd_id <=0xF ? its_cmd_string[cmd_id] : +"Unexpected" );
assert_msg, not report
Quoted 29 lines
lib/arm/gic-v3-its-cmd.c new file +29
-0+return ; + } +cpu_relax (); +udelay (1 ); + } +} + +static void its_send_single_command (its_cmd_builder_t builder, +struct its_cmd_desc *desc) +{ +struct its_cmd_block *cmd, *next_cmd; + + cmd =its_allocate_entry (); +builder (cmd, desc); + next_cmd =its_post_commands (); + +its_wait_for_range_completion (cmd, next_cmd); +} + + +static void its_build_mapd_cmd (struct its_cmd_block *cmd, +struct its_cmd_desc *desc) +{ +unsigned long itt_addr; +u8 size =12 ;//TODO ilog2(desc->its_mapd_cmd.dev->nr_ites); + + itt_addr = (unsigned long )desc->its_mapd_cmd.dev->itt; + itt_addr =ALIGN (itt_addr,ITS_ITT_ALIGN ); +
lib/arm/gic-v3-its-cmd.c line 232
Quoted 10 lines
lib/arm/gic-v3-its-cmd.c new file +10
-0+its_encode_cmd (cmd,GITS_CMD_MAPD ); +its_encode_devid (cmd, desc->its_mapd_cmd.dev->device_id); +its_encode_size (cmd, size -1 ); +its_encode_itt (cmd, itt_addr); +its_encode_valid (cmd, desc->its_mapd_cmd.valid); + +its_fixup_cmd (cmd); +report_info ("MAPD devid=%d size = 0x%x itt=0x%lx valid=%d" , + desc->its_mapd_cmd.dev->device_id, + size, itt_addr, desc->its_mapd_cmd.valid);
printf("ITS: ...\n", ...), not report_info
Quoted 224 lines
lib/arm/gic-v3-its-cmd.c new file +221
-0+ +} + +static void its_build_mapc_cmd (struct its_cmd_block *cmd, +struct its_cmd_desc *desc) +{ +its_encode_cmd (cmd,GITS_CMD_MAPC ); +its_encode_collection (cmd, desc->its_mapc_cmd.col->col_id); +its_encode_target (cmd, desc->its_mapc_cmd.col->target_address); +its_encode_valid (cmd, desc->its_mapc_cmd.valid); + +its_fixup_cmd (cmd); +report_info ("MAPC col_id=%d target_addr = 0x%lx valid=%d" , + desc->its_mapc_cmd.col->col_id, + desc->its_mapc_cmd.col->target_address, + desc->its_mapc_cmd.valid); +} + +static void its_build_mapti_cmd (struct its_cmd_block *cmd, +struct its_cmd_desc *desc) +{ +its_encode_cmd (cmd,GITS_CMD_MAPTI ); +its_encode_devid (cmd, desc->its_mapti_cmd.dev->device_id); +its_encode_event_id (cmd, desc->its_mapti_cmd.event_id); +its_encode_phys_id (cmd, desc->its_mapti_cmd.phys_id); +its_encode_collection (cmd, desc->its_mapti_cmd.col_id); + +its_fixup_cmd (cmd); +report_info ("MAPTI dev_id=%d event_id=%d -> phys_id=%d, col_id=%d" , + desc->its_mapti_cmd.dev->device_id, + desc->its_mapti_cmd.event_id, + desc->its_mapti_cmd.phys_id, + desc->its_mapti_cmd.col_id); +} + +static void its_build_invall_cmd (struct its_cmd_block *cmd, +struct its_cmd_desc *desc) +{ +its_encode_cmd (cmd,GITS_CMD_INVALL ); +its_encode_collection (cmd, desc->its_invall_cmd.col->col_id); + +its_fixup_cmd (cmd); +report_info ("INVALL col_id=%d" , desc->its_invall_cmd.col->col_id); +} + +static void its_build_clear_cmd (struct its_cmd_block *cmd, +struct its_cmd_desc *desc) +{ +its_encode_cmd (cmd,GITS_CMD_CLEAR ); +its_encode_devid (cmd, desc->its_clear_cmd.dev->device_id); +its_encode_event_id (cmd, desc->its_clear_cmd.event_id); + +its_fixup_cmd (cmd); +report_info ("CLEAR col_id=%d" , desc->its_invall_cmd.col->col_id); +} + +static void its_build_discard_cmd (struct its_cmd_block *cmd, +struct its_cmd_desc *desc) +{ +its_encode_cmd (cmd,GITS_CMD_DISCARD ); +its_encode_devid (cmd, desc->its_discard_cmd.dev->device_id); +its_encode_event_id (cmd, desc->its_discard_cmd.event_id); + +its_fixup_cmd (cmd); +report_info ("DISCARD col_id=%d" , desc->its_invall_cmd.col->col_id); +} + +static void its_build_inv_cmd (struct its_cmd_block *cmd, +struct its_cmd_desc *desc) +{ +its_encode_cmd (cmd,GITS_CMD_INV ); +its_encode_devid (cmd, desc->its_inv_cmd.dev->device_id); +its_encode_event_id (cmd, desc->its_inv_cmd.event_id); + +its_fixup_cmd (cmd); +report_info ("INV dev_id=%d event_id=%d" , + desc->its_inv_cmd.dev->device_id, + desc->its_inv_cmd.event_id); +} + +static void its_build_int_cmd (struct its_cmd_block *cmd, +struct its_cmd_desc *desc) +{ +its_encode_cmd (cmd,GITS_CMD_INT ); +its_encode_devid (cmd, desc->its_int_cmd.dev->device_id); +its_encode_event_id (cmd, desc->its_int_cmd.event_id); + +its_fixup_cmd (cmd); +report_info ("INT dev_id=%d event_id=%d" , + desc->its_int_cmd.dev->device_id, + desc->its_int_cmd.event_id); +} + +static void its_build_sync_cmd (struct its_cmd_block *cmd, +struct its_cmd_desc *desc) +{ +its_encode_cmd (cmd,GITS_CMD_SYNC ); +its_encode_target (cmd, desc->its_sync_cmd.col->target_address); +its_fixup_cmd (cmd); +report_info ("SYNC target_addr = 0x%lx" , + desc->its_sync_cmd.col->target_address); +} + +static void its_build_movi_cmd (struct its_cmd_block *cmd, +struct its_cmd_desc *desc) +{ +its_encode_cmd (cmd,GITS_CMD_MOVI ); +its_encode_devid (cmd, desc->its_movi_cmd.dev->device_id); +its_encode_event_id (cmd, desc->its_movi_cmd.event_id); +its_encode_collection (cmd, desc->its_movi_cmd.col->col_id); + +its_fixup_cmd (cmd); +report_info ("MOVI dev_id=%d event_id = %d col_id=%d" , + desc->its_movi_cmd.dev->device_id, + desc->its_movi_cmd.event_id, + desc->its_movi_cmd.col->col_id); +} + +void its_send_mapd (struct its_device *dev,int valid) +{ +struct its_cmd_desc desc; + + desc.its_mapd_cmd.dev = dev; + desc.its_mapd_cmd.valid = !!valid; + +its_send_single_command (its_build_mapd_cmd, &desc); +} + +void its_send_mapc (struct its_collection *col,int valid) +{ +struct its_cmd_desc desc; + + desc.its_mapc_cmd.col = col; + desc.its_mapc_cmd.valid = !!valid; + +its_send_single_command (its_build_mapc_cmd, &desc); +} + +void its_send_mapti (struct its_device *dev,u32 irq_id, +u32 event_id,struct its_collection *col) +{ +struct its_cmd_desc desc; + + desc.its_mapti_cmd.dev = dev; + desc.its_mapti_cmd.phys_id = irq_id; + desc.its_mapti_cmd.event_id = event_id; + desc.its_mapti_cmd.col_id = col->col_id; + +its_send_single_command (its_build_mapti_cmd, &desc); +} + +void its_send_int (struct its_device *dev,u32 event_id) +{ +struct its_cmd_desc desc; + + desc.its_int_cmd.dev = dev; + desc.its_int_cmd.event_id = event_id; + +its_send_single_command (its_build_int_cmd, &desc); +} + +void its_send_movi (struct its_device *dev, +struct its_collection *col,u32 id) +{ +struct its_cmd_desc desc; + + desc.its_movi_cmd.dev = dev; + desc.its_movi_cmd.col = col; + desc.its_movi_cmd.event_id = id; + +its_send_single_command (its_build_movi_cmd, &desc); +} + +void its_send_invall (struct its_collection *col) +{ +struct its_cmd_desc desc; + + desc.its_invall_cmd.col = col; + +its_send_single_command (its_build_invall_cmd, &desc); +} + +void its_send_inv (struct its_device *dev,u32 event_id) +{ +struct its_cmd_desc desc; + + desc.its_inv_cmd.dev = dev; + desc.its_inv_cmd.event_id = event_id; + +its_send_single_command (its_build_inv_cmd, &desc); +} + +void its_send_discard (struct its_device *dev,u32 event_id) +{ +struct its_cmd_desc desc; + + desc.its_discard_cmd.dev = dev; + desc.its_discard_cmd.event_id = event_id; + +its_send_single_command (its_build_discard_cmd, &desc); +} + +void its_send_clear (struct its_device *dev,u32 event_id) +{ +struct its_cmd_desc desc; + + desc.its_clear_cmd.dev = dev; + desc.its_clear_cmd.event_id = event_id; + +its_send_single_command (its_build_clear_cmd, &desc); +} + +void its_send_sync (struct its_collection *col) +{ +struct its_cmd_desc desc; + + desc.its_sync_cmd.col = col; + +its_send_single_command (its_build_sync_cmd, &desc); +} +Signature · 1 line
2.20.1
Thanks,
drew
Re: [kvm-unit-tests PATCH v2 12/16] arm/arm64: ITS: commands
Hi Drew,
Quoted 221 lines · Andrew Jones
Quoted 87 lines · Eric Auger
Implement main ITS commands. The code is largely inherited from the ITS driver.
Signed-off-by Eric Auger <[email protected]>---
v1 -> v2:
- removedits_print_cmd_state--- arm/Makefile.common | 2 +- lib/arm/asm/gic-v3-its.h | 35 +++ lib/arm/gic-v3-its-cmd.c | 453 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 489 insertions(+), 1 deletion(-) create mode 100644 lib/arm/gic-v3-its-cmd.carm/Makefile.common +1
-1@@ -52,7 +52,7 @@ cflatobjs += lib/arm/psci.o cflatobjs += lib/arm/smp.o cflatobjs += lib/arm/delay.o cflatobjs += lib/arm/gic.o lib/arm/gic-v2.o lib/arm/gic-v3.o -cflatobjs += lib/arm/gic-v3-its.o +cflatobjs += lib/arm/gic-v3-its.o lib/arm/gic-v3-its-cmd.o OBJDIRS += lib/armlib/arm/asm/gic-v3-its.h +35
-0@@ -58,6 +58,24 @@#define GITS_MAX_DEVICES 8#define GITS_MAX_COLLECTIONS 8 +/* +* ITS commands +*/ +#define GITS_CMD_MAPD 0x08 +#define GITS_CMD_MAPC 0x09 +#define GITS_CMD_MAPTI 0x0a +/* older GIC documentation used MAPVI for this command */ +#define GITS_CMD_MAPVI GITS_CMD_MAPTI +#define GITS_CMD_MAPI 0x0b +#define GITS_CMD_MOVI 0x01 +#define GITS_CMD_DISCARD 0x0f +#define GITS_CMD_INV 0x0c +#define GITS_CMD_MOVALL 0x0e +#define GITS_CMD_INVALL 0x0d +#define GITS_CMD_INT 0x03 +#define GITS_CMD_CLEAR 0x04 +#define GITS_CMD_SYNC 0x05 +struct its_typer {unsigned int ite_size;unsigned int eventid_bits;@@ -122,5 +140,22 @@ 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); +extern void its_send_mapd (struct its_device *dev,int valid); +extern void its_send_mapc (struct its_collection *col,int valid); +extern void its_send_mapti (struct its_device *dev,u32 irq_id, +u32 event_id,struct its_collection *col); +extern void its_send_int (struct its_device *dev,u32 event_id); +extern void its_send_inv (struct its_device *dev,u32 event_id); +extern void its_send_discard (struct its_device *dev,u32 event_id); +extern void its_send_clear (struct its_device *dev,u32 event_id); +extern void its_send_invall (struct its_collection *col); +extern void its_send_movi (struct its_device *dev, +struct its_collection *col,u32 id); +extern void its_send_sync (struct its_collection *col); + +#define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1ULL << 0) +#define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1) +#define ITS_FLAGS_WORKAROUND_CAVIUM_23144 (1ULL << 2) +#endif /* !__ASSEMBLY__ */ #endif /* _ASMARM_GIC_V3_ITS_H_ */ lib/arm/gic-v3-its-cmd.c new file +0
-0lib/arm/gic-v3-its-cmd.c line 2
Quoted 2 lines
lib/arm/gic-v3-its-cmd.c new file +2
-0@@ -0,0 +1,453 @@ +/* +* Copyright (C) 2016, Red Hat Inc, Eric Auger <[email protected]> 2016?
Quoted 128 lines
lib/arm/gic-v3-its-cmd.c new file +128
-0+* +* Most of the code is copy-pasted from: +* drivers/irqchip/irq-gic-v3-its.c +* This work is licensed under the terms of the GNU LGPL, version 2. +*/ +#include <asm/io.h> +#include <asm/gic.h> + +#define ITS_ITT_ALIGN SZ_256 + +static const char *const its_cmd_string[] = { + [GITS_CMD_MAPD ] ="MAPD" , + [GITS_CMD_MAPC ] ="MAPC" , + [GITS_CMD_MAPTI ] ="MAPTI" , + [GITS_CMD_MAPI ] ="MAPI" , + [GITS_CMD_MOVI ] ="MOVI" , + [GITS_CMD_DISCARD ] ="DISCARD" , + [GITS_CMD_INV ] ="INV" , + [GITS_CMD_MOVALL ] ="MOVALL" , + [GITS_CMD_INVALL ] ="INVALL" , + [GITS_CMD_INT ] ="INT" , + [GITS_CMD_CLEAR ] ="CLEAR" , + [GITS_CMD_SYNC ] ="SYNC" , +}; + +struct its_cmd_desc { +union { +struct { +struct its_device *dev; +u32 event_id; + } its_inv_cmd; + +struct { +struct its_device *dev; +u32 event_id; + } its_int_cmd; + +struct { +struct its_device *dev; +bool valid; + } its_mapd_cmd; + +struct { +struct its_collection *col; +bool valid; + } its_mapc_cmd; + +struct { +struct its_device *dev; +u32 phys_id; +u32 event_id; +u32 col_id; + } its_mapti_cmd; + +struct { +struct its_device *dev; +struct its_collection *col; +u32 event_id; + } its_movi_cmd; + +struct { +struct its_device *dev; +u32 event_id; + } its_discard_cmd; + +struct { +struct its_device *dev; +u32 event_id; + } its_clear_cmd; + +struct { +struct its_collection *col; + } its_invall_cmd; + +struct { +struct its_collection *col; + } its_sync_cmd; + }; +}; + +typedef void (*its_cmd_builder_t )(struct its_cmd_block *, +struct its_cmd_desc *); + +/* ITS COMMANDS */ + +static void its_encode_cmd (struct its_cmd_block *cmd,u8 cmd_nr) +{ + cmd->raw_cmd[0 ] &= ~0xffUL ; + cmd->raw_cmd[0 ] |= cmd_nr; +} + +static void its_encode_devid (struct its_cmd_block *cmd,u32 devid) +{ + cmd->raw_cmd[0 ] &=BIT_ULL (32 ) -1 ; + cmd->raw_cmd[0 ] |= ((u64 )devid) <<32 ; +} + +static void its_encode_event_id (struct its_cmd_block *cmd,u32 id) +{ + cmd->raw_cmd[1 ] &= ~0xffffffffUL ; + cmd->raw_cmd[1 ] |= id; +} + +static void its_encode_phys_id (struct its_cmd_block *cmd,u32 phys_id) +{ + cmd->raw_cmd[1 ] &=0xffffffffUL ; + cmd->raw_cmd[1 ] |= ((u64 )phys_id) <<32 ; +} + +static void its_encode_size (struct its_cmd_block *cmd,u8 size) +{ + cmd->raw_cmd[1 ] &= ~0x1fUL ; + cmd->raw_cmd[1 ] |= size &0x1f ; +} + +static void its_encode_itt (struct its_cmd_block *cmd,u64 itt_addr) +{ + cmd->raw_cmd[2 ] &= ~0xffffffffffffUL ; + cmd->raw_cmd[2 ] |= itt_addr &0xffffffffff00UL ; +} + +static void its_encode_valid (struct its_cmd_block *cmd,int valid) +{ + cmd->raw_cmd[2 ] &= ~(1UL <<63 ); + cmd->raw_cmd[2 ] |= ((u64 )!!valid) <<63 ; +} + +static void its_encode_target (struct its_cmd_block *cmd,u64 target_addr)
Quoted 8 lines
lib/arm/gic-v3-its-cmd.c line 134
Quoted 4 lines
lib/arm/gic-v3-its-cmd.c new file +4
-0+{ + cmd->raw_cmd[2 ] &= ~(0xfffffffffUL <<16 ); + cmd->raw_cmd[2 ] |= (target_addr & (0xffffffffUL <<16 )); +}Did you trying compiling arm (as opposed to arm64)? I see this file and the other ITS files are added to arm/Makefile.common, but I'd expect this to be a problem here, since it's UL instead of ULL.
No I didn't. I will check this.
Quoted 26 lines
Quoted 26 lines
lib/arm/gic-v3-its-cmd.c new file +25
-0+ +static void its_encode_collection (struct its_cmd_block *cmd,u16 col) +{ + cmd->raw_cmd[2 ] &= ~0xffffUL ; + cmd->raw_cmd[2 ] |= col; +} + +static inline void its_fixup_cmd (struct its_cmd_block *cmd) +{ +/* Let's fixup BE commands */ + cmd->raw_cmd[0 ] =cpu_to_le64 (cmd->raw_cmd[0 ]); + cmd->raw_cmd[1 ] =cpu_to_le64 (cmd->raw_cmd[1 ]); + cmd->raw_cmd[2 ] =cpu_to_le64 (cmd->raw_cmd[2 ]); + cmd->raw_cmd[3 ] =cpu_to_le64 (cmd->raw_cmd[3 ]); +} + +static u64 its_cmd_ptr_to_offset (struct its_cmd_block *ptr) +{ +return (ptr - its_data.cmd_base) *sizeof (*ptr); +} + +static struct its_cmd_block *its_post_commands (void ) +{ +u64 wr =its_cmd_ptr_to_offset (its_data.cmd_write); +
Quoted 8 lines
lib/arm/gic-v3-its-cmd.c line 165
Quoted 6 lines
lib/arm/gic-v3-its-cmd.c new file +6
-0+writeq (wr, its_data.base +GITS_CWRITER ); +return its_data.cmd_write; +} + + +/* We just assume the queue is large enough */ Assert when the assuming is wrong?
OK
Quoted 23 lines
Quoted 23 lines
lib/arm/gic-v3-its-cmd.c new file +22
-0+static struct its_cmd_block *its_allocate_entry (void ) +{ +struct its_cmd_block *cmd; + + cmd = its_data.cmd_write++; +return cmd; +} + +static void its_wait_for_range_completion (struct its_cmd_block *from, +struct its_cmd_block *to) +{ +u64 rd_idx, from_idx, to_idx; +u32 count =1000000 ;/* 1s! */ + + from_idx =its_cmd_ptr_to_offset (from); + to_idx =its_cmd_ptr_to_offset (to); +while (1 ) { + rd_idx =readq (its_data.base +GITS_CREADR ); +if (rd_idx >= to_idx || rd_idx < from_idx) +break ; + + count--;
Quoted 8 lines
lib/arm/gic-v3-its-cmd.c line 193
Quoted 6 lines
lib/arm/gic-v3-its-cmd.c new file +6
-0+if (!count) { +unsigned int cmd_id = from->raw_cmd[0 ] &0xFF ; + +report (false,"%s timeout!" , + cmd_id <=0xF ? its_cmd_string[cmd_id] : +"Unexpected" );
assert_msg, not report
OK
Quoted 34 lines
Quoted 34 lines
lib/arm/gic-v3-its-cmd.c new file +33
-0+return ; + } +cpu_relax (); +udelay (1 ); + } +} + +static void its_send_single_command (its_cmd_builder_t builder, +struct its_cmd_desc *desc) +{ +struct its_cmd_block *cmd, *next_cmd; + + cmd =its_allocate_entry (); +builder (cmd, desc); + next_cmd =its_post_commands (); + +its_wait_for_range_completion (cmd, next_cmd); +} + + +static void its_build_mapd_cmd (struct its_cmd_block *cmd, +struct its_cmd_desc *desc) +{ +unsigned long itt_addr; +u8 size =12 ;//TODO ilog2(desc->its_mapd_cmd.dev->nr_ites); + + itt_addr = (unsigned long )desc->its_mapd_cmd.dev->itt; + itt_addr =ALIGN (itt_addr,ITS_ITT_ALIGN ); + +its_encode_cmd (cmd,GITS_CMD_MAPD ); +its_encode_devid (cmd, desc->its_mapd_cmd.dev->device_id); +its_encode_size (cmd, size -1 ); +its_encode_itt (cmd, itt_addr);
Quoted 8 lines
lib/arm/gic-v3-its-cmd.c line 232
Quoted 6 lines
lib/arm/gic-v3-its-cmd.c new file +6
-0+its_encode_valid (cmd, desc->its_mapd_cmd.valid); + +its_fixup_cmd (cmd); +report_info ("MAPD devid=%d size = 0x%x itt=0x%lx valid=%d" , + desc->its_mapd_cmd.dev->device_id, + size, itt_addr, desc->its_mapd_cmd.valid);
printf("ITS: ...\n", ...), notreport_info
OK
Thanks
Eric
Quoted 229 lines
Quoted 225 lines
lib/arm/gic-v3-its-cmd.c new file +221
-0+ +} + +static void its_build_mapc_cmd (struct its_cmd_block *cmd, +struct its_cmd_desc *desc) +{ +its_encode_cmd (cmd,GITS_CMD_MAPC ); +its_encode_collection (cmd, desc->its_mapc_cmd.col->col_id); +its_encode_target (cmd, desc->its_mapc_cmd.col->target_address); +its_encode_valid (cmd, desc->its_mapc_cmd.valid); + +its_fixup_cmd (cmd); +report_info ("MAPC col_id=%d target_addr = 0x%lx valid=%d" , + desc->its_mapc_cmd.col->col_id, + desc->its_mapc_cmd.col->target_address, + desc->its_mapc_cmd.valid); +} + +static void its_build_mapti_cmd (struct its_cmd_block *cmd, +struct its_cmd_desc *desc) +{ +its_encode_cmd (cmd,GITS_CMD_MAPTI ); +its_encode_devid (cmd, desc->its_mapti_cmd.dev->device_id); +its_encode_event_id (cmd, desc->its_mapti_cmd.event_id); +its_encode_phys_id (cmd, desc->its_mapti_cmd.phys_id); +its_encode_collection (cmd, desc->its_mapti_cmd.col_id); + +its_fixup_cmd (cmd); +report_info ("MAPTI dev_id=%d event_id=%d -> phys_id=%d, col_id=%d" , + desc->its_mapti_cmd.dev->device_id, + desc->its_mapti_cmd.event_id, + desc->its_mapti_cmd.phys_id, + desc->its_mapti_cmd.col_id); +} + +static void its_build_invall_cmd (struct its_cmd_block *cmd, +struct its_cmd_desc *desc) +{ +its_encode_cmd (cmd,GITS_CMD_INVALL ); +its_encode_collection (cmd, desc->its_invall_cmd.col->col_id); + +its_fixup_cmd (cmd); +report_info ("INVALL col_id=%d" , desc->its_invall_cmd.col->col_id); +} + +static void its_build_clear_cmd (struct its_cmd_block *cmd, +struct its_cmd_desc *desc) +{ +its_encode_cmd (cmd,GITS_CMD_CLEAR ); +its_encode_devid (cmd, desc->its_clear_cmd.dev->device_id); +its_encode_event_id (cmd, desc->its_clear_cmd.event_id); + +its_fixup_cmd (cmd); +report_info ("CLEAR col_id=%d" , desc->its_invall_cmd.col->col_id); +} + +static void its_build_discard_cmd (struct its_cmd_block *cmd, +struct its_cmd_desc *desc) +{ +its_encode_cmd (cmd,GITS_CMD_DISCARD ); +its_encode_devid (cmd, desc->its_discard_cmd.dev->device_id); +its_encode_event_id (cmd, desc->its_discard_cmd.event_id); + +its_fixup_cmd (cmd); +report_info ("DISCARD col_id=%d" , desc->its_invall_cmd.col->col_id); +} + +static void its_build_inv_cmd (struct its_cmd_block *cmd, +struct its_cmd_desc *desc) +{ +its_encode_cmd (cmd,GITS_CMD_INV ); +its_encode_devid (cmd, desc->its_inv_cmd.dev->device_id); +its_encode_event_id (cmd, desc->its_inv_cmd.event_id); + +its_fixup_cmd (cmd); +report_info ("INV dev_id=%d event_id=%d" , + desc->its_inv_cmd.dev->device_id, + desc->its_inv_cmd.event_id); +} + +static void its_build_int_cmd (struct its_cmd_block *cmd, +struct its_cmd_desc *desc) +{ +its_encode_cmd (cmd,GITS_CMD_INT ); +its_encode_devid (cmd, desc->its_int_cmd.dev->device_id); +its_encode_event_id (cmd, desc->its_int_cmd.event_id); + +its_fixup_cmd (cmd); +report_info ("INT dev_id=%d event_id=%d" , + desc->its_int_cmd.dev->device_id, + desc->its_int_cmd.event_id); +} + +static void its_build_sync_cmd (struct its_cmd_block *cmd, +struct its_cmd_desc *desc) +{ +its_encode_cmd (cmd,GITS_CMD_SYNC ); +its_encode_target (cmd, desc->its_sync_cmd.col->target_address); +its_fixup_cmd (cmd); +report_info ("SYNC target_addr = 0x%lx" , + desc->its_sync_cmd.col->target_address); +} + +static void its_build_movi_cmd (struct its_cmd_block *cmd, +struct its_cmd_desc *desc) +{ +its_encode_cmd (cmd,GITS_CMD_MOVI ); +its_encode_devid (cmd, desc->its_movi_cmd.dev->device_id); +its_encode_event_id (cmd, desc->its_movi_cmd.event_id); +its_encode_collection (cmd, desc->its_movi_cmd.col->col_id); + +its_fixup_cmd (cmd); +report_info ("MOVI dev_id=%d event_id = %d col_id=%d" , + desc->its_movi_cmd.dev->device_id, + desc->its_movi_cmd.event_id, + desc->its_movi_cmd.col->col_id); +} + +void its_send_mapd (struct its_device *dev,int valid) +{ +struct its_cmd_desc desc; + + desc.its_mapd_cmd.dev = dev; + desc.its_mapd_cmd.valid = !!valid; + +its_send_single_command (its_build_mapd_cmd, &desc); +} + +void its_send_mapc (struct its_collection *col,int valid) +{ +struct its_cmd_desc desc; + + desc.its_mapc_cmd.col = col; + desc.its_mapc_cmd.valid = !!valid; + +its_send_single_command (its_build_mapc_cmd, &desc); +} + +void its_send_mapti (struct its_device *dev,u32 irq_id, +u32 event_id,struct its_collection *col) +{ +struct its_cmd_desc desc; + + desc.its_mapti_cmd.dev = dev; + desc.its_mapti_cmd.phys_id = irq_id; + desc.its_mapti_cmd.event_id = event_id; + desc.its_mapti_cmd.col_id = col->col_id; + +its_send_single_command (its_build_mapti_cmd, &desc); +} + +void its_send_int (struct its_device *dev,u32 event_id) +{ +struct its_cmd_desc desc; + + desc.its_int_cmd.dev = dev; + desc.its_int_cmd.event_id = event_id; + +its_send_single_command (its_build_int_cmd, &desc); +} + +void its_send_movi (struct its_device *dev, +struct its_collection *col,u32 id) +{ +struct its_cmd_desc desc; + + desc.its_movi_cmd.dev = dev; + desc.its_movi_cmd.col = col; + desc.its_movi_cmd.event_id = id; + +its_send_single_command (its_build_movi_cmd, &desc); +} + +void its_send_invall (struct its_collection *col) +{ +struct its_cmd_desc desc; + + desc.its_invall_cmd.col = col; + +its_send_single_command (its_build_invall_cmd, &desc); +} + +void its_send_inv (struct its_device *dev,u32 event_id) +{ +struct its_cmd_desc desc; + + desc.its_inv_cmd.dev = dev; + desc.its_inv_cmd.event_id = event_id; + +its_send_single_command (its_build_inv_cmd, &desc); +} + +void its_send_discard (struct its_device *dev,u32 event_id) +{ +struct its_cmd_desc desc; + + desc.its_discard_cmd.dev = dev; + desc.its_discard_cmd.event_id = event_id; + +its_send_single_command (its_build_discard_cmd, &desc); +} + +void its_send_clear (struct its_device *dev,u32 event_id) +{ +struct its_cmd_desc desc; + + desc.its_clear_cmd.dev = dev; + desc.its_clear_cmd.event_id = event_id; + +its_send_single_command (its_build_clear_cmd, &desc); +} + +void its_send_sync (struct its_collection *col) +{ +struct its_cmd_desc desc; + + desc.its_sync_cmd.col = col; + +its_send_single_command (its_build_sync_cmd, &desc); +} +Signature · 1 line
2.20.1Thanks,
drew
PATCH v2 13/16 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.
--- arm/gic.c | 174 +++++++++++++++++++++++++++++++++++++++ arm/unittests.cfg | 6 ++ lib/arm/asm/gic-v3-its.h | 14 ++++ 3 files changed, 194 insertions(+)
arm/gic.c +174 -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; +static struct its_stats lpi_stats;static void nr_cpu_check (int nr) {
@@ -158,6 +159,54 @@ static void ipi_handler(struct pt_regs *regs __unused) } } +static void lpi_handler(struct pt_regs *regs __unused) +{ +u32 irqstat =gic_read_iar (); +int irqnr =gic_iar_irqnr (irqstat); + +gic_write_eoir (irqstat); +if (irqnr <8192 ) +report (false,"Unexpected non LPI interrupt received" ); +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 (void ) +{ +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 (false, +"No LPI received whereas (cpuid=%d, intid=%d) " +"was expected" , lpi_stats.expected.cpu_id, + lpi_stats.expected.lpi_id); + }else { +report (false,"Unexpected LPI (cpuid=%d, intid=%d)" , + lpi_stats.observed.cpu_id, + lpi_stats.observed.lpi_id); + } + }else if (lpi_stats.expected.lpi_id !=-1 ) { +report (true,"LPI %d on CPU %d" , lpi_stats.observed.lpi_id, + lpi_stats.observed.cpu_id); + }else { +report (true,"no LPI received, as expected" ); + } +} +static void gicv2_ipi_send_self (void ) {writel (2 <<24 |IPI_IRQ ,gicv2_dist_base () +GICD_SGIR );
@@ -241,6 +290,14 @@ static void ipi_test(void *data __unused)ipi_recv (); } +static void secondary_lpi_test (void ) +{ +setup_irq (lpi_handler); +cpumask_set_cpu (smp_processor_id (), &ready); +while (1 ) +wfi (); +} +static struct gic gicv2 = { .ipi = { .send_self = gicv2_ipi_send_self,
@@ -551,6 +608,120 @@ static void test_its_baser(void)report_info ("collection baser 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 <4 ) { +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 (); + +lpi_stats_expect (-1 ,-1 ); +check_lpi_stats (); + +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 */ ); + +set_lpi_config (8195 ,LPI_PROP_DEFAULT ); +set_lpi_config (8196 ,LPI_PROP_DEFAULT ); + +its_send_invall (col2); +its_send_invall (col3); + +report_prefix_push ("int" ); + +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 (); + +lpi_stats_expect (2 ,8196 ); +its_send_int (dev7,255 ); +check_lpi_stats (); + +report_prefix_pop (); + +report_prefix_push ("inv/invall" ); + +/* disable 8195 */ +set_lpi_config (8195 ,LPI_PROP_DEFAULT & ~0x1 ); +its_send_inv (dev2,20 ); + +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev2,20 ); +check_lpi_stats (); + +set_lpi_config (8195 ,LPI_PROP_DEFAULT ); +/* willingly forget the INVALL*/ +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev2,20 ); +check_lpi_stats (); + +its_send_invall (col3); +lpi_stats_expect (3 ,8195 ); +its_send_int (dev2,20 ); +check_lpi_stats (); + +report_prefix_pop (); + +report_prefix_push ("mapd valid=false" ); +its_send_mapd (dev2, false); +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev2,20 ); +check_lpi_stats (); +report_prefix_pop (); + +report_prefix_push ("mapc valid=false" ); +its_send_mapc (col2, false); +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev7,255 ); +check_lpi_stats (); +} + +int main (int argc,char **argv) {if (!gic_init ()) {
@@ -581,6 +752,9 @@ int main(int argc, char **argv) }else if (strcmp (argv[1 ],"mmio" ) ==0 ) {report_prefix_push (argv[1 ]);gic_test_mmio (); + }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 ]);
arm/unittests.cfg +6 -0
@@ -134,6 +134,12 @@ smp = $MAX_SMP extra_params = -machine gic-version=3 -append 'its-baser' groups = its +[its-trigger] +file = gic.flat +smp = $MAX_SMP +extra_params = -machine gic-version=3 -append 'its-trigger' +groups = its + # Test PSCI emulation [psci] file = psci.flat
lib/arm/asm/gic-v3-its.h +14 -0
@@ -123,6 +123,16 @@ struct its_data {u32 nr_collections;/* Allocated Collections */ }; +struct its_event { +int cpu_id; +int lpi_id; +}; + +struct its_stats { +struct its_event expected; +struct its_event observed; +}; +extern struct its_data its_data;#define gicv3_its_base () (its_data.base)
@@ -139,6 +149,10 @@ extern void gicv3_rdist_ctrl_lpi(u32 redist, bool set);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); +extern struct its_collection *its_create_collection (u32 col_id,u32 target); + +extern void set_lpi_config (int n,u8 val); +extern u8 get_lpi_config (int n);extern void its_send_mapd (struct its_device *dev,int valid);extern void its_send_mapc (struct its_collection *col,int valid);
Signature · 1 line
2.20.1
Re: [kvm-unit-tests PATCH v2 13/16] arm/arm64: ITS: INT functional tests
Quoted 103 lines · Eric Auger
Triggers 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.
Signed-off-by Eric Auger <[email protected]>--- arm/gic.c | 174 +++++++++++++++++++++++++++++++++++++++ arm/unittests.cfg | 6 ++ lib/arm/asm/gic-v3-its.h | 14 ++++ 3 files changed, 194 insertions(+)arm/gic.c +59
-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; +static struct its_stats lpi_stats;static void nr_cpu_check (int nr) {@@ -158,6 +159,54 @@ static void ipi_handler(struct pt_regs *regs __unused) } } +static void lpi_handler(struct pt_regs *regs __unused) +{ +u32 irqstat =gic_read_iar (); +int irqnr =gic_iar_irqnr (irqstat); + +gic_write_eoir (irqstat); +if (irqnr <8192 ) +report (false,"Unexpected non LPI interrupt received" ); +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 (void ) +{ +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 (false, +"No LPI received whereas (cpuid=%d, intid=%d) " +"was expected" , lpi_stats.expected.cpu_id, + lpi_stats.expected.lpi_id); + }else { +report (false,"Unexpected LPI (cpuid=%d, intid=%d)" , + lpi_stats.observed.cpu_id, + lpi_stats.observed.lpi_id); + } + }else if (lpi_stats.expected.lpi_id !=-1 ) { +report (true,"LPI %d on CPU %d" , lpi_stats.observed.lpi_id, + lpi_stats.observed.cpu_id); + }else { +report (true,"no LPI received, as expected" ); + } +} +static void gicv2_ipi_send_self (void ) {writel (2 <<24 |IPI_IRQ ,gicv2_dist_base () +GICD_SGIR );@@ -241,6 +290,14 @@ static void ipi_test(void *data __unused)ipi_recv (); } +static void secondary_lpi_test (void ) +{ +setup_irq (lpi_handler); +cpumask_set_cpu (smp_processor_id (), &ready); +while (1 ) +wfi (); +} +static struct gic gicv2 = { .ipi = { .send_self = gicv2_ipi_send_self,@@ -551,6 +608,120 @@ static void test_its_baser(void)report_info ("collection baser entry_size = 0x%x" , coll_baser->esz); } +static int its_prerequisites (int nb_cpus) +{
arm/gic.c static void test_its_baser(void) · line 622
Quoted 10 lines
arm/gic.c +10
-0+int cpu; + +if (!gicv3_its_base ()) { +report_skip ("No ITS, skip ..." ); +return -1 ; + } + +if (nr_cpus <4 ) { +report_skip ("Test requires at least %d vcpus" , nb_cpus); +return -1 ;
We have nr_cpu_check() in arm/gic.c that does a report_abort for this case. Is there a reason to do report_skip instead of report_abort?
Also do you plan to return more than 0 - success, -1 - failure? If not, then this could be a bool function.
Quoted 89 lines
arm/gic.c +89
-0+ } + +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 (); + +lpi_stats_expect (-1 ,-1 ); +check_lpi_stats (); + +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 */ ); + +set_lpi_config (8195 ,LPI_PROP_DEFAULT ); +set_lpi_config (8196 ,LPI_PROP_DEFAULT ); + +its_send_invall (col2); +its_send_invall (col3); + +report_prefix_push ("int" ); + +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 (); + +lpi_stats_expect (2 ,8196 ); +its_send_int (dev7,255 ); +check_lpi_stats (); + +report_prefix_pop (); + +report_prefix_push ("inv/invall" ); + +/* disable 8195 */ +set_lpi_config (8195 ,LPI_PROP_DEFAULT & ~0x1 ); +its_send_inv (dev2,20 ); + +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev2,20 ); +check_lpi_stats (); + +set_lpi_config (8195 ,LPI_PROP_DEFAULT ); +/* willingly forget the INVALL*/ +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev2,20 ); +check_lpi_stats (); + +its_send_invall (col3); +lpi_stats_expect (3 ,8195 ); +its_send_int (dev2,20 ); +check_lpi_stats (); + +report_prefix_pop (); + +report_prefix_push ("mapd valid=false" ); +its_send_mapd (dev2, false);
arm/gic.c static void test_its_baser(void) · line 721
Quoted 10 lines
arm/gic.c +10
-0+lpi_stats_expect (-1 ,-1 ); +its_send_int (dev2,20 ); +check_lpi_stats (); +report_prefix_pop (); + +report_prefix_push ("mapc valid=false" ); +its_send_mapc (col2, false); +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev7,255 ); +check_lpi_stats ();
Missing prefix pop here
arm/gic.c static void ipi_handler(struct pt_regs *regs __unused) · line 184
Quoted 3 lines
arm/gic.c +3
-0+} + +
Extra blank line
arm/gic.c int main(int argc, char **argv) · line 758
Quoted 11 lines
arm/gic.c +3
-0int main (int argc,char **argv) {if (!gic_init ()) {@@ -581,6 +752,9 @@ int main(int argc, char **argv) }else if (strcmp (argv[1 ],"mmio" ) ==0 ) {report_prefix_push (argv[1 ]);gic_test_mmio (); + }else if (!strcmp (argv[1 ],"its-trigger" )) { +report_prefix_push (argv[1 ]); +test_its_trigger ();report_prefix_pop ();
You stole the report_prefix_pop from the mmio tests above.
Quoted 26 lines
arm/gic.c +0
-0}else if (strcmp (argv[1 ],"its-introspection" ) ==0 ) {report_prefix_push (argv[1 ]);arm/unittests.cfg +6
-0@@ -134,6 +134,12 @@ smp = $MAX_SMP extra_params = -machine gic-version=3 -append 'its-baser' groups = its +[its-trigger] +file = gic.flat +smp = $MAX_SMP +extra_params = -machine gic-version=3 -append 'its-trigger' +groups = its + # Test PSCI emulation [psci] file = psci.flatlib/arm/asm/gic-v3-its.h +0
-0@@ -123,6 +123,16 @@ struct its_data {u32 nr_collections;/* Allocated Collections */ };
lib/arm/asm/gic-v3-its.h struct its_data { · line 134
Quoted 10 lines
lib/arm/asm/gic-v3-its.h +9
-0+struct its_event { +int cpu_id; +int lpi_id; +}; + +struct its_stats { +struct its_event expected; +struct its_event observed; +};
These structures belong in arm/gic.c as they are unit test structions and driver structures.
lib/arm/asm/gic-v3-its.h extern void gicv3_rdist_ctrl_lpi(u32 redist, bool set); · line 152
Quoted 9 lines
lib/arm/asm/gic-v3-its.h +2
-0+extern struct its_data its_data;#define gicv3_its_base () (its_data.base)@@ -139,6 +149,10 @@ extern void gicv3_rdist_ctrl_lpi(u32 redist, bool set);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); +extern struct its_collection *its_create_collection (u32 col_id,u32 target);
Extra definition of its_create_collection?
lib/arm/asm/gic-v3-its.h extern void gicv3_rdist_ctrl_lpi(u32 redist, bool set); · line 154
Quoted 2 lines
lib/arm/asm/gic-v3-its.h +2
-0+ +extern void set_lpi_config (int n,u8 val);
Please rename: lpi_set_config
lib/arm/asm/gic-v3-its.h extern void gicv3_rdist_ctrl_lpi(u32 redist, bool set); · line 155
Quoted 1 line
lib/arm/asm/gic-v3-its.h +1
-0+extern u8 get_lpi_config (int n);
get_lpi_config doesn't seem to exist.
Quoted 6 lines
lib/arm/asm/gic-v3-its.h +0
-0extern void its_send_mapd (struct its_device *dev,int valid);extern void its_send_mapc (struct its_collection *col,int valid);Signature · 1 line
2.20.1
Thanks,
drew
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Re: [kvm-unit-tests PATCH v2 13/16] arm/arm64: ITS: INT functional tests
Hi Drew,
Quoted 102 lines · Andrew Jones
Quoted 101 lines · Eric Auger
Triggers 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.
Signed-off-by Eric Auger <[email protected]>--- arm/gic.c | 174 +++++++++++++++++++++++++++++++++++++++ arm/unittests.cfg | 6 ++ lib/arm/asm/gic-v3-its.h | 14 ++++ 3 files changed, 194 insertions(+)arm/gic.c +57
-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; +static struct its_stats lpi_stats;static void nr_cpu_check (int nr) {@@ -158,6 +159,54 @@ static void ipi_handler(struct pt_regs *regs __unused) } } +static void lpi_handler(struct pt_regs *regs __unused) +{ +u32 irqstat =gic_read_iar (); +int irqnr =gic_iar_irqnr (irqstat); + +gic_write_eoir (irqstat); +if (irqnr <8192 ) +report (false,"Unexpected non LPI interrupt received" ); +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 (void ) +{ +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 (false, +"No LPI received whereas (cpuid=%d, intid=%d) " +"was expected" , lpi_stats.expected.cpu_id, + lpi_stats.expected.lpi_id); + }else { +report (false,"Unexpected LPI (cpuid=%d, intid=%d)" , + lpi_stats.observed.cpu_id, + lpi_stats.observed.lpi_id); + } + }else if (lpi_stats.expected.lpi_id !=-1 ) { +report (true,"LPI %d on CPU %d" , lpi_stats.observed.lpi_id, + lpi_stats.observed.cpu_id); + }else { +report (true,"no LPI received, as expected" ); + } +} +static void gicv2_ipi_send_self (void ) {writel (2 <<24 |IPI_IRQ ,gicv2_dist_base () +GICD_SGIR );@@ -241,6 +290,14 @@ static void ipi_test(void *data __unused)ipi_recv (); } +static void secondary_lpi_test (void ) +{ +setup_irq (lpi_handler); +cpumask_set_cpu (smp_processor_id (), &ready); +while (1 ) +wfi (); +} +static struct gic gicv2 = { .ipi = { .send_self = gicv2_ipi_send_self,@@ -551,6 +608,120 @@ static void test_its_baser(void)report_info ("collection baser entry_size = 0x%x" , coll_baser->esz); }
Quoted 15 lines
arm/gic.c static void test_its_baser(void) · line 622
Quoted 12 lines
arm/gic.c +12
-0+static int its_prerequisites (int nb_cpus) +{ +int cpu; + +if (!gicv3_its_base ()) { +report_skip ("No ITS, skip ..." ); +return -1 ; + } + +if (nr_cpus <4 ) { +report_skip ("Test requires at least %d vcpus" , nb_cpus); +return -1 ;We have
nr_cpu_check()inarm/gic.cthat does areport_abortfor this case. Is there a reason to doreport_skipinstead ofreport_abort?
Why should we mandate 4 vcpus?
Quoted 3 lines
Also do you plan to return more than 0 - success, -1 - failure? If not, then this could be a bool function.
indeed.
Quoted 94 lines
Quoted 94 lines
arm/gic.c +93
-0+ } + +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 (); + +lpi_stats_expect (-1 ,-1 ); +check_lpi_stats (); + +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 */ ); + +set_lpi_config (8195 ,LPI_PROP_DEFAULT ); +set_lpi_config (8196 ,LPI_PROP_DEFAULT ); + +its_send_invall (col2); +its_send_invall (col3); + +report_prefix_push ("int" ); + +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 (); + +lpi_stats_expect (2 ,8196 ); +its_send_int (dev7,255 ); +check_lpi_stats (); + +report_prefix_pop (); + +report_prefix_push ("inv/invall" ); + +/* disable 8195 */ +set_lpi_config (8195 ,LPI_PROP_DEFAULT & ~0x1 ); +its_send_inv (dev2,20 ); + +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev2,20 ); +check_lpi_stats (); + +set_lpi_config (8195 ,LPI_PROP_DEFAULT ); +/* willingly forget the INVALL*/ +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev2,20 ); +check_lpi_stats (); + +its_send_invall (col3); +lpi_stats_expect (3 ,8195 ); +its_send_int (dev2,20 ); +check_lpi_stats (); + +report_prefix_pop (); + +report_prefix_push ("mapd valid=false" ); +its_send_mapd (dev2, false); +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev2,20 ); +check_lpi_stats (); +report_prefix_pop ();
Quoted 8 lines
arm/gic.c static void test_its_baser(void) · line 721
Quoted 6 lines
arm/gic.c +6
-0+ +report_prefix_push ("mapc valid=false" ); +its_send_mapc (col2, false); +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev7,255 ); +check_lpi_stats ();Missing prefix pop here
OK
Quoted 7 lines
arm/gic.c static void ipi_handler(struct pt_regs *regs __unused) · line 184
Quoted 4 lines
arm/gic.c +3
-0+} + +Extra blank line
Quoted 13 lines
arm/gic.c int main(int argc, char **argv) · line 758
Quoted 11 lines
arm/gic.c +3
-0int main (int argc,char **argv) {if (!gic_init ()) {@@ -581,6 +752,9 @@ int main(int argc, char **argv) }else if (strcmp (argv[1 ],"mmio" ) ==0 ) {report_prefix_push (argv[1 ]);gic_test_mmio (); + }else if (!strcmp (argv[1 ],"its-trigger" )) { +report_prefix_push (argv[1 ]); +test_its_trigger ();report_prefix_pop ();You stole the
report_prefix_popfrom the mmio tests above.
OK
Quoted 28 lines
Quoted 28 lines
arm/gic.c +0
-0}else if (strcmp (argv[1 ],"its-introspection" ) ==0 ) {report_prefix_push (argv[1 ]);arm/unittests.cfg +6
-0@@ -134,6 +134,12 @@ smp = $MAX_SMP extra_params = -machine gic-version=3 -append 'its-baser' groups = its +[its-trigger] +file = gic.flat +smp = $MAX_SMP +extra_params = -machine gic-version=3 -append 'its-trigger' +groups = its + # Test PSCI emulation [psci] file = psci.flatlib/arm/asm/gic-v3-its.h +0
-0@@ -123,6 +123,16 @@ struct its_data {u32 nr_collections;/* Allocated Collections */ };
Quoted 12 lines
lib/arm/asm/gic-v3-its.h struct its_data { · line 134
Quoted 9 lines
lib/arm/asm/gic-v3-its.h +9
-0+struct its_event { +int cpu_id; +int lpi_id; +}; + +struct its_stats { +struct its_event expected; +struct its_event observed; +};These structures belong in
arm/gic.cas they are unit test structions and driver structures.
OK
Quoted 23 lines
lib/arm/asm/gic-v3-its.h extern void gicv3_rdist_ctrl_lpi(u32 redist, bool set); · line 152
Quoted 10 lines
lib/arm/asm/gic-v3-its.h +2
-0+extern struct its_data its_data;#define gicv3_its_base () (its_data.base)@@ -139,6 +149,10 @@ extern void gicv3_rdist_ctrl_lpi(u32 redist, bool set);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); +extern struct its_collection *its_create_collection (u32 col_id,u32 target);Extra definition of
its_create_collection?lib/arm/asm/gic-v3-its.h extern void gicv3_rdist_ctrl_lpi(u32 redist, bool set); · line 154
Quoted 2 lines
lib/arm/asm/gic-v3-its.h +2
-0+ +extern void set_lpi_config (int n,u8 val);Please rename:
lpi_set_configlib/arm/asm/gic-v3-its.h extern void gicv3_rdist_ctrl_lpi(u32 redist, bool set); · line 155
Quoted 1 line
lib/arm/asm/gic-v3-its.h +1
-0+extern u8 get_lpi_config (int n);
get_lpi_configdoesn't seem to exist.Quoted 1 line
Quoted 9 lines
Quoted 5 lines
extern void
its_send_mapd(struct its_device *dev, int valid); extern voidits_send_mapc(struct its_collection *col, int valid);Signature · 1 line
2.20.1Thanks,
drew
Thanks
Eric
Re: [kvm-unit-tests PATCH v2 13/16] arm/arm64: ITS: INT functional tests
Quoted 15 lines · Auger Eric
Quoted 7 lines
Quoted 7 lines
arm/gic.c +7
-0+static int its_prerequisites (int nb_cpus) +{ +int cpu; + +if (!gicv3_its_base ()) { +report_skip ("No ITS, skip ..." ); +return -1 ;Quoted 8 lines
arm/gic.c static void test_its_baser(void) · line 622
Quoted 5 lines
arm/gic.c +5
-0+ } + +if (nr_cpus <4 ) { +report_skip ("Test requires at least %d vcpus" , nb_cpus); +return -1 ;We have
nr_cpu_check()inarm/gic.cthat does areport_abortfor this case. Is there a reason to doreport_skipinstead ofreport_abort?
Quoted 1 line
Why should we mandate 4 vcpus?
I don't know. It's your test :-) afaict if there aren't 4 vcpus then you skip this test and exit, which is the same thing as report_abort'ing. If you intend to run multiple tests and only want to skip a few when there aren't enough vcpus, then I agree report_skip makes some sense.
On a related note, so far I've always tried to write tests that require more than one vcpu to be testable with only two, but then test even more if more are provided. Do you really need four for this test?
Thanks,
drew
PATCH v2 14/16 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).
--- arm/Makefile.common | 2 +- arm/run | 2 +- lib/arm/io.c | 13 +++++++++++++ 3 files changed, 15 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 +13 -0
@@ -87,6 +87,19 @@ void puts(const char *s)spin_unlock (&uart_lock); } +/* +* Minimalist implementation for migration completion detection. +* Needs to be improved for more advanced Rx cases +*/ +int __getchar (void ) +{ +int ret; + + ret =readb (uart0_base); +if (!ret) +return -1 ; +return ret; +}/* * Defining halt to take 'code' as an argument guarantees that it will
Signature · 1 line
2.20.1
Re: [kvm-unit-tests PATCH v2 14/16] arm/run: Allow Migration tests
Quoted 52 lines · Eric Auger
Let'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
__getcharimplement 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).
Signed-off-by Eric Auger <[email protected]>Reviewed-by Thomas Huth <[email protected]>--- arm/Makefile.common | 2 +- arm/run | 2 +- lib/arm/io.c | 13 +++++++++++++ 3 files changed, 15 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.oarm/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 +0
-0
lib/arm/io.c void puts(const char *s) · line 92
Quoted 6 lines
lib/arm/io.c +3
-0@@ -87,6 +87,19 @@ void puts(const char *s)spin_unlock (&uart_lock); } +/* +* Minimalist implementation for migration completion detection. +* Needs to be improved for more advanced Rx cases
Please add that QEMU supports reading a maximum of 16 characters in this minimal mode. We could even add a counter and then assert if we try to read 16 or more.
lib/arm/io.c void puts(const char *s) · line 102
Quoted 10 lines
lib/arm/io.c +10
-0+*/ +int __getchar (void ) +{ +int ret; + + ret =readb (uart0_base); +if (!ret) +return -1 ; +return ret; +}
What about taking the lock?
Quoted 6 lines
lib/arm/io.c +0
-0/* * Defining halt to take 'code' as an argument guarantees that it will Signature · 1 line
2.20.1
What do you think of the __getchar below?
Thanks,
drew
lib/arm/io.c +25 -0
@@ -79,6 +79,31 @@ void io_init(void)chr_testdev_init (); } +static int ____getchar (void ) +{ +int c; + +spin_lock (&uart_lock); + c =readb (uart0_base); +spin_unlock (&uart_lock); + +return c ?:-1 ; +} + +int __getchar (void ) +{ +static int count; +int c; + +if ((c =____getchar ()) !=-1 ) + ++count; + +/* Without special UART initialization we can only read 16 characters. */ +assert (count <16 ); + +return c; +} +void puts (const char *s) {spin_lock (&uart_lock);
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Re: [kvm-unit-tests PATCH v2 14/16] arm/run: Allow Migration tests
Hi Drew,
Quoted 117 lines · Andrew Jones
Quoted 52 lines · Eric Auger
Let'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
__getcharimplement 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).
Signed-off-by Eric Auger <[email protected]>Reviewed-by Thomas Huth <[email protected]>--- arm/Makefile.common | 2 +- arm/run | 2 +- lib/arm/io.c | 13 +++++++++++++ 3 files changed, 15 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.oarm/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 +0
-0lib/arm/io.c void puts(const char *s) · line 92
Quoted 6 lines
lib/arm/io.c +3
-0@@ -87,6 +87,19 @@ void puts(const char *s)spin_unlock (&uart_lock); } +/* +* Minimalist implementation for migration completion detection. +* Needs to be improved for more advanced Rx cases Please add that QEMU supports reading a maximum of 16 characters in this minimal mode. We could even add a counter and then assert if we try to read 16 or more.
lib/arm/io.c void puts(const char *s) · line 102
Quoted 10 lines
lib/arm/io.c +10
-0+*/ +int __getchar (void ) +{ +int ret; + + ret =readb (uart0_base); +if (!ret) +return -1 ; +return ret; +}What about taking the lock?
Quoted 6 lines
lib/arm/io.c +0
-0/* * Defining halt to take 'code' as an argument guarantees that it will Signature · 1 line
2.20.1What do you think of the
__getcharbelow?Thanks,
drewlib/arm/io.c +18
-0@@ -79,6 +79,31 @@ void io_init(void)chr_testdev_init (); } +static int ____getchar (void ) +{ +int c; + +spin_lock (&uart_lock); + c =readb (uart0_base); +spin_unlock (&uart_lock); + +return c ?:-1 ; +} + +int __getchar (void ) +{ +static int count; +int c; + +if ((c =____getchar ()) !=-1 ) + ++count;
lib/arm/io.c void io_init(void) · line 109
Quoted 10 lines
lib/arm/io.c +7
-0+ +/* Without special UART initialization we can only read 16 characters. */ +assert (count <16 ); + +return c; +} +void puts (const char *s) {spin_lock (&uart_lock);
Yep, I will take your improved version.
Thanks
Eric
PATCH v2 15/16 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.
--- arm/gic.c | 55 +++++++++++++++++++++++++++++++++++++--- arm/unittests.cfg | 7 +++++ lib/arm/asm/gic-v3-its.h | 2 ++ lib/arm/gic-v3-its.c | 22 ++++++++++++++++ 4 files changed, 82 insertions(+), 4 deletions(-)
arm/gic.c +51 -4
@@ -641,13 +641,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 */ );
@@ -661,8 +667,6 @@ static void test_its_trigger(void)its_send_invall (col2);its_send_invall (col3); -report_prefix_push ("int" ); -its_send_mapd (dev2, true);its_send_mapd (dev7, true);
@@ -673,6 +677,23 @@ static void test_its_trigger(void) 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 );
@@ -721,6 +742,28 @@ static void test_its_trigger(void)check_lpi_stats (); } +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 (true,"Migration complete" ); + +lpi_stats_expect (3 ,8195 ); +its_send_int (dev2,20 ); +check_lpi_stats (); + +lpi_stats_expect (2 ,8196 ); +its_send_int (dev7,255 ); +check_lpi_stats (); +}int main (int argc,char **argv) {
@@ -756,6 +799,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 +7 -0
@@ -140,6 +140,13 @@ smp = $MAX_SMP extra_params = -machine gic-version=3 -append 'its-trigger' groups = its +[its-migration] +file = gic.flat +smp = $MAX_SMP +accel = kvm +extra_params = -machine gic-version=3 -append 'its-migration' +groups = its migration + # Test PSCI emulation [psci] file = psci.flat
lib/arm/asm/gic-v3-its.h +2 -0
@@ -166,6 +166,8 @@ extern void its_send_invall(struct its_collection *col);extern void its_send_movi (struct its_device *dev,struct its_collection *col,u32 id);extern void its_send_sync (struct its_collection *col); +extern struct its_device *its_get_device (u32 id); +extern struct its_collection *its_get_collection (u32 id);#define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1ULL << 0)#define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1)
lib/arm/gic-v3-its.c +22 -0
@@ -303,3 +303,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]; + } +return NULL ; +} + +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]; + } +return NULL ; +}
Signature · 1 line
2.20.1
PATCH v2 16/16 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.
--- arm/gic.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++ arm/unittests.cfg | 16 ++++- 2 files changed, 163 insertions(+), 1 deletion(-)
arm/gic.c +148 -0
@@ -170,6 +170,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 */ }
@@ -207,6 +208,18 @@ static void check_lpi_stats(void) } } +static void check_lpi_hits (int *expected) +{ +int i; + +for (i =0 ; i < nr_cpus; i++) { +if (acked[i] != expected[i]) +report (false,"expected %d LPIs on PE #%d, %d observed" , + expected[i], i, acked[i]); + } +report (true,"check LPI on all vcpus" ); +} +static void gicv2_ipi_send_self (void ) {writel (2 <<24 |IPI_IRQ ,gicv2_dist_base () +GICD_SGIR );
@@ -641,6 +654,18 @@ 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) +{ +if (!dev || !col) +report_abort ("wrong device or collection" ); + +its_send_mapti (dev, physid, eventid, col); + +set_lpi_config (physid,LPI_PROP_DEFAULT ); +its_send_invall (col); +} +/* * Setup the configuration for those mappings: * dev_id=2 event=20 -> vcpu 3, intid=8195
@@ -765,6 +790,121 @@ static void test_its_migration(void)check_lpi_stats (); } +static void test_migrate_unmapped_collection (void ) +{ +struct its_collection *col; +struct its_device *dev2, *dev7; +u8 config; + +if (its_setup1 ()) +return ; + + col =its_create_collection (nr_cpus -1 , nr_cpus -1 ); + 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 (true,"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 (); + + config =get_lpi_config (8192 ); +report (config ==LPI_PROP_DEFAULT , +"Config of LPI 8192 was properly migrated" ); + +lpi_stats_expect (nr_cpus -1 ,8192 ); +its_send_int (dev2,0 ); +check_lpi_stats (); + +/* unmap the collection */ +its_send_mapc (col, false); + +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev2,0 ); +check_lpi_stats (); + +/* remap event 0 onto lpiid 8193 */ +set_lpi (dev2,0 ,8193 , col); +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev2,0 ); +check_lpi_stats (); + +/* remap the collection */ +its_send_mapc (col, true); +lpi_stats_expect (nr_cpus -1 ,8193 ); +} + +static void test_its_pending_migration (void ) +{ +struct its_device *dev; +struct its_collection *collection[2 ]; +int expected[NR_CPUS ]; +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 (nr_cpus -1 , nr_cpus -1 ); + collection[1 ] =its_create_collection (nr_cpus -2 , nr_cpus -2 ); +its_send_mapc (collection[0 ], true); +its_send_mapc (collection[1 ], true); + +/* disable lpi at redist level */ +gicv3_rdist_ctrl_lpi (nr_cpus -1 , false); +gicv3_rdist_ctrl_lpi (nr_cpus -2 , false); + +/* even lpis are assigned to even cpu */ +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,8192 + i, i, col); +set_lpi_config (8192 + i,LPI_PROP_DEFAULT ); +set_pending_table_bit (vcpu,8192 + i, true); + } +its_send_invall (collection[0 ]); +its_send_invall (collection[1 ]); + +/* Set the PTZ bit on each pendbaser */ + + expected[nr_cpus -1 ] =128 ; + expected[nr_cpus -2 ] =128 ; + + ptr = gicv3_data.redist_base[nr_cpus -1 ] +GICR_PENDBASER ; + pendbaser =readq (ptr); +writeq (pendbaser & ~GICR_PENDBASER_PTZ , ptr); + + ptr = gicv3_data.redist_base[nr_cpus -2 ] +GICR_PENDBASER ; + pendbaser =readq (ptr); +writeq (pendbaser & ~GICR_PENDBASER_PTZ , ptr); + +gicv3_rdist_ctrl_lpi (nr_cpus -1 , true); +gicv3_rdist_ctrl_lpi (nr_cpus -2 , true); + +puts ("Now migrate the VM, then press a key to continue...\n" ); + (void )getchar (); +report (true,"Migration complete" ); + +mdelay (1000 ); + +check_lpi_hits (expected); +} +int main (int argc,char **argv) {if (!gic_init ()) {
@@ -803,6 +943,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 +15 -1
@@ -145,7 +145,21 @@ file = gic.flat smp = $MAX_SMP accel = kvm extra_params = -machine gic-version=3 -append 'its-migration' -groups = its migration +groups = migration + +[its-pending-migration] +file = gic.flat +smp = $MAX_SMP +accel = kvm +extra_params = -machine gic-version=3 -append 'its-pending-migration' +groups = migration + +[its-migrate-unmapped-collection] +file = gic.flat +smp = $MAX_SMP +accel = kvm +extra_params = -machine gic-version=3 -append 'its-migrate-unmapped-collection' +groups = migration # Test PSCI emulation [psci]
Signature · 1 line
2.20.1
Re: [kvm-unit-tests PATCH v2 16/16] arm/arm64: ITS: pending table migration test
Quoted 211 lines · Eric Auger
Add 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.
Signed-off-by Eric Auger <[email protected]>--- arm/gic.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++ arm/unittests.cfg | 16 ++++- 2 files changed, 163 insertions(+), 1 deletion(-)arm/gic.c +148
-0@@ -170,6 +170,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 */ }@@ -207,6 +208,18 @@ static void check_lpi_stats(void) } } +static void check_lpi_hits (int *expected) +{ +int i; + +for (i =0 ; i < nr_cpus; i++) { +if (acked[i] != expected[i]) +report (false,"expected %d LPIs on PE #%d, %d observed" , + expected[i], i, acked[i]); + } +report (true,"check LPI on all vcpus" ); +} +static void gicv2_ipi_send_self (void ) {writel (2 <<24 |IPI_IRQ ,gicv2_dist_base () +GICD_SGIR );@@ -641,6 +654,18 @@ 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) +{ +if (!dev || !col) +report_abort ("wrong device or collection" ); + +its_send_mapti (dev, physid, eventid, col); + +set_lpi_config (physid,LPI_PROP_DEFAULT ); +its_send_invall (col); +} +/* * Setup the configuration for those mappings: * dev_id=2 event=20 -> vcpu 3, intid=8195 @@ -765,6 +790,121 @@ static void test_its_migration(void)check_lpi_stats (); } +static void test_migrate_unmapped_collection (void ) +{ +struct its_collection *col; +struct its_device *dev2, *dev7; +u8 config; + +if (its_setup1 ()) +return ; + + col =its_create_collection (nr_cpus -1 , nr_cpus -1 ); + 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 (true,"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 (); + + config =get_lpi_config (8192 ); +report (config ==LPI_PROP_DEFAULT , +"Config of LPI 8192 was properly migrated" ); + +lpi_stats_expect (nr_cpus -1 ,8192 ); +its_send_int (dev2,0 ); +check_lpi_stats (); + +/* unmap the collection */ +its_send_mapc (col, false); + +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev2,0 ); +check_lpi_stats (); + +/* remap event 0 onto lpiid 8193 */ +set_lpi (dev2,0 ,8193 , col); +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev2,0 ); +check_lpi_stats (); + +/* remap the collection */ +its_send_mapc (col, true); +lpi_stats_expect (nr_cpus -1 ,8193 ); +} + +static void test_its_pending_migration (void ) +{ +struct its_device *dev; +struct its_collection *collection[2 ]; +int expected[NR_CPUS ]; +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 (nr_cpus -1 , nr_cpus -1 ); + collection[1 ] =its_create_collection (nr_cpus -2 , nr_cpus -2 ); +its_send_mapc (collection[0 ], true); +its_send_mapc (collection[1 ], true); + +/* disable lpi at redist level */ +gicv3_rdist_ctrl_lpi (nr_cpus -1 , false); +gicv3_rdist_ctrl_lpi (nr_cpus -2 , false); + +/* even lpis are assigned to even cpu */ +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,8192 + i, i, col); +set_lpi_config (8192 + i,LPI_PROP_DEFAULT ); +set_pending_table_bit (vcpu,8192 + i, true); + } +its_send_invall (collection[0 ]); +its_send_invall (collection[1 ]); + +/* Set the PTZ bit on each pendbaser */ + + expected[nr_cpus -1 ] =128 ; + expected[nr_cpus -2 ] =128 ; + + ptr = gicv3_data.redist_base[nr_cpus -1 ] +GICR_PENDBASER ; + pendbaser =readq (ptr); +writeq (pendbaser & ~GICR_PENDBASER_PTZ , ptr); + + ptr = gicv3_data.redist_base[nr_cpus -2 ] +GICR_PENDBASER ; + pendbaser =readq (ptr); +writeq (pendbaser & ~GICR_PENDBASER_PTZ , ptr); + +gicv3_rdist_ctrl_lpi (nr_cpus -1 , true); +gicv3_rdist_ctrl_lpi (nr_cpus -2 , true); + +puts ("Now migrate the VM, then press a key to continue...\n" ); + (void )getchar (); +report (true,"Migration complete" ); + +mdelay (1000 ); + +check_lpi_hits (expected); +} +int main (int argc,char **argv) {if (!gic_init ()) {@@ -803,6 +943,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 +5
-1@@ -145,7 +145,21 @@ file = gic.flat smp = $MAX_SMP accel = kvm extra_params = -machine gic-version=3 -append 'its-migration' -groups = its migration +groups = migration + +[its-pending-migration] +file = gic.flat +smp = $MAX_SMP
arm/unittests.cfg file = gic.flat · line 162
Quoted 10 lines
arm/unittests.cfg +10
-0+accel = kvm +extra_params = -machine gic-version=3 -append 'its-pending-migration' +groups = migration + +[its-migrate-unmapped-collection] +file = gic.flat +smp = $MAX_SMP +accel = kvm +extra_params = -machine gic-version=3 -append 'its-migrate-unmapped-collection' +groups = migration
Why drop the 'its' group?
Thanks,
drew
Quoted 6 lines
arm/unittests.cfg +0
-0# Test PSCI emulation [psci]Signature · 1 line
2.20.1
Re: [kvm-unit-tests PATCH v2 16/16] arm/arm64: ITS: pending table migration test
Hi Drew,
Quoted 216 lines · Andrew Jones
Quoted 215 lines · Eric Auger
Add 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.
Signed-off-by Eric Auger <[email protected]>--- arm/gic.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++ arm/unittests.cfg | 16 ++++- 2 files changed, 163 insertions(+), 1 deletion(-)arm/gic.c +148
-0@@ -170,6 +170,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 */ }@@ -207,6 +208,18 @@ static void check_lpi_stats(void) } } +static void check_lpi_hits (int *expected) +{ +int i; + +for (i =0 ; i < nr_cpus; i++) { +if (acked[i] != expected[i]) +report (false,"expected %d LPIs on PE #%d, %d observed" , + expected[i], i, acked[i]); + } +report (true,"check LPI on all vcpus" ); +} +static void gicv2_ipi_send_self (void ) {writel (2 <<24 |IPI_IRQ ,gicv2_dist_base () +GICD_SGIR );@@ -641,6 +654,18 @@ 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) +{ +if (!dev || !col) +report_abort ("wrong device or collection" ); + +its_send_mapti (dev, physid, eventid, col); + +set_lpi_config (physid,LPI_PROP_DEFAULT ); +its_send_invall (col); +} +/* * Setup the configuration for those mappings: * dev_id=2 event=20 -> vcpu 3, intid=8195 @@ -765,6 +790,121 @@ static void test_its_migration(void)check_lpi_stats (); } +static void test_migrate_unmapped_collection (void ) +{ +struct its_collection *col; +struct its_device *dev2, *dev7; +u8 config; + +if (its_setup1 ()) +return ; + + col =its_create_collection (nr_cpus -1 , nr_cpus -1 ); + 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 (true,"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 (); + + config =get_lpi_config (8192 ); +report (config ==LPI_PROP_DEFAULT , +"Config of LPI 8192 was properly migrated" ); + +lpi_stats_expect (nr_cpus -1 ,8192 ); +its_send_int (dev2,0 ); +check_lpi_stats (); + +/* unmap the collection */ +its_send_mapc (col, false); + +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev2,0 ); +check_lpi_stats (); + +/* remap event 0 onto lpiid 8193 */ +set_lpi (dev2,0 ,8193 , col); +lpi_stats_expect (-1 ,-1 ); +its_send_int (dev2,0 ); +check_lpi_stats (); + +/* remap the collection */ +its_send_mapc (col, true); +lpi_stats_expect (nr_cpus -1 ,8193 ); +} + +static void test_its_pending_migration (void ) +{ +struct its_device *dev; +struct its_collection *collection[2 ]; +int expected[NR_CPUS ]; +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 (nr_cpus -1 , nr_cpus -1 ); + collection[1 ] =its_create_collection (nr_cpus -2 , nr_cpus -2 ); +its_send_mapc (collection[0 ], true); +its_send_mapc (collection[1 ], true); + +/* disable lpi at redist level */ +gicv3_rdist_ctrl_lpi (nr_cpus -1 , false); +gicv3_rdist_ctrl_lpi (nr_cpus -2 , false); + +/* even lpis are assigned to even cpu */ +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,8192 + i, i, col); +set_lpi_config (8192 + i,LPI_PROP_DEFAULT ); +set_pending_table_bit (vcpu,8192 + i, true); + } +its_send_invall (collection[0 ]); +its_send_invall (collection[1 ]); + +/* Set the PTZ bit on each pendbaser */ + + expected[nr_cpus -1 ] =128 ; + expected[nr_cpus -2 ] =128 ; + + ptr = gicv3_data.redist_base[nr_cpus -1 ] +GICR_PENDBASER ; + pendbaser =readq (ptr); +writeq (pendbaser & ~GICR_PENDBASER_PTZ , ptr); + + ptr = gicv3_data.redist_base[nr_cpus -2 ] +GICR_PENDBASER ; + pendbaser =readq (ptr); +writeq (pendbaser & ~GICR_PENDBASER_PTZ , ptr); + +gicv3_rdist_ctrl_lpi (nr_cpus -1 , true); +gicv3_rdist_ctrl_lpi (nr_cpus -2 , true); + +puts ("Now migrate the VM, then press a key to continue...\n" ); + (void )getchar (); +report (true,"Migration complete" ); + +mdelay (1000 ); + +check_lpi_hits (expected); +} +int main (int argc,char **argv) {if (!gic_init ()) {@@ -803,6 +943,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 +9
-1@@ -145,7 +145,21 @@ file = gic.flat smp = $MAX_SMP accel = kvm extra_params = -machine gic-version=3 -append 'its-migration' -groups = its migration +groups = migration + +[its-pending-migration] +file = gic.flat +smp = $MAX_SMP +accel = kvm +extra_params = -machine gic-version=3 -append 'its-pending-migration' +groups = migration +
Quoted 8 lines
arm/unittests.cfg file = gic.flat · line 162
Quoted 6 lines
arm/unittests.cfg +6
-0+[its-migrate-unmapped-collection] +file = gic.flat +smp = $MAX_SMP +accel = kvm +extra_params = -machine gic-version=3 -append 'its-migrate-unmapped-collection' +groups = migrationWhy drop the 'its' group?
I think the test only works with the migration group. Otherwise it stalls due to the migration infrastructure. I will double check.
Thanks
Eric
Quoted 10 lines
Thanks,
drewQuoted 6 lines
arm/unittests.cfg +0
-0# Test PSCI emulation [psci]Signature · 1 line
2.20.1