blob: 68c57cb21d2e98a102e2e4fed70c6dc28ec6687c [file] [log] [blame]
Janosch Franke2db2952018-03-27 13:55:13 +02001/*
2 * Tests exceptions and data validity for the emulated sthyi
3 * instruction.
4 *
5 * Copyright 2018 IBM Corp.
6 *
7 * Authors:
8 * Janosch Frank <frankja@linux.vnet.ibm.com>
9 *
10 * This code is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Library General Public License version 2.
12 */
13#include <libcflat.h>
14#include <asm/asm-offsets.h>
15#include <asm/interrupt.h>
16#include <asm/page.h>
17#include <asm/facility.h>
18
19#include "sthyi.h"
20
21static uint8_t pagebuf[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
22static char null_buf[32] = {};
23
24static inline int sthyi(uint64_t vaddr, uint64_t fcode, uint64_t *rc,
25 unsigned int r1, unsigned int r2)
26{
27 register uint64_t code asm("0") = fcode;
28 register uint64_t addr asm("2") = vaddr;
29 register uint64_t rc3 asm("3") = 0;
30 int cc = 0;
31
32 asm volatile(".insn rre,0xB2560000,%[r1],%[r2]\n"
33 "ipm %[cc]\n"
34 "srl %[cc],28\n"
35 : [cc] "=d" (cc)
36 : [code] "d" (code), [addr] "a" (addr), [r1] "i" (r1),
37 [r2] "i" (r2)
38 : "memory", "cc", "r3");
39 if (rc)
40 *rc = rc3;
41 return cc;
42}
43
44static void test_exception_addr(void)
45{
46 report_prefix_push("Illegal address check");
47 expect_pgm_int();
48 sthyi(42042, 0, NULL, 0, 2);
49 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
50 report_prefix_pop();
51}
52
53static void test_exception_reg_odd(void)
54{
Janosch Frank92c5b9c2019-02-28 09:35:37 +010055 report_prefix_push("Register check odd R1");
Janosch Franke2db2952018-03-27 13:55:13 +020056 expect_pgm_int();
57 sthyi((uint64_t)pagebuf, 0, NULL, 1, 2);
58 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
Janosch Frank92c5b9c2019-02-28 09:35:37 +010059 report_prefix_pop();
60 report_prefix_push("Register check odd R2");
Janosch Franke2db2952018-03-27 13:55:13 +020061 expect_pgm_int();
62 sthyi((uint64_t)pagebuf, 0, NULL, 0, 3);
63 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
64 report_prefix_pop();
65}
66
67static void test_exception_reg_equal(void)
68{
69 report_prefix_push("Register check equal");
70 expect_pgm_int();
71 sthyi((uint64_t)pagebuf, 0, NULL, 0, 0);
72 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
73 report_prefix_pop();
74}
75
76static void test_function_code(uint64_t addr)
77{
78 uint64_t urc = 0;
79 int cc = sthyi((uint64_t)pagebuf, 42, &urc, 0, 2);
80
Thomas Hutha2998952019-12-06 12:31:02 +010081 report(cc == 3 && urc == CODE_UNSUPP, "Illegal fcode");
Janosch Franke2db2952018-03-27 13:55:13 +020082}
83
84static void test_fcode0_hdr(struct sthyi_hdr_sctn *hdr)
85{
Janosch Frank92c5b9c2019-02-28 09:35:37 +010086 report_prefix_push("Header");
Janosch Franke2db2952018-03-27 13:55:13 +020087
Thomas Hutha2998952019-12-06 12:31:02 +010088 report(hdr->INFHDLN >= sizeof(*hdr) && !(hdr->INFHDLN % 8), "length");
89 report((hdr->INFMLEN >= sizeof(struct sthyi_mach_sctn) && !(hdr->INFMLEN % 8)),
90 "Machine sctn length");
91 report((hdr->INFPLEN >= sizeof(struct sthyi_par_sctn) && !(hdr->INFPLEN % 8)),
92 "Partition section length");
Janosch Frank92c5b9c2019-02-28 09:35:37 +010093
Thomas Hutha2998952019-12-06 12:31:02 +010094 report(hdr->INFMOFF >= hdr->INFHDLN, "Machine offset");
95 report(hdr->INFPOFF >= hdr->INFHDLN, "Partition offset");
Janosch Frank92c5b9c2019-02-28 09:35:37 +010096 report_prefix_pop();
Janosch Franke2db2952018-03-27 13:55:13 +020097}
98
99static void test_fcode0_mach(struct sthyi_mach_sctn *mach)
100{
101 int sum = mach->INFMSCPS + mach->INFMDCPS + mach->INFMSIFL + mach->INFMDIFL;
102
Janosch Frank92c5b9c2019-02-28 09:35:37 +0100103 report_prefix_push("Machine");
Janosch Franke2db2952018-03-27 13:55:13 +0200104 if (mach->INFMVAL1 & MACH_ID_VLD) {
Thomas Hutha2998952019-12-06 12:31:02 +0100105 report(memcmp(mach->INFMTYPE, null_buf, sizeof(mach->INFMTYPE)),
106 "type");
107 report(memcmp(mach->INFMMANU, null_buf, sizeof(mach->INFMMANU)),
108 "manufacturer");
109 report(memcmp(mach->INFMSEQ, null_buf, sizeof(mach->INFMSEQ)),
110 "sequence");
111 report(memcmp(mach->INFMPMAN, null_buf, sizeof(mach->INFMPMAN)),
112 "plant");
Janosch Franke2db2952018-03-27 13:55:13 +0200113 }
114
115 if (mach->INFMVAL1 & MACH_NAME_VLD)
Thomas Hutha2998952019-12-06 12:31:02 +0100116 report(memcmp(mach->INFMNAME, null_buf, sizeof(mach->INFMNAME)),
117 "name");
Janosch Franke2db2952018-03-27 13:55:13 +0200118
119 if (mach->INFMVAL1 & MACH_CNT_VLD)
Thomas Hutha2998952019-12-06 12:31:02 +0100120 report(sum, "core counts");
Janosch Frank92c5b9c2019-02-28 09:35:37 +0100121 report_prefix_pop();
Janosch Franke2db2952018-03-27 13:55:13 +0200122}
123
124static void test_fcode0_par(struct sthyi_par_sctn *par)
125{
126 int sum = par->INFPSCPS + par->INFPDCPS + par->INFPSIFL + par->INFPDIFL;
127
Janosch Frank92c5b9c2019-02-28 09:35:37 +0100128 report_prefix_push("Partition");
Janosch Franke2db2952018-03-27 13:55:13 +0200129 if (par->INFPVAL1 & PART_CNT_VLD)
Thomas Hutha2998952019-12-06 12:31:02 +0100130 report(sum, "core counts");
Janosch Franke2db2952018-03-27 13:55:13 +0200131
132 if (par->INFPVAL1 & PART_STSI_SUC) {
Thomas Hutha2998952019-12-06 12:31:02 +0100133 report(par->INFPPNUM, "number");
134 report(memcmp(par->INFPPNAM, null_buf, sizeof(par->INFPPNAM)),
135 "name");
Janosch Franke2db2952018-03-27 13:55:13 +0200136 }
Janosch Frank92c5b9c2019-02-28 09:35:37 +0100137 report_prefix_pop();
Janosch Franke2db2952018-03-27 13:55:13 +0200138}
139
140static void test_fcode0(void)
141{
142 struct sthyi_hdr_sctn *hdr;
143 struct sthyi_mach_sctn *mach;
144 struct sthyi_par_sctn *par;
145
146 /* Zero destination memory. */
147 memset(pagebuf, 0, PAGE_SIZE);
148
Janosch Frank92c5b9c2019-02-28 09:35:37 +0100149 report_prefix_push("fcode 0");
Janosch Franke2db2952018-03-27 13:55:13 +0200150 sthyi((uint64_t)pagebuf, 0, NULL, 0, 2);
151 hdr = (void *)pagebuf;
152 mach = (void *)pagebuf + hdr->INFMOFF;
153 par = (void *)pagebuf + hdr->INFPOFF;
154
155 test_fcode0_hdr(hdr);
156 test_fcode0_mach(mach);
157 test_fcode0_par(par);
Janosch Frank92c5b9c2019-02-28 09:35:37 +0100158 report_prefix_pop();
Janosch Franke2db2952018-03-27 13:55:13 +0200159}
160
161int main(void)
162{
163 bool has_sthyi = test_facility(74);
164
165 report_prefix_push("sthyi");
166
167 /* Test for availability */
Thomas Huth90016cc2018-06-14 20:25:15 +0200168 if (!has_sthyi) {
169 report_skip("STHYI is not available");
Janosch Franke2db2952018-03-27 13:55:13 +0200170 goto done;
Thomas Huth90016cc2018-06-14 20:25:15 +0200171 }
Janosch Franke2db2952018-03-27 13:55:13 +0200172
173 /* Test register/argument checking. */
Janosch Frank92c5b9c2019-02-28 09:35:37 +0100174 report_prefix_push("Instruction");
Janosch Franke2db2952018-03-27 13:55:13 +0200175 test_exception_addr();
176 test_exception_reg_odd();
177 test_exception_reg_equal();
178 test_function_code((uint64_t) pagebuf);
Janosch Frank92c5b9c2019-02-28 09:35:37 +0100179 report_prefix_pop();
Janosch Franke2db2952018-03-27 13:55:13 +0200180
181 /* Test function code 0 - CP and IFL Capacity Information */
182 test_fcode0();
183
184done:
185 report_prefix_pop();
186 return report_summary();
187}