1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Tests SIE with paging. 4 * 5 * Copyright 2023 IBM Corp. 6 * 7 * Authors: 8 * Nico Boehr <nrb@linux.ibm.com> 9 */ 10 #include <libcflat.h> 11 #include <vmalloc.h> 12 #include <asm/pgtable.h> 13 #include <mmu.h> 14 #include <asm/page.h> 15 #include <asm/interrupt.h> 16 #include <alloc_page.h> 17 #include <sclp.h> 18 #include <sie.h> 19 #include <snippet.h> 20 #include "snippets/c/sie-dat.h" 21 22 static struct vm vm; 23 static pgd_t *guest_root; 24 25 static void test_sie_dat(void) 26 { 27 uint64_t test_page_gpa, test_page_hpa; 28 uint8_t *test_page_hva, expected_val; 29 bool contents_match; 30 uint8_t r1; 31 32 /* guest will tell us the guest physical address of the test buffer */ 33 sie(&vm); 34 assert(vm.sblk->icptcode == ICPT_INST && 35 (vm.sblk->ipa & 0xff00) == 0x8300 && vm.sblk->ipb == 0x9c0000); 36 37 r1 = (vm.sblk->ipa & 0xf0) >> 4; 38 test_page_gpa = vm.save_area.guest.grs[r1]; 39 test_page_hpa = virt_to_pte_phys(guest_root, (void*)test_page_gpa); 40 test_page_hva = __va(test_page_hpa); 41 report_info("test buffer gpa=0x%lx hva=%p", test_page_gpa, test_page_hva); 42 43 /* guest will now write to the test buffer and we verify the contents */ 44 sie(&vm); 45 assert(vm.sblk->icptcode == ICPT_INST && 46 vm.sblk->ipa == 0x8300 && vm.sblk->ipb == 0x440000); 47 48 contents_match = true; 49 for (unsigned int i = 0; i < GUEST_TEST_PAGE_COUNT; i++) { 50 expected_val = 42 + i; 51 if (test_page_hva[i * PAGE_SIZE] != expected_val) { 52 report_fail("page %u mismatch actual_val=%x expected_val=%x", 53 i, test_page_hva[i], expected_val); 54 contents_match = false; 55 } 56 } 57 report(contents_match, "test buffer contents match"); 58 59 /* the guest will now write to an unmapped address and we check that this causes a segment translation exception */ 60 report_prefix_push("guest write to unmapped"); 61 expect_pgm_int(); 62 sie(&vm); 63 check_pgm_int_code(PGM_INT_CODE_SEGMENT_TRANSLATION); 64 report((lowcore.trans_exc_id & PAGE_MASK) == (GUEST_TOTAL_PAGE_COUNT * PAGE_SIZE), "TEID address match"); 65 report_prefix_pop(); 66 } 67 68 static void setup_guest(void) 69 { 70 extern const char SNIPPET_NAME_START(c, sie_dat)[]; 71 extern const char SNIPPET_NAME_END(c, sie_dat)[]; 72 uint64_t guest_max_addr; 73 pgd_t *root; 74 75 setup_vm(); 76 root = (pgd_t *)(stctg(1) & PAGE_MASK); 77 78 snippet_setup_guest(&vm, false); 79 80 /* allocate a region-1 table */ 81 guest_root = pgd_alloc_one(); 82 83 /* map guest memory 1:1 */ 84 guest_max_addr = GUEST_TOTAL_PAGE_COUNT * PAGE_SIZE; 85 for (uint64_t i = 0; i < guest_max_addr; i += PAGE_SIZE) 86 install_page(guest_root, virt_to_pte_phys(root, vm.guest_mem + i), (void *)i); 87 88 /* set up storage limit supression - leave mso and msl intact they are ignored anyways */ 89 vm.sblk->cpuflags |= CPUSTAT_SM; 90 91 /* set up the guest asce */ 92 vm.save_area.guest.asce = __pa(guest_root) | ASCE_DT_REGION1 | REGION_TABLE_LENGTH; 93 94 snippet_init(&vm, SNIPPET_NAME_START(c, sie_dat), 95 SNIPPET_LEN(c, sie_dat), SNIPPET_UNPACK_OFF); 96 } 97 98 int main(void) 99 { 100 report_prefix_push("sie-dat"); 101 if (!sclp_facilities.has_sief2) { 102 report_skip("SIEF2 facility unavailable"); 103 goto done; 104 } 105 106 setup_guest(); 107 test_sie_dat(); 108 sie_guest_destroy(&vm); 109 110 done: 111 report_prefix_pop(); 112 return report_summary(); 113 114 } 115