On 06/11/2018 12:41 PM, Thomas Huth wrote: > On 11.06.2018 11:01, Janosch Frank wrote: >> From: Janosch Frank <frankja@xxxxxxxxxxxxxxxxxx> >> >> Tests no-execute (Instruction Execution Protection) DAT protection. >> >> Signed-off-by: Janosch Frank <frankja@xxxxxxxxxxxxxxxxxx> >> --- >> lib/s390x/interrupt.c | 6 +++++ >> lib/s390x/mmu.c | 46 ++++++++++++++++++++++++++++++++++++-- >> lib/s390x/mmu.h | 20 +++++++++++++++++ >> s390x/Makefile | 1 + >> s390x/iep.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ >> s390x/unittests.cfg | 4 ++++ >> 6 files changed, 137 insertions(+), 2 deletions(-) >> create mode 100644 lib/s390x/mmu.h >> create mode 100644 s390x/iep.c >> >> diff --git a/lib/s390x/interrupt.c b/lib/s390x/interrupt.c >> index 56c7603..bc44e3a 100644 >> --- a/lib/s390x/interrupt.c >> +++ b/lib/s390x/interrupt.c >> @@ -51,6 +51,12 @@ static void fixup_pgm_int(void) >> */ >> lc->pgm_old_psw.mask &= ~PSW_MASK_PSTATE; >> break; >> + case PGM_INT_CODE_PROTECTION: >> + /* Handling for iep.c test case. */ >> + if (lc->trans_exc_id & 0x80UL && lc->trans_exc_id & 0x04UL && >> + !(lc->trans_exc_id & 0x08UL)) > > Nit / bikeshedding: It's IMHO a little bit nicer to test all three bits > at once: > > if ((lc->trans_exc_id & 0x8c) == 0x84) > > [...] >> diff --git a/s390x/iep.c b/s390x/iep.c >> new file mode 100644 >> index 0000000..e4abc72 >> --- /dev/null >> +++ b/s390x/iep.c >> @@ -0,0 +1,62 @@ >> +/* >> + * Instruction Execution Prevention (IEP) DAT test. >> + * >> + * Copyright (c) 2018 IBM Corp >> + * >> + * Authors: >> + * Janosch Frank <frankja@xxxxxxxxxx> >> + * >> + * 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 <mmu.h> >> +#include <asm/pgtable.h> >> +#include <asm-generic/barrier.h> >> + >> +static void test_iep(void) >> +{ >> + uint16_t *code; >> + uint8_t *iepbuf = NULL; >> + void (*fn)(void); >> + >> + /* Enable IEP */ >> + ctl_set_bit(0, 20); >> + >> + /* Get and protect a page with the IEP bit */ >> + iepbuf = alloc_page(); >> + protect_page(iepbuf, PAGE_ENTRY_IEP); >> + >> + /* Code branches into r14 which contains the return address. */ >> + code = (uint16_t *)iepbuf; >> + *code = 0x07fe; >> + fn = (void *)code; > > Not sure if I've got Christian's comment wrt to ipte right, but if I did > (Christian, please correct me if I'm wrong), I think it's better to move > the "protect_page(iepbuf, PAGE_ENTRY_IEP)" here, so that the ipte is > called after you've modified the contents of the page. Not necessary. As I said we only need to flush the TLB while changing the page table. The page content is fine as is.