1 // SPDX-License-Identifier: GPL-2.0 2 3 #include "asm/hvcall.h" 4 #include <linux/log2.h> 5 #include <asm/pgalloc.h> 6 #include <asm/guest-state-buffer.h> 7 8 static const u16 kvmppc_gse_iden_len[__KVMPPC_GSE_TYPE_MAX] = { 9 [KVMPPC_GSE_BE32] = sizeof(__be32), 10 [KVMPPC_GSE_BE64] = sizeof(__be64), 11 [KVMPPC_GSE_VEC128] = sizeof(vector128), 12 [KVMPPC_GSE_PARTITION_TABLE] = sizeof(struct kvmppc_gs_part_table), 13 [KVMPPC_GSE_PROCESS_TABLE] = sizeof(struct kvmppc_gs_proc_table), 14 [KVMPPC_GSE_BUFFER] = sizeof(struct kvmppc_gs_buff_info), 15 }; 16 17 /** 18 * kvmppc_gsb_new() - create a new guest state buffer 19 * @size: total size of the guest state buffer (includes header) 20 * @guest_id: guest_id 21 * @vcpu_id: vcpu_id 22 * @flags: GFP flags 23 * 24 * Returns a guest state buffer. 25 */ 26 struct kvmppc_gs_buff *kvmppc_gsb_new(size_t size, unsigned long guest_id, 27 unsigned long vcpu_id, gfp_t flags) 28 { 29 struct kvmppc_gs_buff *gsb; 30 31 gsb = kzalloc(sizeof(*gsb), flags); 32 if (!gsb) 33 return NULL; 34 35 size = roundup_pow_of_two(size); 36 gsb->hdr = kzalloc(size, GFP_KERNEL); 37 if (!gsb->hdr) 38 goto free; 39 40 gsb->capacity = size; 41 gsb->len = sizeof(struct kvmppc_gs_header); 42 gsb->vcpu_id = vcpu_id; 43 gsb->guest_id = guest_id; 44 45 gsb->hdr->nelems = cpu_to_be32(0); 46 47 return gsb; 48 49 free: 50 kfree(gsb); 51 return NULL; 52 } 53 EXPORT_SYMBOL_GPL(kvmppc_gsb_new); 54 55 /** 56 * kvmppc_gsb_free() - free a guest state buffer 57 * @gsb: guest state buffer 58 */ 59 void kvmppc_gsb_free(struct kvmppc_gs_buff *gsb) 60 { 61 kfree(gsb->hdr); 62 kfree(gsb); 63 } 64 EXPORT_SYMBOL_GPL(kvmppc_gsb_free); 65 66 /** 67 * kvmppc_gsb_put() - allocate space in a guest state buffer 68 * @gsb: buffer to allocate in 69 * @size: amount of space to allocate 70 * 71 * Returns a pointer to the amount of space requested within the buffer and 72 * increments the count of elements in the buffer. 73 * 74 * Does not check if there is enough space in the buffer. 75 */ 76 void *kvmppc_gsb_put(struct kvmppc_gs_buff *gsb, size_t size) 77 { 78 u32 nelems = kvmppc_gsb_nelems(gsb); 79 void *p; 80 81 p = (void *)kvmppc_gsb_header(gsb) + kvmppc_gsb_len(gsb); 82 gsb->len += size; 83 84 kvmppc_gsb_header(gsb)->nelems = cpu_to_be32(nelems + 1); 85 return p; 86 } 87 EXPORT_SYMBOL_GPL(kvmppc_gsb_put); 88 89 static int kvmppc_gsid_class(u16 iden) 90 { 91 if ((iden >= KVMPPC_GSE_GUESTWIDE_START) && 92 (iden <= KVMPPC_GSE_GUESTWIDE_END)) 93 return KVMPPC_GS_CLASS_GUESTWIDE; 94 95 if ((iden >= KVMPPC_GSE_META_START) && (iden <= KVMPPC_GSE_META_END)) 96 return KVMPPC_GS_CLASS_META; 97 98 if ((iden >= KVMPPC_GSE_DW_REGS_START) && 99 (iden <= KVMPPC_GSE_DW_REGS_END)) 100 return KVMPPC_GS_CLASS_DWORD_REG; 101 102 if ((iden >= KVMPPC_GSE_W_REGS_START) && 103 (iden <= KVMPPC_GSE_W_REGS_END)) 104 return KVMPPC_GS_CLASS_WORD_REG; 105 106 if ((iden >= KVMPPC_GSE_VSRS_START) && (iden <= KVMPPC_GSE_VSRS_END)) 107 return KVMPPC_GS_CLASS_VECTOR; 108 109 if ((iden >= KVMPPC_GSE_INTR_REGS_START) && 110 (iden <= KVMPPC_GSE_INTR_REGS_END)) 111 return KVMPPC_GS_CLASS_INTR; 112 113 return -1; 114 } 115 116 static int kvmppc_gsid_type(u16 iden) 117 { 118 int type = -1; 119 120 switch (kvmppc_gsid_class(iden)) { 121 case KVMPPC_GS_CLASS_GUESTWIDE: 122 switch (iden) { 123 case KVMPPC_GSID_HOST_STATE_SIZE: 124 case KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE: 125 case KVMPPC_GSID_TB_OFFSET: 126 type = KVMPPC_GSE_BE64; 127 break; 128 case KVMPPC_GSID_PARTITION_TABLE: 129 type = KVMPPC_GSE_PARTITION_TABLE; 130 break; 131 case KVMPPC_GSID_PROCESS_TABLE: 132 type = KVMPPC_GSE_PROCESS_TABLE; 133 break; 134 case KVMPPC_GSID_LOGICAL_PVR: 135 type = KVMPPC_GSE_BE32; 136 break; 137 } 138 break; 139 case KVMPPC_GS_CLASS_META: 140 switch (iden) { 141 case KVMPPC_GSID_RUN_INPUT: 142 case KVMPPC_GSID_RUN_OUTPUT: 143 type = KVMPPC_GSE_BUFFER; 144 break; 145 case KVMPPC_GSID_VPA: 146 type = KVMPPC_GSE_BE64; 147 break; 148 } 149 break; 150 case KVMPPC_GS_CLASS_DWORD_REG: 151 type = KVMPPC_GSE_BE64; 152 break; 153 case KVMPPC_GS_CLASS_WORD_REG: 154 type = KVMPPC_GSE_BE32; 155 break; 156 case KVMPPC_GS_CLASS_VECTOR: 157 type = KVMPPC_GSE_VEC128; 158 break; 159 case KVMPPC_GS_CLASS_INTR: 160 switch (iden) { 161 case KVMPPC_GSID_HDAR: 162 case KVMPPC_GSID_ASDR: 163 case KVMPPC_GSID_HEIR: 164 type = KVMPPC_GSE_BE64; 165 break; 166 case KVMPPC_GSID_HDSISR: 167 type = KVMPPC_GSE_BE32; 168 break; 169 } 170 break; 171 } 172 173 return type; 174 } 175 176 /** 177 * kvmppc_gsid_flags() - the flags for a guest state ID 178 * @iden: guest state ID 179 * 180 * Returns any flags for the guest state ID. 181 */ 182 unsigned long kvmppc_gsid_flags(u16 iden) 183 { 184 unsigned long flags = 0; 185 186 switch (kvmppc_gsid_class(iden)) { 187 case KVMPPC_GS_CLASS_GUESTWIDE: 188 flags = KVMPPC_GS_FLAGS_WIDE; 189 break; 190 case KVMPPC_GS_CLASS_META: 191 case KVMPPC_GS_CLASS_DWORD_REG: 192 case KVMPPC_GS_CLASS_WORD_REG: 193 case KVMPPC_GS_CLASS_VECTOR: 194 case KVMPPC_GS_CLASS_INTR: 195 break; 196 } 197 198 return flags; 199 } 200 EXPORT_SYMBOL_GPL(kvmppc_gsid_flags); 201 202 /** 203 * kvmppc_gsid_size() - the size of a guest state ID 204 * @iden: guest state ID 205 * 206 * Returns the size of guest state ID. 207 */ 208 u16 kvmppc_gsid_size(u16 iden) 209 { 210 int type; 211 212 type = kvmppc_gsid_type(iden); 213 if (type == -1) 214 return 0; 215 216 if (type >= __KVMPPC_GSE_TYPE_MAX) 217 return 0; 218 219 return kvmppc_gse_iden_len[type]; 220 } 221 EXPORT_SYMBOL_GPL(kvmppc_gsid_size); 222 223 /** 224 * kvmppc_gsid_mask() - the settable bits of a guest state ID 225 * @iden: guest state ID 226 * 227 * Returns a mask of settable bits for a guest state ID. 228 */ 229 u64 kvmppc_gsid_mask(u16 iden) 230 { 231 u64 mask = ~0ull; 232 233 switch (iden) { 234 case KVMPPC_GSID_LPCR: 235 mask = LPCR_DPFD | LPCR_ILE | LPCR_AIL | LPCR_LD | LPCR_MER | 236 LPCR_GTSE; 237 break; 238 case KVMPPC_GSID_MSR: 239 mask = ~(MSR_HV | MSR_S | MSR_ME); 240 break; 241 } 242 243 return mask; 244 } 245 EXPORT_SYMBOL_GPL(kvmppc_gsid_mask); 246 247 /** 248 * __kvmppc_gse_put() - add a guest state element to a buffer 249 * @gsb: buffer to the element to 250 * @iden: guest state ID 251 * @size: length of data 252 * @data: pointer to data 253 */ 254 int __kvmppc_gse_put(struct kvmppc_gs_buff *gsb, u16 iden, u16 size, 255 const void *data) 256 { 257 struct kvmppc_gs_elem *gse; 258 u16 total_size; 259 260 total_size = sizeof(*gse) + size; 261 if (total_size + kvmppc_gsb_len(gsb) > kvmppc_gsb_capacity(gsb)) 262 return -ENOMEM; 263 264 if (kvmppc_gsid_size(iden) != size) 265 return -EINVAL; 266 267 gse = kvmppc_gsb_put(gsb, total_size); 268 gse->iden = cpu_to_be16(iden); 269 gse->len = cpu_to_be16(size); 270 memcpy(gse->data, data, size); 271 272 return 0; 273 } 274 EXPORT_SYMBOL_GPL(__kvmppc_gse_put); 275 276 /** 277 * kvmppc_gse_parse() - create a parse map from a guest state buffer 278 * @gsp: guest state parser 279 * @gsb: guest state buffer 280 */ 281 int kvmppc_gse_parse(struct kvmppc_gs_parser *gsp, struct kvmppc_gs_buff *gsb) 282 { 283 struct kvmppc_gs_elem *curr; 284 int rem, i; 285 286 kvmppc_gsb_for_each_elem(i, curr, gsb, rem) { 287 if (kvmppc_gse_len(curr) != 288 kvmppc_gsid_size(kvmppc_gse_iden(curr))) 289 return -EINVAL; 290 kvmppc_gsp_insert(gsp, kvmppc_gse_iden(curr), curr); 291 } 292 293 if (kvmppc_gsb_nelems(gsb) != i) 294 return -EINVAL; 295 return 0; 296 } 297 EXPORT_SYMBOL_GPL(kvmppc_gse_parse); 298 299 static inline int kvmppc_gse_flatten_iden(u16 iden) 300 { 301 int bit = 0; 302 int class; 303 304 class = kvmppc_gsid_class(iden); 305 306 if (class == KVMPPC_GS_CLASS_GUESTWIDE) { 307 bit += iden - KVMPPC_GSE_GUESTWIDE_START; 308 return bit; 309 } 310 311 bit += KVMPPC_GSE_GUESTWIDE_COUNT; 312 313 if (class == KVMPPC_GS_CLASS_META) { 314 bit += iden - KVMPPC_GSE_META_START; 315 return bit; 316 } 317 318 bit += KVMPPC_GSE_META_COUNT; 319 320 if (class == KVMPPC_GS_CLASS_DWORD_REG) { 321 bit += iden - KVMPPC_GSE_DW_REGS_START; 322 return bit; 323 } 324 325 bit += KVMPPC_GSE_DW_REGS_COUNT; 326 327 if (class == KVMPPC_GS_CLASS_WORD_REG) { 328 bit += iden - KVMPPC_GSE_W_REGS_START; 329 return bit; 330 } 331 332 bit += KVMPPC_GSE_W_REGS_COUNT; 333 334 if (class == KVMPPC_GS_CLASS_VECTOR) { 335 bit += iden - KVMPPC_GSE_VSRS_START; 336 return bit; 337 } 338 339 bit += KVMPPC_GSE_VSRS_COUNT; 340 341 if (class == KVMPPC_GS_CLASS_INTR) { 342 bit += iden - KVMPPC_GSE_INTR_REGS_START; 343 return bit; 344 } 345 346 return 0; 347 } 348 349 static inline u16 kvmppc_gse_unflatten_iden(int bit) 350 { 351 u16 iden; 352 353 if (bit < KVMPPC_GSE_GUESTWIDE_COUNT) { 354 iden = KVMPPC_GSE_GUESTWIDE_START + bit; 355 return iden; 356 } 357 bit -= KVMPPC_GSE_GUESTWIDE_COUNT; 358 359 if (bit < KVMPPC_GSE_META_COUNT) { 360 iden = KVMPPC_GSE_META_START + bit; 361 return iden; 362 } 363 bit -= KVMPPC_GSE_META_COUNT; 364 365 if (bit < KVMPPC_GSE_DW_REGS_COUNT) { 366 iden = KVMPPC_GSE_DW_REGS_START + bit; 367 return iden; 368 } 369 bit -= KVMPPC_GSE_DW_REGS_COUNT; 370 371 if (bit < KVMPPC_GSE_W_REGS_COUNT) { 372 iden = KVMPPC_GSE_W_REGS_START + bit; 373 return iden; 374 } 375 bit -= KVMPPC_GSE_W_REGS_COUNT; 376 377 if (bit < KVMPPC_GSE_VSRS_COUNT) { 378 iden = KVMPPC_GSE_VSRS_START + bit; 379 return iden; 380 } 381 bit -= KVMPPC_GSE_VSRS_COUNT; 382 383 if (bit < KVMPPC_GSE_IDEN_COUNT) { 384 iden = KVMPPC_GSE_INTR_REGS_START + bit; 385 return iden; 386 } 387 388 return 0; 389 } 390 391 /** 392 * kvmppc_gsp_insert() - add a mapping from an guest state ID to an element 393 * @gsp: guest state parser 394 * @iden: guest state id (key) 395 * @gse: guest state element (value) 396 */ 397 void kvmppc_gsp_insert(struct kvmppc_gs_parser *gsp, u16 iden, 398 struct kvmppc_gs_elem *gse) 399 { 400 int i; 401 402 i = kvmppc_gse_flatten_iden(iden); 403 kvmppc_gsbm_set(&gsp->iterator, iden); 404 gsp->gses[i] = gse; 405 } 406 EXPORT_SYMBOL_GPL(kvmppc_gsp_insert); 407 408 /** 409 * kvmppc_gsp_lookup() - lookup an element from a guest state ID 410 * @gsp: guest state parser 411 * @iden: guest state ID (key) 412 * 413 * Returns the guest state element if present. 414 */ 415 struct kvmppc_gs_elem *kvmppc_gsp_lookup(struct kvmppc_gs_parser *gsp, u16 iden) 416 { 417 int i; 418 419 i = kvmppc_gse_flatten_iden(iden); 420 return gsp->gses[i]; 421 } 422 EXPORT_SYMBOL_GPL(kvmppc_gsp_lookup); 423 424 /** 425 * kvmppc_gsbm_set() - set the guest state ID 426 * @gsbm: guest state bitmap 427 * @iden: guest state ID 428 */ 429 void kvmppc_gsbm_set(struct kvmppc_gs_bitmap *gsbm, u16 iden) 430 { 431 set_bit(kvmppc_gse_flatten_iden(iden), gsbm->bitmap); 432 } 433 EXPORT_SYMBOL_GPL(kvmppc_gsbm_set); 434 435 /** 436 * kvmppc_gsbm_clear() - clear the guest state ID 437 * @gsbm: guest state bitmap 438 * @iden: guest state ID 439 */ 440 void kvmppc_gsbm_clear(struct kvmppc_gs_bitmap *gsbm, u16 iden) 441 { 442 clear_bit(kvmppc_gse_flatten_iden(iden), gsbm->bitmap); 443 } 444 EXPORT_SYMBOL_GPL(kvmppc_gsbm_clear); 445 446 /** 447 * kvmppc_gsbm_test() - test the guest state ID 448 * @gsbm: guest state bitmap 449 * @iden: guest state ID 450 */ 451 bool kvmppc_gsbm_test(struct kvmppc_gs_bitmap *gsbm, u16 iden) 452 { 453 return test_bit(kvmppc_gse_flatten_iden(iden), gsbm->bitmap); 454 } 455 EXPORT_SYMBOL_GPL(kvmppc_gsbm_test); 456 457 /** 458 * kvmppc_gsbm_next() - return the next set guest state ID 459 * @gsbm: guest state bitmap 460 * @prev: last guest state ID 461 */ 462 u16 kvmppc_gsbm_next(struct kvmppc_gs_bitmap *gsbm, u16 prev) 463 { 464 int bit, pbit; 465 466 pbit = prev ? kvmppc_gse_flatten_iden(prev) + 1 : 0; 467 bit = find_next_bit(gsbm->bitmap, KVMPPC_GSE_IDEN_COUNT, pbit); 468 469 if (bit < KVMPPC_GSE_IDEN_COUNT) 470 return kvmppc_gse_unflatten_iden(bit); 471 return 0; 472 } 473 EXPORT_SYMBOL_GPL(kvmppc_gsbm_next); 474 475 /** 476 * kvmppc_gsm_init() - initialize a guest state message 477 * @gsm: guest state message 478 * @ops: callbacks 479 * @data: private data 480 * @flags: guest wide or thread wide 481 */ 482 int kvmppc_gsm_init(struct kvmppc_gs_msg *gsm, struct kvmppc_gs_msg_ops *ops, 483 void *data, unsigned long flags) 484 { 485 memset(gsm, 0, sizeof(*gsm)); 486 gsm->ops = ops; 487 gsm->data = data; 488 gsm->flags = flags; 489 490 return 0; 491 } 492 EXPORT_SYMBOL_GPL(kvmppc_gsm_init); 493 494 /** 495 * kvmppc_gsm_new() - creates a new guest state message 496 * @ops: callbacks 497 * @data: private data 498 * @flags: guest wide or thread wide 499 * @gfp_flags: GFP allocation flags 500 * 501 * Returns an initialized guest state message. 502 */ 503 struct kvmppc_gs_msg *kvmppc_gsm_new(struct kvmppc_gs_msg_ops *ops, void *data, 504 unsigned long flags, gfp_t gfp_flags) 505 { 506 struct kvmppc_gs_msg *gsm; 507 508 gsm = kzalloc(sizeof(*gsm), gfp_flags); 509 if (!gsm) 510 return NULL; 511 512 kvmppc_gsm_init(gsm, ops, data, flags); 513 514 return gsm; 515 } 516 EXPORT_SYMBOL_GPL(kvmppc_gsm_new); 517 518 /** 519 * kvmppc_gsm_size() - creates a new guest state message 520 * @gsm: self 521 * 522 * Returns the size required for the message. 523 */ 524 size_t kvmppc_gsm_size(struct kvmppc_gs_msg *gsm) 525 { 526 if (gsm->ops->get_size) 527 return gsm->ops->get_size(gsm); 528 return 0; 529 } 530 EXPORT_SYMBOL_GPL(kvmppc_gsm_size); 531 532 /** 533 * kvmppc_gsm_free() - free guest state message 534 * @gsm: guest state message 535 * 536 * Returns the size required for the message. 537 */ 538 void kvmppc_gsm_free(struct kvmppc_gs_msg *gsm) 539 { 540 kfree(gsm); 541 } 542 EXPORT_SYMBOL_GPL(kvmppc_gsm_free); 543 544 /** 545 * kvmppc_gsm_fill_info() - serialises message to guest state buffer format 546 * @gsm: self 547 * @gsb: buffer to serialise into 548 */ 549 int kvmppc_gsm_fill_info(struct kvmppc_gs_msg *gsm, struct kvmppc_gs_buff *gsb) 550 { 551 if (!gsm->ops->fill_info) 552 return -EINVAL; 553 554 return gsm->ops->fill_info(gsb, gsm); 555 } 556 EXPORT_SYMBOL_GPL(kvmppc_gsm_fill_info); 557 558 /** 559 * kvmppc_gsm_refresh_info() - deserialises from guest state buffer 560 * @gsm: self 561 * @gsb: buffer to serialise from 562 */ 563 int kvmppc_gsm_refresh_info(struct kvmppc_gs_msg *gsm, 564 struct kvmppc_gs_buff *gsb) 565 { 566 if (!gsm->ops->fill_info) 567 return -EINVAL; 568 569 return gsm->ops->refresh_info(gsm, gsb); 570 } 571 EXPORT_SYMBOL_GPL(kvmppc_gsm_refresh_info); 572 573 /** 574 * kvmppc_gsb_send - send all elements in the buffer to the hypervisor. 575 * @gsb: guest state buffer 576 * @flags: guest wide or thread wide 577 * 578 * Performs the H_GUEST_SET_STATE hcall for the guest state buffer. 579 */ 580 int kvmppc_gsb_send(struct kvmppc_gs_buff *gsb, unsigned long flags) 581 { 582 unsigned long hflags = 0; 583 unsigned long i; 584 int rc; 585 586 if (kvmppc_gsb_nelems(gsb) == 0) 587 return 0; 588 589 if (flags & KVMPPC_GS_FLAGS_WIDE) 590 hflags |= H_GUEST_FLAGS_WIDE; 591 592 rc = plpar_guest_set_state(hflags, gsb->guest_id, gsb->vcpu_id, 593 __pa(gsb->hdr), gsb->capacity, &i); 594 return rc; 595 } 596 EXPORT_SYMBOL_GPL(kvmppc_gsb_send); 597 598 /** 599 * kvmppc_gsb_recv - request all elements in the buffer have their value 600 * updated. 601 * @gsb: guest state buffer 602 * @flags: guest wide or thread wide 603 * 604 * Performs the H_GUEST_GET_STATE hcall for the guest state buffer. 605 * After returning from the hcall the guest state elements that were 606 * present in the buffer will have updated values from the hypervisor. 607 */ 608 int kvmppc_gsb_recv(struct kvmppc_gs_buff *gsb, unsigned long flags) 609 { 610 unsigned long hflags = 0; 611 unsigned long i; 612 int rc; 613 614 if (flags & KVMPPC_GS_FLAGS_WIDE) 615 hflags |= H_GUEST_FLAGS_WIDE; 616 617 rc = plpar_guest_get_state(hflags, gsb->guest_id, gsb->vcpu_id, 618 __pa(gsb->hdr), gsb->capacity, &i); 619 return rc; 620 } 621 EXPORT_SYMBOL_GPL(kvmppc_gsb_recv); 622
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.