Re: [kvm-unit-tests PATCH 5/8] s390x: Add pfmf tests

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

 



On 14.03.2018 05:59, Thomas Huth wrote:
> On 13.03.2018 13:01, Janosch Frank wrote:
>> Perform Frame Management Functions (pfmf) is an instruction that sets
>> storage keys or clears memory for frames in the size of 4k, 1m and
>> 2g. Hence it's quite complex and deserves some testing.
>>
>> Signed-off-by: Janosch Frank <frankja@xxxxxxxxxxxxxxxxxx>
>> ---
>>  s390x/Makefile      |   1 +
>>  s390x/pfmf.c        | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  s390x/unittests.cfg |   3 ++
>>  3 files changed, 147 insertions(+)
>>  create mode 100644 s390x/pfmf.c
>>
>> diff --git a/s390x/Makefile b/s390x/Makefile
>> index bc5dd91..438c6b2 100644
>> --- a/s390x/Makefile
>> +++ b/s390x/Makefile
>> @@ -5,6 +5,7 @@ tests += $(TEST_DIR)/sieve.elf
>>  tests += $(TEST_DIR)/sthyi.elf
>>  tests += $(TEST_DIR)/skey.elf
>>  tests += $(TEST_DIR)/diag10.elf
>> +tests += $(TEST_DIR)/pfmf.elf
>>  
>>  all: directories test_cases
>>  
>> diff --git a/s390x/pfmf.c b/s390x/pfmf.c
>> new file mode 100644
>> index 0000000..fe31a82
>> --- /dev/null
>> +++ b/s390x/pfmf.c
>> @@ -0,0 +1,143 @@
>> +/*
>> + * Perform Frame Management Function (pfmf) tests
>> + *
>> + * Copyright (c) 2017 IBM
>> + *
>> + * Authors:
>> + *  Janosch Frank <frankja@xxxxxxxxxxxxxxxxxx>
>> + *
>> + * This code is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU Library General Public License version 2.
>> + */
>> +#include <libcflat.h>
>> +#include <asm/asm-offsets.h>
>> +#include <asm/interrupt.h>
>> +#include <asm/page.h>
>> +#include <asm/facility.h>
>> +#include <asm/mem.h>
>> +
>> +#define FSC_4K 0
>> +#define FSC_1M 1
>> +#define FSC_2G 3
> 
> According to my version of the PoP, FSC_2G should be 2 instead?

Yes, it should be 2.
Well it seems, I never tested 2G and it came to haunt me.

> 
>> +union r1 {
>> +	struct {
>> +		unsigned long pad0 : 32;
>> +		unsigned long pad1 : 12;
>> +		unsigned long pad_fmfi : 2;
>> +		unsigned long sk : 1; /* set key*/
>> +		unsigned long cf : 1; /* clear frame */
>> +		unsigned long ui : 1; /* usage indication */
>> +		unsigned long fsc : 3;
>> +		unsigned long pad2 : 1;
>> +		unsigned long mr : 1;
>> +		unsigned long mc : 1;
>> +		unsigned long pad3 : 1;
>> +		unsigned long key : 8; /* storage keys */
>> +	} reg;
>> +	unsigned long val;
>> +};
>> +
>> +static uint8_t pagebuf[PAGE_SIZE * 256] __attribute__((aligned(PAGE_SIZE * 256)));
>> +
>> +static inline unsigned long pfmf(unsigned long r1, unsigned long paddr)
>> +{
>> +	register uint64_t addr asm("1") = paddr;
>> +
>> +	asm volatile(".insn rrf,0xb9af0000,%[r1],%[addr],0,0"
> 
> PFMF is only "rre", not "rrf". Then you can also omit the ",0,0" here.
> 
>> +		     : [addr] "+a" (addr) : [r1] "d" (r1));
> 
> Since pfmf can be used to clear memory, you should add "memory" to the
> clobber list.

Good catch

> 
>> +	return addr;
>> +}
>> +
>> +static void test_priv(void)
>> +{
>> +	expect_pgm_int();
>> +	enter_pstate();
>> +	pfmf(0, (unsigned long) pagebuf);
>> +	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
>> +}
>> +
>> +static void test_4k_key(void)
>> +{
>> +	union r1 r1;
>> +	union skey skey;
>> +
>> +	r1.val = 0;
>> +	r1.reg.sk = 1;
>> +	r1.reg.fsc = FSC_4K;
>> +	r1.reg.key = 0x30;
>> +	pfmf(r1.val, (unsigned long) pagebuf);
>> +	skey.val = get_storage_key((unsigned long) pagebuf);
>> +	report("set 4k", skey.val == 0x30);
>> +}
>> +
>> +static void test_1m_key(void)
>> +{
>> +	int i;
>> +	union r1 r1;
>> +
>> +	if (!test_facility(8))
>> +		return;
> 
> You already checked that in the main() function, no need to check it
> here again.

Ugh, yes.

> 
>> +	r1.val = 0;
>> +	r1.reg.sk = 1;
>> +	r1.reg.fsc = FSC_1M;
>> +	r1.reg.key = 0x30;
>> +	pfmf(r1.val, (unsigned long) pagebuf);
>> +	for (i = 0; i < 256; i++) {
>> +		if (get_storage_key((unsigned long) pagebuf + i * PAGE_SIZE) != 0x30) {
>> +			report("set 1M", false);
>> +			return;
>> +		}
>> +	}
>> +	report("set 1M", true);
>> +}
>> +
>> +static void test_4k_clear(void)
>> +{
>> +	union r1 r1;
>> +
>> +	r1.val = 0;
>> +	r1.reg.cf = 1;
>> +	r1.reg.fsc = FSC_4K;
>> +
>> +	memset(pagebuf, 42, PAGE_SIZE);
>> +	pfmf(r1.val, (unsigned long) pagebuf);
>> +	report("clear 4k", !memcmp(pagebuf, pagebuf + PAGE_SIZE, PAGE_SIZE));
>> +}
>> +
>> +static void test_1m_clear(void)
>> +{
>> +	int i;
>> +	union r1 r1;
>> +	unsigned long sum = 0;
>> +
>> +	r1.val = 0;
>> +	r1.reg.cf = 1;
>> +	r1.reg.fsc = FSC_1M;
>> +
>> +	memset(pagebuf, 42, PAGE_SIZE * 256);
>> +	pfmf(r1.val, (unsigned long) pagebuf);
>> +	for (i = 0; i < PAGE_SIZE * 256; i++)
>> +		sum += pagebuf[i];
> 
> Maybe better use "|=" instead of "+=" to avoid that the sum wraps around
> to 0 again by accident.

Sure

> 
>> +	report("clear 1m", !sum);
>> +}
>> +
>> +int main(void)
>> +{
>> +	if (!test_facility(8)) {
>> +		printf("EDAT facility not available, hence pfmf is not available.");
>> +		return 0;
>> +	}
>> +
>> +	report_prefix_push("pfmf");
>> +	test_priv();
>> +	/* Force the buffer pages in */
>> +	memset(pagebuf, 0, PAGE_SIZE * 256);
>> +
>> +	test_4k_key();
>> +	test_1m_key();
>> +	test_4k_clear();
>> +	test_1m_clear();
>> +	return report_summary();
>> +}
> 
>  Thomas
> 


Attachment: signature.asc
Description: OpenPGP digital signature


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

  Powered by Linux