1
2
3
4
5
6
7
8
9
10
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
47
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
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
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
123
124
125
126
127
128
129
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