Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: PPC: Add helper library for Guest State Buffers

The PAPR "Nestedv2" guest API introduces the concept of a Guest State
Buffer for communication about L2 guests between L1 and L0 hosts.

In the new API, the L0 manages the L2 on behalf of the L1. This means
that if the L1 needs to change L2 state (e.g. GPRs, SPRs, partition
table...), it must request the L0 perform the modification. If the
nested host needs to read L2 state likewise this request must
go through the L0.

The Guest State Buffer is a Type-Length-Value style data format defined
in the PAPR which assigns all relevant partition state a unique
identity. Unlike a typical TLV format the length is redundant as the
length of each identity is fixed but is included for checking
correctness.

A guest state buffer consists of an element count followed by a stream
of elements, where elements are composed of an ID number, data length,
then the data:

Header:

<---4 bytes--->
+----------------+-----
| Element Count | Elements...
+----------------+-----

Element:

<----2 bytes---> <-2 bytes-> <-Length bytes->
+----------------+-----------+----------------+
| Guest State ID | Length | Data |
+----------------+-----------+----------------+

Guest State IDs have other attributes defined in the PAPR such as
whether they are per thread or per guest, or read-only.

Introduce a library for using guest state buffers. This includes support
for actions such as creating buffers, adding elements to buffers,
reading the value of elements and parsing buffers. This will be used
later by the nestedv2 guest support.

Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20230914030600.16993-9-jniethe5@gmail.com

authored by

Jordan Niethe and committed by
Michael Ellerman
6ccbbc33 6de2e837

