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