linux/arch/s390/include/asm/uv.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/*
   3 * Ultravisor Interfaces
   4 *
   5 * Copyright IBM Corp. 2019
   6 *
   7 * Author(s):
   8 *      Vasily Gorbik <gor@linux.ibm.com>
   9 *      Janosch Frank <frankja@linux.ibm.com>
  10 */
  11#ifndef _ASM_S390_UV_H
  12#define _ASM_S390_UV_H
  13
  14#include <linux/types.h>
  15#include <linux/errno.h>
  16#include <linux/bug.h>
  17#include <linux/sched.h>
  18#include <asm/page.h>
  19#include <asm/gmap.h>
  20
  21#define UVC_RC_EXECUTED         0x0001
  22#define UVC_RC_INV_CMD          0x0002
  23#define UVC_RC_INV_STATE        0x0003
  24#define UVC_RC_INV_LEN          0x0005
  25#define UVC_RC_NO_RESUME        0x0007
  26#define UVC_RC_NEED_DESTROY     0x8000
  27
  28#define UVC_CMD_QUI                     0x0001
  29#define UVC_CMD_INIT_UV                 0x000f
  30#define UVC_CMD_CREATE_SEC_CONF         0x0100
  31#define UVC_CMD_DESTROY_SEC_CONF        0x0101
  32#define UVC_CMD_CREATE_SEC_CPU          0x0120
  33#define UVC_CMD_DESTROY_SEC_CPU         0x0121
  34#define UVC_CMD_CONV_TO_SEC_STOR        0x0200
  35#define UVC_CMD_CONV_FROM_SEC_STOR      0x0201
  36#define UVC_CMD_DESTR_SEC_STOR          0x0202
  37#define UVC_CMD_SET_SEC_CONF_PARAMS     0x0300
  38#define UVC_CMD_UNPACK_IMG              0x0301
  39#define UVC_CMD_VERIFY_IMG              0x0302
  40#define UVC_CMD_CPU_RESET               0x0310
  41#define UVC_CMD_CPU_RESET_INITIAL       0x0311
  42#define UVC_CMD_PREPARE_RESET           0x0320
  43#define UVC_CMD_CPU_RESET_CLEAR         0x0321
  44#define UVC_CMD_CPU_SET_STATE           0x0330
  45#define UVC_CMD_SET_UNSHARE_ALL         0x0340
  46#define UVC_CMD_PIN_PAGE_SHARED         0x0341
  47#define UVC_CMD_UNPIN_PAGE_SHARED       0x0342
  48#define UVC_CMD_SET_SHARED_ACCESS       0x1000
  49#define UVC_CMD_REMOVE_SHARED_ACCESS    0x1001
  50
  51/* Bits in installed uv calls */
  52enum uv_cmds_inst {
  53        BIT_UVC_CMD_QUI = 0,
  54        BIT_UVC_CMD_INIT_UV = 1,
  55        BIT_UVC_CMD_CREATE_SEC_CONF = 2,
  56        BIT_UVC_CMD_DESTROY_SEC_CONF = 3,
  57        BIT_UVC_CMD_CREATE_SEC_CPU = 4,
  58        BIT_UVC_CMD_DESTROY_SEC_CPU = 5,
  59        BIT_UVC_CMD_CONV_TO_SEC_STOR = 6,
  60        BIT_UVC_CMD_CONV_FROM_SEC_STOR = 7,
  61        BIT_UVC_CMD_SET_SHARED_ACCESS = 8,
  62        BIT_UVC_CMD_REMOVE_SHARED_ACCESS = 9,
  63        BIT_UVC_CMD_SET_SEC_PARMS = 11,
  64        BIT_UVC_CMD_UNPACK_IMG = 13,
  65        BIT_UVC_CMD_VERIFY_IMG = 14,
  66        BIT_UVC_CMD_CPU_RESET = 15,
  67        BIT_UVC_CMD_CPU_RESET_INITIAL = 16,
  68        BIT_UVC_CMD_CPU_SET_STATE = 17,
  69        BIT_UVC_CMD_PREPARE_RESET = 18,
  70        BIT_UVC_CMD_CPU_PERFORM_CLEAR_RESET = 19,
  71        BIT_UVC_CMD_UNSHARE_ALL = 20,
  72        BIT_UVC_CMD_PIN_PAGE_SHARED = 21,
  73        BIT_UVC_CMD_UNPIN_PAGE_SHARED = 22,
  74};
  75
  76enum uv_feat_ind {
  77        BIT_UV_FEAT_MISC = 0,
  78};
  79
  80struct uv_cb_header {
  81        u16 len;
  82        u16 cmd;        /* Command Code */
  83        u16 rc;         /* Response Code */
  84        u16 rrc;        /* Return Reason Code */
  85} __packed __aligned(8);
  86
  87/* Query Ultravisor Information */
  88struct uv_cb_qui {
  89        struct uv_cb_header header;
  90        u64 reserved08;
  91        u64 inst_calls_list[4];
  92        u64 reserved30[2];
  93        u64 uv_base_stor_len;
  94        u64 reserved48;
  95        u64 conf_base_phys_stor_len;
  96        u64 conf_base_virt_stor_len;
  97        u64 conf_virt_var_stor_len;
  98        u64 cpu_stor_len;
  99        u32 reserved70[3];
 100        u32 max_num_sec_conf;
 101        u64 max_guest_stor_addr;
 102        u8  reserved88[158 - 136];
 103        u16 max_guest_cpu_id;
 104        u64 uv_feature_indications;
 105        u8  reserveda0[200 - 168];
 106} __packed __aligned(8);
 107
 108/* Initialize Ultravisor */
 109struct uv_cb_init {
 110        struct uv_cb_header header;
 111        u64 reserved08[2];
 112        u64 stor_origin;
 113        u64 stor_len;
 114        u64 reserved28[4];
 115} __packed __aligned(8);
 116
 117/* Create Guest Configuration */
 118struct uv_cb_cgc {
 119        struct uv_cb_header header;
 120        u64 reserved08[2];
 121        u64 guest_handle;
 122        u64 conf_base_stor_origin;
 123        u64 conf_virt_stor_origin;
 124        u64 reserved30;
 125        u64 guest_stor_origin;
 126        u64 guest_stor_len;
 127        u64 guest_sca;
 128        u64 guest_asce;
 129        u64 reserved58[5];
 130} __packed __aligned(8);
 131
 132/* Create Secure CPU */
 133struct uv_cb_csc {
 134        struct uv_cb_header header;
 135        u64 reserved08[2];
 136        u64 cpu_handle;
 137        u64 guest_handle;
 138        u64 stor_origin;
 139        u8  reserved30[6];
 140        u16 num;
 141        u64 state_origin;
 142        u64 reserved40[4];
 143} __packed __aligned(8);
 144
 145/* Convert to Secure */
 146struct uv_cb_cts {
 147        struct uv_cb_header header;
 148        u64 reserved08[2];
 149        u64 guest_handle;
 150        u64 gaddr;
 151} __packed __aligned(8);
 152
 153/* Convert from Secure / Pin Page Shared */
 154struct uv_cb_cfs {
 155        struct uv_cb_header header;
 156        u64 reserved08[2];
 157        u64 paddr;
 158} __packed __aligned(8);
 159
 160/* Set Secure Config Parameter */
 161struct uv_cb_ssc {
 162        struct uv_cb_header header;
 163        u64 reserved08[2];
 164        u64 guest_handle;
 165        u64 sec_header_origin;
 166        u32 sec_header_len;
 167        u32 reserved2c;
 168        u64 reserved30[4];
 169} __packed __aligned(8);
 170
 171/* Unpack */
 172struct uv_cb_unp {
 173        struct uv_cb_header header;
 174        u64 reserved08[2];
 175        u64 guest_handle;
 176        u64 gaddr;
 177        u64 tweak[2];
 178        u64 reserved38[3];
 179} __packed __aligned(8);
 180
 181#define PV_CPU_STATE_OPR        1
 182#define PV_CPU_STATE_STP        2
 183#define PV_CPU_STATE_CHKSTP     3
 184#define PV_CPU_STATE_OPR_LOAD   5
 185
 186struct uv_cb_cpu_set_state {
 187        struct uv_cb_header header;
 188        u64 reserved08[2];
 189        u64 cpu_handle;
 190        u8  reserved20[7];
 191        u8  state;
 192        u64 reserved28[5];
 193};
 194
 195/*
 196 * A common UV call struct for calls that take no payload
 197 * Examples:
 198 * Destroy cpu/config
 199 * Verify
 200 */
 201struct uv_cb_nodata {
 202        struct uv_cb_header header;
 203        u64 reserved08[2];
 204        u64 handle;
 205        u64 reserved20[4];
 206} __packed __aligned(8);
 207
 208/* Set Shared Access */
 209struct uv_cb_share {
 210        struct uv_cb_header header;
 211        u64 reserved08[3];
 212        u64 paddr;
 213        u64 reserved28;
 214} __packed __aligned(8);
 215
 216static inline int __uv_call(unsigned long r1, unsigned long r2)
 217{
 218        int cc;
 219
 220        asm volatile(
 221                "       .insn rrf,0xB9A40000,%[r1],%[r2],0,0\n"
 222                "       ipm     %[cc]\n"
 223                "       srl     %[cc],28\n"
 224                : [cc] "=d" (cc)
 225                : [r1] "a" (r1), [r2] "a" (r2)
 226                : "memory", "cc");
 227        return cc;
 228}
 229
 230static inline int uv_call(unsigned long r1, unsigned long r2)
 231{
 232        int cc;
 233
 234        do {
 235                cc = __uv_call(r1, r2);
 236        } while (cc > 1);
 237        return cc;
 238}
 239
 240/* Low level uv_call that avoids stalls for long running busy conditions  */
 241static inline int uv_call_sched(unsigned long r1, unsigned long r2)
 242{
 243        int cc;
 244
 245        do {
 246                cc = __uv_call(r1, r2);
 247                cond_resched();
 248        } while (cc > 1);
 249        return cc;
 250}
 251
 252/*
 253 * special variant of uv_call that only transports the cpu or guest
 254 * handle and the command, like destroy or verify.
 255 */
 256static inline int uv_cmd_nodata(u64 handle, u16 cmd, u16 *rc, u16 *rrc)
 257{
 258        struct uv_cb_nodata uvcb = {
 259                .header.cmd = cmd,
 260                .header.len = sizeof(uvcb),
 261                .handle = handle,
 262        };
 263        int cc;
 264
 265        WARN(!handle, "No handle provided to Ultravisor call cmd %x\n", cmd);
 266        cc = uv_call_sched(0, (u64)&uvcb);
 267        *rc = uvcb.header.rc;
 268        *rrc = uvcb.header.rrc;
 269        return cc ? -EINVAL : 0;
 270}
 271
 272struct uv_info {
 273        unsigned long inst_calls_list[4];
 274        unsigned long uv_base_stor_len;
 275        unsigned long guest_base_stor_len;
 276        unsigned long guest_virt_base_stor_len;
 277        unsigned long guest_virt_var_stor_len;
 278        unsigned long guest_cpu_stor_len;
 279        unsigned long max_sec_stor_addr;
 280        unsigned int max_num_sec_conf;
 281        unsigned short max_guest_cpu_id;
 282        unsigned long uv_feature_indications;
 283};
 284
 285extern struct uv_info uv_info;
 286
 287#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST
 288extern int prot_virt_guest;
 289
 290static inline int is_prot_virt_guest(void)
 291{
 292        return prot_virt_guest;
 293}
 294
 295static inline int share(unsigned long addr, u16 cmd)
 296{
 297        struct uv_cb_share uvcb = {
 298                .header.cmd = cmd,
 299                .header.len = sizeof(uvcb),
 300                .paddr = addr
 301        };
 302
 303        if (!is_prot_virt_guest())
 304                return -EOPNOTSUPP;
 305        /*
 306         * Sharing is page wise, if we encounter addresses that are
 307         * not page aligned, we assume something went wrong. If
 308         * malloced structs are passed to this function, we could leak
 309         * data to the hypervisor.
 310         */
 311        BUG_ON(addr & ~PAGE_MASK);
 312
 313        if (!uv_call(0, (u64)&uvcb))
 314                return 0;
 315        return -EINVAL;
 316}
 317
 318/*
 319 * Guest 2 request to the Ultravisor to make a page shared with the
 320 * hypervisor for IO.
 321 *
 322 * @addr: Real or absolute address of the page to be shared
 323 */
 324static inline int uv_set_shared(unsigned long addr)
 325{
 326        return share(addr, UVC_CMD_SET_SHARED_ACCESS);
 327}
 328
 329/*
 330 * Guest 2 request to the Ultravisor to make a page unshared.
 331 *
 332 * @addr: Real or absolute address of the page to be unshared
 333 */
 334static inline int uv_remove_shared(unsigned long addr)
 335{
 336        return share(addr, UVC_CMD_REMOVE_SHARED_ACCESS);
 337}
 338
 339#else
 340#define is_prot_virt_guest() 0
 341static inline int uv_set_shared(unsigned long addr) { return 0; }
 342static inline int uv_remove_shared(unsigned long addr) { return 0; }
 343#endif
 344
 345#if IS_ENABLED(CONFIG_KVM)
 346extern int prot_virt_host;
 347
 348static inline int is_prot_virt_host(void)
 349{
 350        return prot_virt_host;
 351}
 352
 353int gmap_make_secure(struct gmap *gmap, unsigned long gaddr, void *uvcb);
 354int uv_destroy_page(unsigned long paddr);
 355int uv_convert_from_secure(unsigned long paddr);
 356int gmap_convert_to_secure(struct gmap *gmap, unsigned long gaddr);
 357
 358void setup_uv(void);
 359#else
 360#define is_prot_virt_host() 0
 361static inline void setup_uv(void) {}
 362
 363static inline int uv_destroy_page(unsigned long paddr)
 364{
 365        return 0;
 366}
 367
 368static inline int uv_convert_from_secure(unsigned long paddr)
 369{
 370        return 0;
 371}
 372#endif
 373
 374#endif /* _ASM_S390_UV_H */
 375