+1818
+12
arch/powerpc/Kconfig.debug
··· 82 82 bool "Run self-tests of the MSI bitmap code" 83 83 depends on DEBUG_KERNEL 84 84 85 + config GUEST_STATE_BUFFER_TEST 86 + def_tristate n 87 + prompt "Enable Guest State Buffer unit tests" 88 + depends on KUNIT 89 + depends on KVM_BOOK3S_HV_POSSIBLE 90 + default KUNIT_ALL_TESTS 91 + help 92 + The Guest State Buffer is a data format specified in the PAPR. 93 + It is by hcalls to communicate the state of L2 guests between 94 + the L1 and L0 hypervisors. Enable unit tests for the library 95 + used to create and use guest state buffers. 96 + 85 97 config PPC_IRQ_SOFT_MASK_DEBUG 86 98 bool "Include extra checks for powerpc irq soft masking" 87 99 depends on PPC64
+904
arch/powerpc/include/asm/guest-state-buffer.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Interface based on include/net/netlink.h 4 + */ 5 + #ifndef _ASM_POWERPC_GUEST_STATE_BUFFER_H 6 + #define _ASM_POWERPC_GUEST_STATE_BUFFER_H 7 + 8 + #include <linux/gfp.h> 9 + #include <linux/bitmap.h> 10 + #include <asm/plpar_wrappers.h> 11 + 12 + /************************************************************************** 13 + * Guest State Buffer Constants 14 + **************************************************************************/ 15 + /* Element without a value and any length */ 16 + #define KVMPPC_GSID_BLANK 0x0000 17 + /* Size required for the L0's internal VCPU representation */ 18 + #define KVMPPC_GSID_HOST_STATE_SIZE 0x0001 19 + /* Minimum size for the H_GUEST_RUN_VCPU output buffer */ 20 + #define KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE 0x0002 21 + /* "Logical" PVR value as defined in the PAPR */ 22 + #define KVMPPC_GSID_LOGICAL_PVR 0x0003 23 + /* L0 relative timebase offset */ 24 + #define KVMPPC_GSID_TB_OFFSET 0x0004 25 + /* Partition Scoped Page Table Info */ 26 + #define KVMPPC_GSID_PARTITION_TABLE 0x0005 27 + /* Process Table Info */ 28 + #define KVMPPC_GSID_PROCESS_TABLE 0x0006 29 + 30 + /* H_GUEST_RUN_VCPU input buffer Info */ 31 + #define KVMPPC_GSID_RUN_INPUT 0x0C00 32 + /* H_GUEST_RUN_VCPU output buffer Info */ 33 + #define KVMPPC_GSID_RUN_OUTPUT 0x0C01 34 + #define KVMPPC_GSID_VPA 0x0C02 35 + 36 + #define KVMPPC_GSID_GPR(x) (0x1000 + (x)) 37 + #define KVMPPC_GSID_HDEC_EXPIRY_TB 0x1020 38 + #define KVMPPC_GSID_NIA 0x1021 39 + #define KVMPPC_GSID_MSR 0x1022 40 + #define KVMPPC_GSID_LR 0x1023 41 + #define KVMPPC_GSID_XER 0x1024 42 + #define KVMPPC_GSID_CTR 0x1025 43 + #define KVMPPC_GSID_CFAR 0x1026 44 + #define KVMPPC_GSID_SRR0 0x1027 45 + #define KVMPPC_GSID_SRR1 0x1028 46 + #define KVMPPC_GSID_DAR 0x1029 47 + #define KVMPPC_GSID_DEC_EXPIRY_TB 0x102A 48 + #define KVMPPC_GSID_VTB 0x102B 49 + #define KVMPPC_GSID_LPCR 0x102C 50 + #define KVMPPC_GSID_HFSCR 0x102D 51 + #define KVMPPC_GSID_FSCR 0x102E 52 + #define KVMPPC_GSID_FPSCR 0x102F 53 + #define KVMPPC_GSID_DAWR0 0x1030 54 + #define KVMPPC_GSID_DAWR1 0x1031 55 + #define KVMPPC_GSID_CIABR 0x1032 56 + #define KVMPPC_GSID_PURR 0x1033 57 + #define KVMPPC_GSID_SPURR 0x1034 58 + #define KVMPPC_GSID_IC 0x1035 59 + #define KVMPPC_GSID_SPRG0 0x1036 60 + #define KVMPPC_GSID_SPRG1 0x1037 61 + #define KVMPPC_GSID_SPRG2 0x1038 62 + #define KVMPPC_GSID_SPRG3 0x1039 63 + #define KVMPPC_GSID_PPR 0x103A 64 + #define KVMPPC_GSID_MMCR(x) (0x103B + (x)) 65 + #define KVMPPC_GSID_MMCRA 0x103F 66 + #define KVMPPC_GSID_SIER(x) (0x1040 + (x)) 67 + #define KVMPPC_GSID_BESCR 0x1043 68 + #define KVMPPC_GSID_EBBHR 0x1044 69 + #define KVMPPC_GSID_EBBRR 0x1045 70 + #define KVMPPC_GSID_AMR 0x1046 71 + #define KVMPPC_GSID_IAMR 0x1047 72 + #define KVMPPC_GSID_AMOR 0x1048 73 + #define KVMPPC_GSID_UAMOR 0x1049 74 + #define KVMPPC_GSID_SDAR 0x104A 75 + #define KVMPPC_GSID_SIAR 0x104B 76 + #define KVMPPC_GSID_DSCR 0x104C 77 + #define KVMPPC_GSID_TAR 0x104D 78 + #define KVMPPC_GSID_DEXCR 0x104E 79 + #define KVMPPC_GSID_HDEXCR 0x104F 80 + #define KVMPPC_GSID_HASHKEYR 0x1050 81 + #define KVMPPC_GSID_HASHPKEYR 0x1051 82 + #define KVMPPC_GSID_CTRL 0x1052 83 + 84 + #define KVMPPC_GSID_CR 0x2000 85 + #define KVMPPC_GSID_PIDR 0x2001 86 + #define KVMPPC_GSID_DSISR 0x2002 87 + #define KVMPPC_GSID_VSCR 0x2003 88 + #define KVMPPC_GSID_VRSAVE 0x2004 89 + #define KVMPPC_GSID_DAWRX0 0x2005 90 + #define KVMPPC_GSID_DAWRX1 0x2006 91 + #define KVMPPC_GSID_PMC(x) (0x2007 + (x)) 92 + #define KVMPPC_GSID_WORT 0x200D 93 + #define KVMPPC_GSID_PSPB 0x200E 94 + 95 + #define KVMPPC_GSID_VSRS(x) (0x3000 + (x)) 96 + 97 + #define KVMPPC_GSID_HDAR 0xF000 98 + #define KVMPPC_GSID_HDSISR 0xF001 99 + #define KVMPPC_GSID_HEIR 0xF002 100 + #define KVMPPC_GSID_ASDR 0xF003 101 + 102 + #define KVMPPC_GSE_GUESTWIDE_START KVMPPC_GSID_BLANK 103 + #define KVMPPC_GSE_GUESTWIDE_END KVMPPC_GSID_PROCESS_TABLE 104 + #define KVMPPC_GSE_GUESTWIDE_COUNT \ 105 + (KVMPPC_GSE_GUESTWIDE_END - KVMPPC_GSE_GUESTWIDE_START + 1) 106 + 107 + #define KVMPPC_GSE_META_START KVMPPC_GSID_RUN_INPUT 108 + #define KVMPPC_GSE_META_END KVMPPC_GSID_VPA 109 + #define KVMPPC_GSE_META_COUNT (KVMPPC_GSE_META_END - KVMPPC_GSE_META_START + 1) 110 + 111 + #define KVMPPC_GSE_DW_REGS_START KVMPPC_GSID_GPR(0) 112 + #define KVMPPC_GSE_DW_REGS_END KVMPPC_GSID_CTRL 113 + #define KVMPPC_GSE_DW_REGS_COUNT \ 114 + (KVMPPC_GSE_DW_REGS_END - KVMPPC_GSE_DW_REGS_START + 1) 115 + 116 + #define KVMPPC_GSE_W_REGS_START KVMPPC_GSID_CR 117 + #define KVMPPC_GSE_W_REGS_END KVMPPC_GSID_PSPB 118 + #define KVMPPC_GSE_W_REGS_COUNT \ 119 + (KVMPPC_GSE_W_REGS_END - KVMPPC_GSE_W_REGS_START + 1) 120 + 121 + #define KVMPPC_GSE_VSRS_START KVMPPC_GSID_VSRS(0) 122 + #define KVMPPC_GSE_VSRS_END KVMPPC_GSID_VSRS(63) 123 + #define KVMPPC_GSE_VSRS_COUNT (KVMPPC_GSE_VSRS_END - KVMPPC_GSE_VSRS_START + 1) 124 + 125 + #define KVMPPC_GSE_INTR_REGS_START KVMPPC_GSID_HDAR 126 + #define KVMPPC_GSE_INTR_REGS_END KVMPPC_GSID_ASDR 127 + #define KVMPPC_GSE_INTR_REGS_COUNT \ 128 + (KVMPPC_GSE_INTR_REGS_END - KVMPPC_GSE_INTR_REGS_START + 1) 129 + 130 + #define KVMPPC_GSE_IDEN_COUNT \ 131 + (KVMPPC_GSE_GUESTWIDE_COUNT + KVMPPC_GSE_META_COUNT + \ 132 + KVMPPC_GSE_DW_REGS_COUNT + KVMPPC_GSE_W_REGS_COUNT + \ 133 + KVMPPC_GSE_VSRS_COUNT + KVMPPC_GSE_INTR_REGS_COUNT) 134 + 135 + /** 136 + * Ranges of guest state buffer elements 137 + */ 138 + enum { 139 + KVMPPC_GS_CLASS_GUESTWIDE = 0x01, 140 + KVMPPC_GS_CLASS_META = 0x02, 141 + KVMPPC_GS_CLASS_DWORD_REG = 0x04, 142 + KVMPPC_GS_CLASS_WORD_REG = 0x08, 143 + KVMPPC_GS_CLASS_VECTOR = 0x10, 144 + KVMPPC_GS_CLASS_INTR = 0x20, 145 + }; 146 + 147 + /** 148 + * Types of guest state buffer elements 149 + */ 150 + enum { 151 + KVMPPC_GSE_BE32, 152 + KVMPPC_GSE_BE64, 153 + KVMPPC_GSE_VEC128, 154 + KVMPPC_GSE_PARTITION_TABLE, 155 + KVMPPC_GSE_PROCESS_TABLE, 156 + KVMPPC_GSE_BUFFER, 157 + __KVMPPC_GSE_TYPE_MAX, 158 + }; 159 + 160 + /** 161 + * Flags for guest state elements 162 + */ 163 + enum { 164 + KVMPPC_GS_FLAGS_WIDE = 0x01, 165 + }; 166 + 167 + /** 168 + * struct kvmppc_gs_part_table - deserialized partition table information 169 + * element 170 + * @address: start of the partition table 171 + * @ea_bits: number of bits in the effective address 172 + * @gpd_size: root page directory size 173 + */ 174 + struct kvmppc_gs_part_table { 175 + u64 address; 176 + u64 ea_bits; 177 + u64 gpd_size; 178 + }; 179 + 180 + /** 181 + * struct kvmppc_gs_proc_table - deserialized process table information element 182 + * @address: start of the process table 183 + * @gpd_size: process table size 184 + */ 185 + struct kvmppc_gs_proc_table { 186 + u64 address; 187 + u64 gpd_size; 188 + }; 189 + 190 + /** 191 + * struct kvmppc_gs_buff_info - deserialized meta guest state buffer information 192 + * @address: start of the guest state buffer 193 + * @size: size of the guest state buffer 194 + */ 195 + struct kvmppc_gs_buff_info { 196 + u64 address; 197 + u64 size; 198 + }; 199 + 200 + /** 201 + * struct kvmppc_gs_header - serialized guest state buffer header 202 + * @nelem: count of guest state elements in the buffer 203 + * @data: start of the stream of elements in the buffer 204 + */ 205 + struct kvmppc_gs_header { 206 + __be32 nelems; 207 + char data[]; 208 + } __packed; 209 + 210 + /** 211 + * struct kvmppc_gs_elem - serialized guest state buffer element 212 + * @iden: Guest State ID 213 + * @len: length of data 214 + * @data: the guest state buffer element's value 215 + */ 216 + struct kvmppc_gs_elem { 217 + __be16 iden; 218 + __be16 len; 219 + char data[]; 220 + } __packed; 221 + 222 + /** 223 + * struct kvmppc_gs_buff - a guest state buffer with metadata. 224 + * @capacity: total length of the buffer 225 + * @len: current length of the elements and header 226 + * @guest_id: guest id associated with the buffer 227 + * @vcpu_id: vcpu_id associated with the buffer 228 + * @hdr: the serialised guest state buffer 229 + */ 230 + struct kvmppc_gs_buff { 231 + size_t capacity; 232 + size_t len; 233 + unsigned long guest_id; 234 + unsigned long vcpu_id; 235 + struct kvmppc_gs_header *hdr; 236 + }; 237 + 238 + /** 239 + * struct kvmppc_gs_bitmap - a bitmap for element ids 240 + * @bitmap: a bitmap large enough for all Guest State IDs 241 + */ 242 + struct kvmppc_gs_bitmap { 243 + /* private: */ 244 + DECLARE_BITMAP(bitmap, KVMPPC_GSE_IDEN_COUNT); 245 + }; 246 + 247 + /** 248 + * struct kvmppc_gs_parser - a map of element ids to locations in a buffer 249 + * @iterator: bitmap used for iterating 250 + * @gses: contains the pointers to elements 251 + * 252 + * A guest state parser is used for deserialising a guest state buffer. 253 + * Given a buffer, it then allows looking up guest state elements using 254 + * a guest state id. 255 + */ 256 + struct kvmppc_gs_parser { 257 + /* private: */ 258 + struct kvmppc_gs_bitmap iterator; 259 + struct kvmppc_gs_elem *gses[KVMPPC_GSE_IDEN_COUNT]; 260 + }; 261 + 262 + enum { 263 + GSM_GUEST_WIDE = 0x1, 264 + GSM_SEND = 0x2, 265 + GSM_RECEIVE = 0x4, 266 + GSM_GSB_OWNER = 0x8, 267 + }; 268 + 269 + struct kvmppc_gs_msg; 270 + 271 + /** 272 + * struct kvmppc_gs_msg_ops - guest state message behavior 273 + * @get_size: maximum size required for the message data 274 + * @fill_info: serializes to the guest state buffer format 275 + * @refresh_info: dserializes from the guest state buffer format 276 + */ 277 + struct kvmppc_gs_msg_ops { 278 + size_t (*get_size)(struct kvmppc_gs_msg *gsm); 279 + int (*fill_info)(struct kvmppc_gs_buff *gsb, struct kvmppc_gs_msg *gsm); 280 + int (*refresh_info)(struct kvmppc_gs_msg *gsm, 281 + struct kvmppc_gs_buff *gsb); 282 + }; 283 + 284 + /** 285 + * struct kvmppc_gs_msg - a guest state message 286 + * @bitmap: the guest state ids that should be included 287 + * @ops: modify message behavior for reading and writing to buffers 288 + * @flags: guest wide or thread wide 289 + * @data: location where buffer data will be written to or from. 290 + * 291 + * A guest state message is allows flexibility in sending in receiving data 292 + * in a guest state buffer format. 293 + */ 294 + struct kvmppc_gs_msg { 295 + struct kvmppc_gs_bitmap bitmap; 296 + struct kvmppc_gs_msg_ops *ops; 297 + unsigned long flags; 298 + void *data; 299 + }; 300 + 301 + /************************************************************************** 302 + * Guest State IDs 303 + **************************************************************************/ 304 + 305 + u16 kvmppc_gsid_size(u16 iden); 306 + unsigned long kvmppc_gsid_flags(u16 iden); 307 + u64 kvmppc_gsid_mask(u16 iden); 308 + 309 + /************************************************************************** 310 + * Guest State Buffers 311 + **************************************************************************/ 312 + struct kvmppc_gs_buff *kvmppc_gsb_new(size_t size, unsigned long guest_id, 313 + unsigned long vcpu_id, gfp_t flags); 314 + void kvmppc_gsb_free(struct kvmppc_gs_buff *gsb); 315 + void *kvmppc_gsb_put(struct kvmppc_gs_buff *gsb, size_t size); 316 + 317 + /** 318 + * kvmppc_gsb_header() - the header of a guest state buffer 319 + * @gsb: guest state buffer 320 + * 321 + * Returns a pointer to the buffer header. 322 + */ 323 + static inline struct kvmppc_gs_header * 324 + kvmppc_gsb_header(struct kvmppc_gs_buff *gsb) 325 + { 326 + return gsb->hdr; 327 + } 328 + 329 + /** 330 + * kvmppc_gsb_data() - the elements of a guest state buffer 331 + * @gsb: guest state buffer 332 + * 333 + * Returns a pointer to the first element of the buffer data. 334 + */ 335 + static inline struct kvmppc_gs_elem *kvmppc_gsb_data(struct kvmppc_gs_buff *gsb) 336 + { 337 + return (struct kvmppc_gs_elem *)kvmppc_gsb_header(gsb)->data; 338 + } 339 + 340 + /** 341 + * kvmppc_gsb_len() - the current length of a guest state buffer 342 + * @gsb: guest state buffer 343 + * 344 + * Returns the length including the header of a buffer. 345 + */ 346 + static inline size_t kvmppc_gsb_len(struct kvmppc_gs_buff *gsb) 347 + { 348 + return gsb->len; 349 + } 350 + 351 + /** 352 + * kvmppc_gsb_capacity() - the capacity of a guest state buffer 353 + * @gsb: guest state buffer 354 + * 355 + * Returns the capacity of a buffer. 356 + */ 357 + static inline size_t kvmppc_gsb_capacity(struct kvmppc_gs_buff *gsb) 358 + { 359 + return gsb->capacity; 360 + } 361 + 362 + /** 363 + * kvmppc_gsb_paddress() - the physical address of buffer 364 + * @gsb: guest state buffer 365 + * 366 + * Returns the physical address of the buffer. 367 + */ 368 + static inline u64 kvmppc_gsb_paddress(struct kvmppc_gs_buff *gsb) 369 + { 370 + return __pa(kvmppc_gsb_header(gsb)); 371 + } 372 + 373 + /** 374 + * kvmppc_gsb_nelems() - the number of elements in a buffer 375 + * @gsb: guest state buffer 376 + * 377 + * Returns the number of elements in a buffer 378 + */ 379 + static inline u32 kvmppc_gsb_nelems(struct kvmppc_gs_buff *gsb) 380 + { 381 + return be32_to_cpu(kvmppc_gsb_header(gsb)->nelems); 382 + } 383 + 384 + /** 385 + * kvmppc_gsb_reset() - empty a guest state buffer 386 + * @gsb: guest state buffer 387 + * 388 + * Reset the number of elements and length of buffer to empty. 389 + */ 390 + static inline void kvmppc_gsb_reset(struct kvmppc_gs_buff *gsb) 391 + { 392 + kvmppc_gsb_header(gsb)->nelems = cpu_to_be32(0); 393 + gsb->len = sizeof(struct kvmppc_gs_header); 394 + } 395 + 396 + /** 397 + * kvmppc_gsb_data_len() - the length of a buffer excluding the header 398 + * @gsb: guest state buffer 399 + * 400 + * Returns the length of a buffer excluding the header 401 + */ 402 + static inline size_t kvmppc_gsb_data_len(struct kvmppc_gs_buff *gsb) 403 + { 404 + return gsb->len - sizeof(struct kvmppc_gs_header); 405 + } 406 + 407 + /** 408 + * kvmppc_gsb_data_cap() - the capacity of a buffer excluding the header 409 + * @gsb: guest state buffer 410 + * 411 + * Returns the capacity of a buffer excluding the header 412 + */ 413 + static inline size_t kvmppc_gsb_data_cap(struct kvmppc_gs_buff *gsb) 414 + { 415 + return gsb->capacity - sizeof(struct kvmppc_gs_header); 416 + } 417 + 418 + /** 419 + * kvmppc_gsb_for_each_elem - iterate over the elements in a buffer 420 + * @i: loop counter 421 + * @pos: set to current element 422 + * @gsb: guest state buffer 423 + * @rem: initialized to buffer capacity, holds bytes currently remaining in 424 + * stream 425 + */ 426 + #define kvmppc_gsb_for_each_elem(i, pos, gsb, rem) \ 427 + kvmppc_gse_for_each_elem(i, kvmppc_gsb_nelems(gsb), pos, \ 428 + kvmppc_gsb_data(gsb), \ 429 + kvmppc_gsb_data_cap(gsb), rem) 430 + 431 + /************************************************************************** 432 + * Guest State Elements 433 + **************************************************************************/ 434 + 435 + /** 436 + * kvmppc_gse_iden() - guest state ID of element 437 + * @gse: guest state element 438 + * 439 + * Return the guest state ID in host endianness. 440 + */ 441 + static inline u16 kvmppc_gse_iden(const struct kvmppc_gs_elem *gse) 442 + { 443 + return be16_to_cpu(gse->iden); 444 + } 445 + 446 + /** 447 + * kvmppc_gse_len() - length of guest state element data 448 + * @gse: guest state element 449 + * 450 + * Returns the length of guest state element data 451 + */ 452 + static inline u16 kvmppc_gse_len(const struct kvmppc_gs_elem *gse) 453 + { 454 + return be16_to_cpu(gse->len); 455 + } 456 + 457 + /** 458 + * kvmppc_gse_total_len() - total length of guest state element 459 + * @gse: guest state element 460 + * 461 + * Returns the length of the data plus the ID and size header. 462 + */ 463 + static inline u16 kvmppc_gse_total_len(const struct kvmppc_gs_elem *gse) 464 + { 465 + return be16_to_cpu(gse->len) + sizeof(*gse); 466 + } 467 + 468 + /** 469 + * kvmppc_gse_total_size() - space needed for a given data length 470 + * @size: data length 471 + * 472 + * Returns size plus the space needed for the ID and size header. 473 + */ 474 + static inline u16 kvmppc_gse_total_size(u16 size) 475 + { 476 + return sizeof(struct kvmppc_gs_elem) + size; 477 + } 478 + 479 + /** 480 + * kvmppc_gse_data() - pointer to data of a guest state element 481 + * @gse: guest state element 482 + * 483 + * Returns a pointer to the beginning of guest state element data. 484 + */ 485 + static inline void *kvmppc_gse_data(const struct kvmppc_gs_elem *gse) 486 + { 487 + return (void *)gse->data; 488 + } 489 + 490 + /** 491 + * kvmppc_gse_ok() - checks space exists for guest state element 492 + * @gse: guest state element 493 + * @remaining: bytes of space remaining 494 + * 495 + * Returns true if the guest state element can fit in remaining space. 496 + */ 497 + static inline bool kvmppc_gse_ok(const struct kvmppc_gs_elem *gse, 498 + int remaining) 499 + { 500 + return remaining >= kvmppc_gse_total_len(gse); 501 + } 502 + 503 + /** 504 + * kvmppc_gse_next() - iterate to the next guest state element in a stream 505 + * @gse: stream of guest state elements 506 + * @remaining: length of the guest element stream 507 + * 508 + * Returns the next guest state element in a stream of elements. The length of 509 + * the stream is updated in remaining. 510 + */ 511 + static inline struct kvmppc_gs_elem * 512 + kvmppc_gse_next(const struct kvmppc_gs_elem *gse, int *remaining) 513 + { 514 + int len = sizeof(*gse) + kvmppc_gse_len(gse); 515 + 516 + *remaining -= len; 517 + return (struct kvmppc_gs_elem *)(gse->data + kvmppc_gse_len(gse)); 518 + } 519 + 520 + /** 521 + * kvmppc_gse_for_each_elem - iterate over a stream of guest state elements 522 + * @i: loop counter 523 + * @max: number of elements 524 + * @pos: set to current element 525 + * @head: head of elements 526 + * @len: length of the stream 527 + * @rem: initialized to len, holds bytes currently remaining elements 528 + */ 529 + #define kvmppc_gse_for_each_elem(i, max, pos, head, len, rem) \ 530 + for (i = 0, pos = head, rem = len; kvmppc_gse_ok(pos, rem) && i < max; \ 531 + pos = kvmppc_gse_next(pos, &(rem)), i++) 532 + 533 + int __kvmppc_gse_put(struct kvmppc_gs_buff *gsb, u16 iden, u16 size, 534 + const void *data); 535 + int kvmppc_gse_parse(struct kvmppc_gs_parser *gsp, struct kvmppc_gs_buff *gsb); 536 + 537 + /** 538 + * kvmppc_gse_put_be32() - add a be32 guest state element to a buffer 539 + * @gsb: guest state buffer to add element to 540 + * @iden: guest state ID 541 + * @val: big endian value 542 + */ 543 + static inline int kvmppc_gse_put_be32(struct kvmppc_gs_buff *gsb, u16 iden, 544 + __be32 val) 545 + { 546 + __be32 tmp; 547 + 548 + tmp = val; 549 + return __kvmppc_gse_put(gsb, iden, sizeof(__be32), &tmp); 550 + } 551 + 552 + /** 553 + * kvmppc_gse_put_u32() - add a host endian 32bit int guest state element to a 554 + * buffer 555 + * @gsb: guest state buffer to add element to 556 + * @iden: guest state ID 557 + * @val: host endian value 558 + */ 559 + static inline int kvmppc_gse_put_u32(struct kvmppc_gs_buff *gsb, u16 iden, 560 + u32 val) 561 + { 562 + __be32 tmp; 563 + 564 + val &= kvmppc_gsid_mask(iden); 565 + tmp = cpu_to_be32(val); 566 + return kvmppc_gse_put_be32(gsb, iden, tmp); 567 + } 568 + 569 + /** 570 + * kvmppc_gse_put_be64() - add a be64 guest state element to a buffer 571 + * @gsb: guest state buffer to add element to 572 + * @iden: guest state ID 573 + * @val: big endian value 574 + */ 575 + static inline int kvmppc_gse_put_be64(struct kvmppc_gs_buff *gsb, u16 iden, 576 + __be64 val) 577 + { 578 + __be64 tmp; 579 + 580 + tmp = val; 581 + return __kvmppc_gse_put(gsb, iden, sizeof(__be64), &tmp); 582 + } 583 + 584 + /** 585 + * kvmppc_gse_put_u64() - add a host endian 64bit guest state element to a 586 + * buffer 587 + * @gsb: guest state buffer to add element to 588 + * @iden: guest state ID 589 + * @val: host endian value 590 + */ 591 + static inline int kvmppc_gse_put_u64(struct kvmppc_gs_buff *gsb, u16 iden, 592 + u64 val) 593 + { 594 + __be64 tmp; 595 + 596 + val &= kvmppc_gsid_mask(iden); 597 + tmp = cpu_to_be64(val); 598 + return kvmppc_gse_put_be64(gsb, iden, tmp); 599 + } 600 + 601 + /** 602 + * __kvmppc_gse_put_reg() - add a register type guest state element to a buffer 603 + * @gsb: guest state buffer to add element to 604 + * @iden: guest state ID 605 + * @val: host endian value 606 + * 607 + * Adds a register type guest state element. Uses the guest state ID for 608 + * determining the length of the guest element. If the guest state ID has 609 + * bits that can not be set they will be cleared. 610 + */ 611 + static inline int __kvmppc_gse_put_reg(struct kvmppc_gs_buff *gsb, u16 iden, 612 + u64 val) 613 + { 614 + val &= kvmppc_gsid_mask(iden); 615 + if (kvmppc_gsid_size(iden) == sizeof(u64)) 616 + return kvmppc_gse_put_u64(gsb, iden, val); 617 + 618 + if (kvmppc_gsid_size(iden) == sizeof(u32)) { 619 + u32 tmp; 620 + 621 + tmp = (u32)val; 622 + if (tmp != val) 623 + return -EINVAL; 624 + 625 + return kvmppc_gse_put_u32(gsb, iden, tmp); 626 + } 627 + return -EINVAL; 628 + } 629 + 630 + /** 631 + * kvmppc_gse_put_vector128() - add a vector guest state element to a buffer 632 + * @gsb: guest state buffer to add element to 633 + * @iden: guest state ID 634 + * @val: 16 byte vector value 635 + */ 636 + static inline int kvmppc_gse_put_vector128(struct kvmppc_gs_buff *gsb, u16 iden, 637 + vector128 *val) 638 + { 639 + __be64 tmp[2] = { 0 }; 640 + union { 641 + __vector128 v; 642 + u64 dw[2]; 643 + } u; 644 + 645 + u.v = *val; 646 + tmp[0] = cpu_to_be64(u.dw[TS_FPROFFSET]); 647 + #ifdef CONFIG_VSX 648 + tmp[1] = cpu_to_be64(u.dw[TS_VSRLOWOFFSET]); 649 + #endif 650 + return __kvmppc_gse_put(gsb, iden, sizeof(tmp), &tmp); 651 + } 652 + 653 + /** 654 + * kvmppc_gse_put_part_table() - add a partition table guest state element to a 655 + * buffer 656 + * @gsb: guest state buffer to add element to 657 + * @iden: guest state ID 658 + * @val: partition table value 659 + */ 660 + static inline int kvmppc_gse_put_part_table(struct kvmppc_gs_buff *gsb, 661 + u16 iden, 662 + struct kvmppc_gs_part_table val) 663 + { 664 + __be64 tmp[3]; 665 + 666 + tmp[0] = cpu_to_be64(val.address); 667 + tmp[1] = cpu_to_be64(val.ea_bits); 668 + tmp[2] = cpu_to_be64(val.gpd_size); 669 + return __kvmppc_gse_put(gsb, KVMPPC_GSID_PARTITION_TABLE, sizeof(tmp), 670 + &tmp); 671 + } 672 + 673 + /** 674 + * kvmppc_gse_put_proc_table() - add a process table guest state element to a 675 + * buffer 676 + * @gsb: guest state buffer to add element to 677 + * @iden: guest state ID 678 + * @val: process table value 679 + */ 680 + static inline int kvmppc_gse_put_proc_table(struct kvmppc_gs_buff *gsb, 681 + u16 iden, 682 + struct kvmppc_gs_proc_table val) 683 + { 684 + __be64 tmp[2]; 685 + 686 + tmp[0] = cpu_to_be64(val.address); 687 + tmp[1] = cpu_to_be64(val.gpd_size); 688 + return __kvmppc_gse_put(gsb, KVMPPC_GSID_PROCESS_TABLE, sizeof(tmp), 689 + &tmp); 690 + } 691 + 692 + /** 693 + * kvmppc_gse_put_buff_info() - adds a GSB description guest state element to a 694 + * buffer 695 + * @gsb: guest state buffer to add element to 696 + * @iden: guest state ID 697 + * @val: guest state buffer description value 698 + */ 699 + static inline int kvmppc_gse_put_buff_info(struct kvmppc_gs_buff *gsb, u16 iden, 700 + struct kvmppc_gs_buff_info val) 701 + { 702 + __be64 tmp[2]; 703 + 704 + tmp[0] = cpu_to_be64(val.address); 705 + tmp[1] = cpu_to_be64(val.size); 706 + return __kvmppc_gse_put(gsb, iden, sizeof(tmp), &tmp); 707 + } 708 + 709 + int __kvmppc_gse_put(struct kvmppc_gs_buff *gsb, u16 iden, u16 size, 710 + const void *data); 711 + 712 + /** 713 + * kvmppc_gse_get_be32() - return the data of a be32 element 714 + * @gse: guest state element 715 + */ 716 + static inline __be32 kvmppc_gse_get_be32(const struct kvmppc_gs_elem *gse) 717 + { 718 + if (WARN_ON(kvmppc_gse_len(gse) != sizeof(__be32))) 719 + return 0; 720 + return *(__be32 *)kvmppc_gse_data(gse); 721 + } 722 + 723 + /** 724 + * kvmppc_gse_get_u32() - return the data of a be32 element in host endianness 725 + * @gse: guest state element 726 + */ 727 + static inline u32 kvmppc_gse_get_u32(const struct kvmppc_gs_elem *gse) 728 + { 729 + return be32_to_cpu(kvmppc_gse_get_be32(gse)); 730 + } 731 + 732 + /** 733 + * kvmppc_gse_get_be64() - return the data of a be64 element 734 + * @gse: guest state element 735 + */ 736 + static inline __be64 kvmppc_gse_get_be64(const struct kvmppc_gs_elem *gse) 737 + { 738 + if (WARN_ON(kvmppc_gse_len(gse) != sizeof(__be64))) 739 + return 0; 740 + return *(__be64 *)kvmppc_gse_data(gse); 741 + } 742 + 743 + /** 744 + * kvmppc_gse_get_u64() - return the data of a be64 element in host endianness 745 + * @gse: guest state element 746 + */ 747 + static inline u64 kvmppc_gse_get_u64(const struct kvmppc_gs_elem *gse) 748 + { 749 + return be64_to_cpu(kvmppc_gse_get_be64(gse)); 750 + } 751 + 752 + /** 753 + * kvmppc_gse_get_vector128() - return the data of a vector element 754 + * @gse: guest state element 755 + */ 756 + static inline void kvmppc_gse_get_vector128(const struct kvmppc_gs_elem *gse, 757 + vector128 *v) 758 + { 759 + union { 760 + __vector128 v; 761 + u64 dw[2]; 762 + } u = { 0 }; 763 + __be64 *src; 764 + 765 + if (WARN_ON(kvmppc_gse_len(gse) != sizeof(__vector128))) 766 + *v = u.v; 767 + 768 + src = (__be64 *)kvmppc_gse_data(gse); 769 + u.dw[TS_FPROFFSET] = be64_to_cpu(src[0]); 770 + #ifdef CONFIG_VSX 771 + u.dw[TS_VSRLOWOFFSET] = be64_to_cpu(src[1]); 772 + #endif 773 + *v = u.v; 774 + } 775 + 776 + /************************************************************************** 777 + * Guest State Bitmap 778 + **************************************************************************/ 779 + 780 + bool kvmppc_gsbm_test(struct kvmppc_gs_bitmap *gsbm, u16 iden); 781 + void kvmppc_gsbm_set(struct kvmppc_gs_bitmap *gsbm, u16 iden); 782 + void kvmppc_gsbm_clear(struct kvmppc_gs_bitmap *gsbm, u16 iden); 783 + u16 kvmppc_gsbm_next(struct kvmppc_gs_bitmap *gsbm, u16 prev); 784 + 785 + /** 786 + * kvmppc_gsbm_zero - zero the entire bitmap 787 + * @gsbm: guest state buffer bitmap 788 + */ 789 + static inline void kvmppc_gsbm_zero(struct kvmppc_gs_bitmap *gsbm) 790 + { 791 + bitmap_zero(gsbm->bitmap, KVMPPC_GSE_IDEN_COUNT); 792 + } 793 + 794 + /** 795 + * kvmppc_gsbm_fill - fill the entire bitmap 796 + * @gsbm: guest state buffer bitmap 797 + */ 798 + static inline void kvmppc_gsbm_fill(struct kvmppc_gs_bitmap *gsbm) 799 + { 800 + bitmap_fill(gsbm->bitmap, KVMPPC_GSE_IDEN_COUNT); 801 + clear_bit(0, gsbm->bitmap); 802 + } 803 + 804 + /** 805 + * kvmppc_gsbm_for_each - iterate the present guest state IDs 806 + * @gsbm: guest state buffer bitmap 807 + * @iden: current guest state ID 808 + */ 809 + #define kvmppc_gsbm_for_each(gsbm, iden) \ 810 + for (iden = kvmppc_gsbm_next(gsbm, 0); iden != 0; \ 811 + iden = kvmppc_gsbm_next(gsbm, iden)) 812 + 813 + /************************************************************************** 814 + * Guest State Parser 815 + **************************************************************************/ 816 + 817 + void kvmppc_gsp_insert(struct kvmppc_gs_parser *gsp, u16 iden, 818 + struct kvmppc_gs_elem *gse); 819 + struct kvmppc_gs_elem *kvmppc_gsp_lookup(struct kvmppc_gs_parser *gsp, 820 + u16 iden); 821 + 822 + /** 823 + * kvmppc_gsp_for_each - iterate the <guest state IDs, guest state element> 824 + * pairs 825 + * @gsp: guest state buffer bitmap 826 + * @iden: current guest state ID 827 + * @gse: guest state element 828 + */ 829 + #define kvmppc_gsp_for_each(gsp, iden, gse) \ 830 + for (iden = kvmppc_gsbm_next(&(gsp)->iterator, 0), \ 831 + gse = kvmppc_gsp_lookup((gsp), iden); \ 832 + iden != 0; iden = kvmppc_gsbm_next(&(gsp)->iterator, iden), \ 833 + gse = kvmppc_gsp_lookup((gsp), iden)) 834 + 835 + /************************************************************************** 836 + * Guest State Message 837 + **************************************************************************/ 838 + 839 + /** 840 + * kvmppc_gsm_for_each - iterate the guest state IDs included in a guest state 841 + * message 842 + * @gsp: guest state buffer bitmap 843 + * @iden: current guest state ID 844 + * @gse: guest state element 845 + */ 846 + #define kvmppc_gsm_for_each(gsm, iden) \ 847 + for (iden = kvmppc_gsbm_next(&gsm->bitmap, 0); iden != 0; \ 848 + iden = kvmppc_gsbm_next(&gsm->bitmap, iden)) 849 + 850 + int kvmppc_gsm_init(struct kvmppc_gs_msg *mgs, struct kvmppc_gs_msg_ops *ops, 851 + void *data, unsigned long flags); 852 + 853 + struct kvmppc_gs_msg *kvmppc_gsm_new(struct kvmppc_gs_msg_ops *ops, void *data, 854 + unsigned long flags, gfp_t gfp_flags); 855 + void kvmppc_gsm_free(struct kvmppc_gs_msg *gsm); 856 + size_t kvmppc_gsm_size(struct kvmppc_gs_msg *gsm); 857 + int kvmppc_gsm_fill_info(struct kvmppc_gs_msg *gsm, struct kvmppc_gs_buff *gsb); 858 + int kvmppc_gsm_refresh_info(struct kvmppc_gs_msg *gsm, 859 + struct kvmppc_gs_buff *gsb); 860 + 861 + /** 862 + * kvmppc_gsm_include - indicate a guest state ID should be included when 863 + * serializing 864 + * @gsm: guest state message 865 + * @iden: guest state ID 866 + */ 867 + static inline void kvmppc_gsm_include(struct kvmppc_gs_msg *gsm, u16 iden) 868 + { 869 + kvmppc_gsbm_set(&gsm->bitmap, iden); 870 + } 871 + 872 + /** 873 + * kvmppc_gsm_includes - check if a guest state ID will be included when 874 + * serializing 875 + * @gsm: guest state message 876 + * @iden: guest state ID 877 + */ 878 + static inline bool kvmppc_gsm_includes(struct kvmppc_gs_msg *gsm, u16 iden) 879 + { 880 + return kvmppc_gsbm_test(&gsm->bitmap, iden); 881 + } 882 + 883 + /** 884 + * kvmppc_gsm_includes - indicate all guest state IDs should be included when 885 + * serializing 886 + * @gsm: guest state message 887 + * @iden: guest state ID 888 + */ 889 + static inline void kvmppc_gsm_include_all(struct kvmppc_gs_msg *gsm) 890 + { 891 + kvmppc_gsbm_fill(&gsm->bitmap); 892 + } 893 + 894 + /** 895 + * kvmppc_gsm_include - clear the guest state IDs that should be included when 896 + * serializing 897 + * @gsm: guest state message 898 + */ 899 + static inline void kvmppc_gsm_reset(struct kvmppc_gs_msg *gsm) 900 + { 901 + kvmppc_gsbm_zero(&gsm->bitmap); 902 + } 903 + 904 + #endif /* _ASM_POWERPC_GUEST_STATE_BUFFER_H */
+3
arch/powerpc/kvm/Makefile
··· 87 87 book3s_hv_ras.o \ 88 88 book3s_hv_builtin.o \ 89 89 book3s_hv_p9_perf.o \ 90 + guest-state-buffer.o \ 90 91 $(kvm-book3s_64-builtin-tm-objs-y) \ 91 92 $(kvm-book3s_64-builtin-xics-objs-y) 93 + 94 + obj-$(CONFIG_GUEST_STATE_BUFFER_TEST) += test-guest-state-buffer.o 92 95 endif 93 96 94 97 kvm-book3s_64-objs-$(CONFIG_KVM_XICS) += \
+571
arch/powerpc/kvm/guest-state-buffer.c
··· 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);
+328
arch/powerpc/kvm/test-guest-state-buffer.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + 3 + #include <linux/init.h> 4 + #include <linux/log2.h> 5 + #include <kunit/test.h> 6 + 7 + #include <asm/guest-state-buffer.h> 8 + 9 + static void test_creating_buffer(struct kunit *test) 10 + { 11 + struct kvmppc_gs_buff *gsb; 12 + size_t size = 0x100; 13 + 14 + gsb = kvmppc_gsb_new(size, 0, 0, GFP_KERNEL); 15 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb); 16 + 17 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb->hdr); 18 + 19 + KUNIT_EXPECT_EQ(test, gsb->capacity, roundup_pow_of_two(size)); 20 + KUNIT_EXPECT_EQ(test, gsb->len, sizeof(__be32)); 21 + 22 + kvmppc_gsb_free(gsb); 23 + } 24 + 25 + static void test_adding_element(struct kunit *test) 26 + { 27 + const struct kvmppc_gs_elem *head, *curr; 28 + union { 29 + __vector128 v; 30 + u64 dw[2]; 31 + } u; 32 + int rem; 33 + struct kvmppc_gs_buff *gsb; 34 + size_t size = 0x1000; 35 + int i, rc; 36 + u64 data; 37 + 38 + gsb = kvmppc_gsb_new(size, 0, 0, GFP_KERNEL); 39 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb); 40 + 41 + /* Single elements, direct use of __kvmppc_gse_put() */ 42 + data = 0xdeadbeef; 43 + rc = __kvmppc_gse_put(gsb, KVMPPC_GSID_GPR(0), 8, &data); 44 + KUNIT_EXPECT_GE(test, rc, 0); 45 + 46 + head = kvmppc_gsb_data(gsb); 47 + KUNIT_EXPECT_EQ(test, kvmppc_gse_iden(head), KVMPPC_GSID_GPR(0)); 48 + KUNIT_EXPECT_EQ(test, kvmppc_gse_len(head), 8); 49 + data = 0; 50 + memcpy(&data, kvmppc_gse_data(head), 8); 51 + KUNIT_EXPECT_EQ(test, data, 0xdeadbeef); 52 + 53 + /* Multiple elements, simple wrapper */ 54 + rc = kvmppc_gse_put_u64(gsb, KVMPPC_GSID_GPR(1), 0xcafef00d); 55 + KUNIT_EXPECT_GE(test, rc, 0); 56 + 57 + u.dw[0] = 0x1; 58 + u.dw[1] = 0x2; 59 + rc = kvmppc_gse_put_vector128(gsb, KVMPPC_GSID_VSRS(0), &u.v); 60 + KUNIT_EXPECT_GE(test, rc, 0); 61 + u.dw[0] = 0x0; 62 + u.dw[1] = 0x0; 63 + 64 + kvmppc_gsb_for_each_elem(i, curr, gsb, rem) { 65 + switch (i) { 66 + case 0: 67 + KUNIT_EXPECT_EQ(test, kvmppc_gse_iden(curr), 68 + KVMPPC_GSID_GPR(0)); 69 + KUNIT_EXPECT_EQ(test, kvmppc_gse_len(curr), 8); 70 + KUNIT_EXPECT_EQ(test, kvmppc_gse_get_be64(curr), 71 + 0xdeadbeef); 72 + break; 73 + case 1: 74 + KUNIT_EXPECT_EQ(test, kvmppc_gse_iden(curr), 75 + KVMPPC_GSID_GPR(1)); 76 + KUNIT_EXPECT_EQ(test, kvmppc_gse_len(curr), 8); 77 + KUNIT_EXPECT_EQ(test, kvmppc_gse_get_u64(curr), 78 + 0xcafef00d); 79 + break; 80 + case 2: 81 + KUNIT_EXPECT_EQ(test, kvmppc_gse_iden(curr), 82 + KVMPPC_GSID_VSRS(0)); 83 + KUNIT_EXPECT_EQ(test, kvmppc_gse_len(curr), 16); 84 + kvmppc_gse_get_vector128(curr, &u.v); 85 + KUNIT_EXPECT_EQ(test, u.dw[0], 0x1); 86 + KUNIT_EXPECT_EQ(test, u.dw[1], 0x2); 87 + break; 88 + } 89 + } 90 + KUNIT_EXPECT_EQ(test, i, 3); 91 + 92 + kvmppc_gsb_reset(gsb); 93 + KUNIT_EXPECT_EQ(test, kvmppc_gsb_nelems(gsb), 0); 94 + KUNIT_EXPECT_EQ(test, kvmppc_gsb_len(gsb), 95 + sizeof(struct kvmppc_gs_header)); 96 + 97 + kvmppc_gsb_free(gsb); 98 + } 99 + 100 + static void test_gs_parsing(struct kunit *test) 101 + { 102 + struct kvmppc_gs_elem *gse; 103 + struct kvmppc_gs_parser gsp = { 0 }; 104 + struct kvmppc_gs_buff *gsb; 105 + size_t size = 0x1000; 106 + u64 tmp1, tmp2; 107 + 108 + gsb = kvmppc_gsb_new(size, 0, 0, GFP_KERNEL); 109 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb); 110 + 111 + tmp1 = 0xdeadbeefull; 112 + kvmppc_gse_put_u64(gsb, KVMPPC_GSID_GPR(0), tmp1); 113 + 114 + KUNIT_EXPECT_GE(test, kvmppc_gse_parse(&gsp, gsb), 0); 115 + 116 + gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_GPR(0)); 117 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gse); 118 + 119 + tmp2 = kvmppc_gse_get_u64(gse); 120 + KUNIT_EXPECT_EQ(test, tmp2, 0xdeadbeefull); 121 + 122 + kvmppc_gsb_free(gsb); 123 + } 124 + 125 + static void test_gs_bitmap(struct kunit *test) 126 + { 127 + struct kvmppc_gs_bitmap gsbm = { 0 }; 128 + struct kvmppc_gs_bitmap gsbm1 = { 0 }; 129 + struct kvmppc_gs_bitmap gsbm2 = { 0 }; 130 + u16 iden; 131 + int i, j; 132 + 133 + i = 0; 134 + for (u16 iden = KVMPPC_GSID_HOST_STATE_SIZE; 135 + iden <= KVMPPC_GSID_PROCESS_TABLE; iden++) { 136 + kvmppc_gsbm_set(&gsbm, iden); 137 + kvmppc_gsbm_set(&gsbm1, iden); 138 + KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden)); 139 + kvmppc_gsbm_clear(&gsbm, iden); 140 + KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden)); 141 + i++; 142 + } 143 + 144 + for (u16 iden = KVMPPC_GSID_RUN_INPUT; iden <= KVMPPC_GSID_VPA; 145 + iden++) { 146 + kvmppc_gsbm_set(&gsbm, iden); 147 + kvmppc_gsbm_set(&gsbm1, iden); 148 + KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden)); 149 + kvmppc_gsbm_clear(&gsbm, iden); 150 + KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden)); 151 + i++; 152 + } 153 + 154 + for (u16 iden = KVMPPC_GSID_GPR(0); iden <= KVMPPC_GSID_CTRL; iden++) { 155 + kvmppc_gsbm_set(&gsbm, iden); 156 + kvmppc_gsbm_set(&gsbm1, iden); 157 + KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden)); 158 + kvmppc_gsbm_clear(&gsbm, iden); 159 + KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden)); 160 + i++; 161 + } 162 + 163 + for (u16 iden = KVMPPC_GSID_CR; iden <= KVMPPC_GSID_PSPB; iden++) { 164 + kvmppc_gsbm_set(&gsbm, iden); 165 + kvmppc_gsbm_set(&gsbm1, iden); 166 + KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden)); 167 + kvmppc_gsbm_clear(&gsbm, iden); 168 + KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden)); 169 + i++; 170 + } 171 + 172 + for (u16 iden = KVMPPC_GSID_VSRS(0); iden <= KVMPPC_GSID_VSRS(63); 173 + iden++) { 174 + kvmppc_gsbm_set(&gsbm, iden); 175 + kvmppc_gsbm_set(&gsbm1, iden); 176 + KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden)); 177 + kvmppc_gsbm_clear(&gsbm, iden); 178 + KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden)); 179 + i++; 180 + } 181 + 182 + for (u16 iden = KVMPPC_GSID_HDAR; iden <= KVMPPC_GSID_ASDR; iden++) { 183 + kvmppc_gsbm_set(&gsbm, iden); 184 + kvmppc_gsbm_set(&gsbm1, iden); 185 + KUNIT_EXPECT_TRUE(test, kvmppc_gsbm_test(&gsbm, iden)); 186 + kvmppc_gsbm_clear(&gsbm, iden); 187 + KUNIT_EXPECT_FALSE(test, kvmppc_gsbm_test(&gsbm, iden)); 188 + i++; 189 + } 190 + 191 + j = 0; 192 + kvmppc_gsbm_for_each(&gsbm1, iden) 193 + { 194 + kvmppc_gsbm_set(&gsbm2, iden); 195 + j++; 196 + } 197 + KUNIT_EXPECT_EQ(test, i, j); 198 + KUNIT_EXPECT_MEMEQ(test, &gsbm1, &gsbm2, sizeof(gsbm1)); 199 + } 200 + 201 + struct kvmppc_gs_msg_test1_data { 202 + u64 a; 203 + u32 b; 204 + struct kvmppc_gs_part_table c; 205 + struct kvmppc_gs_proc_table d; 206 + struct kvmppc_gs_buff_info e; 207 + }; 208 + 209 + static size_t test1_get_size(struct kvmppc_gs_msg *gsm) 210 + { 211 + size_t size = 0; 212 + u16 ids[] = { 213 + KVMPPC_GSID_PARTITION_TABLE, 214 + KVMPPC_GSID_PROCESS_TABLE, 215 + KVMPPC_GSID_RUN_INPUT, 216 + KVMPPC_GSID_GPR(0), 217 + KVMPPC_GSID_CR, 218 + }; 219 + 220 + for (int i = 0; i < ARRAY_SIZE(ids); i++) 221 + size += kvmppc_gse_total_size(kvmppc_gsid_size(ids[i])); 222 + return size; 223 + } 224 + 225 + static int test1_fill_info(struct kvmppc_gs_buff *gsb, 226 + struct kvmppc_gs_msg *gsm) 227 + { 228 + struct kvmppc_gs_msg_test1_data *data = gsm->data; 229 + 230 + if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_GPR(0))) 231 + kvmppc_gse_put_u64(gsb, KVMPPC_GSID_GPR(0), data->a); 232 + 233 + if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_CR)) 234 + kvmppc_gse_put_u32(gsb, KVMPPC_GSID_CR, data->b); 235 + 236 + if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_PARTITION_TABLE)) 237 + kvmppc_gse_put_part_table(gsb, KVMPPC_GSID_PARTITION_TABLE, 238 + data->c); 239 + 240 + if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_PROCESS_TABLE)) 241 + kvmppc_gse_put_proc_table(gsb, KVMPPC_GSID_PARTITION_TABLE, 242 + data->d); 243 + 244 + if (kvmppc_gsm_includes(gsm, KVMPPC_GSID_RUN_INPUT)) 245 + kvmppc_gse_put_buff_info(gsb, KVMPPC_GSID_RUN_INPUT, data->e); 246 + 247 + return 0; 248 + } 249 + 250 + static int test1_refresh_info(struct kvmppc_gs_msg *gsm, 251 + struct kvmppc_gs_buff *gsb) 252 + { 253 + struct kvmppc_gs_parser gsp = { 0 }; 254 + struct kvmppc_gs_msg_test1_data *data = gsm->data; 255 + struct kvmppc_gs_elem *gse; 256 + int rc; 257 + 258 + rc = kvmppc_gse_parse(&gsp, gsb); 259 + if (rc < 0) 260 + return rc; 261 + 262 + gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_GPR(0)); 263 + if (gse) 264 + data->a = kvmppc_gse_get_u64(gse); 265 + 266 + gse = kvmppc_gsp_lookup(&gsp, KVMPPC_GSID_CR); 267 + if (gse) 268 + data->b = kvmppc_gse_get_u32(gse); 269 + 270 + return 0; 271 + } 272 + 273 + static struct kvmppc_gs_msg_ops gs_msg_test1_ops = { 274 + .get_size = test1_get_size, 275 + .fill_info = test1_fill_info, 276 + .refresh_info = test1_refresh_info, 277 + }; 278 + 279 + static void test_gs_msg(struct kunit *test) 280 + { 281 + struct kvmppc_gs_msg_test1_data test1_data = { 282 + .a = 0xdeadbeef, 283 + .b = 0x1, 284 + }; 285 + struct kvmppc_gs_msg *gsm; 286 + struct kvmppc_gs_buff *gsb; 287 + 288 + gsm = kvmppc_gsm_new(&gs_msg_test1_ops, &test1_data, GSM_SEND, 289 + GFP_KERNEL); 290 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsm); 291 + 292 + gsb = kvmppc_gsb_new(kvmppc_gsm_size(gsm), 0, 0, GFP_KERNEL); 293 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gsb); 294 + 295 + kvmppc_gsm_include(gsm, KVMPPC_GSID_PARTITION_TABLE); 296 + kvmppc_gsm_include(gsm, KVMPPC_GSID_PROCESS_TABLE); 297 + kvmppc_gsm_include(gsm, KVMPPC_GSID_RUN_INPUT); 298 + kvmppc_gsm_include(gsm, KVMPPC_GSID_GPR(0)); 299 + kvmppc_gsm_include(gsm, KVMPPC_GSID_CR); 300 + 301 + kvmppc_gsm_fill_info(gsm, gsb); 302 + 303 + memset(&test1_data, 0, sizeof(test1_data)); 304 + 305 + kvmppc_gsm_refresh_info(gsm, gsb); 306 + KUNIT_EXPECT_EQ(test, test1_data.a, 0xdeadbeef); 307 + KUNIT_EXPECT_EQ(test, test1_data.b, 0x1); 308 + 309 + kvmppc_gsm_free(gsm); 310 + } 311 + 312 + static struct kunit_case guest_state_buffer_testcases[] = { 313 + KUNIT_CASE(test_creating_buffer), 314 + KUNIT_CASE(test_adding_element), 315 + KUNIT_CASE(test_gs_bitmap), 316 + KUNIT_CASE(test_gs_parsing), 317 + KUNIT_CASE(test_gs_msg), 318 + {} 319 + }; 320 + 321 + static struct kunit_suite guest_state_buffer_test_suite = { 322 + .name = "guest_state_buffer_test", 323 + .test_cases = guest_state_buffer_testcases, 324 + }; 325 + 326 + kunit_test_suites(&guest_state_buffer_test_suite); 327 + 328 + MODULE_LICENSE("GPL");