|  | /* SPDX-License-Identifier: GPL-2.0 */ | 
|  | /* | 
|  | * Interface based on include/net/netlink.h | 
|  | */ | 
|  | #ifndef _ASM_POWERPC_GUEST_STATE_BUFFER_H | 
|  | #define _ASM_POWERPC_GUEST_STATE_BUFFER_H | 
|  |  | 
|  | #include "asm/hvcall.h" | 
|  | #include <linux/gfp.h> | 
|  | #include <linux/bitmap.h> | 
|  | #include <asm/plpar_wrappers.h> | 
|  |  | 
|  | /************************************************************************** | 
|  | * Guest State Buffer Constants | 
|  | **************************************************************************/ | 
|  | /* Element without a value and any length */ | 
|  | #define KVMPPC_GSID_BLANK			0x0000 | 
|  | /* Size required for the L0's internal VCPU representation */ | 
|  | #define KVMPPC_GSID_HOST_STATE_SIZE		0x0001 | 
|  | /* Minimum size for the H_GUEST_RUN_VCPU output buffer */ | 
|  | #define KVMPPC_GSID_RUN_OUTPUT_MIN_SIZE		0x0002 | 
|  | /* "Logical" PVR value as defined in the PAPR */ | 
|  | #define KVMPPC_GSID_LOGICAL_PVR			0x0003 | 
|  | /* L0 relative timebase offset */ | 
|  | #define KVMPPC_GSID_TB_OFFSET			0x0004 | 
|  | /* Partition Scoped Page Table Info */ | 
|  | #define KVMPPC_GSID_PARTITION_TABLE		0x0005 | 
|  | /* Process Table Info */ | 
|  | #define KVMPPC_GSID_PROCESS_TABLE		0x0006 | 
|  |  | 
|  | /* H_GUEST_RUN_VCPU input buffer Info */ | 
|  | #define KVMPPC_GSID_RUN_INPUT			0x0C00 | 
|  | /* H_GUEST_RUN_VCPU output buffer Info */ | 
|  | #define KVMPPC_GSID_RUN_OUTPUT			0x0C01 | 
|  | #define KVMPPC_GSID_VPA				0x0C02 | 
|  |  | 
|  | #define KVMPPC_GSID_GPR(x)			(0x1000 + (x)) | 
|  | #define KVMPPC_GSID_HDEC_EXPIRY_TB		0x1020 | 
|  | #define KVMPPC_GSID_NIA				0x1021 | 
|  | #define KVMPPC_GSID_MSR				0x1022 | 
|  | #define KVMPPC_GSID_LR				0x1023 | 
|  | #define KVMPPC_GSID_XER				0x1024 | 
|  | #define KVMPPC_GSID_CTR				0x1025 | 
|  | #define KVMPPC_GSID_CFAR			0x1026 | 
|  | #define KVMPPC_GSID_SRR0			0x1027 | 
|  | #define KVMPPC_GSID_SRR1			0x1028 | 
|  | #define KVMPPC_GSID_DAR				0x1029 | 
|  | #define KVMPPC_GSID_DEC_EXPIRY_TB		0x102A | 
|  | #define KVMPPC_GSID_VTB				0x102B | 
|  | #define KVMPPC_GSID_LPCR			0x102C | 
|  | #define KVMPPC_GSID_HFSCR			0x102D | 
|  | #define KVMPPC_GSID_FSCR			0x102E | 
|  | #define KVMPPC_GSID_FPSCR			0x102F | 
|  | #define KVMPPC_GSID_DAWR0			0x1030 | 
|  | #define KVMPPC_GSID_DAWR1			0x1031 | 
|  | #define KVMPPC_GSID_CIABR			0x1032 | 
|  | #define KVMPPC_GSID_PURR			0x1033 | 
|  | #define KVMPPC_GSID_SPURR			0x1034 | 
|  | #define KVMPPC_GSID_IC				0x1035 | 
|  | #define KVMPPC_GSID_SPRG0			0x1036 | 
|  | #define KVMPPC_GSID_SPRG1			0x1037 | 
|  | #define KVMPPC_GSID_SPRG2			0x1038 | 
|  | #define KVMPPC_GSID_SPRG3			0x1039 | 
|  | #define KVMPPC_GSID_PPR				0x103A | 
|  | #define KVMPPC_GSID_MMCR(x)			(0x103B + (x)) | 
|  | #define KVMPPC_GSID_MMCRA			0x103F | 
|  | #define KVMPPC_GSID_SIER(x)			(0x1040 + (x)) | 
|  | #define KVMPPC_GSID_BESCR			0x1043 | 
|  | #define KVMPPC_GSID_EBBHR			0x1044 | 
|  | #define KVMPPC_GSID_EBBRR			0x1045 | 
|  | #define KVMPPC_GSID_AMR				0x1046 | 
|  | #define KVMPPC_GSID_IAMR			0x1047 | 
|  | #define KVMPPC_GSID_AMOR			0x1048 | 
|  | #define KVMPPC_GSID_UAMOR			0x1049 | 
|  | #define KVMPPC_GSID_SDAR			0x104A | 
|  | #define KVMPPC_GSID_SIAR			0x104B | 
|  | #define KVMPPC_GSID_DSCR			0x104C | 
|  | #define KVMPPC_GSID_TAR				0x104D | 
|  | #define KVMPPC_GSID_DEXCR			0x104E | 
|  | #define KVMPPC_GSID_HDEXCR			0x104F | 
|  | #define KVMPPC_GSID_HASHKEYR			0x1050 | 
|  | #define KVMPPC_GSID_HASHPKEYR			0x1051 | 
|  | #define KVMPPC_GSID_CTRL			0x1052 | 
|  |  | 
|  | #define KVMPPC_GSID_CR				0x2000 | 
|  | #define KVMPPC_GSID_PIDR			0x2001 | 
|  | #define KVMPPC_GSID_DSISR			0x2002 | 
|  | #define KVMPPC_GSID_VSCR			0x2003 | 
|  | #define KVMPPC_GSID_VRSAVE			0x2004 | 
|  | #define KVMPPC_GSID_DAWRX0			0x2005 | 
|  | #define KVMPPC_GSID_DAWRX1			0x2006 | 
|  | #define KVMPPC_GSID_PMC(x)			(0x2007 + (x)) | 
|  | #define KVMPPC_GSID_WORT			0x200D | 
|  | #define KVMPPC_GSID_PSPB			0x200E | 
|  |  | 
|  | #define KVMPPC_GSID_VSRS(x)			(0x3000 + (x)) | 
|  |  | 
|  | #define KVMPPC_GSID_HDAR			0xF000 | 
|  | #define KVMPPC_GSID_HDSISR			0xF001 | 
|  | #define KVMPPC_GSID_HEIR			0xF002 | 
|  | #define KVMPPC_GSID_ASDR			0xF003 | 
|  |  | 
|  | #define KVMPPC_GSE_GUESTWIDE_START KVMPPC_GSID_BLANK | 
|  | #define KVMPPC_GSE_GUESTWIDE_END KVMPPC_GSID_PROCESS_TABLE | 
|  | #define KVMPPC_GSE_GUESTWIDE_COUNT \ | 
|  | (KVMPPC_GSE_GUESTWIDE_END - KVMPPC_GSE_GUESTWIDE_START + 1) | 
|  |  | 
|  | #define KVMPPC_GSE_META_START KVMPPC_GSID_RUN_INPUT | 
|  | #define KVMPPC_GSE_META_END KVMPPC_GSID_VPA | 
|  | #define KVMPPC_GSE_META_COUNT (KVMPPC_GSE_META_END - KVMPPC_GSE_META_START + 1) | 
|  |  | 
|  | #define KVMPPC_GSE_DW_REGS_START KVMPPC_GSID_GPR(0) | 
|  | #define KVMPPC_GSE_DW_REGS_END KVMPPC_GSID_CTRL | 
|  | #define KVMPPC_GSE_DW_REGS_COUNT \ | 
|  | (KVMPPC_GSE_DW_REGS_END - KVMPPC_GSE_DW_REGS_START + 1) | 
|  |  | 
|  | #define KVMPPC_GSE_W_REGS_START KVMPPC_GSID_CR | 
|  | #define KVMPPC_GSE_W_REGS_END KVMPPC_GSID_PSPB | 
|  | #define KVMPPC_GSE_W_REGS_COUNT \ | 
|  | (KVMPPC_GSE_W_REGS_END - KVMPPC_GSE_W_REGS_START + 1) | 
|  |  | 
|  | #define KVMPPC_GSE_VSRS_START KVMPPC_GSID_VSRS(0) | 
|  | #define KVMPPC_GSE_VSRS_END KVMPPC_GSID_VSRS(63) | 
|  | #define KVMPPC_GSE_VSRS_COUNT (KVMPPC_GSE_VSRS_END - KVMPPC_GSE_VSRS_START + 1) | 
|  |  | 
|  | #define KVMPPC_GSE_INTR_REGS_START KVMPPC_GSID_HDAR | 
|  | #define KVMPPC_GSE_INTR_REGS_END KVMPPC_GSID_ASDR | 
|  | #define KVMPPC_GSE_INTR_REGS_COUNT \ | 
|  | (KVMPPC_GSE_INTR_REGS_END - KVMPPC_GSE_INTR_REGS_START + 1) | 
|  |  | 
|  | #define KVMPPC_GSE_IDEN_COUNT                                 \ | 
|  | (KVMPPC_GSE_GUESTWIDE_COUNT + KVMPPC_GSE_META_COUNT + \ | 
|  | KVMPPC_GSE_DW_REGS_COUNT + KVMPPC_GSE_W_REGS_COUNT + \ | 
|  | KVMPPC_GSE_VSRS_COUNT + KVMPPC_GSE_INTR_REGS_COUNT) | 
|  |  | 
|  | /** | 
|  | * Ranges of guest state buffer elements | 
|  | */ | 
|  | enum { | 
|  | KVMPPC_GS_CLASS_GUESTWIDE = 0x01, | 
|  | KVMPPC_GS_CLASS_META = 0x02, | 
|  | KVMPPC_GS_CLASS_DWORD_REG = 0x04, | 
|  | KVMPPC_GS_CLASS_WORD_REG = 0x08, | 
|  | KVMPPC_GS_CLASS_VECTOR = 0x10, | 
|  | KVMPPC_GS_CLASS_INTR = 0x20, | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * Types of guest state buffer elements | 
|  | */ | 
|  | enum { | 
|  | KVMPPC_GSE_BE32, | 
|  | KVMPPC_GSE_BE64, | 
|  | KVMPPC_GSE_VEC128, | 
|  | KVMPPC_GSE_PARTITION_TABLE, | 
|  | KVMPPC_GSE_PROCESS_TABLE, | 
|  | KVMPPC_GSE_BUFFER, | 
|  | __KVMPPC_GSE_TYPE_MAX, | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * Flags for guest state elements | 
|  | */ | 
|  | enum { | 
|  | KVMPPC_GS_FLAGS_WIDE = 0x01, | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * struct kvmppc_gs_part_table - deserialized partition table information | 
|  | * element | 
|  | * @address: start of the partition table | 
|  | * @ea_bits: number of bits in the effective address | 
|  | * @gpd_size: root page directory size | 
|  | */ | 
|  | struct kvmppc_gs_part_table { | 
|  | u64 address; | 
|  | u64 ea_bits; | 
|  | u64 gpd_size; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * struct kvmppc_gs_proc_table - deserialized process table information element | 
|  | * @address: start of the process table | 
|  | * @gpd_size: process table size | 
|  | */ | 
|  | struct kvmppc_gs_proc_table { | 
|  | u64 address; | 
|  | u64 gpd_size; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * struct kvmppc_gs_buff_info - deserialized meta guest state buffer information | 
|  | * @address: start of the guest state buffer | 
|  | * @size: size of the guest state buffer | 
|  | */ | 
|  | struct kvmppc_gs_buff_info { | 
|  | u64 address; | 
|  | u64 size; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * struct kvmppc_gs_header - serialized guest state buffer header | 
|  | * @nelem: count of guest state elements in the buffer | 
|  | * @data: start of the stream of elements in the buffer | 
|  | */ | 
|  | struct kvmppc_gs_header { | 
|  | __be32 nelems; | 
|  | char data[]; | 
|  | } __packed; | 
|  |  | 
|  | /** | 
|  | * struct kvmppc_gs_elem - serialized guest state buffer element | 
|  | * @iden: Guest State ID | 
|  | * @len: length of data | 
|  | * @data: the guest state buffer element's value | 
|  | */ | 
|  | struct kvmppc_gs_elem { | 
|  | __be16 iden; | 
|  | __be16 len; | 
|  | char data[]; | 
|  | } __packed; | 
|  |  | 
|  | /** | 
|  | * struct kvmppc_gs_buff - a guest state buffer with metadata. | 
|  | * @capacity: total length of the buffer | 
|  | * @len: current length of the elements and header | 
|  | * @guest_id: guest id associated with the buffer | 
|  | * @vcpu_id: vcpu_id associated with the buffer | 
|  | * @hdr: the serialised guest state buffer | 
|  | */ | 
|  | struct kvmppc_gs_buff { | 
|  | size_t capacity; | 
|  | size_t len; | 
|  | unsigned long guest_id; | 
|  | unsigned long vcpu_id; | 
|  | struct kvmppc_gs_header *hdr; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * struct kvmppc_gs_bitmap - a bitmap for element ids | 
|  | * @bitmap: a bitmap large enough for all Guest State IDs | 
|  | */ | 
|  | struct kvmppc_gs_bitmap { | 
|  | /* private: */ | 
|  | DECLARE_BITMAP(bitmap, KVMPPC_GSE_IDEN_COUNT); | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * struct kvmppc_gs_parser - a map of element ids to locations in a buffer | 
|  | * @iterator: bitmap used for iterating | 
|  | * @gses: contains the pointers to elements | 
|  | * | 
|  | * A guest state parser is used for deserialising a guest state buffer. | 
|  | * Given a buffer, it then allows looking up guest state elements using | 
|  | * a guest state id. | 
|  | */ | 
|  | struct kvmppc_gs_parser { | 
|  | /* private: */ | 
|  | struct kvmppc_gs_bitmap iterator; | 
|  | struct kvmppc_gs_elem *gses[KVMPPC_GSE_IDEN_COUNT]; | 
|  | }; | 
|  |  | 
|  | enum { | 
|  | GSM_GUEST_WIDE = 0x1, | 
|  | GSM_SEND = 0x2, | 
|  | GSM_RECEIVE = 0x4, | 
|  | GSM_GSB_OWNER = 0x8, | 
|  | }; | 
|  |  | 
|  | struct kvmppc_gs_msg; | 
|  |  | 
|  | /** | 
|  | * struct kvmppc_gs_msg_ops - guest state message behavior | 
|  | * @get_size: maximum size required for the message data | 
|  | * @fill_info: serializes to the guest state buffer format | 
|  | * @refresh_info: dserializes from the guest state buffer format | 
|  | */ | 
|  | struct kvmppc_gs_msg_ops { | 
|  | size_t (*get_size)(struct kvmppc_gs_msg *gsm); | 
|  | int (*fill_info)(struct kvmppc_gs_buff *gsb, struct kvmppc_gs_msg *gsm); | 
|  | int (*refresh_info)(struct kvmppc_gs_msg *gsm, | 
|  | struct kvmppc_gs_buff *gsb); | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * struct kvmppc_gs_msg - a guest state message | 
|  | * @bitmap: the guest state ids that should be included | 
|  | * @ops: modify message behavior for reading and writing to buffers | 
|  | * @flags: guest wide or thread wide | 
|  | * @data: location where buffer data will be written to or from. | 
|  | * | 
|  | * A guest state message is allows flexibility in sending in receiving data | 
|  | * in a guest state buffer format. | 
|  | */ | 
|  | struct kvmppc_gs_msg { | 
|  | struct kvmppc_gs_bitmap bitmap; | 
|  | struct kvmppc_gs_msg_ops *ops; | 
|  | unsigned long flags; | 
|  | void *data; | 
|  | }; | 
|  |  | 
|  | /************************************************************************** | 
|  | * Guest State IDs | 
|  | **************************************************************************/ | 
|  |  | 
|  | u16 kvmppc_gsid_size(u16 iden); | 
|  | unsigned long kvmppc_gsid_flags(u16 iden); | 
|  | u64 kvmppc_gsid_mask(u16 iden); | 
|  |  | 
|  | /************************************************************************** | 
|  | * Guest State Buffers | 
|  | **************************************************************************/ | 
|  | struct kvmppc_gs_buff *kvmppc_gsb_new(size_t size, unsigned long guest_id, | 
|  | unsigned long vcpu_id, gfp_t flags); | 
|  | void kvmppc_gsb_free(struct kvmppc_gs_buff *gsb); | 
|  | void *kvmppc_gsb_put(struct kvmppc_gs_buff *gsb, size_t size); | 
|  | int kvmppc_gsb_send(struct kvmppc_gs_buff *gsb, unsigned long flags); | 
|  | int kvmppc_gsb_recv(struct kvmppc_gs_buff *gsb, unsigned long flags); | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsb_header() - the header of a guest state buffer | 
|  | * @gsb: guest state buffer | 
|  | * | 
|  | * Returns a pointer to the buffer header. | 
|  | */ | 
|  | static inline struct kvmppc_gs_header * | 
|  | kvmppc_gsb_header(struct kvmppc_gs_buff *gsb) | 
|  | { | 
|  | return gsb->hdr; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsb_data() - the elements of a guest state buffer | 
|  | * @gsb: guest state buffer | 
|  | * | 
|  | * Returns a pointer to the first element of the buffer data. | 
|  | */ | 
|  | static inline struct kvmppc_gs_elem *kvmppc_gsb_data(struct kvmppc_gs_buff *gsb) | 
|  | { | 
|  | return (struct kvmppc_gs_elem *)kvmppc_gsb_header(gsb)->data; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsb_len() - the current length of a guest state buffer | 
|  | * @gsb: guest state buffer | 
|  | * | 
|  | * Returns the length including the header of a buffer. | 
|  | */ | 
|  | static inline size_t kvmppc_gsb_len(struct kvmppc_gs_buff *gsb) | 
|  | { | 
|  | return gsb->len; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsb_capacity() - the capacity of a guest state buffer | 
|  | * @gsb: guest state buffer | 
|  | * | 
|  | * Returns the capacity of a buffer. | 
|  | */ | 
|  | static inline size_t kvmppc_gsb_capacity(struct kvmppc_gs_buff *gsb) | 
|  | { | 
|  | return gsb->capacity; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsb_paddress() - the physical address of buffer | 
|  | * @gsb: guest state buffer | 
|  | * | 
|  | * Returns the physical address of the buffer. | 
|  | */ | 
|  | static inline u64 kvmppc_gsb_paddress(struct kvmppc_gs_buff *gsb) | 
|  | { | 
|  | return __pa(kvmppc_gsb_header(gsb)); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsb_nelems() - the number of elements in a buffer | 
|  | * @gsb: guest state buffer | 
|  | * | 
|  | * Returns the number of elements in a buffer | 
|  | */ | 
|  | static inline u32 kvmppc_gsb_nelems(struct kvmppc_gs_buff *gsb) | 
|  | { | 
|  | return be32_to_cpu(kvmppc_gsb_header(gsb)->nelems); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsb_reset() - empty a guest state buffer | 
|  | * @gsb: guest state buffer | 
|  | * | 
|  | * Reset the number of elements and length of buffer to empty. | 
|  | */ | 
|  | static inline void kvmppc_gsb_reset(struct kvmppc_gs_buff *gsb) | 
|  | { | 
|  | kvmppc_gsb_header(gsb)->nelems = cpu_to_be32(0); | 
|  | gsb->len = sizeof(struct kvmppc_gs_header); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsb_data_len() - the length of a buffer excluding the header | 
|  | * @gsb: guest state buffer | 
|  | * | 
|  | * Returns the length of a buffer excluding the header | 
|  | */ | 
|  | static inline size_t kvmppc_gsb_data_len(struct kvmppc_gs_buff *gsb) | 
|  | { | 
|  | return gsb->len - sizeof(struct kvmppc_gs_header); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsb_data_cap() - the capacity of a buffer excluding the header | 
|  | * @gsb: guest state buffer | 
|  | * | 
|  | * Returns the capacity of a buffer excluding the header | 
|  | */ | 
|  | static inline size_t kvmppc_gsb_data_cap(struct kvmppc_gs_buff *gsb) | 
|  | { | 
|  | return gsb->capacity - sizeof(struct kvmppc_gs_header); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsb_for_each_elem - iterate over the elements in a buffer | 
|  | * @i: loop counter | 
|  | * @pos: set to current element | 
|  | * @gsb: guest state buffer | 
|  | * @rem: initialized to buffer capacity, holds bytes currently remaining in | 
|  | *  stream | 
|  | */ | 
|  | #define kvmppc_gsb_for_each_elem(i, pos, gsb, rem)               \ | 
|  | kvmppc_gse_for_each_elem(i, kvmppc_gsb_nelems(gsb), pos, \ | 
|  | kvmppc_gsb_data(gsb),           \ | 
|  | kvmppc_gsb_data_cap(gsb), rem) | 
|  |  | 
|  | /************************************************************************** | 
|  | * Guest State Elements | 
|  | **************************************************************************/ | 
|  |  | 
|  | /** | 
|  | * kvmppc_gse_iden() - guest state ID of element | 
|  | * @gse: guest state element | 
|  | * | 
|  | * Return the guest state ID in host endianness. | 
|  | */ | 
|  | static inline u16 kvmppc_gse_iden(const struct kvmppc_gs_elem *gse) | 
|  | { | 
|  | return be16_to_cpu(gse->iden); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gse_len() - length of guest state element data | 
|  | * @gse: guest state element | 
|  | * | 
|  | * Returns the length of guest state element data | 
|  | */ | 
|  | static inline u16 kvmppc_gse_len(const struct kvmppc_gs_elem *gse) | 
|  | { | 
|  | return be16_to_cpu(gse->len); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gse_total_len() - total length of guest state element | 
|  | * @gse: guest state element | 
|  | * | 
|  | * Returns the length of the data plus the ID and size header. | 
|  | */ | 
|  | static inline u16 kvmppc_gse_total_len(const struct kvmppc_gs_elem *gse) | 
|  | { | 
|  | return be16_to_cpu(gse->len) + sizeof(*gse); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gse_total_size() - space needed for a given data length | 
|  | * @size: data length | 
|  | * | 
|  | * Returns size plus the space needed for the ID and size header. | 
|  | */ | 
|  | static inline u16 kvmppc_gse_total_size(u16 size) | 
|  | { | 
|  | return sizeof(struct kvmppc_gs_elem) + size; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gse_data() - pointer to data of a guest state element | 
|  | * @gse: guest state element | 
|  | * | 
|  | * Returns a pointer to the beginning of guest state element data. | 
|  | */ | 
|  | static inline void *kvmppc_gse_data(const struct kvmppc_gs_elem *gse) | 
|  | { | 
|  | return (void *)gse->data; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gse_ok() - checks space exists for guest state element | 
|  | * @gse: guest state element | 
|  | * @remaining: bytes of space remaining | 
|  | * | 
|  | * Returns true if the guest state element can fit in remaining space. | 
|  | */ | 
|  | static inline bool kvmppc_gse_ok(const struct kvmppc_gs_elem *gse, | 
|  | int remaining) | 
|  | { | 
|  | return remaining >= kvmppc_gse_total_len(gse); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gse_next() - iterate to the next guest state element in a stream | 
|  | * @gse: stream of guest state elements | 
|  | * @remaining: length of the guest element stream | 
|  | * | 
|  | * Returns the next guest state element in a stream of elements. The length of | 
|  | * the stream is updated in remaining. | 
|  | */ | 
|  | static inline struct kvmppc_gs_elem * | 
|  | kvmppc_gse_next(const struct kvmppc_gs_elem *gse, int *remaining) | 
|  | { | 
|  | int len = sizeof(*gse) + kvmppc_gse_len(gse); | 
|  |  | 
|  | *remaining -= len; | 
|  | return (struct kvmppc_gs_elem *)(gse->data + kvmppc_gse_len(gse)); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gse_for_each_elem - iterate over a stream of guest state elements | 
|  | * @i: loop counter | 
|  | * @max: number of elements | 
|  | * @pos: set to current element | 
|  | * @head: head of elements | 
|  | * @len: length of the stream | 
|  | * @rem: initialized to len, holds bytes currently remaining elements | 
|  | */ | 
|  | #define kvmppc_gse_for_each_elem(i, max, pos, head, len, rem)                  \ | 
|  | for (i = 0, pos = head, rem = len; kvmppc_gse_ok(pos, rem) && i < max; \ | 
|  | pos = kvmppc_gse_next(pos, &(rem)), i++) | 
|  |  | 
|  | int __kvmppc_gse_put(struct kvmppc_gs_buff *gsb, u16 iden, u16 size, | 
|  | const void *data); | 
|  | int kvmppc_gse_parse(struct kvmppc_gs_parser *gsp, struct kvmppc_gs_buff *gsb); | 
|  |  | 
|  | /** | 
|  | * kvmppc_gse_put_be32() - add a be32 guest state element to a buffer | 
|  | * @gsb: guest state buffer to add element to | 
|  | * @iden: guest state ID | 
|  | * @val: big endian value | 
|  | */ | 
|  | static inline int kvmppc_gse_put_be32(struct kvmppc_gs_buff *gsb, u16 iden, | 
|  | __be32 val) | 
|  | { | 
|  | __be32 tmp; | 
|  |  | 
|  | tmp = val; | 
|  | return __kvmppc_gse_put(gsb, iden, sizeof(__be32), &tmp); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gse_put_u32() - add a host endian 32bit int guest state element to a | 
|  | * buffer | 
|  | * @gsb: guest state buffer to add element to | 
|  | * @iden: guest state ID | 
|  | * @val: host endian value | 
|  | */ | 
|  | static inline int kvmppc_gse_put_u32(struct kvmppc_gs_buff *gsb, u16 iden, | 
|  | u32 val) | 
|  | { | 
|  | __be32 tmp; | 
|  |  | 
|  | val &= kvmppc_gsid_mask(iden); | 
|  | tmp = cpu_to_be32(val); | 
|  | return kvmppc_gse_put_be32(gsb, iden, tmp); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gse_put_be64() - add a be64 guest state element to a buffer | 
|  | * @gsb: guest state buffer to add element to | 
|  | * @iden: guest state ID | 
|  | * @val: big endian value | 
|  | */ | 
|  | static inline int kvmppc_gse_put_be64(struct kvmppc_gs_buff *gsb, u16 iden, | 
|  | __be64 val) | 
|  | { | 
|  | __be64 tmp; | 
|  |  | 
|  | tmp = val; | 
|  | return __kvmppc_gse_put(gsb, iden, sizeof(__be64), &tmp); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gse_put_u64() - add a host endian 64bit guest state element to a | 
|  | * buffer | 
|  | * @gsb: guest state buffer to add element to | 
|  | * @iden: guest state ID | 
|  | * @val: host endian value | 
|  | */ | 
|  | static inline int kvmppc_gse_put_u64(struct kvmppc_gs_buff *gsb, u16 iden, | 
|  | u64 val) | 
|  | { | 
|  | __be64 tmp; | 
|  |  | 
|  | val &= kvmppc_gsid_mask(iden); | 
|  | tmp = cpu_to_be64(val); | 
|  | return kvmppc_gse_put_be64(gsb, iden, tmp); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * __kvmppc_gse_put_reg() - add a register type guest state element to a buffer | 
|  | * @gsb: guest state buffer to add element to | 
|  | * @iden: guest state ID | 
|  | * @val: host endian value | 
|  | * | 
|  | * Adds a register type guest state element. Uses the guest state ID for | 
|  | * determining the length of the guest element. If the guest state ID has | 
|  | * bits that can not be set they will be cleared. | 
|  | */ | 
|  | static inline int __kvmppc_gse_put_reg(struct kvmppc_gs_buff *gsb, u16 iden, | 
|  | u64 val) | 
|  | { | 
|  | val &= kvmppc_gsid_mask(iden); | 
|  | if (kvmppc_gsid_size(iden) == sizeof(u64)) | 
|  | return kvmppc_gse_put_u64(gsb, iden, val); | 
|  |  | 
|  | if (kvmppc_gsid_size(iden) == sizeof(u32)) { | 
|  | u32 tmp; | 
|  |  | 
|  | tmp = (u32)val; | 
|  | if (tmp != val) | 
|  | return -EINVAL; | 
|  |  | 
|  | return kvmppc_gse_put_u32(gsb, iden, tmp); | 
|  | } | 
|  | return -EINVAL; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gse_put_vector128() - add a vector guest state element to a buffer | 
|  | * @gsb: guest state buffer to add element to | 
|  | * @iden: guest state ID | 
|  | * @val: 16 byte vector value | 
|  | */ | 
|  | static inline int kvmppc_gse_put_vector128(struct kvmppc_gs_buff *gsb, u16 iden, | 
|  | vector128 *val) | 
|  | { | 
|  | __be64 tmp[2] = { 0 }; | 
|  | union { | 
|  | __vector128 v; | 
|  | u64 dw[2]; | 
|  | } u; | 
|  |  | 
|  | u.v = *val; | 
|  | tmp[0] = cpu_to_be64(u.dw[TS_FPROFFSET]); | 
|  | #ifdef CONFIG_VSX | 
|  | tmp[1] = cpu_to_be64(u.dw[TS_VSRLOWOFFSET]); | 
|  | #endif | 
|  | return __kvmppc_gse_put(gsb, iden, sizeof(tmp), &tmp); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gse_put_part_table() - add a partition table guest state element to a | 
|  | * buffer | 
|  | * @gsb: guest state buffer to add element to | 
|  | * @iden: guest state ID | 
|  | * @val: partition table value | 
|  | */ | 
|  | static inline int kvmppc_gse_put_part_table(struct kvmppc_gs_buff *gsb, | 
|  | u16 iden, | 
|  | struct kvmppc_gs_part_table val) | 
|  | { | 
|  | __be64 tmp[3]; | 
|  |  | 
|  | tmp[0] = cpu_to_be64(val.address); | 
|  | tmp[1] = cpu_to_be64(val.ea_bits); | 
|  | tmp[2] = cpu_to_be64(val.gpd_size); | 
|  | return __kvmppc_gse_put(gsb, KVMPPC_GSID_PARTITION_TABLE, sizeof(tmp), | 
|  | &tmp); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gse_put_proc_table() - add a process table guest state element to a | 
|  | * buffer | 
|  | * @gsb: guest state buffer to add element to | 
|  | * @iden: guest state ID | 
|  | * @val: process table value | 
|  | */ | 
|  | static inline int kvmppc_gse_put_proc_table(struct kvmppc_gs_buff *gsb, | 
|  | u16 iden, | 
|  | struct kvmppc_gs_proc_table val) | 
|  | { | 
|  | __be64 tmp[2]; | 
|  |  | 
|  | tmp[0] = cpu_to_be64(val.address); | 
|  | tmp[1] = cpu_to_be64(val.gpd_size); | 
|  | return __kvmppc_gse_put(gsb, KVMPPC_GSID_PROCESS_TABLE, sizeof(tmp), | 
|  | &tmp); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gse_put_buff_info() - adds a GSB description guest state element to a | 
|  | * buffer | 
|  | * @gsb: guest state buffer to add element to | 
|  | * @iden: guest state ID | 
|  | * @val: guest state buffer description value | 
|  | */ | 
|  | static inline int kvmppc_gse_put_buff_info(struct kvmppc_gs_buff *gsb, u16 iden, | 
|  | struct kvmppc_gs_buff_info val) | 
|  | { | 
|  | __be64 tmp[2]; | 
|  |  | 
|  | tmp[0] = cpu_to_be64(val.address); | 
|  | tmp[1] = cpu_to_be64(val.size); | 
|  | return __kvmppc_gse_put(gsb, iden, sizeof(tmp), &tmp); | 
|  | } | 
|  |  | 
|  | int __kvmppc_gse_put(struct kvmppc_gs_buff *gsb, u16 iden, u16 size, | 
|  | const void *data); | 
|  |  | 
|  | /** | 
|  | * kvmppc_gse_get_be32() - return the data of a be32 element | 
|  | * @gse: guest state element | 
|  | */ | 
|  | static inline __be32 kvmppc_gse_get_be32(const struct kvmppc_gs_elem *gse) | 
|  | { | 
|  | if (WARN_ON(kvmppc_gse_len(gse) != sizeof(__be32))) | 
|  | return 0; | 
|  | return *(__be32 *)kvmppc_gse_data(gse); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gse_get_u32() - return the data of a be32 element in host endianness | 
|  | * @gse: guest state element | 
|  | */ | 
|  | static inline u32 kvmppc_gse_get_u32(const struct kvmppc_gs_elem *gse) | 
|  | { | 
|  | return be32_to_cpu(kvmppc_gse_get_be32(gse)); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gse_get_be64() - return the data of a be64 element | 
|  | * @gse: guest state element | 
|  | */ | 
|  | static inline __be64 kvmppc_gse_get_be64(const struct kvmppc_gs_elem *gse) | 
|  | { | 
|  | if (WARN_ON(kvmppc_gse_len(gse) != sizeof(__be64))) | 
|  | return 0; | 
|  | return *(__be64 *)kvmppc_gse_data(gse); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gse_get_u64() - return the data of a be64 element in host endianness | 
|  | * @gse: guest state element | 
|  | */ | 
|  | static inline u64 kvmppc_gse_get_u64(const struct kvmppc_gs_elem *gse) | 
|  | { | 
|  | return be64_to_cpu(kvmppc_gse_get_be64(gse)); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gse_get_vector128() - return the data of a vector element | 
|  | * @gse: guest state element | 
|  | */ | 
|  | static inline void kvmppc_gse_get_vector128(const struct kvmppc_gs_elem *gse, | 
|  | vector128 *v) | 
|  | { | 
|  | union { | 
|  | __vector128 v; | 
|  | u64 dw[2]; | 
|  | } u = { 0 }; | 
|  | __be64 *src; | 
|  |  | 
|  | if (WARN_ON(kvmppc_gse_len(gse) != sizeof(__vector128))) | 
|  | *v = u.v; | 
|  |  | 
|  | src = (__be64 *)kvmppc_gse_data(gse); | 
|  | u.dw[TS_FPROFFSET] = be64_to_cpu(src[0]); | 
|  | #ifdef CONFIG_VSX | 
|  | u.dw[TS_VSRLOWOFFSET] = be64_to_cpu(src[1]); | 
|  | #endif | 
|  | *v = u.v; | 
|  | } | 
|  |  | 
|  | /************************************************************************** | 
|  | * Guest State Bitmap | 
|  | **************************************************************************/ | 
|  |  | 
|  | bool kvmppc_gsbm_test(struct kvmppc_gs_bitmap *gsbm, u16 iden); | 
|  | void kvmppc_gsbm_set(struct kvmppc_gs_bitmap *gsbm, u16 iden); | 
|  | void kvmppc_gsbm_clear(struct kvmppc_gs_bitmap *gsbm, u16 iden); | 
|  | u16 kvmppc_gsbm_next(struct kvmppc_gs_bitmap *gsbm, u16 prev); | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsbm_zero - zero the entire bitmap | 
|  | * @gsbm: guest state buffer bitmap | 
|  | */ | 
|  | static inline void kvmppc_gsbm_zero(struct kvmppc_gs_bitmap *gsbm) | 
|  | { | 
|  | bitmap_zero(gsbm->bitmap, KVMPPC_GSE_IDEN_COUNT); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsbm_fill - fill the entire bitmap | 
|  | * @gsbm: guest state buffer bitmap | 
|  | */ | 
|  | static inline void kvmppc_gsbm_fill(struct kvmppc_gs_bitmap *gsbm) | 
|  | { | 
|  | bitmap_fill(gsbm->bitmap, KVMPPC_GSE_IDEN_COUNT); | 
|  | clear_bit(0, gsbm->bitmap); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsbm_for_each - iterate the present guest state IDs | 
|  | * @gsbm: guest state buffer bitmap | 
|  | * @iden: current guest state ID | 
|  | */ | 
|  | #define kvmppc_gsbm_for_each(gsbm, iden)                  \ | 
|  | for (iden = kvmppc_gsbm_next(gsbm, 0); iden != 0; \ | 
|  | iden = kvmppc_gsbm_next(gsbm, iden)) | 
|  |  | 
|  | /************************************************************************** | 
|  | * Guest State Parser | 
|  | **************************************************************************/ | 
|  |  | 
|  | void kvmppc_gsp_insert(struct kvmppc_gs_parser *gsp, u16 iden, | 
|  | struct kvmppc_gs_elem *gse); | 
|  | struct kvmppc_gs_elem *kvmppc_gsp_lookup(struct kvmppc_gs_parser *gsp, | 
|  | u16 iden); | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsp_for_each - iterate the <guest state IDs, guest state element> | 
|  | * pairs | 
|  | * @gsp: guest state buffer bitmap | 
|  | * @iden: current guest state ID | 
|  | * @gse: guest state element | 
|  | */ | 
|  | #define kvmppc_gsp_for_each(gsp, iden, gse)                              \ | 
|  | for (iden = kvmppc_gsbm_next(&(gsp)->iterator, 0),               \ | 
|  | gse = kvmppc_gsp_lookup((gsp), iden);                        \ | 
|  | iden != 0; iden = kvmppc_gsbm_next(&(gsp)->iterator, iden), \ | 
|  | gse = kvmppc_gsp_lookup((gsp), iden)) | 
|  |  | 
|  | /************************************************************************** | 
|  | * Guest State Message | 
|  | **************************************************************************/ | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsm_for_each - iterate the guest state IDs included in a guest state | 
|  | * message | 
|  | * @gsp: guest state buffer bitmap | 
|  | * @iden: current guest state ID | 
|  | * @gse: guest state element | 
|  | */ | 
|  | #define kvmppc_gsm_for_each(gsm, iden)                            \ | 
|  | for (iden = kvmppc_gsbm_next(&gsm->bitmap, 0); iden != 0; \ | 
|  | iden = kvmppc_gsbm_next(&gsm->bitmap, iden)) | 
|  |  | 
|  | int kvmppc_gsm_init(struct kvmppc_gs_msg *mgs, struct kvmppc_gs_msg_ops *ops, | 
|  | void *data, unsigned long flags); | 
|  |  | 
|  | struct kvmppc_gs_msg *kvmppc_gsm_new(struct kvmppc_gs_msg_ops *ops, void *data, | 
|  | unsigned long flags, gfp_t gfp_flags); | 
|  | void kvmppc_gsm_free(struct kvmppc_gs_msg *gsm); | 
|  | size_t kvmppc_gsm_size(struct kvmppc_gs_msg *gsm); | 
|  | int kvmppc_gsm_fill_info(struct kvmppc_gs_msg *gsm, struct kvmppc_gs_buff *gsb); | 
|  | int kvmppc_gsm_refresh_info(struct kvmppc_gs_msg *gsm, | 
|  | struct kvmppc_gs_buff *gsb); | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsm_include - indicate a guest state ID should be included when | 
|  | * serializing | 
|  | * @gsm: guest state message | 
|  | * @iden: guest state ID | 
|  | */ | 
|  | static inline void kvmppc_gsm_include(struct kvmppc_gs_msg *gsm, u16 iden) | 
|  | { | 
|  | kvmppc_gsbm_set(&gsm->bitmap, iden); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsm_includes - check if a guest state ID will be included when | 
|  | * serializing | 
|  | * @gsm: guest state message | 
|  | * @iden: guest state ID | 
|  | */ | 
|  | static inline bool kvmppc_gsm_includes(struct kvmppc_gs_msg *gsm, u16 iden) | 
|  | { | 
|  | return kvmppc_gsbm_test(&gsm->bitmap, iden); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsm_includes - indicate all guest state IDs should be included when | 
|  | * serializing | 
|  | * @gsm: guest state message | 
|  | * @iden: guest state ID | 
|  | */ | 
|  | static inline void kvmppc_gsm_include_all(struct kvmppc_gs_msg *gsm) | 
|  | { | 
|  | kvmppc_gsbm_fill(&gsm->bitmap); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsm_include - clear the guest state IDs that should be included when | 
|  | * serializing | 
|  | * @gsm: guest state message | 
|  | */ | 
|  | static inline void kvmppc_gsm_reset(struct kvmppc_gs_msg *gsm) | 
|  | { | 
|  | kvmppc_gsbm_zero(&gsm->bitmap); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsb_receive_data - flexibly update values from a guest state buffer | 
|  | * @gsb: guest state buffer | 
|  | * @gsm: guest state message | 
|  | * | 
|  | * Requests updated values for the guest state values included in the guest | 
|  | * state message. The guest state message will then deserialize the guest state | 
|  | * buffer. | 
|  | */ | 
|  | static inline int kvmppc_gsb_receive_data(struct kvmppc_gs_buff *gsb, | 
|  | struct kvmppc_gs_msg *gsm) | 
|  | { | 
|  | int rc; | 
|  |  | 
|  | kvmppc_gsb_reset(gsb); | 
|  | rc = kvmppc_gsm_fill_info(gsm, gsb); | 
|  | if (rc < 0) | 
|  | return rc; | 
|  |  | 
|  | rc = kvmppc_gsb_recv(gsb, gsm->flags); | 
|  | if (rc < 0) | 
|  | return rc; | 
|  |  | 
|  | rc = kvmppc_gsm_refresh_info(gsm, gsb); | 
|  | if (rc < 0) | 
|  | return rc; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsb_recv - receive a single guest state ID | 
|  | * @gsb: guest state buffer | 
|  | * @gsm: guest state message | 
|  | * @iden: guest state identity | 
|  | */ | 
|  | static inline int kvmppc_gsb_receive_datum(struct kvmppc_gs_buff *gsb, | 
|  | struct kvmppc_gs_msg *gsm, u16 iden) | 
|  | { | 
|  | int rc; | 
|  |  | 
|  | kvmppc_gsm_include(gsm, iden); | 
|  | rc = kvmppc_gsb_receive_data(gsb, gsm); | 
|  | if (rc < 0) | 
|  | return rc; | 
|  | kvmppc_gsm_reset(gsm); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsb_send_data - flexibly send values from a guest state buffer | 
|  | * @gsb: guest state buffer | 
|  | * @gsm: guest state message | 
|  | * | 
|  | * Sends the guest state values included in the guest state message. | 
|  | */ | 
|  | static inline int kvmppc_gsb_send_data(struct kvmppc_gs_buff *gsb, | 
|  | struct kvmppc_gs_msg *gsm) | 
|  | { | 
|  | int rc; | 
|  |  | 
|  | kvmppc_gsb_reset(gsb); | 
|  | rc = kvmppc_gsm_fill_info(gsm, gsb); | 
|  | if (rc < 0) | 
|  | return rc; | 
|  | rc = kvmppc_gsb_send(gsb, gsm->flags); | 
|  |  | 
|  | return rc; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * kvmppc_gsb_recv - send a single guest state ID | 
|  | * @gsb: guest state buffer | 
|  | * @gsm: guest state message | 
|  | * @iden: guest state identity | 
|  | */ | 
|  | static inline int kvmppc_gsb_send_datum(struct kvmppc_gs_buff *gsb, | 
|  | struct kvmppc_gs_msg *gsm, u16 iden) | 
|  | { | 
|  | int rc; | 
|  |  | 
|  | kvmppc_gsm_include(gsm, iden); | 
|  | rc = kvmppc_gsb_send_data(gsb, gsm); | 
|  | if (rc < 0) | 
|  | return rc; | 
|  | kvmppc_gsm_reset(gsm); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | #endif /* _ASM_POWERPC_GUEST_STATE_BUFFER_H */ |