xref: /kvm-unit-tests/s390x/diag10.c (revision 06846df56370af39fb4c9cfd71c032197133929b)
1 /*
2  * Release pages hypercall tests (DIAG 10)
3  *
4  * Copyright (c) 2018 IBM Corp
5  *
6  * Authors:
7  *  Janosch Frank <frankja@linux.vnet.ibm.com>
8  *
9  * This code is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Library General Public License version 2.
11  */
12 
13 #include <libcflat.h>
14 #include <asm/asm-offsets.h>
15 #include <asm/interrupt.h>
16 #include <asm/page.h>
17 
18 static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE * 2)));
19 const unsigned long page0 = (unsigned long)pagebuf;
20 const unsigned long page1 = (unsigned long)(pagebuf + PAGE_SIZE);
21 
22 /* Tells the host to release pages from guest real addresses start to
23  * end. Parameters have to be page aligned, instruction is privileged.
24  */
25 static inline void diag10(unsigned long start, unsigned long end)
26 {
27 	asm volatile (
28 		"diag	%0,%1,0x10\n"
29 		: : "a" (start), "a" (end));
30 }
31 
32 /* Try freeing the prefix */
33 static void test_prefix(void)
34 {
35 	report_prefix_push("lowcore freeing");
36 
37 	report_prefix_push("0x0000/0x0000");
38 	expect_pgm_int();
39 	diag10(0, 0);
40 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
41 	report_prefix_pop();
42 
43 
44 	report_prefix_push("0x1000/0x1000");
45 	expect_pgm_int();
46 	diag10(0x1000, 0x1000);
47 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
48 	report_prefix_pop();
49 
50 	report_prefix_push("0x0000/0x1000");
51 	expect_pgm_int();
52 	diag10(0, 0x1000);
53 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
54 	report_prefix_pop();
55 
56 	report_prefix_pop();
57 }
58 
59 static void test_params(void)
60 {
61 	report_prefix_push("start/end");
62 
63 	/* end < start */
64 	report_prefix_push("end < start");
65 	expect_pgm_int();
66 	diag10(page1, page0);
67 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
68 	report_prefix_pop();
69 
70 	/* Unaligned start */
71 	report_prefix_push("unaligned start");
72 	expect_pgm_int();
73 	diag10((unsigned long) pagebuf + 42, page1);
74 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
75 	report_prefix_pop();
76 
77 	/* Unaligned end */
78 	report_prefix_push("unaligned end");
79 	expect_pgm_int();
80 	diag10(page0, (unsigned long) pagebuf + PAGE_SIZE + 42);
81 	check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
82 	report_prefix_pop();
83 
84 	report_prefix_pop();
85 }
86 
87 static void test_priv(void)
88 {
89 	report_prefix_push("privileged");
90 	expect_pgm_int();
91 	enter_pstate();
92 	diag10(page0, page0);
93 	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
94 	report_prefix_pop();
95 }
96 
97 int main(void)
98 {
99 	report_prefix_push("diag10");
100 	test_prefix();
101 	test_params();
102 	test_priv();
103 	return report_summary();
104 }
105