/** * uv_secret_list_item_hdr - UV secret metadata. * @index: Index of the secret in the secret list. * @type: Type of the secret. See `enum uv_secret_types`. * @length: Length of the stored secret.
*/ struct uv_secret_list_item_hdr {
u16 index;
u16 type;
u32 length;
} __packed __aligned(8);
#define UV_SECRET_ID_LEN 32 /** * uv_secret_list_item - UV secret entry. * @hdr: The metadata of this secret. * @id: The ID of this secret, not the secret itself.
*/ struct uv_secret_list_item { struct uv_secret_list_item_hdr hdr;
u64 reserverd08;
u8 id[UV_SECRET_ID_LEN];
} __packed __aligned(8);
/** * uv_secret_list - UV secret-metadata list. * @num_secr_stored: Number of secrets stored in this list. * @total_num_secrets: Number of secrets stored in the UV for this guest. * @next_secret_idx: positive number if there are more secrets available or zero. * @secrets: Up to 85 UV-secret metadata entries.
*/ struct uv_secret_list {
u16 num_secr_stored;
u16 total_num_secrets;
u16 next_secret_idx;
u16 reserved_06;
u64 reserved_08; struct uv_secret_list_item secrets[85];
} __packed __aligned(8);
static_assert(sizeof(struct uv_secret_list) == PAGE_SIZE);
staticinlineint __uv_call(unsignedlong r1, unsignedlong r2)
{ int cc;
asmvolatile( " .insn rrf,0xb9a40000,%[r1],%[r2],0,0\n"
CC_IPM(cc)
: CC_OUT(cc, cc)
: [r1] "a" (r1), [r2] "a" (r2)
: CC_CLOBBER_LIST("memory")); return CC_TRANSFORM(cc);
}
staticinlineint uv_call(unsignedlong r1, unsignedlong r2)
{ int cc;
do {
cc = __uv_call(r1, r2);
} while (cc > 1); return cc;
}
/* Low level uv_call that avoids stalls for long running busy conditions */ staticinlineint uv_call_sched(unsignedlong r1, unsignedlong r2)
{ int cc;
do {
cc = __uv_call(r1, r2);
cond_resched();
} while (cc > 1); return cc;
}
/* * special variant of uv_call that only transports the cpu or guest * handle and the command, like destroy or verify.
*/ staticinlineint uv_cmd_nodata(u64 handle, u16 cmd, u16 *rc, u16 *rrc)
{ struct uv_cb_nodata uvcb = {
.header.cmd = cmd,
.header.len = sizeof(uvcb),
.handle = handle,
}; int cc;
WARN(!handle, "No handle provided to Ultravisor call cmd %x\n", cmd);
cc = uv_call_sched(0, (u64)&uvcb);
*rc = uvcb.header.rc;
*rrc = uvcb.header.rrc; return cc ? -EINVAL : 0;
}
/** * uv_list_secrets() - Do a List Secrets UVC. * * @buf: Buffer to write list into; size of one page. * @start_idx: The smallest index that should be included in the list. * For the fist invocation use 0. * @rc: Pointer to store the return code or NULL. * @rrc: Pointer to store the return reason code or NULL. * * This function calls the List Secrets UVC. The result is written into `buf`, * that needs to be at least one page of writable memory. * `buf` consists of: * * %struct uv_secret_list_hdr * * %struct uv_secret_list_item (multiple) * * For `start_idx` use _0_ for the first call. If there are more secrets available * but could not fit into the page then `rc` is `UVC_RC_MORE_DATA`. * In this case use `uv_secret_list_hdr.next_secret_idx` for `start_idx`. * * Context: might sleep. * * Return: The UVC condition code.
*/ staticinlineint uv_list_secrets(struct uv_secret_list *buf, u16 start_idx,
u16 *rc, u16 *rrc)
{ struct uv_cb_list_secrets uvcb = {
.header.len = sizeof(uvcb),
.header.cmd = UVC_CMD_LIST_SECRETS,
.start_idx = start_idx,
.list_addr = (u64)buf,
}; int cc = uv_call_sched(0, (u64)&uvcb);
if (rc)
*rc = uvcb.header.rc; if (rrc)
*rrc = uvcb.header.rrc;
if (!is_prot_virt_guest()) return -EOPNOTSUPP; /* * Sharing is page wise, if we encounter addresses that are * not page aligned, we assume something went wrong. If * malloced structs are passed to this function, we could leak * data to the hypervisor.
*/
BUG_ON(addr & ~PAGE_MASK);
if (!uv_call(0, (u64)&uvcb)) return 0;
pr_err("%s UVC failed (rc: 0x%x, rrc: 0x%x), possible hypervisor bug.\n",
uvcb.header.cmd == UVC_CMD_SET_SHARED_ACCESS ? "Share" : "Unshare",
uvcb.header.rc, uvcb.header.rrc);
panic("System security cannot be guaranteed unless the system panics now.\n");
}
/* * Guest 2 request to the Ultravisor to make a page shared with the * hypervisor for IO. * * @addr: Real or absolute address of the page to be shared
*/ staticinlineint uv_set_shared(unsignedlong addr)
{ return share(addr, UVC_CMD_SET_SHARED_ACCESS);
}
/* * Guest 2 request to the Ultravisor to make a page unshared. * * @addr: Real or absolute address of the page to be unshared
*/ staticinlineint uv_remove_shared(unsignedlong addr)
{ return share(addr, UVC_CMD_REMOVE_SHARED_ACCESS);
}
int uv_find_secret(const u8 secret_id[UV_SECRET_ID_LEN], struct uv_secret_list *list, struct uv_secret_list_item_hdr *secret); int uv_retrieve_secret(u16 secret_idx, u8 *buf, size_t buf_size);
int uv_pin_shared(unsignedlong paddr); int uv_destroy_folio(struct folio *folio); int uv_destroy_pte(pte_t pte); int uv_convert_from_secure_pte(pte_t pte); int make_hva_secure(struct mm_struct *mm, unsignedlong hva, struct uv_cb_header *uvcb); int uv_convert_from_secure(unsignedlong paddr); int uv_convert_from_secure_folio(struct folio *folio);
void setup_uv(void);
#endif/* _ASM_S390_UV_H */
Messung V0.5
¤ Dauer der Verarbeitung: 0.25 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.