On Mon, 23 May 2022 15:24:04 +0200 Janis Schoetterl-Glausch <scgl@xxxxxxxxxxxxx> wrote: > On a protection exception, test that the Translation-Exception > Identification (TEID) values are correct given the circumstances of the > particular test. > The meaning of the TEID values is dependent on the installed > suppression-on-protection facility. > > Signed-off-by: Janis Schoetterl-Glausch <scgl@xxxxxxxxxxxxx> > --- > s390x/skey.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++----- > 1 file changed, 69 insertions(+), 6 deletions(-) > > diff --git a/s390x/skey.c b/s390x/skey.c > index 42bf598c..5e234cde 100644 > --- a/s390x/skey.c > +++ b/s390x/skey.c > @@ -8,6 +8,7 @@ > * Janosch Frank <frankja@xxxxxxxxxxxxxxxxxx> > */ > #include <libcflat.h> > +#include <asm/arch_def.h> > #include <asm/asm-offsets.h> > #include <asm/interrupt.h> > #include <vmalloc.h> > @@ -158,6 +159,68 @@ static void test_test_protection(void) > report_prefix_pop(); > } > > +enum access { > + ACC_STORE = 1, > + ACC_FETCH = 2, > + ACC_UPDATE = 3, > +}; > + > +enum protection { > + PROT_STORE = 1, > + PROT_FETCH_STORE = 3, > +}; > + > +static void check_key_prot_exc(enum access access, enum protection prot) > +{ > + union teid teid; > + int access_code; > + > + check_pgm_int_code(PGM_INT_CODE_PROTECTION); > + report_prefix_push("TEID"); > + teid.val = lowcore.trans_exc_id; > + switch (get_supp_on_prot_facility()) { > + case SOP_NONE: > + case SOP_BASIC: > + break; for basic you should check for sop_teid_predictable and sop_acc_list > + case SOP_ENHANCED_1: > + report(!teid.esop1_acc_list_or_dat, "valid protection code"); actually, both values of esop1_acc_list_or_dat are wrong, since we're expecting neither an access list nor a dat exception. you need to check for esop1_teid_predictable instead (which you need to add, see comment in that patchseries) > + break; > + case SOP_ENHANCED_2: > + switch (teid_esop2_prot_code(teid)) { > + case PROT_KEY: > + access_code = teid.acc_exc_f_s; is the f/s feature guaranteed to be present when we have esop2? can the f/s feature be present with esop1 or basic sop? > + > + switch (access_code) { > + case 0: > + report_pass("valid access code"); > + break; > + case 1: > + case 2: > + report((access & access_code) && (prot & access_code), > + "valid access code"); > + break; > + case 3: > + /* > + * This is incorrect in that reserved values > + * should be ignored, but kvm should not return > + * a reserved value and having a test for that > + * is more valuable. > + */ > + report_fail("valid access code"); > + break; > + } > + /* fallthrough */ > + case PROT_KEY_LAP: > + report_pass("valid protection code"); > + break; > + default: > + report_fail("valid protection code"); > + } > + break; > + } > + report_prefix_pop(); > +} > + > /* > * Perform STORE CPU ADDRESS (STAP) instruction while temporarily executing > * with access key 1. > @@ -199,7 +262,7 @@ static void test_store_cpu_address(void) > expect_pgm_int(); > *out = 0xbeef; > store_cpu_address_key_1(out); > - check_pgm_int_code(PGM_INT_CODE_PROTECTION); > + check_key_prot_exc(ACC_STORE, PROT_STORE); > report(*out == 0xbeef, "no store occurred"); > report_prefix_pop(); > > @@ -210,7 +273,7 @@ static void test_store_cpu_address(void) > expect_pgm_int(); > *out = 0xbeef; > store_cpu_address_key_1(out); > - check_pgm_int_code(PGM_INT_CODE_PROTECTION); > + check_key_prot_exc(ACC_STORE, PROT_STORE); > report(*out == 0xbeef, "no store occurred"); > report_prefix_pop(); > > @@ -228,7 +291,7 @@ static void test_store_cpu_address(void) > expect_pgm_int(); > *out = 0xbeef; > store_cpu_address_key_1(out); > - check_pgm_int_code(PGM_INT_CODE_PROTECTION); > + check_key_prot_exc(ACC_STORE, PROT_STORE); > report(*out == 0xbeef, "no store occurred"); > report_prefix_pop(); > > @@ -314,7 +377,7 @@ static void test_set_prefix(void) > set_storage_key(pagebuf, 0x28, 0); > expect_pgm_int(); > set_prefix_key_1(prefix_ptr); > - check_pgm_int_code(PGM_INT_CODE_PROTECTION); > + check_key_prot_exc(ACC_FETCH, PROT_FETCH_STORE); > report(get_prefix() == old_prefix, "did not set prefix"); > report_prefix_pop(); > > @@ -327,7 +390,7 @@ static void test_set_prefix(void) > install_page(root, virt_to_pte_phys(root, pagebuf), 0); > set_prefix_key_1((uint32_t *)0); > install_page(root, 0, 0); > - check_pgm_int_code(PGM_INT_CODE_PROTECTION); > + check_key_prot_exc(ACC_FETCH, PROT_FETCH_STORE); > report(get_prefix() == old_prefix, "did not set prefix"); > report_prefix_pop(); > > @@ -351,7 +414,7 @@ static void test_set_prefix(void) > install_page(root, virt_to_pte_phys(root, pagebuf), 0); > set_prefix_key_1((uint32_t *)&mem_all[2048]); > install_page(root, 0, 0); > - check_pgm_int_code(PGM_INT_CODE_PROTECTION); > + check_key_prot_exc(ACC_FETCH, PROT_FETCH_STORE); > report(get_prefix() == old_prefix, "did not set prefix"); > report_prefix_pop(); >