1/* $NetBSD: apei_interp.c,v 1.4 2024/03/22 20:48:05 riastradh Exp $ */ 2 3/*- 4 * Copyright (c) 2024 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29/* 30 * APEI action interpreter. 31 * 32 * APEI provides a generalized abstraction to implement the actions an 33 * OS must take to inject an error, or save state in a persistent error 34 * record for the next boot, since there are many different hardware 35 * register interfaces for, e.g., injecting errors. 36 * 37 * You might think that APEI, being part of ACPI, would use the usual 38 * ACPI interpreter to run ACPI methods for these actions. You would 39 * be wrong. Alas. 40 * 41 * Instead, there is an entirely different little language of actions 42 * that an OS must write programs in to inject errors, and an entirely 43 * different little language of instructions that the interpreter for 44 * the actions uses to interpret the OS's error injection program. Got 45 * it? 46 * 47 * The EINJ and ERST tables provide a series entries that look like: 48 * 49 * +-----------------------------------------------+ 50 * | Action=SET_ERROR_TYPE | 51 * | Instruction=SKIP_NEXT_INSTRUCTION_IF_TRUE | 52 * | Register=0x7fabcd10 [memory] | 53 * | Value=0xdeadbeef | 54 * +-----------------------------------------------+ 55 * | Action=SET_ERROR_TYPE | 56 * | Instruction=WRITE_REGISTER_VALUE | 57 * | Register=0x7fabcd14 [memory] | 58 * | Value=1 | 59 * +-----------------------------------------------+ 60 * | Action=SET_ERROR_TYPE | 61 * | Instruction=READ_REGISTER | 62 * | Register=0x7fabcd1c [memory] | 63 * +-----------------------------------------------+ 64 * | Action=SET_ERROR_TYPE | 65 * | Instruction=WRITE_REGISTER | 66 * | Register=0x7fabcd20 [memory] | 67 * +-----------------------------------------------+ 68 * | Action=EXECUTE_OPERATION | 69 * | Instruction=LOAD_VAR1 | 70 * | Register=0x7fabcf00 [memory] | 71 * +-----------------------------------------------+ 72 * | Action=SET_ERROR_TYPE | 73 * | Instruction=WRITE_REGISTER_VALUE | 74 * | Register=0x7fabcd24 [memory] | 75 * | Value=42 | 76 * +-----------------------------------------------+ 77 * | ... | 78 * +-----------------------------------------------+ 79 * 80 * The entries tell the OS, for each action the OS might want to 81 * perform like BEGIN_INJECTION_OPERATION or SET_ERROR_TYPE or 82 * EXECUTE_OPERATION, what instructions must be executed and in what 83 * order. 84 * 85 * The instructions run in one of two little state machines -- there's 86 * a different instruction set for EINJ and ERST -- and vary from noops 87 * to reading and writing registers to arithmetic on registers to 88 * conditional and unconditional branches. 89 * 90 * Yes, that means this little language -- the ERST language, anyway, 91 * not the EINJ language -- is Turing-complete. 92 * 93 * This APEI interpreter first compiles the table into a contiguous 94 * sequence of instructions for each action, to make execution easier, 95 * since there's no requirement that the instructions for an action be 96 * contiguous in the table, and the GOTO instruction relies on 97 * contiguous indexing of the instructions for an action. 98 * 99 * This interpreter also does a little validation so the firmware 100 * doesn't, e.g., GOTO somewhere in oblivion. The validation is mainly 101 * a convenience for catching mistakes in firmware, not a security 102 * measure, since the OS is absolutely vulnerable to malicious firmware 103 * anyway. 104 */ 105 106#include <sys/cdefs.h> 107__KERNEL_RCSID(0, "$NetBSD: apei_interp.c,v 1.4 2024/03/22 20:48:05 riastradh Exp $"); 108 109#include <sys/types.h> 110 111#include <sys/kmem.h> 112#include <sys/systm.h> 113 114#include <dev/acpi/acpivar.h> 115#include <dev/acpi/apei_interp.h> 116#include <dev/acpi/apei_mapreg.h> 117 118/* 119 * struct apei_actinst 120 * 121 * Sequence of instructions to execute for an action. 122 */ 123struct apei_actinst { 124 uint32_t ninst; 125 uint32_t ip; 126 struct { 127 struct acpi_whea_header *header; 128 struct apei_mapreg *map; 129 } *inst; 130 bool disable; 131}; 132 133/* 134 * struct apei_interp 135 * 136 * Table of instructions to interpret APEI actions. 137*/ 138struct apei_interp { 139 const char *name; 140 const char *const *actname; 141 unsigned nact; 142 const char *const *instname; 143 unsigned ninst; 144 const bool *instreg; 145 bool (*instvalid)(ACPI_WHEA_HEADER *, uint32_t, 146 uint32_t); 147 void (*instfunc)(ACPI_WHEA_HEADER *, 148 struct apei_mapreg *, void *, uint32_t *, 149 uint32_t); 150 struct apei_actinst actinst[]; 151}; 152 153struct apei_interp * 154apei_interp_create(const char *name, 155 const char *const *actname, unsigned nact, 156 const char *const *instname, unsigned ninst, 157 const bool *instreg, 158 bool (*instvalid)(ACPI_WHEA_HEADER *, uint32_t, uint32_t), 159 void (*instfunc)(ACPI_WHEA_HEADER *, struct apei_mapreg *, void *, 160 uint32_t *, uint32_t)) 161{ 162 struct apei_interp *I; 163 164 I = kmem_zalloc(offsetof(struct apei_interp, actinst[nact]), KM_SLEEP); 165 I->name = name; 166 I->actname = actname; 167 I->nact = nact; 168 I->instname = instname; 169 I->ninst = ninst; 170 I->instreg = instreg; 171 I->instvalid = instvalid; 172 I->instfunc = instfunc; 173 174 return I; 175} 176 177void 178apei_interp_destroy(struct apei_interp *I) 179{ 180 unsigned action, nact = I->nact; 181 182 for (action = 0; action < nact; action++) { 183 struct apei_actinst *const A = &I->actinst[action]; 184 unsigned j; 185 186 if (A->ninst == 0 || A->inst == NULL) 187 continue; 188 189 for (j = 0; j < A->ninst; j++) { 190 ACPI_WHEA_HEADER *const E = A->inst[j].header; 191 struct apei_mapreg *const map = A->inst[j].map; 192 193 if (map != NULL) 194 apei_mapreg_unmap(&E->RegisterRegion, map); 195 } 196 197 kmem_free(A->inst, A->ninst * sizeof(A->inst[0])); 198 A->inst = NULL; 199 } 200 201 kmem_free(I, offsetof(struct apei_interp, actinst[nact])); 202} 203 204/* 205 * apei_interp_pass1_load(I, i, E) 206 * 207 * Load the ith table entry E into the interpreter I. To be 208 * called for each entry in the table sequentially. 209 * 210 * This first pass counts the number of instructions for each 211 * action, so we can allocate an array of instructions for 212 * indexing each action. 213 */ 214void 215apei_interp_pass1_load(struct apei_interp *I, uint32_t i, 216 ACPI_WHEA_HEADER *E) 217{ 218 219 /* 220 * If we don't recognize this action, ignore it and move on. 221 */ 222 if (E->Action >= I->nact || I->actname[E->Action] == NULL) { 223 aprint_error("%s[%"PRIu32"]: unknown action: 0x%"PRIx8"\n", 224 I->name, i, E->Action); 225 return; 226 } 227 struct apei_actinst *const A = &I->actinst[E->Action]; 228 229 /* 230 * If we can't interpret this instruction for this action, or 231 * if we couldn't interpret a previous instruction for this 232 * action, disable this action and move on. 233 */ 234 if (E->Instruction >= I->ninst || 235 I->instname[E->Instruction] == NULL) { 236 aprint_error("%s[%"PRIu32"]: unknown instruction: 0x%02"PRIx8 237 "\n", I->name, i, E->Instruction); 238 A->ninst = 0; 239 A->disable = true; 240 return; 241 } 242 if (A->disable) 243 return; 244 245 /* 246 * Count another instruction. We will make a pointer 247 * to it in a later pass. 248 */ 249 A->ninst++; 250 251 /* 252 * If it overflows a reasonable size, disable the action 253 * altogether. 254 */ 255 if (A->ninst >= 256) { 256 aprint_error("%s[%"PRIu32"]:" 257 " too many instructions for action %"PRIu32" (%s)\n", 258 I->name, i, 259 E->Action, I->actname[E->Action]); 260 A->ninst = 0; 261 A->disable = true; 262 return; 263 } 264} 265 266/* 267 * apei_interp_pass2_verify(I, i, E) 268 * 269 * Verify the ith entry's instruction, using the caller's 270 * instvalid function, now that all the instructions have been 271 * counted. To be called for each entry in the table 272 * sequentially. 273 * 274 * This second pass checks that GOTO instructions in particular 275 * don't jump out of bounds. 276 */ 277void 278apei_interp_pass2_verify(struct apei_interp *I, uint32_t i, 279 ACPI_WHEA_HEADER *E) 280{ 281 282 /* 283 * If there's no instruction validation function, skip this 284 * pass. 285 */ 286 if (I->instvalid == NULL) 287 return; 288 289 /* 290 * If we skipped it in earlier passes, skip it now. 291 */ 292 if (E->Action > I->nact || I->actname[E->Action] == NULL) 293 return; 294 295 /* 296 * If the instruction is invalid, disable the whole action. 297 */ 298 struct apei_actinst *const A = &I->actinst[E->Action]; 299 if (!(*I->instvalid)(E, A->ninst, i)) { 300 A->ninst = 0; 301 A->disable = true; 302 } 303} 304 305/* 306 * apei_interp_pass3_alloc(I) 307 * 308 * Allocate an array of instructions for each action that we 309 * didn't disable. 310 */ 311void 312apei_interp_pass3_alloc(struct apei_interp *I) 313{ 314 unsigned action; 315 316 for (action = 0; action < I->nact; action++) { 317 struct apei_actinst *const A = &I->actinst[action]; 318 if (A->ninst == 0 || A->disable) 319 continue; 320 A->inst = kmem_zalloc(A->ninst * sizeof(A->inst[0]), KM_SLEEP); 321 } 322} 323 324/* 325 * apei_interp_pass4_assemble(I, i, E) 326 * 327 * Put the instruction for the ith entry E into the instruction 328 * array for its action. To be called for each entry in the table 329 * sequentially. 330 */ 331void 332apei_interp_pass4_assemble(struct apei_interp *I, uint32_t i, 333 ACPI_WHEA_HEADER *E) 334{ 335 336 /* 337 * If we skipped it in earlier passes, skip it now. 338 */ 339 if (E->Action >= I->nact || I->actname[E->Action] == NULL) 340 return; 341 342 struct apei_actinst *const A = &I->actinst[E->Action]; 343 if (A->disable) 344 return; 345 346 KASSERT(A->ip < A->ninst); 347 const uint32_t ip = A->ip++; 348 A->inst[ip].header = E; 349 A->inst[ip].map = I->instreg[E->Instruction] ? 350 apei_mapreg_map(&E->RegisterRegion) : NULL; 351} 352 353/* 354 * apei_interp_pass5_verify(I) 355 * 356 * Paranoia: Verify we got all the instructions for each action, 357 * verify the actions point to their own instructions, and dump 358 * the instructions for each action, collated, with aprint_debug. 359 */ 360void 361apei_interp_pass5_verify(struct apei_interp *I) 362{ 363 unsigned action; 364 365 for (action = 0; action < I->nact; action++) { 366 struct apei_actinst *const A = &I->actinst[action]; 367 unsigned j; 368 369 /* 370 * If the action is disabled, it's all set. 371 */ 372 if (A->disable) 373 continue; 374 KASSERTMSG(A->ip == A->ninst, 375 "action %s ip=%"PRIu32" ninstruction=%"PRIu32, 376 I->actname[action], A->ip, A->ninst); 377 378 /* 379 * XXX Dump the complete instruction table. 380 */ 381 for (j = 0; j < A->ninst; j++) { 382 ACPI_WHEA_HEADER *const E = A->inst[j].header; 383 384 KASSERT(E->Action == action); 385 386 /* 387 * If we need the register and weren't able to 388 * map it, disable the action. 389 */ 390 if (I->instreg[E->Instruction] && 391 A->inst[j].map == NULL) { 392 A->disable = true; 393 continue; 394 } 395 396 aprint_debug("%s: %s[%"PRIu32"]: %s\n", 397 I->name, I->actname[action], j, 398 I->instname[E->Instruction]); 399 } 400 } 401} 402 403/* 404 * apei_interpret(I, action, cookie) 405 * 406 * Run the instructions associated with the given action by 407 * calling the interpreter's instfunc for each one. 408 * 409 * Halt when the instruction pointer runs past the end of the 410 * array, or after 1000 cycles, whichever comes first. 411 */ 412void 413apei_interpret(struct apei_interp *I, unsigned action, void *cookie) 414{ 415 unsigned juice = 1000; 416 uint32_t ip = 0; 417 418 if (action > I->nact || I->actname[action] == NULL) 419 return; 420 struct apei_actinst *const A = &I->actinst[action]; 421 if (A->disable) 422 return; 423 424 while (ip < A->ninst && juice --> 0) { 425 ACPI_WHEA_HEADER *const E = A->inst[ip].header; 426 struct apei_mapreg *const map = A->inst[ip].map; 427 428 ip++; 429 (*I->instfunc)(E, map, cookie, &ip, A->ninst); 430 } 431} 432