diff mbox series

[kvm-unit-tests,v2,06/16] arm/arm64: ITS: Test BASER

Message ID 20200110145412.14937-7-eric.auger@redhat.com
State New
Headers show
Series arm/arm64: Add ITS tests | expand

Commit Message

Eric Auger Jan. 10, 2020, 2:54 p.m. UTC
Add helper routines to parse and set up BASER registers.
Add a new test dedicated to BASER<n> accesses.

Signed-off-by: Eric Auger <eric.auger@redhat.com>

---

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(-)

Comments

Andrew Jones Jan. 13, 2020, 5:21 p.m. UTC | #1
On Fri, Jan 10, 2020 at 03:54:02PM +0100, Eric Auger wrote:
> Add helper routines to parse and set up BASER registers.
> Add a new test dedicated to BASER<n> accesses.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> 
> ---
> 
> 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(-)
> 
> diff --git a/arm/gic.c b/arm/gic.c
> index adeb981..3597ac3 100644
> --- a/arm/gic.c
> +++ b/arm/gic.c
> @@ -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]);
>  	}
> diff --git a/arm/unittests.cfg b/arm/unittests.cfg
> index bd20460..2234a0f 100644
> --- a/arm/unittests.cfg
> +++ b/arm/unittests.cfg
> @@ -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
Eric Auger Jan. 15, 2020, 5:16 p.m. UTC | #2
Hi,

On 1/13/20 6:21 PM, Andrew Jones wrote:
> On Fri, Jan 10, 2020 at 03:54:02PM +0100, Eric Auger wrote:
>> Add helper routines to parse and set up BASER registers.
>> Add a new test dedicated to BASER<n> accesses.
>>
>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>>
>> ---
>>
>> 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(-)
>>
>> diff --git a/arm/gic.c b/arm/gic.c
>> index adeb981..3597ac3 100644
>> --- a/arm/gic.c
>> +++ b/arm/gic.c
>> @@ -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]);
>>  	}
>> diff --git a/arm/unittests.cfg b/arm/unittests.cfg
>> index bd20460..2234a0f 100644
>> --- a/arm/unittests.cfg
>> +++ b/arm/unittests.cfg
>> @@ -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.
Not really. To me it is easier to debug and analyze when the fail
though. I will merge both.

Thanks

Eric
> 
> Thanks,
> drew
>
diff mbox series

Patch

diff --git a/arm/gic.c b/arm/gic.c
index adeb981..3597ac3 100644
--- a/arm/gic.c
+++ b/arm/gic.c
@@ -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]);
 	}
diff --git a/arm/unittests.cfg b/arm/unittests.cfg
index bd20460..2234a0f 100644
--- a/arm/unittests.cfg
+++ b/arm/unittests.cfg
@@ -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
diff --git a/lib/arm/asm/gic-v3-its.h b/lib/arm/asm/gic-v3-its.h
index 8816d57..5a4dfe9 100644
--- a/lib/arm/asm/gic-v3-its.h
+++ b/lib/arm/asm/gic-v3-its.h
@@ -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_ */
diff --git a/lib/arm/gic-v3-its.c b/lib/arm/gic-v3-its.c
index ce607bb..79946c3 100644
--- a/lib/arm/gic-v3-its.c
+++ b/lib/arm/gic-v3-its.c
@@ -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;
 
@@ -29,11 +30,90 @@  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;
+	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;
+	}
+	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];
+
+		if (baser->type == type)
+			return baser;
+	}
+	return NULL;
+}
+
 void its_init(void)
 {
+	int i;
+
 	if (!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;
+	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)	|
+		(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);
 }