Re: [kvm-unit-tests PATCH] s390x: IEP tests

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

 



On 16.05.2018 16:13, David Hildenbrand wrote:
> On 16.05.2018 11:10, Janosch Frank wrote:
>> From: Janosch Frank <frankja@xxxxxxxxxxxxxxxxxx>
>>
>> Tests no-execute (Instruction Execution Protection) DAT protection.
>>
>> Signed-off-by: Janosch Frank <frankja@xxxxxxxxxxxxx>
>> ---
>>
>> This was originally part of my first patchset, but was pushed back
>> after David introduced virtual memory allocation. It's more a RFC, as
>> I'm not completely happy with the memory management manipulation I do.
>>
>> ---
>>  lib/s390x/asm/interrupt.h |  1 +
>>  lib/s390x/interrupt.c     |  9 +++++
>>  s390x/Makefile            |  1 +
>>  s390x/iep.c               | 89 +++++++++++++++++++++++++++++++++++++++++++++++
>>  s390x/unittests.cfg       |  4 +++
>>  5 files changed, 104 insertions(+)
>>  create mode 100644 s390x/iep.c
>>
>> diff --git a/lib/s390x/asm/interrupt.h b/lib/s390x/asm/interrupt.h
>> index 3ccc8e3..39ae534 100644
>> --- a/lib/s390x/asm/interrupt.h
>> +++ b/lib/s390x/asm/interrupt.h
>> @@ -15,6 +15,7 @@ void handle_pgm_int(void);
>>  void expect_pgm_int(void);
>>  uint16_t clear_pgm_int(void);
>>  void check_pgm_int_code(uint16_t code);
>> +void register_pgm_handler(void (*handler)(struct lowcore *));
>>  
>>  /* Activate low-address protection */
>>  static inline void low_prot_enable(void)
>> diff --git a/lib/s390x/interrupt.c b/lib/s390x/interrupt.c
>> index 56c7603..fe6cdba 100644
>> --- a/lib/s390x/interrupt.c
>> +++ b/lib/s390x/interrupt.c
>> @@ -15,6 +15,7 @@
>>  
>>  static bool pgm_int_expected;
>>  static struct lowcore *lc;
>> +static void (*custom_pgm_handler)(struct lowcore *);
>>  
>>  void expect_pgm_int(void)
>>  {
>> @@ -41,8 +42,16 @@ void check_pgm_int_code(uint16_t code)
>>  	       code == lc->pgm_int_code, code, lc->pgm_int_code);
>>  }
>>  
>> +void register_pgm_handler(void (*handler)(struct lowcore *))
>> +{
>> +	custom_pgm_handler = handler;
>> +}
>> +
>>  static void fixup_pgm_int(void)
>>  {
>> +	if (custom_pgm_handler)
>> +		return custom_pgm_handler(lc);
>> +
>>  	switch (lc->pgm_int_code) {
>>  	case PGM_INT_CODE_PRIVILEGED_OPERATION:
>>  		/* Normal operation is in supervisor state, so this exception
>> diff --git a/s390x/Makefile b/s390x/Makefile
>> index abc3242..d4275a1 100644
>> --- a/s390x/Makefile
>> +++ b/s390x/Makefile
>> @@ -9,6 +9,7 @@ tests += $(TEST_DIR)/pfmf.elf
>>  tests += $(TEST_DIR)/cmm.elf
>>  tests += $(TEST_DIR)/vector.elf
>>  tests += $(TEST_DIR)/gs.elf
>> +tests += $(TEST_DIR)/iep.elf
>>  
>>  all: directories test_cases
>>  
>> diff --git a/s390x/iep.c b/s390x/iep.c
>> new file mode 100644
>> index 0000000..87f3007
>> --- /dev/null
>> +++ b/s390x/iep.c
>> @@ -0,0 +1,89 @@
>> +/*
>> + * Instruction Execution Prevention (IEP) DAT test.
>> + *
>> + * Copyright (c) 2018 IBM Corp
>> + *
>> + * Authors:
>> + *	Janosch Frank <frankja@xxxxxxxxxxxxx>
>> + *
>> + * 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 <vmalloc.h>
>> +#include <asm/facility.h>
>> +#include <asm/interrupt.h>
>> +#include <asm/page.h>
>> +#include <asm/pgtable.h>
>> +#include <asm-generic/barrier.h>
>> +
>> +static pteval_t *get_pte(pgd_t *pgtable, uintptr_t vaddr)
>> +{
>> +	pgd_t *pgd = pgd_offset(pgtable, vaddr);
>> +	p4d_t *p4d = p4d_offset(pgd, vaddr);
>> +	pud_t *pud = pud_offset(p4d, vaddr);
>> +	pmd_t *pmd = pmd_offset(pud, vaddr);
>> +	pte_t *pte = pte_offset(pmd, vaddr);
>> +
>> +	return &pte_val(*pte);
>> +}
> 
> You could factor that out into some sort of
> 
> protect_range() / protect_page()
> unprotect_range() / unprotect_page()

Would the page protection be enough for now?
Then I'd add that to our mmu.c

> 
> And implement iep handling directly in the core. The handling of
> resetting the old psw seems to be generic enough.

It will break two tests, that's why I added a custom handler.

> 
> The all you would have to do is enable iep and check for
> PGM_INT_CODE_PROTECTION
> 
>> +
>> +void iep_handler(struct lowcore *lc)
>> +{
>> +	if (lc->pgm_int_code == PGM_INT_CODE_PROTECTION)
>> +		lc->pgm_old_psw.addr = lc->sw_int_grs[14];
>> +}
>> +
>> +static void test_iep(void)
>> +{
>> +	uint16_t *code;
>> +	uint8_t *iepbuf = 0;
>> +	void (*fn)(void);
>> +	pteval_t *pte;
>> +	pgd_t *pgtable = (pgd_t *)(stctg(1) & ~(ASCE_DT_REGION1 | REGION_TABLE_LENGTH));
>> +
>> +
>> +	/* Enable IEP */
>> +	ctl_set_bit(0, 20);
>> +
>> +	/* Get and protect a page with the IEP bit */
>> +	iepbuf = alloc_page();
>> +	pte = get_pte(pgtable, (uintptr_t)iepbuf);
>> +	ipte((uintptr_t)iepbuf, pte);
>> +	*pte |= PAGE_ENTRY_IEP;
>> +	*pte &= ~PAGE_ENTRY_I;
>> +	mb();
>> +
>> +	register_pgm_handler(&iep_handler);
>> +
>> +	/* Code branches into r14 which contains the return address. */
>> +	code = (uint16_t *)iepbuf;
>> +	*code = 0x07fe;
>> +	asm volatile("" : : "m" (code));
>> +	fn = (void *)code;
>> +	mb();
>> +
>> +	expect_pgm_int();
>> +	/* Jump into protected page */
>> +	fn();
>> +	check_pgm_int_code(PGM_INT_CODE_PROTECTION);
>> +	ctl_clear_bit(0, 20);
>> +}
>> +
>> +int main(void)
>> +{
>> +	bool has_iep = test_facility(130);
>> +
>> +	report_prefix_push("iep");
>> +	report_xfail("DAT IEP available", !has_iep, has_iep);
>> +	if (!has_iep)
>> +		goto done;
>> +
>> +	/* Setup DAT 1:1 mapping and memory management */
>> +	setup_vm();
>> +	test_iep();
>> +
>> +done:
>> +	report_prefix_pop();
>> +	return report_summary();
>> +}
>> diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
>> index ff7eea1..760402e 100644
>> --- a/s390x/unittests.cfg
>> +++ b/s390x/unittests.cfg
>> @@ -55,3 +55,7 @@ file = vector.elf
>>  
>>  [gs]
>>  file = gs.elf
>> +
>> +[iep]
>> +file = iep.elf
>> +
>>
> 
> 


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