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