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 1688693ab2SClaudio Imbrenda #include "qemu/units.h" 17651615d9SDavid Gibson #include "qapi/error.h" 18c3347ed0SJanosch Frank #include "qemu/error-report.h" 19*32cad1ffSPhilippe Mathieu-Daudé #include "system/kvm.h" 20*32cad1ffSPhilippe Mathieu-Daudé #include "system/cpus.h" 21651615d9SDavid Gibson #include "qom/object_interfaces.h" 22651615d9SDavid Gibson #include "exec/confidential-guest-support.h" 23fbc1384cSChristian Borntraeger #include "hw/s390x/ipl.h" 2475d7150cSCédric Le Goater #include "hw/s390x/sclp.h" 2503d83ecfSJanosch Frank #include "target/s390x/kvm/kvm_s390x.h" 26f5f9c6eaSPhilippe Mathieu-Daudé #include "target/s390x/kvm/pv.h" 2703d83ecfSJanosch Frank 2803d83ecfSJanosch Frank static bool info_valid; 2903d83ecfSJanosch Frank static struct kvm_s390_pv_info_vm info_vm; 3003d83ecfSJanosch Frank static struct kvm_s390_pv_info_dump info_dump; 31c3347ed0SJanosch Frank 327af51621SThomas Huth static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data, 337af51621SThomas Huth int *pvrc) 34c3347ed0SJanosch Frank { 35c3347ed0SJanosch Frank struct kvm_pv_cmd pv_cmd = { 36c3347ed0SJanosch Frank .cmd = cmd, 37c3347ed0SJanosch Frank .data = (uint64_t)data, 38c3347ed0SJanosch Frank }; 39e8d12a55SChristian Borntraeger int rc; 40e8d12a55SChristian Borntraeger 41e8d12a55SChristian Borntraeger do { 42e8d12a55SChristian Borntraeger rc = kvm_vm_ioctl(kvm_state, KVM_S390_PV_COMMAND, &pv_cmd); 43e8d12a55SChristian Borntraeger } while (rc == -EINTR); 44c3347ed0SJanosch Frank 45c3347ed0SJanosch Frank if (rc) { 46c3347ed0SJanosch Frank error_report("KVM PV command %d (%s) failed: header rc %x rrc %x " 47c3347ed0SJanosch Frank "IOCTL rc: %d", cmd, cmdname, pv_cmd.rc, pv_cmd.rrc, 48c3347ed0SJanosch Frank rc); 49c3347ed0SJanosch Frank } 507af51621SThomas Huth if (pvrc) { 517af51621SThomas Huth *pvrc = pv_cmd.rc; 527af51621SThomas Huth } 53c3347ed0SJanosch Frank return rc; 54c3347ed0SJanosch Frank } 55c3347ed0SJanosch Frank 56c3347ed0SJanosch Frank /* 57c3347ed0SJanosch Frank * This macro lets us pass the command as a string to the function so 58c3347ed0SJanosch Frank * we can print it on an error. 59c3347ed0SJanosch Frank */ 607af51621SThomas Huth #define s390_pv_cmd(cmd, data) __s390_pv_cmd(cmd, #cmd, data, NULL) 617af51621SThomas Huth #define s390_pv_cmd_pvrc(cmd, data, pvrc) __s390_pv_cmd(cmd, #cmd, data, pvrc) 62c3347ed0SJanosch Frank #define s390_pv_cmd_exit(cmd, data) \ 63c3347ed0SJanosch Frank { \ 64c3347ed0SJanosch Frank int rc; \ 65c3347ed0SJanosch Frank \ 667af51621SThomas Huth rc = __s390_pv_cmd(cmd, #cmd, data, NULL); \ 67c3347ed0SJanosch Frank if (rc) { \ 68c3347ed0SJanosch Frank exit(1); \ 69c3347ed0SJanosch Frank } \ 70c3347ed0SJanosch Frank } 71c3347ed0SJanosch Frank 7203d83ecfSJanosch Frank int s390_pv_query_info(void) 7303d83ecfSJanosch Frank { 7403d83ecfSJanosch Frank struct kvm_s390_pv_info info = { 7503d83ecfSJanosch Frank .header.id = KVM_PV_INFO_VM, 7603d83ecfSJanosch Frank .header.len_max = sizeof(info.header) + sizeof(info.vm), 7703d83ecfSJanosch Frank }; 7803d83ecfSJanosch Frank int rc; 7903d83ecfSJanosch Frank 8003d83ecfSJanosch Frank /* Info API's first user is dump so they are bundled */ 8103d83ecfSJanosch Frank if (!kvm_s390_get_protected_dump()) { 8203d83ecfSJanosch Frank return 0; 8303d83ecfSJanosch Frank } 8403d83ecfSJanosch Frank 8503d83ecfSJanosch Frank rc = s390_pv_cmd(KVM_PV_INFO, &info); 8603d83ecfSJanosch Frank if (rc) { 8703d83ecfSJanosch Frank error_report("KVM PV INFO cmd %x failed: %s", 8803d83ecfSJanosch Frank info.header.id, strerror(-rc)); 8903d83ecfSJanosch Frank return rc; 9003d83ecfSJanosch Frank } 9103d83ecfSJanosch Frank memcpy(&info_vm, &info.vm, sizeof(info.vm)); 9203d83ecfSJanosch Frank 9303d83ecfSJanosch Frank info.header.id = KVM_PV_INFO_DUMP; 9403d83ecfSJanosch Frank info.header.len_max = sizeof(info.header) + sizeof(info.dump); 9503d83ecfSJanosch Frank rc = s390_pv_cmd(KVM_PV_INFO, &info); 9603d83ecfSJanosch Frank if (rc) { 9703d83ecfSJanosch Frank error_report("KVM PV INFO cmd %x failed: %s", 9803d83ecfSJanosch Frank info.header.id, strerror(-rc)); 9903d83ecfSJanosch Frank return rc; 10003d83ecfSJanosch Frank } 10103d83ecfSJanosch Frank 10203d83ecfSJanosch Frank memcpy(&info_dump, &info.dump, sizeof(info.dump)); 10303d83ecfSJanosch Frank info_valid = true; 10403d83ecfSJanosch Frank 10503d83ecfSJanosch Frank return rc; 10603d83ecfSJanosch Frank } 10703d83ecfSJanosch Frank 108c3347ed0SJanosch Frank int s390_pv_vm_enable(void) 109c3347ed0SJanosch Frank { 110c3347ed0SJanosch Frank return s390_pv_cmd(KVM_PV_ENABLE, NULL); 111c3347ed0SJanosch Frank } 112c3347ed0SJanosch Frank 113c3347ed0SJanosch Frank void s390_pv_vm_disable(void) 114c3347ed0SJanosch Frank { 115c3347ed0SJanosch Frank s390_pv_cmd_exit(KVM_PV_DISABLE, NULL); 116c3347ed0SJanosch Frank } 117c3347ed0SJanosch Frank 118c3a073c6SClaudio Imbrenda static void *s390_pv_do_unprot_async_fn(void *p) 119c3a073c6SClaudio Imbrenda { 120c3a073c6SClaudio Imbrenda s390_pv_cmd_exit(KVM_PV_ASYNC_CLEANUP_PERFORM, NULL); 121c3a073c6SClaudio Imbrenda return NULL; 122c3a073c6SClaudio Imbrenda } 123c3a073c6SClaudio Imbrenda 12488693ab2SClaudio Imbrenda bool s390_pv_vm_try_disable_async(S390CcwMachineState *ms) 125c3a073c6SClaudio Imbrenda { 126c3a073c6SClaudio Imbrenda /* 127c3a073c6SClaudio Imbrenda * t is only needed to create the thread; once qemu_thread_create 128c3a073c6SClaudio Imbrenda * returns, it can safely be discarded. 129c3a073c6SClaudio Imbrenda */ 130c3a073c6SClaudio Imbrenda QemuThread t; 131c3a073c6SClaudio Imbrenda 13288693ab2SClaudio Imbrenda /* 13388693ab2SClaudio Imbrenda * If the feature is not present or if the VM is not larger than 2 GiB, 13488693ab2SClaudio Imbrenda * KVM_PV_ASYNC_CLEANUP_PREPARE fill fail; no point in attempting it. 13588693ab2SClaudio Imbrenda */ 13688693ab2SClaudio Imbrenda if ((MACHINE(ms)->maxram_size <= 2 * GiB) || 13788693ab2SClaudio Imbrenda !kvm_check_extension(kvm_state, KVM_CAP_S390_PROTECTED_ASYNC_DISABLE)) { 138c3a073c6SClaudio Imbrenda return false; 139c3a073c6SClaudio Imbrenda } 140c3a073c6SClaudio Imbrenda if (s390_pv_cmd(KVM_PV_ASYNC_CLEANUP_PREPARE, NULL) != 0) { 141c3a073c6SClaudio Imbrenda return false; 142c3a073c6SClaudio Imbrenda } 143c3a073c6SClaudio Imbrenda 144c3a073c6SClaudio Imbrenda qemu_thread_create(&t, "async_cleanup", s390_pv_do_unprot_async_fn, NULL, 145c3a073c6SClaudio Imbrenda QEMU_THREAD_DETACHED); 146c3a073c6SClaudio Imbrenda 147c3a073c6SClaudio Imbrenda return true; 148c3a073c6SClaudio Imbrenda } 149c3a073c6SClaudio Imbrenda 1507af51621SThomas Huth int s390_pv_set_sec_parms(uint64_t origin, uint64_t length, Error **errp) 151c3347ed0SJanosch Frank { 1527af51621SThomas Huth int ret, pvrc; 153c3347ed0SJanosch Frank struct kvm_s390_pv_sec_parm args = { 154c3347ed0SJanosch Frank .origin = origin, 155c3347ed0SJanosch Frank .length = length, 156c3347ed0SJanosch Frank }; 157c3347ed0SJanosch Frank 1587af51621SThomas Huth ret = s390_pv_cmd_pvrc(KVM_PV_SET_SEC_PARMS, &args, &pvrc); 1597af51621SThomas Huth if (ret) { 1607af51621SThomas Huth error_setg(errp, "Failed to set secure execution parameters"); 1617af51621SThomas Huth if (pvrc == 0x108) { 1627af51621SThomas Huth error_append_hint(errp, "Please check whether the image is " 1637af51621SThomas Huth "correctly encrypted for this host\n"); 1647af51621SThomas Huth } 1657af51621SThomas Huth } 1667af51621SThomas Huth 1677af51621SThomas Huth return ret; 168c3347ed0SJanosch Frank } 169c3347ed0SJanosch Frank 170c3347ed0SJanosch Frank /* 171c3347ed0SJanosch Frank * Called for each component in the SE type IPL parameter block 0. 172c3347ed0SJanosch Frank */ 173c3347ed0SJanosch Frank int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak) 174c3347ed0SJanosch Frank { 175c3347ed0SJanosch Frank struct kvm_s390_pv_unp args = { 176c3347ed0SJanosch Frank .addr = addr, 177c3347ed0SJanosch Frank .size = size, 178c3347ed0SJanosch Frank .tweak = tweak, 179c3347ed0SJanosch Frank }; 180c3347ed0SJanosch Frank 181c3347ed0SJanosch Frank return s390_pv_cmd(KVM_PV_UNPACK, &args); 182c3347ed0SJanosch Frank } 183c3347ed0SJanosch Frank 1849a432597SJanosch Frank void s390_pv_prep_reset(void) 185c3347ed0SJanosch Frank { 186c3347ed0SJanosch Frank s390_pv_cmd_exit(KVM_PV_PREP_RESET, NULL); 187c3347ed0SJanosch Frank } 188c3347ed0SJanosch Frank 189c3347ed0SJanosch Frank int s390_pv_verify(void) 190c3347ed0SJanosch Frank { 191c3347ed0SJanosch Frank return s390_pv_cmd(KVM_PV_VERIFY, NULL); 192c3347ed0SJanosch Frank } 193c3347ed0SJanosch Frank 194c3347ed0SJanosch Frank void s390_pv_unshare(void) 195c3347ed0SJanosch Frank { 196c3347ed0SJanosch Frank s390_pv_cmd_exit(KVM_PV_UNSHARE_ALL, NULL); 197c3347ed0SJanosch Frank } 198fbc1384cSChristian Borntraeger 199fbc1384cSChristian Borntraeger void s390_pv_inject_reset_error(CPUState *cs) 200fbc1384cSChristian Borntraeger { 201fbc1384cSChristian Borntraeger int r1 = (cs->kvm_run->s390_sieic.ipa & 0x00f0) >> 4; 202fbc1384cSChristian Borntraeger CPUS390XState *env = &S390_CPU(cs)->env; 203fbc1384cSChristian Borntraeger 204fbc1384cSChristian Borntraeger /* Report that we are unable to enter protected mode */ 205fbc1384cSChristian Borntraeger env->regs[r1 + 1] = DIAG_308_RC_INVAL_FOR_PV; 206fbc1384cSChristian Borntraeger } 207651615d9SDavid Gibson 20803d83ecfSJanosch Frank uint64_t kvm_s390_pv_dmp_get_size_cpu(void) 20903d83ecfSJanosch Frank { 21003d83ecfSJanosch Frank return info_dump.dump_cpu_buffer_len; 21103d83ecfSJanosch Frank } 21203d83ecfSJanosch Frank 21303d83ecfSJanosch Frank uint64_t kvm_s390_pv_dmp_get_size_completion_data(void) 21403d83ecfSJanosch Frank { 21503d83ecfSJanosch Frank return info_dump.dump_config_finalize_len; 21603d83ecfSJanosch Frank } 21703d83ecfSJanosch Frank 21803d83ecfSJanosch Frank uint64_t kvm_s390_pv_dmp_get_size_mem_state(void) 21903d83ecfSJanosch Frank { 22003d83ecfSJanosch Frank return info_dump.dump_config_mem_buffer_per_1m; 22103d83ecfSJanosch Frank } 22203d83ecfSJanosch Frank 22303d83ecfSJanosch Frank bool kvm_s390_pv_info_basic_valid(void) 22403d83ecfSJanosch Frank { 22503d83ecfSJanosch Frank return info_valid; 22603d83ecfSJanosch Frank } 22703d83ecfSJanosch Frank 228753ca06fSJanosch Frank static int s390_pv_dump_cmd(uint64_t subcmd, uint64_t uaddr, uint64_t gaddr, 229753ca06fSJanosch Frank uint64_t len) 230753ca06fSJanosch Frank { 231753ca06fSJanosch Frank struct kvm_s390_pv_dmp dmp = { 232753ca06fSJanosch Frank .subcmd = subcmd, 233753ca06fSJanosch Frank .buff_addr = uaddr, 234753ca06fSJanosch Frank .buff_len = len, 235753ca06fSJanosch Frank .gaddr = gaddr, 236753ca06fSJanosch Frank }; 237753ca06fSJanosch Frank int ret; 238753ca06fSJanosch Frank 239753ca06fSJanosch Frank ret = s390_pv_cmd(KVM_PV_DUMP, (void *)&dmp); 240753ca06fSJanosch Frank if (ret) { 241753ca06fSJanosch Frank error_report("KVM DUMP command %ld failed", subcmd); 242753ca06fSJanosch Frank } 243753ca06fSJanosch Frank return ret; 244753ca06fSJanosch Frank } 245753ca06fSJanosch Frank 246753ca06fSJanosch Frank int kvm_s390_dump_cpu(S390CPU *cpu, void *buff) 247753ca06fSJanosch Frank { 248753ca06fSJanosch Frank struct kvm_s390_pv_dmp dmp = { 249753ca06fSJanosch Frank .subcmd = KVM_PV_DUMP_CPU, 250753ca06fSJanosch Frank .buff_addr = (uint64_t)buff, 251753ca06fSJanosch Frank .gaddr = 0, 252753ca06fSJanosch Frank .buff_len = info_dump.dump_cpu_buffer_len, 253753ca06fSJanosch Frank }; 254753ca06fSJanosch Frank struct kvm_pv_cmd pv = { 255753ca06fSJanosch Frank .cmd = KVM_PV_DUMP, 256753ca06fSJanosch Frank .data = (uint64_t)&dmp, 257753ca06fSJanosch Frank }; 258753ca06fSJanosch Frank 259753ca06fSJanosch Frank return kvm_vcpu_ioctl(CPU(cpu), KVM_S390_PV_CPU_COMMAND, &pv); 260753ca06fSJanosch Frank } 261753ca06fSJanosch Frank 262753ca06fSJanosch Frank int kvm_s390_dump_init(void) 263753ca06fSJanosch Frank { 264753ca06fSJanosch Frank return s390_pv_dump_cmd(KVM_PV_DUMP_INIT, 0, 0, 0); 265753ca06fSJanosch Frank } 266753ca06fSJanosch Frank 267753ca06fSJanosch Frank int kvm_s390_dump_mem_state(uint64_t gaddr, size_t len, void *dest) 268753ca06fSJanosch Frank { 269753ca06fSJanosch Frank return s390_pv_dump_cmd(KVM_PV_DUMP_CONFIG_STOR_STATE, (uint64_t)dest, 270753ca06fSJanosch Frank gaddr, len); 271753ca06fSJanosch Frank } 272753ca06fSJanosch Frank 273753ca06fSJanosch Frank int kvm_s390_dump_completion_data(void *buff) 274753ca06fSJanosch Frank { 275753ca06fSJanosch Frank return s390_pv_dump_cmd(KVM_PV_DUMP_COMPLETE, (uint64_t)buff, 0, 276753ca06fSJanosch Frank info_dump.dump_config_finalize_len); 277753ca06fSJanosch Frank } 278753ca06fSJanosch Frank 279651615d9SDavid Gibson #define TYPE_S390_PV_GUEST "s390-pv-guest" 280651615d9SDavid Gibson OBJECT_DECLARE_SIMPLE_TYPE(S390PVGuest, S390_PV_GUEST) 281651615d9SDavid Gibson 282651615d9SDavid Gibson /** 283651615d9SDavid Gibson * S390PVGuest: 284651615d9SDavid Gibson * 285651615d9SDavid Gibson * The S390PVGuest object is basically a dummy used to tell the 286651615d9SDavid Gibson * confidential guest support system to use s390's PV mechanism. 287651615d9SDavid Gibson * 288651615d9SDavid Gibson * # $QEMU \ 289651615d9SDavid Gibson * -object s390-pv-guest,id=pv0 \ 290651615d9SDavid Gibson * -machine ...,confidential-guest-support=pv0 291651615d9SDavid Gibson */ 292651615d9SDavid Gibson struct S390PVGuest { 293651615d9SDavid Gibson ConfidentialGuestSupport parent_obj; 294651615d9SDavid Gibson }; 295651615d9SDavid Gibson 296651615d9SDavid Gibson typedef struct S390PVGuestClass S390PVGuestClass; 297651615d9SDavid Gibson 298651615d9SDavid Gibson struct S390PVGuestClass { 299651615d9SDavid Gibson ConfidentialGuestSupportClass parent_class; 300651615d9SDavid Gibson }; 301651615d9SDavid Gibson 30275d7150cSCédric Le Goater /* 30375d7150cSCédric Le Goater * If protected virtualization is enabled, the amount of data that the 30475d7150cSCédric Le Goater * Read SCP Info Service Call can use is limited to one page. The 30575d7150cSCédric Le Goater * available space also depends on the Extended-Length SCCB (ELS) 30675d7150cSCédric Le Goater * feature which can take more buffer space to store feature 30775d7150cSCédric Le Goater * information. This impacts the maximum number of CPUs supported in 30875d7150cSCédric Le Goater * the machine. 30975d7150cSCédric Le Goater */ 31075d7150cSCédric Le Goater static uint32_t s390_pv_get_max_cpus(void) 31175d7150cSCédric Le Goater { 31275d7150cSCédric Le Goater int offset_cpu = s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB) ? 31375d7150cSCédric Le Goater offsetof(ReadInfo, entries) : SCLP_READ_SCP_INFO_FIXED_CPU_OFFSET; 31475d7150cSCédric Le Goater 31575d7150cSCédric Le Goater return (TARGET_PAGE_SIZE - offset_cpu) / sizeof(CPUEntry); 31675d7150cSCédric Le Goater } 31775d7150cSCédric Le Goater 31875d7150cSCédric Le Goater static bool s390_pv_check_cpus(Error **errp) 31975d7150cSCédric Le Goater { 32075d7150cSCédric Le Goater MachineState *ms = MACHINE(qdev_get_machine()); 32175d7150cSCédric Le Goater uint32_t pv_max_cpus = s390_pv_get_max_cpus(); 32275d7150cSCédric Le Goater 32375d7150cSCédric Le Goater if (ms->smp.max_cpus > pv_max_cpus) { 32475d7150cSCédric Le Goater error_setg(errp, "Protected VMs support a maximum of %d CPUs", 32575d7150cSCédric Le Goater pv_max_cpus); 32675d7150cSCédric Le Goater return false; 32775d7150cSCédric Le Goater } 32875d7150cSCédric Le Goater 32975d7150cSCédric Le Goater return true; 33075d7150cSCédric Le Goater } 33175d7150cSCédric Le Goater 33275d7150cSCédric Le Goater static bool s390_pv_guest_check(ConfidentialGuestSupport *cgs, Error **errp) 33375d7150cSCédric Le Goater { 33475d7150cSCédric Le Goater return s390_pv_check_cpus(errp); 33575d7150cSCédric Le Goater } 33675d7150cSCédric Le Goater 337a14a2b01SXiaoyao Li static int s390_pv_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) 338651615d9SDavid Gibson { 339651615d9SDavid Gibson if (!object_dynamic_cast(OBJECT(cgs), TYPE_S390_PV_GUEST)) { 340651615d9SDavid Gibson return 0; 341651615d9SDavid Gibson } 342651615d9SDavid Gibson 343a14a2b01SXiaoyao Li if (!kvm_enabled()) { 344a14a2b01SXiaoyao Li error_setg(errp, "Protected Virtualization requires KVM"); 345a14a2b01SXiaoyao Li return -1; 346a14a2b01SXiaoyao Li } 347a14a2b01SXiaoyao Li 348651615d9SDavid Gibson if (!s390_has_feat(S390_FEAT_UNPACK)) { 349651615d9SDavid Gibson error_setg(errp, 350651615d9SDavid Gibson "CPU model does not support Protected Virtualization"); 351651615d9SDavid Gibson return -1; 352651615d9SDavid Gibson } 353651615d9SDavid Gibson 35475d7150cSCédric Le Goater if (!s390_pv_guest_check(cgs, errp)) { 35575d7150cSCédric Le Goater return -1; 35675d7150cSCédric Le Goater } 35775d7150cSCédric Le Goater 358651615d9SDavid Gibson cgs->ready = true; 359651615d9SDavid Gibson 360651615d9SDavid Gibson return 0; 361651615d9SDavid Gibson } 362651615d9SDavid Gibson 363651615d9SDavid Gibson OBJECT_DEFINE_TYPE_WITH_INTERFACES(S390PVGuest, 364651615d9SDavid Gibson s390_pv_guest, 365651615d9SDavid Gibson S390_PV_GUEST, 366651615d9SDavid Gibson CONFIDENTIAL_GUEST_SUPPORT, 367651615d9SDavid Gibson { TYPE_USER_CREATABLE }, 368651615d9SDavid Gibson { NULL }) 369651615d9SDavid Gibson 370651615d9SDavid Gibson static void s390_pv_guest_class_init(ObjectClass *oc, void *data) 371651615d9SDavid Gibson { 372a14a2b01SXiaoyao Li ConfidentialGuestSupportClass *klass = CONFIDENTIAL_GUEST_SUPPORT_CLASS(oc); 373a14a2b01SXiaoyao Li 374a14a2b01SXiaoyao Li klass->kvm_init = s390_pv_kvm_init; 375651615d9SDavid Gibson } 376651615d9SDavid Gibson 377651615d9SDavid Gibson static void s390_pv_guest_init(Object *obj) 378651615d9SDavid Gibson { 379651615d9SDavid Gibson } 380651615d9SDavid Gibson 381651615d9SDavid Gibson static void s390_pv_guest_finalize(Object *obj) 382651615d9SDavid Gibson { 383651615d9SDavid Gibson } 384