qemu/hw/s390x/pv.c
<<
>>
Prefs
   1/*
   2 * Protected Virtualization functions
   3 *
   4 * Copyright IBM Corp. 2020
   5 * Author(s):
   6 *  Janosch Frank <frankja@linux.ibm.com>
   7 *
   8 * This work is licensed under the terms of the GNU GPL, version 2 or (at
   9 * your option) any later version. See the COPYING file in the top-level
  10 * directory.
  11 */
  12#include "qemu/osdep.h"
  13
  14#include <linux/kvm.h>
  15
  16#include "qapi/error.h"
  17#include "qemu/error-report.h"
  18#include "sysemu/kvm.h"
  19#include "qom/object_interfaces.h"
  20#include "exec/confidential-guest-support.h"
  21#include "hw/s390x/ipl.h"
  22#include "hw/s390x/pv.h"
  23
  24static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data)
  25{
  26    struct kvm_pv_cmd pv_cmd = {
  27        .cmd = cmd,
  28        .data = (uint64_t)data,
  29    };
  30    int rc;
  31
  32    do {
  33        rc = kvm_vm_ioctl(kvm_state, KVM_S390_PV_COMMAND, &pv_cmd);
  34    } while (rc == -EINTR);
  35
  36    if (rc) {
  37        error_report("KVM PV command %d (%s) failed: header rc %x rrc %x "
  38                     "IOCTL rc: %d", cmd, cmdname, pv_cmd.rc, pv_cmd.rrc,
  39                     rc);
  40    }
  41    return rc;
  42}
  43
  44/*
  45 * This macro lets us pass the command as a string to the function so
  46 * we can print it on an error.
  47 */
  48#define s390_pv_cmd(cmd, data) __s390_pv_cmd(cmd, #cmd, data);
  49#define s390_pv_cmd_exit(cmd, data)    \
  50{                                      \
  51    int rc;                            \
  52                                       \
  53    rc = __s390_pv_cmd(cmd, #cmd, data);\
  54    if (rc) {                          \
  55        exit(1);                       \
  56    }                                  \
  57}
  58
  59int s390_pv_vm_enable(void)
  60{
  61    return s390_pv_cmd(KVM_PV_ENABLE, NULL);
  62}
  63
  64void s390_pv_vm_disable(void)
  65{
  66     s390_pv_cmd_exit(KVM_PV_DISABLE, NULL);
  67}
  68
  69int s390_pv_set_sec_parms(uint64_t origin, uint64_t length)
  70{
  71    struct kvm_s390_pv_sec_parm args = {
  72        .origin = origin,
  73        .length = length,
  74    };
  75
  76    return s390_pv_cmd(KVM_PV_SET_SEC_PARMS, &args);
  77}
  78
  79/*
  80 * Called for each component in the SE type IPL parameter block 0.
  81 */
  82int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak)
  83{
  84    struct kvm_s390_pv_unp args = {
  85        .addr = addr,
  86        .size = size,
  87        .tweak = tweak,
  88    };
  89
  90    return s390_pv_cmd(KVM_PV_UNPACK, &args);
  91}
  92
  93void s390_pv_prep_reset(void)
  94{
  95    s390_pv_cmd_exit(KVM_PV_PREP_RESET, NULL);
  96}
  97
  98int s390_pv_verify(void)
  99{
 100    return s390_pv_cmd(KVM_PV_VERIFY, NULL);
 101}
 102
 103void s390_pv_unshare(void)
 104{
 105    s390_pv_cmd_exit(KVM_PV_UNSHARE_ALL, NULL);
 106}
 107
 108void s390_pv_inject_reset_error(CPUState *cs)
 109{
 110    int r1 = (cs->kvm_run->s390_sieic.ipa & 0x00f0) >> 4;
 111    CPUS390XState *env = &S390_CPU(cs)->env;
 112
 113    /* Report that we are unable to enter protected mode */
 114    env->regs[r1 + 1] = DIAG_308_RC_INVAL_FOR_PV;
 115}
 116
 117#define TYPE_S390_PV_GUEST "s390-pv-guest"
 118OBJECT_DECLARE_SIMPLE_TYPE(S390PVGuest, S390_PV_GUEST)
 119
 120/**
 121 * S390PVGuest:
 122 *
 123 * The S390PVGuest object is basically a dummy used to tell the
 124 * confidential guest support system to use s390's PV mechanism.
 125 *
 126 * # $QEMU \
 127 *         -object s390-pv-guest,id=pv0 \
 128 *         -machine ...,confidential-guest-support=pv0
 129 */
 130struct S390PVGuest {
 131    ConfidentialGuestSupport parent_obj;
 132};
 133
 134typedef struct S390PVGuestClass S390PVGuestClass;
 135
 136struct S390PVGuestClass {
 137    ConfidentialGuestSupportClass parent_class;
 138};
 139
 140int s390_pv_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
 141{
 142    if (!object_dynamic_cast(OBJECT(cgs), TYPE_S390_PV_GUEST)) {
 143        return 0;
 144    }
 145
 146    if (!s390_has_feat(S390_FEAT_UNPACK)) {
 147        error_setg(errp,
 148                   "CPU model does not support Protected Virtualization");
 149        return -1;
 150    }
 151
 152    cgs->ready = true;
 153
 154    return 0;
 155}
 156
 157OBJECT_DEFINE_TYPE_WITH_INTERFACES(S390PVGuest,
 158                                   s390_pv_guest,
 159                                   S390_PV_GUEST,
 160                                   CONFIDENTIAL_GUEST_SUPPORT,
 161                                   { TYPE_USER_CREATABLE },
 162                                   { NULL })
 163
 164static void s390_pv_guest_class_init(ObjectClass *oc, void *data)
 165{
 166}
 167
 168static void s390_pv_guest_init(Object *obj)
 169{
 170}
 171
 172static void s390_pv_guest_finalize(Object *obj)
 173{
 174}
 175