xref: /qemu/target/s390x/kvm/pv.c (revision 651615d92d244a6dfd7c81ab97bd3369fbe41d06)
1c3347ed0SJanosch Frank /*
2c3347ed0SJanosch Frank  * Protected Virtualization functions
3c3347ed0SJanosch Frank  *
4c3347ed0SJanosch Frank  * Copyright IBM Corp. 2020
5c3347ed0SJanosch Frank  * Author(s):
6c3347ed0SJanosch Frank  *  Janosch Frank <frankja@linux.ibm.com>
7c3347ed0SJanosch Frank  *
8c3347ed0SJanosch Frank  * This work is licensed under the terms of the GNU GPL, version 2 or (at
9c3347ed0SJanosch Frank  * your option) any later version. See the COPYING file in the top-level
10c3347ed0SJanosch Frank  * directory.
11c3347ed0SJanosch Frank  */
12c3347ed0SJanosch Frank #include "qemu/osdep.h"
13c3347ed0SJanosch Frank 
14c3347ed0SJanosch Frank #include <linux/kvm.h>
15c3347ed0SJanosch Frank 
16fbc1384cSChristian Borntraeger #include "cpu.h"
17651615d9SDavid Gibson #include "qapi/error.h"
18c3347ed0SJanosch Frank #include "qemu/error-report.h"
19c3347ed0SJanosch Frank #include "sysemu/kvm.h"
20651615d9SDavid Gibson #include "qom/object_interfaces.h"
21651615d9SDavid Gibson #include "exec/confidential-guest-support.h"
22fbc1384cSChristian Borntraeger #include "hw/s390x/ipl.h"
23c3347ed0SJanosch Frank #include "hw/s390x/pv.h"
24c3347ed0SJanosch Frank 
25c3347ed0SJanosch Frank static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data)
26c3347ed0SJanosch Frank {
27c3347ed0SJanosch Frank     struct kvm_pv_cmd pv_cmd = {
28c3347ed0SJanosch Frank         .cmd = cmd,
29c3347ed0SJanosch Frank         .data = (uint64_t)data,
30c3347ed0SJanosch Frank     };
31e8d12a55SChristian Borntraeger     int rc;
32e8d12a55SChristian Borntraeger 
33e8d12a55SChristian Borntraeger     do {
34e8d12a55SChristian Borntraeger         rc = kvm_vm_ioctl(kvm_state, KVM_S390_PV_COMMAND, &pv_cmd);
35e8d12a55SChristian Borntraeger     } while (rc == -EINTR);
36c3347ed0SJanosch Frank 
37c3347ed0SJanosch Frank     if (rc) {
38c3347ed0SJanosch Frank         error_report("KVM PV command %d (%s) failed: header rc %x rrc %x "
39c3347ed0SJanosch Frank                      "IOCTL rc: %d", cmd, cmdname, pv_cmd.rc, pv_cmd.rrc,
40c3347ed0SJanosch Frank                      rc);
41c3347ed0SJanosch Frank     }
42c3347ed0SJanosch Frank     return rc;
43c3347ed0SJanosch Frank }
44c3347ed0SJanosch Frank 
45c3347ed0SJanosch Frank /*
46c3347ed0SJanosch Frank  * This macro lets us pass the command as a string to the function so
47c3347ed0SJanosch Frank  * we can print it on an error.
48c3347ed0SJanosch Frank  */
49c3347ed0SJanosch Frank #define s390_pv_cmd(cmd, data) __s390_pv_cmd(cmd, #cmd, data);
50c3347ed0SJanosch Frank #define s390_pv_cmd_exit(cmd, data)    \
51c3347ed0SJanosch Frank {                                      \
52c3347ed0SJanosch Frank     int rc;                            \
53c3347ed0SJanosch Frank                                        \
54c3347ed0SJanosch Frank     rc = __s390_pv_cmd(cmd, #cmd, data);\
55c3347ed0SJanosch Frank     if (rc) {                          \
56c3347ed0SJanosch Frank         exit(1);                       \
57c3347ed0SJanosch Frank     }                                  \
58c3347ed0SJanosch Frank }
59c3347ed0SJanosch Frank 
60c3347ed0SJanosch Frank int s390_pv_vm_enable(void)
61c3347ed0SJanosch Frank {
62c3347ed0SJanosch Frank     return s390_pv_cmd(KVM_PV_ENABLE, NULL);
63c3347ed0SJanosch Frank }
64c3347ed0SJanosch Frank 
65c3347ed0SJanosch Frank void s390_pv_vm_disable(void)
66c3347ed0SJanosch Frank {
67c3347ed0SJanosch Frank      s390_pv_cmd_exit(KVM_PV_DISABLE, NULL);
68c3347ed0SJanosch Frank }
69c3347ed0SJanosch Frank 
70c3347ed0SJanosch Frank int s390_pv_set_sec_parms(uint64_t origin, uint64_t length)
71c3347ed0SJanosch Frank {
72c3347ed0SJanosch Frank     struct kvm_s390_pv_sec_parm args = {
73c3347ed0SJanosch Frank         .origin = origin,
74c3347ed0SJanosch Frank         .length = length,
75c3347ed0SJanosch Frank     };
76c3347ed0SJanosch Frank 
77c3347ed0SJanosch Frank     return s390_pv_cmd(KVM_PV_SET_SEC_PARMS, &args);
78c3347ed0SJanosch Frank }
79c3347ed0SJanosch Frank 
80c3347ed0SJanosch Frank /*
81c3347ed0SJanosch Frank  * Called for each component in the SE type IPL parameter block 0.
82c3347ed0SJanosch Frank  */
83c3347ed0SJanosch Frank int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak)
84c3347ed0SJanosch Frank {
85c3347ed0SJanosch Frank     struct kvm_s390_pv_unp args = {
86c3347ed0SJanosch Frank         .addr = addr,
87c3347ed0SJanosch Frank         .size = size,
88c3347ed0SJanosch Frank         .tweak = tweak,
89c3347ed0SJanosch Frank     };
90c3347ed0SJanosch Frank 
91c3347ed0SJanosch Frank     return s390_pv_cmd(KVM_PV_UNPACK, &args);
92c3347ed0SJanosch Frank }
93c3347ed0SJanosch Frank 
949a432597SJanosch Frank void s390_pv_prep_reset(void)
95c3347ed0SJanosch Frank {
96c3347ed0SJanosch Frank     s390_pv_cmd_exit(KVM_PV_PREP_RESET, NULL);
97c3347ed0SJanosch Frank }
98c3347ed0SJanosch Frank 
99c3347ed0SJanosch Frank int s390_pv_verify(void)
100c3347ed0SJanosch Frank {
101c3347ed0SJanosch Frank     return s390_pv_cmd(KVM_PV_VERIFY, NULL);
102c3347ed0SJanosch Frank }
103c3347ed0SJanosch Frank 
104c3347ed0SJanosch Frank void s390_pv_unshare(void)
105c3347ed0SJanosch Frank {
106c3347ed0SJanosch Frank     s390_pv_cmd_exit(KVM_PV_UNSHARE_ALL, NULL);
107c3347ed0SJanosch Frank }
108fbc1384cSChristian Borntraeger 
109fbc1384cSChristian Borntraeger void s390_pv_inject_reset_error(CPUState *cs)
110fbc1384cSChristian Borntraeger {
111fbc1384cSChristian Borntraeger     int r1 = (cs->kvm_run->s390_sieic.ipa & 0x00f0) >> 4;
112fbc1384cSChristian Borntraeger     CPUS390XState *env = &S390_CPU(cs)->env;
113fbc1384cSChristian Borntraeger 
114fbc1384cSChristian Borntraeger     /* Report that we are unable to enter protected mode */
115fbc1384cSChristian Borntraeger     env->regs[r1 + 1] = DIAG_308_RC_INVAL_FOR_PV;
116fbc1384cSChristian Borntraeger }
117651615d9SDavid Gibson 
118651615d9SDavid Gibson #define TYPE_S390_PV_GUEST "s390-pv-guest"
119651615d9SDavid Gibson OBJECT_DECLARE_SIMPLE_TYPE(S390PVGuest, S390_PV_GUEST)
120651615d9SDavid Gibson 
121651615d9SDavid Gibson /**
122651615d9SDavid Gibson  * S390PVGuest:
123651615d9SDavid Gibson  *
124651615d9SDavid Gibson  * The S390PVGuest object is basically a dummy used to tell the
125651615d9SDavid Gibson  * confidential guest support system to use s390's PV mechanism.
126651615d9SDavid Gibson  *
127651615d9SDavid Gibson  * # $QEMU \
128651615d9SDavid Gibson  *         -object s390-pv-guest,id=pv0 \
129651615d9SDavid Gibson  *         -machine ...,confidential-guest-support=pv0
130651615d9SDavid Gibson  */
131651615d9SDavid Gibson struct S390PVGuest {
132651615d9SDavid Gibson     ConfidentialGuestSupport parent_obj;
133651615d9SDavid Gibson };
134651615d9SDavid Gibson 
135651615d9SDavid Gibson typedef struct S390PVGuestClass S390PVGuestClass;
136651615d9SDavid Gibson 
137651615d9SDavid Gibson struct S390PVGuestClass {
138651615d9SDavid Gibson     ConfidentialGuestSupportClass parent_class;
139651615d9SDavid Gibson };
140651615d9SDavid Gibson 
141651615d9SDavid Gibson int s390_pv_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
142651615d9SDavid Gibson {
143651615d9SDavid Gibson     if (!object_dynamic_cast(OBJECT(cgs), TYPE_S390_PV_GUEST)) {
144651615d9SDavid Gibson         return 0;
145651615d9SDavid Gibson     }
146651615d9SDavid Gibson 
147651615d9SDavid Gibson     if (!s390_has_feat(S390_FEAT_UNPACK)) {
148651615d9SDavid Gibson         error_setg(errp,
149651615d9SDavid Gibson                    "CPU model does not support Protected Virtualization");
150651615d9SDavid Gibson         return -1;
151651615d9SDavid Gibson     }
152651615d9SDavid Gibson 
153651615d9SDavid Gibson     cgs->ready = true;
154651615d9SDavid Gibson 
155651615d9SDavid Gibson     return 0;
156651615d9SDavid Gibson }
157651615d9SDavid Gibson 
158651615d9SDavid Gibson OBJECT_DEFINE_TYPE_WITH_INTERFACES(S390PVGuest,
159651615d9SDavid Gibson                                    s390_pv_guest,
160651615d9SDavid Gibson                                    S390_PV_GUEST,
161651615d9SDavid Gibson                                    CONFIDENTIAL_GUEST_SUPPORT,
162651615d9SDavid Gibson                                    { TYPE_USER_CREATABLE },
163651615d9SDavid Gibson                                    { NULL })
164651615d9SDavid Gibson 
165651615d9SDavid Gibson static void s390_pv_guest_class_init(ObjectClass *oc, void *data)
166651615d9SDavid Gibson {
167651615d9SDavid Gibson }
168651615d9SDavid Gibson 
169651615d9SDavid Gibson static void s390_pv_guest_init(Object *obj)
170651615d9SDavid Gibson {
171651615d9SDavid Gibson }
172651615d9SDavid Gibson 
173651615d9SDavid Gibson static void s390_pv_guest_finalize(Object *obj)
174651615d9SDavid Gibson {
175651615d9SDavid Gibson }
176