arm/arm64: Add ITS tests
Subsystems (3)
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 around 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]
The series can be fount at:
https://github.com/eauger/kut/tree/its-v1
Best Regards
Eric
[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/
For ITS migration testing use:
./run_tests.sh -g migration (blocks on TCG but I think it is beyond the scope of that series)
For other ITS tests:
./run_tests.sh -g its
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 | 447 +++++++++++++++++++++++++++++++++-- arm/run | 2 +- arm/unittests.cfg | 39 ++++ lib/arm/asm/gic-v3-its.h | 217 +++++++++++++++++ lib/arm/asm/gic-v3.h | 87 +++++++ lib/arm/asm/gic.h | 13 ++ lib/arm/gic-v3-its-cmd.c | 462 +++++++++++++++++++++++++++++++++++++ lib/arm/gic-v3-its.c | 354 ++++++++++++++++++++++++++++ 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, 1745 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 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
Re: [kvm-unit-tests PATCH 01/16] libcflat: Add other size defines
Quoted 14 lines · Eric Auger
Introduce additional
SZ_256,SZ_8K,SZ_16Kmacros that will be used by ITS tests.Signed-off-by Eric Auger <[email protected]>--- lib/libcflat.h | 3 +++ 1 file changed, 3 insertions(+)lib/libcflat.h +0
-0
lib/libcflat.h line 45
Quoted 10 lines
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)
PATCH 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 | 9 +++++ lib/arm/gic.c | 90 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 101 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 +9 -0
@@ -15,6 +15,7 @@#define GICD_IIDR 0x0008#define GICD_IGROUPR 0x0080#define GICD_ISENABLER 0x0100 +#define GICD_ICENABLER 0x0180#define GICD_ISPENDR 0x0200#define GICD_ICPENDR 0x0280#define GICD_ISACTIVER 0x0300
@@ -73,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 · 1 line
2.20.1
PATCH 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 · 1 line
2.20.1
PATCH 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)
@@ -35,6 +36,11 @@#define GICR_ISENABLER0 GICD_ISENABLER#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 · 1 line
2.20.1
PATCH 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.
--- arm/Makefile.common | 1 + arm/gic.c | 34 +++++++++++ arm/unittests.cfg | 6 ++ lib/arm/asm/gic-v3-its.h | 116 +++++++++++++++++++++++++++++++++++++ lib/arm/asm/gic.h | 1 + lib/arm/gic-v3-its.c | 41 +++++++++++++ lib/arm/gic.c | 31 ++++++++-- lib/arm64/asm/gic-v3-its.h | 1 + 8 files changed, 226 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 +116 -0
116 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 +41 -0
41 lines not on this page · raw message
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
Zenghui Yu
reviewerRe: [kvm-unit-tests PATCH 05/16] arm/arm64: ITS: Introspection tests
Hi Eric,
I have to admit that this is the first time I've looked into the kvm-unit-tests code, so only some minor comments inline :)
Quoted 7 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]>
[...]
Quoted 44 lines
lib/arm/asm/gic-v3-its.h new file +38
-0@@ -0,0 +1,116 @@ +/* +* All ITS* defines are lifted from include/linux/irqchip/arm-gic-v3.h +* +* Copyright (C) 2016, Red Hat Inc, Andrew Jones <[email protected]> +* +* 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 (1UL << 0) +#define GITS_TYPER_IDBITS_SHIFT 8 +#define GITS_TYPER_DEVBITS_SHIFT 13 +#define GITS_TYPER_DEVBITS (r) ((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1) +#define GITS_TYPER_PTA (1UL << 19) +#define GITS_TYPER_HWCOLLCNT_SHIFT 24 + +#define GITS_CTLR_ENABLE (1U << 0) + +#define GITS_CBASER_VALID (1UL << 63) +#define GITS_CBASER_SHAREABILITY_SHIFT (10) +#define GITS_CBASER_INNER_CACHEABILITY_SHIFT (59) +#define GITS_CBASER_OUTER_CACHEABILITY_SHIFT (53) +#define GITS_CBASER_SHAREABILITY_MASK \ + GIC_BASER_SHAREABILITY(GITS_CBASER, SHAREABILITY_MASK) +#define GITS_CBASER_INNER_CACHEABILITY_MASK \ + GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, MASK) +#define GITS_CBASER_OUTER_CACHEABILITY_MASK \
lib/arm/asm/gic-v3-its.h line 48
Quoted 10 lines
lib/arm/asm/gic-v3-its.h new file +10
-0+ GIC_BASER_CACHEABILITY(GITS_CBASER, OUTER, MASK) +#define GITS_CBASER_CACHEABILITY_MASK GITS_CBASER_INNER_CACHEABILITY_MASK + +#define GITS_CBASER_InnerShareable \ + GIC_BASER_SHAREABILITY(GITS_CBASER, InnerShareable) + +#define GITS_CBASER_nCnB GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, nCnB) +#define GITS_CBASER_nC GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, nC) +#define GITS_CBASER_RaWt GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWt) +#define GITS_CBASER_RaWb GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWt)
s/RaWt/RaWb/
Quoted 27 lines
lib/arm/asm/gic-v3-its.h new file +27
-0+#define GITS_CBASER_WaWt GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, WaWt) +#define GITS_CBASER_WaWb GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, WaWb) +#define GITS_CBASER_RaWaWt GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWaWt) +#define GITS_CBASER_RaWaWb GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWaWb) + +#define GITS_BASER_NR_REGS 8 + +#define GITS_BASER_VALID (1UL << 63) +#define GITS_BASER_INDIRECT (1ULL << 62) + +#define GITS_BASER_INNER_CACHEABILITY_SHIFT (59) +#define GITS_BASER_OUTER_CACHEABILITY_SHIFT (53) +#define GITS_BASER_CACHEABILITY_MASK 0x7 + +#define GITS_BASER_nCnB GIC_BASER_CACHEABILITY(GITS_BASER, INNER, nCnB) + +#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_SHAREABILITY_SHIFT (10) +#define GITS_BASER_InnerShareable \ + GIC_BASER_SHAREABILITY(GITS_BASER, InnerShareable) +#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)
lib/arm/asm/gic-v3-its.h line 85
Quoted 10 lines
lib/arm/asm/gic-v3-its.h new file +10
-0+#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_VCPU 2 +#define GITS_BASER_TYPE_CPU 3
'3' is one of the reserved values of the GITS_BASER.Type field, and what do we expect with a "GITS_BASER_TYPE_CPU" table type? ;-)
I think we can copy (and might update in the future) all these macros against the latest Linux kernel.
Quoted 56 lines
lib/arm/asm/gic-v3-its.h new file +30
-0+#define GITS_BASER_TYPE_COLLECTION 4 + +#define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1ULL << 0) > + +struct its_typer { +unsigned int ite_size; +unsigned int eventid_bits; +unsigned int deviceid_bits; +unsigned int collid_bits; +unsigned int hw_collections; +bool pta; +bool cil; +bool cct; +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 +8
-0@@ -0,0 +1,41 @@ +/* +* 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;
lib/arm/gic-v3-its.c line 18
Quoted 10 lines
lib/arm/gic-v3-its.c new file +10
-0+ +void its_parse_typer (void ) +{ +u64 typer =readq (gicv3_its_base () +GITS_TYPER ); + + its_data.typer.ite_size = ((typer >>4 ) &0xf ) +1 ; + its_data.typer.pta = typer &GITS_TYPER_PTA ; + its_data.typer.eventid_bits = + ((typer >>GITS_TYPER_IDBITS_SHIFT ) &0x1f ) +1 ; + its_data.typer.deviceid_bits =GITS_TYPER_DEVBITS (typer) +1 ;
No need to '+1'. As GITS_TYPER_DEVBITS already helps us to calculate the implemented DeviceID bits.
lib/arm/gic-v3-its.c line 31
Quoted 13 lines
lib/arm/gic-v3-its.c new file +13
-0+ + its_data.typer.cil = (typer >>36 ) &0x1 ; +if (its_data.typer.cil) + its_data.typer.collid_bits = ((typer >>32 ) &0xf ) +1 ; +else + its_data.typer.collid_bits =16 ; + + its_data.typer.hw_collections = + (typer >>GITS_TYPER_HWCOLLCNT_SHIFT ) &0xff ; + + its_data.typer.cct = typer &0x4 ; + its_data.typer.virt_lpi = typer &0x2 ; + its_data.typer.phys_lpi = typer &GITS_TYPER_PLPIS ;
Personally, mix using of GITS_TYPER_* macros and some magic constants to parse the TYPER makes it a bit difficult to review the code. Maybe we can have more such kinds of macros in the header file and get rid of all hardcoded numbers?
Thanks,
Zenghui
Re: [kvm-unit-tests PATCH 05/16] arm/arm64: ITS: Introspection tests
Hi Zenghui,
Quoted 4 lines · Zenghui Yu
Hi Eric,
I have to admit that this is the first time I've looked into the kvm-unit-tests code, so only some minor comments inline :)
no problem. Thank you for looking at this.
By the way, with patch 16 I was able to test yout fix: "KVM: arm/arm64:
vgic: Don't rely on the wrong pending table". Reverting it produced an error. I forgot to mention that.
Quoted 70 lines · Eric Auger
Quoted 7 lines
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]>[...]
Quoted 58 lines
lib/arm/asm/gic-v3-its.h new file +24
-0@@ -0,0 +1,116 @@ +/* +* All ITS* defines are lifted from include/linux/irqchip/arm-gic-v3.h +* +* Copyright (C) 2016, Red Hat Inc, Andrew Jones <[email protected]> +* +* 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 (1UL << 0) +#define GITS_TYPER_IDBITS_SHIFT 8 +#define GITS_TYPER_DEVBITS_SHIFT 13 +#define GITS_TYPER_DEVBITS (r) ((((r) >>
GITS_TYPER_DEVBITS_SHIFT) &0x1f) + 1)lib/arm/asm/gic-v3-its.h new file +10
-0+#define GITS_TYPER_PTA (1UL << 19) +#define GITS_TYPER_HWCOLLCNT_SHIFT 24 + +#define GITS_CTLR_ENABLE (1U << 0) + +#define GITS_CBASER_VALID (1UL << 63) +#define GITS_CBASER_SHAREABILITY_SHIFT (10) +#define GITS_CBASER_INNER_CACHEABILITY_SHIFT (59) +#define GITS_CBASER_OUTER_CACHEABILITY_SHIFT (53) +#defineGITS_CBASER_SHAREABILITY_MASK \
+GIC_BASER_SHAREABILITY(GITS_CBASER, SHAREABILITY_MASK)+#define
GITS_CBASER_INNER_CACHEABILITY_MASK \
+GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, MASK)+#define
GITS_CBASER_OUTER_CACHEABILITY_MASK \
+GIC_BASER_CACHEABILITY(GITS_CBASER, OUTER, MASK)+#defineGITS_CBASER_CACHEABILITY_MASKGITS_CBASER_INNER_CACHEABILITY_MASKlib/arm/asm/gic-v3-its.h new file +2
-0+ +#defineGITS_CBASER_InnerShareable \
+GIC_BASER_SHAREABILITY(GITS_CBASER, InnerShareable)lib/arm/asm/gic-v3-its.h new file +2
-0+ +#define GITS_CBASER_nCnB GIC_BASER_CACHEABILITY(GITS_CBASER,INNER, nCnB)
Quoted 8 lines
Quoted 6 lines
+#define GITS_CBASER_nC
GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, nC)
+#define GITS_CBASER_RaWtGIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWt)
+#define GITS_CBASER_RaWbGIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWt)s/RaWt/RaWb/
OK
Quoted 45 lines
Quoted 45 lines
+#define GITS_CBASER_WaWt
GIC_BASER_CACHEABILITY(GITS_CBASER, INNER, WaWt)
+#define GITS_CBASER_WaWbGIC_BASER_CACHEABILITY(GITS_CBASER, INNER, WaWb)
+#define GITS_CBASER_RaWaWtGIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWaWt)
+#define GITS_CBASER_RaWaWbGIC_BASER_CACHEABILITY(GITS_CBASER, INNER, RaWaWb)lib/arm/asm/gic-v3-its.h new file +11
-0+ +#define GITS_BASER_NR_REGS 8 + +#define GITS_BASER_VALID (1UL << 63) +#define GITS_BASER_INDIRECT (1ULL << 62) + +#define GITS_BASER_INNER_CACHEABILITY_SHIFT (59) +#define GITS_BASER_OUTER_CACHEABILITY_SHIFT (53) +#define GITS_BASER_CACHEABILITY_MASK 0x7 + +#define GITS_BASER_nCnB GIC_BASER_CACHEABILITY(GITS_BASER,INNER, nCnB)
lib/arm/asm/gic-v3-its.h new file +3
-0+ +#define GITS_BASER_TYPE_SHIFT (56) +#define GITS_BASER_TYPE (r) (((r) >>
GITS_BASER_TYPE_SHIFT) & 7)lib/arm/asm/gic-v3-its.h new file +2
-0+#define GITS_BASER_ENTRY_SIZE_SHIFT (48) +#define GITS_BASER_ENTRY_SIZE (r) ((((r) >>
GITS_BASER_ENTRY_SIZE_SHIFT) &0x1f) + 1)lib/arm/asm/gic-v3-its.h new file +2
-0+#define GITS_BASER_SHAREABILITY_SHIFT (10) +#defineGITS_BASER_InnerShareable \
+GIC_BASER_SHAREABILITY(GITS_BASER, InnerShareable)lib/arm/asm/gic-v3-its.h new file +2
-0+#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)lib/arm/asm/gic-v3-its.h new file +4
-0+#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
Quoted 8 lines
lib/arm/asm/gic-v3-its.h line 85
Quoted 5 lines
lib/arm/asm/gic-v3-its.h new file +5
-0+ +#define GITS_BASER_TYPE_NONE 0 +#define GITS_BASER_TYPE_DEVICE 1 +#define GITS_BASER_TYPE_VCPU 2 +#define GITS_BASER_TYPE_CPU 3'3' is one of the reserved values of the GITS_BASER.Type field, and what do we expect with a "
GITS_BASER_TYPE_CPU" table type? ;-)
Yes I agree. This is code extracted from the irqchip header in Dec 2016. I should have checked again. I only use DEVICE and COLLECTION here.
I will remove all the defines I am not using at the moment. I guess most of the defines related to memory/cache mgt are not mandated either.
Quoted 63 lines
I think we can copy (and might update in the future) all these macros against the latest Linux kernel.
Quoted 59 lines
lib/arm/asm/gic-v3-its.h new file +30
-0+#define GITS_BASER_TYPE_COLLECTION 4 + +#define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1ULL << 0) > + +struct its_typer { + unsigned int ite_size; + unsigned int eventid_bits; + unsigned int deviceid_bits; + unsigned int collid_bits; + unsigned int hw_collections; + bool pta; + bool cil; + bool cct; + 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 +13
-0@@ -0,0 +1,41 @@ +/* +* 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); +
Quoted 8 lines
lib/arm/gic-v3-its.c line 18
Quoted 5 lines
lib/arm/gic-v3-its.c new file +5
-0+ its_data.typer.ite_size = ((typer >> 4) & 0xf) + 1; + its_data.typer.pta = typer & GITS_TYPER_PTA; + its_data.typer.eventid_bits = + ((typer >> GITS_TYPER_IDBITS_SHIFT) & 0x1f) + 1; + its_data.typer.deviceid_bits = GITS_TYPER_DEVBITS(typer) + 1;No need to '+1'. As
GITS_TYPER_DEVBITSalready helps us to calculate the implemented DeviceID bits.
OK
Quoted 11 lines
Quoted 11 lines
lib/arm/gic-v3-its.c new file +10
-0+ + its_data.typer.cil = (typer >> 36) & 0x1; + if (its_data.typer.cil) + its_data.typer.collid_bits = ((typer >> 32) & 0xf) + 1; + else + its_data.typer.collid_bits = 16; + + its_data.typer.hw_collections = + (typer >> GITS_TYPER_HWCOLLCNT_SHIFT) & 0xff; +
Quoted 8 lines
lib/arm/gic-v3-its.c line 31
Quoted 3 lines
lib/arm/gic-v3-its.c new file +3
-0+ its_data.typer.cct = typer & 0x4; + its_data.typer.virt_lpi = typer & 0x2; + its_data.typer.phys_lpi = typer & GITS_TYPER_PLPIS;Personally, mix using of GITS_TYPER_* macros and some magic constants to parse the TYPER makes it a bit difficult to review the code. Maybe we can have more such kinds of macros in the header file and get rid of all hardcoded numbers?
Sure I will clean that up.
Thanks!
Eric
Quoted 6 lines
Thanks,
Zenghui
Zenghui Yu
reviewerRe: [kvm-unit-tests PATCH 05/16] arm/arm64: ITS: Introspection tests
Quoted 5 lines · Auger Eric
Hi Zenghui,
Quoted 2 lines · Zenghui Yu
Hi Eric,
Quoted 8 lines
Quoted 2 lines
I have to admit that this is the first time I've looked into the kvm-unit-tests code, so only some minor comments inline :)
no problem. Thank you for looking at this.
By the way, with patch 16 I was able to test yout fix: "KVM: arm/arm64:
vgic: Don't rely on the wrong pending table". Reverting it produced an error.
which is great! Thanks for your work!
Zenghui
PATCH 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.
--- arm/gic.c | 20 ++++++++++ arm/unittests.cfg | 6 +++ lib/arm/asm/gic-v3-its.h | 17 ++++++++ lib/arm/gic-v3-its.c | 84 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 127 insertions(+)
arm/gic.c +20 -0
@@ -536,6 +536,22 @@ static void test_its_introspection(void) 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" , dev_baser->esz); +} +int main (int argc,char **argv) {if (!gic_init ()) {
@@ -571,6 +587,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 +17 -0
@@ -100,9 +100,23 @@ struct its_typer {bool virt_lpi; }; +struct its_baser { +unsigned int index; +int type; +u64 cache; +int shr; +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;
@@ -111,6 +125,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 +84 -0
101 lines not on this page · raw message
Signature · 1 line
2.20.1
Zenghui Yu
reviewerRe: [kvm-unit-tests PATCH 06/16] arm/arm64: ITS: Test BASER
Hi Eric,
Quoted 23 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]>--- arm/gic.c | 20 ++++++++++ arm/unittests.cfg | 6 +++ lib/arm/asm/gic-v3-its.h | 17 ++++++++ lib/arm/gic-v3-its.c | 84 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 127 insertions(+)arm/gic.c +4
-0@@ -536,6 +536,22 @@ static void test_its_introspection(void) typer->pta ? "Redist basse address" : "PE #"); } +static void test_its_baser (void ) +{ +struct its_baser *dev_baser, *coll_baser; +
arm/gic.c static void test_its_introspection(void) · line 552
Quoted 10 lines
arm/gic.c +10
-0+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" , dev_baser->esz);
s/dev_baser/coll_baser/
Quoted 38 lines
arm/gic.c +6
-0+} +int main (int argc,char **argv) {if (!gic_init ()) {@@ -571,6 +587,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.flatlib/arm/asm/gic-v3-its.h +0
-0
lib/arm/asm/gic-v3-its.h struct its_typer { · line 104
Quoted 5 lines
lib/arm/asm/gic-v3-its.h +2
-0@@ -100,9 +100,23 @@ struct its_typer {bool virt_lpi; }; +struct its_baser { +unsigned int index;
We've already maintained an array of GITS_BASERs, so 'index' is not needed.
Quoted 85 lines
lib/arm/asm/gic-v3-its.h +15
-0+int type; +u64 cache; +int shr; +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;@@ -111,6 +125,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 +42
-0@@ -4,6 +4,7 @@* This work is licensed under the terms of the GNU LGPL, version 2. */ #include <asm/gic.h> +#include <alloc_page.h> struct its_data its_data;@@ -31,11 +32,94 @@ void its_parse_typer(void) its_data.typer.phys_lpi = typer &GITS_TYPER_PLPIS ; } +int its_parse_baser (int i,struct its_baser *baser) +{ +void *reg_addr =gicv3_its_base () +GITS_BASER + i *8 ; +u64 val =readq (reg_addr); + +if (!val) { +memset (baser,0 ,sizeof (*baser)); +return -1 ; + } + + baser->valid = val &GITS_BASER_VALID ; + baser->indirect = val &GITS_BASER_INDIRECT ; + baser->type =GITS_BASER_TYPE (val); + baser->esz =GITS_BASER_ENTRY_SIZE (val); + baser->nr_pages =GITS_BASER_NR_PAGES (val); + baser->table_addr = val &GITS_BASER_PHYS_ADDR_MASK ; + baser->cache = (val >>GITS_BASER_INNER_CACHEABILITY_SHIFT ) & +GITS_BASER_CACHEABILITY_MASK ; +switch (val &GITS_BASER_PAGE_SIZE_MASK ) { +case GITS_BASER_PAGE_SIZE_4K : + baser->psz =SZ_4K ; +break ; +case GITS_BASER_PAGE_SIZE_16K : + baser->psz =SZ_16K ; +break ; +case GITS_BASER_PAGE_SIZE_64K : + baser->psz =SZ_64K ; +break ; +default : + baser->psz =SZ_64K ; + } + baser->shr = (val >>10 ) &0x3 ; +return 0 ; +} + +struct its_baser *its_lookup_baser (int type) +{ +int i; + +for (i =0 ; i <GITS_BASER_NR_REGS ; i++) { +struct its_baser *baser = &its_data.baser[i];
lib/arm/gic-v3-its.c void its_parse_typer(void) · line 85
Quoted 10 lines
lib/arm/gic-v3-its.c +8
-0+ +if (baser->type == type) +return baser; + } +return NULL ; +} +void its_init (void ) { +int i;
Please add a blank line here.
Quoted 12 lines
lib/arm/gic-v3-its.c +8
-0if (!its_data.base)return ;its_parse_typer (); +for (i =0 ; i <GITS_BASER_NR_REGS ; i++) +its_parse_baser (i, &its_data.baser[i]); +} + +void its_setup_baser (int i,struct its_baser *baser) +{ +unsigned long n = (baser->nr_pages * baser->psz) >>PAGE_SHIFT ; +unsigned long order =is_power_of_2 (n) ?fls (n) :fls (n) +1 ;
lib/arm/gic-v3-its.c void its_parse_typer(void) · line 107
Quoted 10 lines
lib/arm/gic-v3-its.c +10
-0+u64 val; + + baser->table_addr = (u64 )virt_to_phys (alloc_pages (order)); + + val = ((u64)baser->table_addr | + ((u64)baser->type << GITS_BASER_TYPE_SHIFT) | + ((u64)(baser->esz - 1) << GITS_BASER_ENTRY_SIZE_SHIFT) | + ((baser->nr_pages - 1) << GITS_BASER_PAGES_SHIFT) | + baser->cache | + baser->shr |
baser->cache << GITS_BASER_INNER_CACHEABILITY_SHIFT | baser->shr << 10 (GITS_BASER_SHAREABILITY_SHIFT) ?
Thanks,
Zenghui
Quoted 19 lines
lib/arm/gic-v3-its.c +16
-0+ (u64 )baser->indirect <<62 | + (u64)baser->valid << 63); + +switch (baser->psz) { +case SZ_4K : + val |=GITS_BASER_PAGE_SIZE_4K ; +break ; +case SZ_16K : + val |=GITS_BASER_PAGE_SIZE_16K ; +break ; +case SZ_64K : + val |=GITS_BASER_PAGE_SIZE_64K ; +break ; + } + +writeq (val,gicv3_its_base () +GITS_BASER + i *8 ); }
PATCH 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.
--- lib/arm/asm/gic-v3-its.h | 3 ++ lib/arm/asm/gic-v3.h | 79 ++++++++++++++++++++++++++++++++++++++++ lib/arm/gic-v3-its.c | 65 +++++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+)
lib/arm/asm/gic-v3-its.h +3 -0
@@ -128,6 +128,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 +79 -0
91 lines not on this page · raw message
lib/arm/gic-v3-its.c +65 -0
68 lines not on this page · raw message
Signature · 1 line
2.20.1
PATCH 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.
--- lib/arm/asm/gic-v3-its.h | 7 +++++++ lib/arm/gic-v3-its.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+)
lib/arm/asm/gic-v3-its.h +7 -0
@@ -113,10 +113,17 @@ 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; +struct its_cmd_block *cmd_readr; };extern struct its_data its_data;
lib/arm/gic-v3-its.c +37 -0
@@ -188,3 +188,40 @@ 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, tmp; + + its_data.cmd_base = (void *)virt_to_phys (alloc_pages (order)); + + cbaser = ((u64 )its_data.cmd_base | + GITS_CBASER_WaWb | + GITS_CBASER_InnerShareable | + (SZ_64K /SZ_4K -1 ) | +GITS_CBASER_VALID ); + +writeq (cbaser, its_data.base +GITS_CBASER ); + tmp =readq (its_data.base +GITS_CBASER ); + +if ((tmp ^ cbaser) &GITS_CBASER_SHAREABILITY_MASK ) { +if (!(tmp &GITS_CBASER_SHAREABILITY_MASK )) { + cbaser &= ~(GITS_CBASER_SHAREABILITY_MASK | +GITS_CBASER_CACHEABILITY_MASK ); + cbaser |= GITS_CBASER_nC; +writeq (cbaser, its_data.base +GITS_CBASER ); + } + } + + its_data.cmd_write = its_data.cmd_base; + its_data.cmd_readr = its_data.cmd_base; +writeq (0 , its_data.base +GITS_CWRITER ); +writeq (0 , its_data.base +GITS_CREADR ); +}
Signature · 1 line
2.20.1
Zenghui Yu
reviewerRe: [kvm-unit-tests PATCH 08/16] arm/arm64: ITS: Init the command queue
Hi Eric,
Quoted 20 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.
Signed-off-by Eric Auger <[email protected]>--- lib/arm/asm/gic-v3-its.h | 7 +++++++ lib/arm/gic-v3-its.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+)lib/arm/asm/gic-v3-its.h +1
-0@@ -113,10 +113,17 @@ struct its_baser {int esz; }; +struct its_cmd_block {
lib/arm/asm/gic-v3-its.h struct its_baser { · line 126
Quoted 10 lines
lib/arm/asm/gic-v3-its.h +6
-0+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; +struct its_cmd_block *cmd_readr;
I think we can just get rid of the 'cmd_readr'. As GITS_CREADR is generally manipulated by the ITS, and ...
Quoted 22 lines
lib/arm/asm/gic-v3-its.h +0
-0};extern struct its_data its_data;lib/arm/gic-v3-its.c +11
-0@@ -188,3 +188,40 @@ 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, tmp;
lib/arm/gic-v3-its.c void set_pending_table_bit(int rdist, int n, bool set) · line 211
Quoted 10 lines
lib/arm/gic-v3-its.c +10
-0+ + its_data.cmd_base = (void *)virt_to_phys (alloc_pages (order)); + + cbaser = ((u64 )its_data.cmd_base | + GITS_CBASER_WaWb | + GITS_CBASER_InnerShareable | + (SZ_64K /SZ_4K -1 ) | +GITS_CBASER_VALID ); + +writeq (cbaser, its_data.base +GITS_CBASER );
..."(CREADR) is cleared to 0 when a value is written to GITS_CBASER." -- from IHI0069E 9.19.3
Quoted 5 lines
lib/arm/gic-v3-its.c +5
-0+ tmp =readq (its_data.base +GITS_CBASER ); + +if ((tmp ^ cbaser) &GITS_CBASER_SHAREABILITY_MASK ) { +if (!(tmp &GITS_CBASER_SHAREABILITY_MASK )) { + cbaser &= ~(GITS_CBASER_SHAREABILITY_MASK |
lib/arm/gic-v3-its.c void set_pending_table_bit(int rdist, int n, bool set) · line 226
Quoted 10 lines
lib/arm/gic-v3-its.c +10
-0+ GITS_CBASER_CACHEABILITY_MASK); + cbaser |= GITS_CBASER_nC; +writeq (cbaser, its_data.base +GITS_CBASER ); + } + } + + its_data.cmd_write = its_data.cmd_base; + its_data.cmd_readr = its_data.cmd_base; +writeq (0 , its_data.base +GITS_CWRITER ); +writeq (0 , its_data.base +GITS_CREADR );
So this writeq() is also not needed.
Or I've just missed the point that this is done by intention to test "whether the GITS_CREADR implemented by KVM is Write Ignored"? If so, please ignore all of the comments above :)
Thanks,
Zenghui
Re: [kvm-unit-tests PATCH 08/16] arm/arm64: ITS: Init the command queue
Hi Zenghui,
Quoted 90 lines · Zenghui Yu
Hi Eric,
Quoted 19 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.
Signed-off-by Eric Auger <[email protected]>---
lib/arm/asm/gic-v3-its.h| 7 +++++++ lib/arm/gic-v3-its.c | 37 +++++++++++++++++++++++++++++++++++++2 files changed, 44 insertions(+)lib/arm/asm/gic-v3-its.h +0
-0@@ -113,10 +113,17 @@ struct its_baser { int esz; }; +struct its_cmd_block {lib/arm/asm/gic-v3-its.h struct its_baser { · line 125
Quoted 10 lines
lib/arm/asm/gic-v3-its.h +6
-0+ 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; + struct its_cmd_block *cmd_readr;I think we can just get rid of the '
cmd_readr'. AsGITS_CREADRis generally manipulated by the ITS, and ...Quoted 22 lines
lib/arm/asm/gic-v3-its.h +0
-0}; extern struct its_data its_data;lib/arm/gic-v3-its.c +0
-0@@ -188,3 +188,40 @@ void set_pending_table_bit(int rdist, int n, bool set) byte &= ~mask; *ptr = byte;}
lib/arm/gic-v3-its.c +11
-0+ +/** +* 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, tmp;lib/arm/gic-v3-its.c void set_pending_table_bit(int rdist, int n, bool set) · line 211
Quoted 10 lines
lib/arm/gic-v3-its.c +10
-0+ + its_data.cmd_base = (void *)virt_to_phys(alloc_pages(order)); + + cbaser = ((u64)its_data.cmd_base | + GITS_CBASER_WaWb | + GITS_CBASER_InnerShareable | + (SZ_64K / SZ_4K - 1) | + GITS_CBASER_VALID); + + writeq(cbaser, its_data.base + GITS_CBASER);..."(CREADR) is cleared to 0 when a value is written to
GITS_CBASER." -- from IHI0069E 9.19.3Quoted 5 lines
+ tmp =
readq(its_data.base + GITS_CBASER);lib/arm/gic-v3-its.c +4
-0+ + if ((tmp ^ cbaser) & GITS_CBASER_SHAREABILITY_MASK) { + if (!(tmp & GITS_CBASER_SHAREABILITY_MASK)) { + cbaser &= ~(GITS_CBASER_SHAREABILITY_MASK |lib/arm/gic-v3-its.c void set_pending_table_bit(int rdist, int n, bool set) · line 226
Quoted 10 lines
lib/arm/gic-v3-its.c +10
-0+ GITS_CBASER_CACHEABILITY_MASK); + cbaser |= GITS_CBASER_nC; + writeq(cbaser, its_data.base + GITS_CBASER); + } + } + + its_data.cmd_write = its_data.cmd_base; + its_data.cmd_readr = its_data.cmd_base; + writeq(0, its_data.base + GITS_CWRITER); + writeq(0, its_data.base + GITS_CREADR);So this
writeq()is also not needed.
Quoted 3 lines
Or I've just missed the point that this is done by intention to test "whether the
GITS_CREADRimplemented by KVM is Write Ignored"? If so, please ignore all of the comments above :)
No I must admit this was not done on purpose. I can remove it from the its_data struct at the moment.
Thanks
Eric
Quoted 5 lines
Thanks,
Zenghui
PATCH 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
@@ -138,6 +138,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
@@ -225,3 +225,21 @@ void init_cmd_queue(void)writeq (0 , its_data.base +GITS_CWRITER );writeq (0 , its_data.base +GITS_CREADR ); } + +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
PATCH 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 | 41 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+)
lib/arm/asm/gic-v3-its.h +1 -0
@@ -139,6 +139,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 +41 -0
44 lines not on this page · raw message
Signature · 1 line
2.20.1
PATCH 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).
---
--- 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
@@ -87,6 +87,9 @@#define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1ULL << 0) +#define GITS_MAX_DEVICES 8 +#define GITS_MAX_COLLECTIONS 8 +struct its_typer {unsigned int ite_size;unsigned int eventid_bits;
@@ -117,6 +120,17 @@ 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;
@@ -124,6 +138,10 @@ struct its_data {struct its_cmd_block *cmd_base;struct its_cmd_block *cmd_write;struct its_cmd_block *cmd_readr; +struct its_device devices[GITS_MAX_DEVICES ]; +u32 nb_devices;/* Allocated Devices */ +struct its_collection collections[GITS_MAX_COLLECTIONS ]; +u32 nb_collections;/* Allocated Collections */ };extern struct its_data its_data;
@@ -140,6 +158,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
Zenghui Yu
reviewerRe: [kvm-unit-tests PATCH 11/16] arm/arm64: ITS: Device and collection Initialization
Hi Eric,
Quoted 49 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]>---
--- 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 +14
-0@@ -87,6 +87,9 @@#define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1ULL << 0) +#define GITS_MAX_DEVICES 8 +#define GITS_MAX_COLLECTIONS 8 +struct its_typer {unsigned int ite_size;unsigned int eventid_bits;@@ -117,6 +120,17 @@ 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;
lib/arm/asm/gic-v3-its.h struct its_data { · line 144
Quoted 7 lines
lib/arm/asm/gic-v3-its.h +4
-0@@ -124,6 +138,10 @@ struct its_data {struct its_cmd_block *cmd_base;struct its_cmd_block *cmd_write;struct its_cmd_block *cmd_readr; +struct its_device devices[GITS_MAX_DEVICES ]; +u32 nb_devices;/* Allocated Devices */ +struct its_collection collections[GITS_MAX_COLLECTIONS ]; +u32 nb_collections;/* Allocated Collections */
('nr_*' may be the more widely used one.)
Quoted 30 lines
lib/arm/asm/gic-v3-its.h +2
-0};extern struct its_data its_data;@@ -140,6 +158,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 +10
-0@@ -284,3 +284,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.nb_devices >=GITS_MAX_DEVICES ) +report_abort ("%s redimension GITS_MAX_DEVICES" , __func__); +
lib/arm/gic-v3-its.c void its_enable_defaults(void) · line 306
Quoted 10 lines
lib/arm/gic-v3-its.c +10
-0+ baser =its_lookup_baser (GITS_BASER_TYPE_DEVICE ); +if (!baser) +return NULL ; + + new = &its_data.devices[its_data.nb_devices]; + + new->device_id = device_id; + new->nr_ites = nr_ites; + + n = (baser->esz * nr_ites) >>PAGE_SHIFT ;
baser->esz is GITS_BASER.Entry_Size, which indicates the size of Device Table entry.
We're allocating ITT for this device now, shouldn't we use its_data.typer.esz?
Thanks,
Zenghui
Quoted 27 lines
lib/arm/gic-v3-its.c +26
-0+ order =is_power_of_2 (n) ?fls (n) :fls (n) +1 ; + new->itt = (void *)virt_to_phys (alloc_pages (order)); + + its_data.nb_devices++; +return new; +} + +struct its_collection *its_create_collection (u32 col_id,u32 pe) +{ +struct its_collection *new; + +if (its_data.nb_collections >=GITS_MAX_COLLECTIONS ) +report_abort ("%s redimension GITS_MAX_COLLECTIONS" , __func__); + + new = &its_data.collections[its_data.nb_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.nb_collections++; +return new; +}
Re: [kvm-unit-tests PATCH 11/16] arm/arm64: ITS: Device and collection Initialization
Hi Zenghui,
Quoted 94 lines · Zenghui Yu
Hi Eric,
Quoted 46 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]>---
---
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 +0
-0@@ -87,6 +87,9 @@ #define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1ULL << 0)+#define GITS_MAX_DEVICES 8
lib/arm/asm/gic-v3-its.h +2
-0+#define GITS_MAX_COLLECTIONS 8 +struct
its_typer{
unsigned intite_size;
unsigned inteventid_bits;lib/arm/asm/gic-v3-its.h +10
-0@@ -117,6 +120,17 @@ 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;lib/arm/asm/gic-v3-its.h struct its_data { · line 144
Quoted 7 lines
lib/arm/asm/gic-v3-its.h +4
-0@@ -124,6 +138,10 @@ struct its_data { struct its_cmd_block *cmd_base; struct its_cmd_block *cmd_write; struct its_cmd_block *cmd_readr; + struct its_device devices[GITS_MAX_DEVICES]; + u32 nb_devices; /* Allocated Devices */ + struct its_collection collections[GITS_MAX_COLLECTIONS]; + u32 nb_collections; /* Allocated Collections */('nr_*' may be the more widely used one.)
Quoted 35 lines
lib/arm/asm/gic-v3-its.h +2
-0}; extern struct its_data its_data;@@ -140,6 +158,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 +17
-0@@ -284,3 +284,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.nb_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.nb_devices]; + + new->device_id = device_id;
Quoted 8 lines
lib/arm/gic-v3-its.c void its_enable_defaults(void) · line 306
Quoted 3 lines
lib/arm/gic-v3-its.c +3
-0+ new->nr_ites = nr_ites; + + n = (baser->esz * nr_ites) >> PAGE_SHIFT;
baser->eszis GITS_BASER.Entry_Size, which indicates the size of Device Table entry.
We're allocating ITT for this device now, shouldn't we use its_data.typer.esz?
Yes you're definitively right. I should use its_data.typer.ite_size.
Thank you!
Eric
Quoted 33 lines
Thanks,
ZenghuiQuoted 27 lines
lib/arm/gic-v3-its.c +26
-0+ order = is_power_of_2(n) ? fls(n) : fls(n) + 1; + new->itt = (void *)virt_to_phys(alloc_pages(order)); + + its_data.nb_devices++; + return new; +} + +struct its_collection *its_create_collection (u32 col_id,u32 pe) +{ + struct its_collection *new; + + if (its_data.nb_collections >= GITS_MAX_COLLECTIONS) + report_abort("%s redimension GITS_MAX_COLLECTIONS", __func__); + + new = &its_data.collections[its_data.nb_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.nb_collections++; + return new; +}
PATCH 12/16 arm/arm64: ITS: commands
In reply to Eric AugerImplement main ITS commands. The code is largely inherited from the ITS driver.
--- arm/Makefile.common | 2 +- lib/arm/asm/gic-v3-its.h | 36 +++ lib/arm/gic-v3-its-cmd.c | 462 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 499 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 +36 -0
@@ -90,6 +90,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;
@@ -161,5 +179,23 @@ 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); +extern void its_print_cmd_state (void ); + +#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 +462 -0
462 lines not on this page · raw message
Signature · 1 line
2.20.1
Zenghui Yu
reviewerRe: [kvm-unit-tests PATCH 12/16] arm/arm64: ITS: commands
Hi Eric,
Quoted 5 lines · Eric Auger
Implement main ITS commands. The code is largely inherited from the ITS driver.
Signed-off-by Eric Auger <[email protected]>---
[...]
Quoted 11 lines
lib/arm/asm/gic-v3-its.h +3
-0@@ -161,5 +179,23 @@ 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,
lib/arm/asm/gic-v3-its.h extern void its_enable_defaults(void); · line 194
Quoted 10 lines
lib/arm/asm/gic-v3-its.h +10
-0+ 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); +extern void its_print_cmd_state (void );
This function is not used by later patches, I guess it's mostly used for debug.
(Assuming the Linux ITS driver has done the right thing ;-), I just skip looking at this patch.)
Thanks,
Zenghui
PATCH 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,
@@ -552,6 +609,120 @@ static void test_its_baser(void)report_info ("collection baser entry_size = 0x%x" , dev_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 ()) {
@@ -582,6 +753,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
@@ -162,6 +162,16 @@ struct its_data {u32 nb_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)
@@ -178,6 +188,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
PATCH 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 14/16] arm/run: Allow Migration tests
Quoted 53 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]>--- 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@@ -87,6 +87,19 @@ void puts(const char *s)spin_unlock (&uart_lock); }
lib/arm/io.c void puts(const char *s) · line 98
Quoted 10 lines
lib/arm/io.c +9
-0+/* +* Minimalist implementation for migration completion detection. +* Needs to be improved for more advanced Rx cases +*/ +int __getchar (void ) +{ +int ret; + + ret =readb (uart0_base);
Duplicated space before "readb"...
lib/arm/io.c void puts(const char *s) · line 105
Quoted 8 lines
lib/arm/io.c +4
-0+if (!ret) +return -1 ; +return ret; +}/* * Defining halt to take 'code' as an argument guarantees that it will
... but apart from that nit:
PATCH 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
@@ -642,13 +642,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 */ );
@@ -662,8 +668,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);
@@ -674,6 +678,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 );
@@ -722,6 +743,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) {
@@ -757,6 +800,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
@@ -206,6 +206,8 @@ 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 void its_print_cmd_state (void ); +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
@@ -330,3 +330,25 @@ struct its_collection *its_create_collection(u32 col_id, u32 pe) its_data.nb_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 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 );
@@ -642,6 +655,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
@@ -766,6 +791,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 ()) {
@@ -804,6 +944,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