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. > + expect_pgm_int(); > + /* Jump into protected page */ > + fn(); > + check_pgm_int_code(PGM_INT_CODE_PROTECTION); > + unprotect_page(iepbuf, PAGE_ENTRY_IEP); > + 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 > + Nit: "git am" complains about the trailing empty line here. (No need to resend just because of this nit, but in case Christian confirms the issue with ipte, please fix this as well). Thomas