xref: /openbmc/qemu/hw/i386/vmport.c (revision d45a5270d075ea589f0b0ddcf963a5fea1f500ac)
1323d7d1dSPhilippe Mathieu-Daudé /*
2323d7d1dSPhilippe Mathieu-Daudé  * QEMU VMPort emulation
3323d7d1dSPhilippe Mathieu-Daudé  *
4323d7d1dSPhilippe Mathieu-Daudé  * Copyright (C) 2007 Hervé Poussineau
5323d7d1dSPhilippe Mathieu-Daudé  *
6323d7d1dSPhilippe Mathieu-Daudé  * Permission is hereby granted, free of charge, to any person obtaining a copy
7323d7d1dSPhilippe Mathieu-Daudé  * of this software and associated documentation files (the "Software"), to deal
8323d7d1dSPhilippe Mathieu-Daudé  * in the Software without restriction, including without limitation the rights
9323d7d1dSPhilippe Mathieu-Daudé  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10323d7d1dSPhilippe Mathieu-Daudé  * copies of the Software, and to permit persons to whom the Software is
11323d7d1dSPhilippe Mathieu-Daudé  * furnished to do so, subject to the following conditions:
12323d7d1dSPhilippe Mathieu-Daudé  *
13323d7d1dSPhilippe Mathieu-Daudé  * The above copyright notice and this permission notice shall be included in
14323d7d1dSPhilippe Mathieu-Daudé  * all copies or substantial portions of the Software.
15323d7d1dSPhilippe Mathieu-Daudé  *
16323d7d1dSPhilippe Mathieu-Daudé  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17323d7d1dSPhilippe Mathieu-Daudé  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18323d7d1dSPhilippe Mathieu-Daudé  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19323d7d1dSPhilippe Mathieu-Daudé  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20323d7d1dSPhilippe Mathieu-Daudé  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21323d7d1dSPhilippe Mathieu-Daudé  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22323d7d1dSPhilippe Mathieu-Daudé  * THE SOFTWARE.
23323d7d1dSPhilippe Mathieu-Daudé  */
2429282253SLiran Alon 
2529282253SLiran Alon /*
2629282253SLiran Alon  * Guest code that interacts with this virtual device can be found
2729282253SLiran Alon  * in VMware open-vm-tools open-source project:
2829282253SLiran Alon  * https://github.com/vmware/open-vm-tools
2929282253SLiran Alon  */
3029282253SLiran Alon 
31323d7d1dSPhilippe Mathieu-Daudé #include "qemu/osdep.h"
32323d7d1dSPhilippe Mathieu-Daudé #include "hw/isa/isa.h"
33d8f23d61SLiran Alon #include "hw/i386/vmport.h"
34c9ab24ceSLiran Alon #include "hw/qdev-properties.h"
35*86378b29SPaolo Bonzini #include "hw/boards.h"
36aaacf1c1SLiran Alon #include "sysemu/sysemu.h"
37323d7d1dSPhilippe Mathieu-Daudé #include "sysemu/hw_accel.h"
38c781a2ccSPhilippe Mathieu-Daudé #include "sysemu/qtest.h"
3943ab9a53SLaurent Vivier #include "qemu/log.h"
407299e1a4SPhilippe Mathieu-Daudé #include "trace.h"
41db1015e9SEduardo Habkost #include "qom/object.h"
42323d7d1dSPhilippe Mathieu-Daudé 
43323d7d1dSPhilippe Mathieu-Daudé #define VMPORT_MAGIC   0x564D5868
44323d7d1dSPhilippe Mathieu-Daudé 
45b8892129SLiran Alon /* Compatibility flags for migration */
46b8892129SLiran Alon #define VMPORT_COMPAT_READ_SET_EAX_BIT              0
470342ee76SLiran Alon #define VMPORT_COMPAT_SIGNAL_UNSUPPORTED_CMD_BIT    1
48f8bdc550SLiran Alon #define VMPORT_COMPAT_REPORT_VMX_TYPE_BIT           2
49aaacf1c1SLiran Alon #define VMPORT_COMPAT_CMDS_V2_BIT                   3
50b8892129SLiran Alon #define VMPORT_COMPAT_READ_SET_EAX              \
51b8892129SLiran Alon     (1 << VMPORT_COMPAT_READ_SET_EAX_BIT)
520342ee76SLiran Alon #define VMPORT_COMPAT_SIGNAL_UNSUPPORTED_CMD    \
530342ee76SLiran Alon     (1 << VMPORT_COMPAT_SIGNAL_UNSUPPORTED_CMD_BIT)
54f8bdc550SLiran Alon #define VMPORT_COMPAT_REPORT_VMX_TYPE           \
55f8bdc550SLiran Alon     (1 << VMPORT_COMPAT_REPORT_VMX_TYPE_BIT)
56aaacf1c1SLiran Alon #define VMPORT_COMPAT_CMDS_V2                   \
57aaacf1c1SLiran Alon     (1 << VMPORT_COMPAT_CMDS_V2_BIT)
58b8892129SLiran Alon 
59acacd355SLiran Alon /* vCPU features reported by CMD_GET_VCPU_INFO */
60acacd355SLiran Alon #define VCPU_INFO_SLC64_BIT             0
61acacd355SLiran Alon #define VCPU_INFO_SYNC_VTSCS_BIT        1
62acacd355SLiran Alon #define VCPU_INFO_HV_REPLAY_OK_BIT      2
63acacd355SLiran Alon #define VCPU_INFO_LEGACY_X2APIC_BIT     3
64acacd355SLiran Alon #define VCPU_INFO_RESERVED_BIT          31
65acacd355SLiran Alon 
668063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(VMPortState, VMPORT)
67323d7d1dSPhilippe Mathieu-Daudé 
68db1015e9SEduardo Habkost struct VMPortState {
69323d7d1dSPhilippe Mathieu-Daudé     ISADevice parent_obj;
70323d7d1dSPhilippe Mathieu-Daudé 
71323d7d1dSPhilippe Mathieu-Daudé     MemoryRegion io;
72323d7d1dSPhilippe Mathieu-Daudé     VMPortReadFunc *func[VMPORT_ENTRIES];
73323d7d1dSPhilippe Mathieu-Daudé     void *opaque[VMPORT_ENTRIES];
74b8892129SLiran Alon 
752fd2f799SLiran Alon     uint32_t vmware_vmx_version;
76f8bdc550SLiran Alon     uint8_t vmware_vmx_type;
772fd2f799SLiran Alon 
78b8892129SLiran Alon     uint32_t compat_flags;
79db1015e9SEduardo Habkost };
80323d7d1dSPhilippe Mathieu-Daudé 
81323d7d1dSPhilippe Mathieu-Daudé static VMPortState *port_state;
82323d7d1dSPhilippe Mathieu-Daudé 
vmport_register(VMPortCommand command,VMPortReadFunc * func,void * opaque)83dcd938f0SLiran Alon void vmport_register(VMPortCommand command, VMPortReadFunc *func, void *opaque)
84323d7d1dSPhilippe Mathieu-Daudé {
85dcd938f0SLiran Alon     assert(command < VMPORT_ENTRIES);
8623accdf1SLiran Alon     assert(port_state);
8723accdf1SLiran Alon 
887299e1a4SPhilippe Mathieu-Daudé     trace_vmport_register(command, func, opaque);
89323d7d1dSPhilippe Mathieu-Daudé     port_state->func[command] = func;
90323d7d1dSPhilippe Mathieu-Daudé     port_state->opaque[command] = opaque;
91323d7d1dSPhilippe Mathieu-Daudé }
92323d7d1dSPhilippe Mathieu-Daudé 
vmport_ioport_read(void * opaque,hwaddr addr,unsigned size)93323d7d1dSPhilippe Mathieu-Daudé static uint64_t vmport_ioport_read(void *opaque, hwaddr addr,
94323d7d1dSPhilippe Mathieu-Daudé                                    unsigned size)
95323d7d1dSPhilippe Mathieu-Daudé {
96323d7d1dSPhilippe Mathieu-Daudé     VMPortState *s = opaque;
97323d7d1dSPhilippe Mathieu-Daudé     CPUState *cs = current_cpu;
98323d7d1dSPhilippe Mathieu-Daudé     X86CPU *cpu = X86_CPU(cs);
99c781a2ccSPhilippe Mathieu-Daudé     CPUX86State *env;
100323d7d1dSPhilippe Mathieu-Daudé     unsigned char command;
101323d7d1dSPhilippe Mathieu-Daudé     uint32_t eax;
102323d7d1dSPhilippe Mathieu-Daudé 
103c781a2ccSPhilippe Mathieu-Daudé     if (qtest_enabled()) {
104c781a2ccSPhilippe Mathieu-Daudé         return -1;
105c781a2ccSPhilippe Mathieu-Daudé     }
106c781a2ccSPhilippe Mathieu-Daudé     env = &cpu->env;
107323d7d1dSPhilippe Mathieu-Daudé     cpu_synchronize_state(cs);
108323d7d1dSPhilippe Mathieu-Daudé 
109323d7d1dSPhilippe Mathieu-Daudé     eax = env->regs[R_EAX];
110323d7d1dSPhilippe Mathieu-Daudé     if (eax != VMPORT_MAGIC) {
1110342ee76SLiran Alon         goto err;
112323d7d1dSPhilippe Mathieu-Daudé     }
113323d7d1dSPhilippe Mathieu-Daudé 
114323d7d1dSPhilippe Mathieu-Daudé     command = env->regs[R_ECX];
1157299e1a4SPhilippe Mathieu-Daudé     trace_vmport_command(command);
1167299e1a4SPhilippe Mathieu-Daudé     if (command >= VMPORT_ENTRIES || !s->func[command]) {
1177299e1a4SPhilippe Mathieu-Daudé         qemu_log_mask(LOG_UNIMP, "vmport: unknown command %x\n", command);
1180342ee76SLiran Alon         goto err;
119323d7d1dSPhilippe Mathieu-Daudé     }
120323d7d1dSPhilippe Mathieu-Daudé 
121b8892129SLiran Alon     eax = s->func[command](s->opaque[command], addr);
1220342ee76SLiran Alon     goto out;
1230342ee76SLiran Alon 
1240342ee76SLiran Alon err:
1250342ee76SLiran Alon     if (s->compat_flags & VMPORT_COMPAT_SIGNAL_UNSUPPORTED_CMD) {
1260342ee76SLiran Alon         eax = UINT32_MAX;
1270342ee76SLiran Alon     }
128b8892129SLiran Alon 
129b8892129SLiran Alon out:
130b8892129SLiran Alon     /*
131b8892129SLiran Alon      * The call above to cpu_synchronize_state() gets vCPU registers values
132b8892129SLiran Alon      * to QEMU but also cause QEMU to write QEMU vCPU registers values to
133b8892129SLiran Alon      * vCPU implementation (e.g. Accelerator such as KVM) just before
134b8892129SLiran Alon      * resuming guest.
135b8892129SLiran Alon      *
136b8892129SLiran Alon      * Therefore, in order to make IOPort return value propagate to
137b8892129SLiran Alon      * guest EAX, we need to explicitly update QEMU EAX register value.
138b8892129SLiran Alon      */
139b8892129SLiran Alon     if (s->compat_flags & VMPORT_COMPAT_READ_SET_EAX) {
140b8892129SLiran Alon         cpu->env.regs[R_EAX] = eax;
141b8892129SLiran Alon     }
142b8892129SLiran Alon 
143b8892129SLiran Alon     return eax;
144323d7d1dSPhilippe Mathieu-Daudé }
145323d7d1dSPhilippe Mathieu-Daudé 
vmport_ioport_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)146323d7d1dSPhilippe Mathieu-Daudé static void vmport_ioport_write(void *opaque, hwaddr addr,
147323d7d1dSPhilippe Mathieu-Daudé                                 uint64_t val, unsigned size)
148323d7d1dSPhilippe Mathieu-Daudé {
149323d7d1dSPhilippe Mathieu-Daudé     X86CPU *cpu = X86_CPU(current_cpu);
150323d7d1dSPhilippe Mathieu-Daudé 
151c781a2ccSPhilippe Mathieu-Daudé     if (qtest_enabled()) {
152c781a2ccSPhilippe Mathieu-Daudé         return;
153c781a2ccSPhilippe Mathieu-Daudé     }
154323d7d1dSPhilippe Mathieu-Daudé     cpu->env.regs[R_EAX] = vmport_ioport_read(opaque, addr, 4);
155323d7d1dSPhilippe Mathieu-Daudé }
156323d7d1dSPhilippe Mathieu-Daudé 
vmport_cmd_get_version(void * opaque,uint32_t addr)157323d7d1dSPhilippe Mathieu-Daudé static uint32_t vmport_cmd_get_version(void *opaque, uint32_t addr)
158323d7d1dSPhilippe Mathieu-Daudé {
159323d7d1dSPhilippe Mathieu-Daudé     X86CPU *cpu = X86_CPU(current_cpu);
160323d7d1dSPhilippe Mathieu-Daudé 
161c781a2ccSPhilippe Mathieu-Daudé     if (qtest_enabled()) {
162c781a2ccSPhilippe Mathieu-Daudé         return -1;
163c781a2ccSPhilippe Mathieu-Daudé     }
164323d7d1dSPhilippe Mathieu-Daudé     cpu->env.regs[R_EBX] = VMPORT_MAGIC;
165f8bdc550SLiran Alon     if (port_state->compat_flags & VMPORT_COMPAT_REPORT_VMX_TYPE) {
166f8bdc550SLiran Alon         cpu->env.regs[R_ECX] = port_state->vmware_vmx_type;
167f8bdc550SLiran Alon     }
1682fd2f799SLiran Alon     return port_state->vmware_vmx_version;
169323d7d1dSPhilippe Mathieu-Daudé }
170323d7d1dSPhilippe Mathieu-Daudé 
vmport_cmd_get_bios_uuid(void * opaque,uint32_t addr)171aaacf1c1SLiran Alon static uint32_t vmport_cmd_get_bios_uuid(void *opaque, uint32_t addr)
172aaacf1c1SLiran Alon {
173aaacf1c1SLiran Alon     X86CPU *cpu = X86_CPU(current_cpu);
174aaacf1c1SLiran Alon     uint32_t *uuid_parts = (uint32_t *)(qemu_uuid.data);
175aaacf1c1SLiran Alon 
176aaacf1c1SLiran Alon     cpu->env.regs[R_EAX] = le32_to_cpu(uuid_parts[0]);
177aaacf1c1SLiran Alon     cpu->env.regs[R_EBX] = le32_to_cpu(uuid_parts[1]);
178aaacf1c1SLiran Alon     cpu->env.regs[R_ECX] = le32_to_cpu(uuid_parts[2]);
179aaacf1c1SLiran Alon     cpu->env.regs[R_EDX] = le32_to_cpu(uuid_parts[3]);
180aaacf1c1SLiran Alon     return cpu->env.regs[R_EAX];
181aaacf1c1SLiran Alon }
182aaacf1c1SLiran Alon 
vmport_cmd_ram_size(void * opaque,uint32_t addr)183323d7d1dSPhilippe Mathieu-Daudé static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t addr)
184323d7d1dSPhilippe Mathieu-Daudé {
185323d7d1dSPhilippe Mathieu-Daudé     X86CPU *cpu = X86_CPU(current_cpu);
186323d7d1dSPhilippe Mathieu-Daudé 
187c781a2ccSPhilippe Mathieu-Daudé     if (qtest_enabled()) {
188c781a2ccSPhilippe Mathieu-Daudé         return -1;
189c781a2ccSPhilippe Mathieu-Daudé     }
190323d7d1dSPhilippe Mathieu-Daudé     cpu->env.regs[R_EBX] = 0x1177;
191*86378b29SPaolo Bonzini     return current_machine->ram_size;
192323d7d1dSPhilippe Mathieu-Daudé }
193323d7d1dSPhilippe Mathieu-Daudé 
vmport_cmd_get_hz(void * opaque,uint32_t addr)194d6048bfdSLiran Alon static uint32_t vmport_cmd_get_hz(void *opaque, uint32_t addr)
195d6048bfdSLiran Alon {
196d6048bfdSLiran Alon     X86CPU *cpu = X86_CPU(current_cpu);
197d6048bfdSLiran Alon 
198d6048bfdSLiran Alon     if (cpu->env.tsc_khz && cpu->env.apic_bus_freq) {
199d6048bfdSLiran Alon         uint64_t tsc_freq = (uint64_t)cpu->env.tsc_khz * 1000;
200d6048bfdSLiran Alon 
201d6048bfdSLiran Alon         cpu->env.regs[R_ECX] = cpu->env.apic_bus_freq;
202d6048bfdSLiran Alon         cpu->env.regs[R_EBX] = (uint32_t)(tsc_freq >> 32);
203d6048bfdSLiran Alon         cpu->env.regs[R_EAX] = (uint32_t)tsc_freq;
204d6048bfdSLiran Alon     } else {
205d6048bfdSLiran Alon         /* Signal cmd as not supported */
206d6048bfdSLiran Alon         cpu->env.regs[R_EBX] = UINT32_MAX;
207d6048bfdSLiran Alon     }
208d6048bfdSLiran Alon 
209d6048bfdSLiran Alon     return cpu->env.regs[R_EAX];
210d6048bfdSLiran Alon }
211d6048bfdSLiran Alon 
vmport_cmd_get_vcpu_info(void * opaque,uint32_t addr)212acacd355SLiran Alon static uint32_t vmport_cmd_get_vcpu_info(void *opaque, uint32_t addr)
213acacd355SLiran Alon {
2147f9114b7SLiran Alon     X86CPU *cpu = X86_CPU(current_cpu);
2157f9114b7SLiran Alon     uint32_t ret = 0;
2167f9114b7SLiran Alon 
2177f9114b7SLiran Alon     if (cpu->env.features[FEAT_1_ECX] & CPUID_EXT_X2APIC) {
2187f9114b7SLiran Alon         ret |= 1 << VCPU_INFO_LEGACY_X2APIC_BIT;
2197f9114b7SLiran Alon     }
2207f9114b7SLiran Alon 
2217f9114b7SLiran Alon     return ret;
222acacd355SLiran Alon }
223acacd355SLiran Alon 
224323d7d1dSPhilippe Mathieu-Daudé static const MemoryRegionOps vmport_ops = {
225323d7d1dSPhilippe Mathieu-Daudé     .read = vmport_ioport_read,
226323d7d1dSPhilippe Mathieu-Daudé     .write = vmport_ioport_write,
227323d7d1dSPhilippe Mathieu-Daudé     .impl = {
228323d7d1dSPhilippe Mathieu-Daudé         .min_access_size = 4,
229323d7d1dSPhilippe Mathieu-Daudé         .max_access_size = 4,
230323d7d1dSPhilippe Mathieu-Daudé     },
231323d7d1dSPhilippe Mathieu-Daudé     .endianness = DEVICE_LITTLE_ENDIAN,
232323d7d1dSPhilippe Mathieu-Daudé };
233323d7d1dSPhilippe Mathieu-Daudé 
vmport_realizefn(DeviceState * dev,Error ** errp)234323d7d1dSPhilippe Mathieu-Daudé static void vmport_realizefn(DeviceState *dev, Error **errp)
235323d7d1dSPhilippe Mathieu-Daudé {
236323d7d1dSPhilippe Mathieu-Daudé     ISADevice *isadev = ISA_DEVICE(dev);
237323d7d1dSPhilippe Mathieu-Daudé     VMPortState *s = VMPORT(dev);
238323d7d1dSPhilippe Mathieu-Daudé 
239323d7d1dSPhilippe Mathieu-Daudé     memory_region_init_io(&s->io, OBJECT(s), &vmport_ops, s, "vmport", 1);
240323d7d1dSPhilippe Mathieu-Daudé     isa_register_ioport(isadev, &s->io, 0x5658);
241323d7d1dSPhilippe Mathieu-Daudé 
242323d7d1dSPhilippe Mathieu-Daudé     port_state = s;
243aaacf1c1SLiran Alon 
244323d7d1dSPhilippe Mathieu-Daudé     /* Register some generic port commands */
245323d7d1dSPhilippe Mathieu-Daudé     vmport_register(VMPORT_CMD_GETVERSION, vmport_cmd_get_version, NULL);
246323d7d1dSPhilippe Mathieu-Daudé     vmport_register(VMPORT_CMD_GETRAMSIZE, vmport_cmd_ram_size, NULL);
247aaacf1c1SLiran Alon     if (s->compat_flags & VMPORT_COMPAT_CMDS_V2) {
248aaacf1c1SLiran Alon         vmport_register(VMPORT_CMD_GETBIOSUUID, vmport_cmd_get_bios_uuid, NULL);
249d6048bfdSLiran Alon         vmport_register(VMPORT_CMD_GETHZ, vmport_cmd_get_hz, NULL);
250acacd355SLiran Alon         vmport_register(VMPORT_CMD_GET_VCPU_INFO, vmport_cmd_get_vcpu_info,
251acacd355SLiran Alon                         NULL);
252aaacf1c1SLiran Alon     }
253323d7d1dSPhilippe Mathieu-Daudé }
254323d7d1dSPhilippe Mathieu-Daudé 
255c9ab24ceSLiran Alon static Property vmport_properties[] = {
256b8892129SLiran Alon     /* Used to enforce compatibility for migration */
257b8892129SLiran Alon     DEFINE_PROP_BIT("x-read-set-eax", VMPortState, compat_flags,
258b8892129SLiran Alon                     VMPORT_COMPAT_READ_SET_EAX_BIT, true),
2590342ee76SLiran Alon     DEFINE_PROP_BIT("x-signal-unsupported-cmd", VMPortState, compat_flags,
2600342ee76SLiran Alon                     VMPORT_COMPAT_SIGNAL_UNSUPPORTED_CMD_BIT, true),
261f8bdc550SLiran Alon     DEFINE_PROP_BIT("x-report-vmx-type", VMPortState, compat_flags,
262f8bdc550SLiran Alon                     VMPORT_COMPAT_REPORT_VMX_TYPE_BIT, true),
263aaacf1c1SLiran Alon     DEFINE_PROP_BIT("x-cmds-v2", VMPortState, compat_flags,
264aaacf1c1SLiran Alon                     VMPORT_COMPAT_CMDS_V2_BIT, true),
2652fd2f799SLiran Alon 
2662fd2f799SLiran Alon     /* Default value taken from open-vm-tools code VERSION_MAGIC definition */
2672fd2f799SLiran Alon     DEFINE_PROP_UINT32("vmware-vmx-version", VMPortState,
2682fd2f799SLiran Alon                        vmware_vmx_version, 6),
269f8bdc550SLiran Alon     /*
270f8bdc550SLiran Alon      * Value determines which VMware product type host report itself to guest.
271f8bdc550SLiran Alon      *
272f8bdc550SLiran Alon      * Most guests are fine with exposing host as VMware ESX server.
273f8bdc550SLiran Alon      * Some legacy/proprietary guests hard-code a given type.
274f8bdc550SLiran Alon      *
275f8bdc550SLiran Alon      * For a complete list of values, refer to enum VMXType at open-vm-tools
276f8bdc550SLiran Alon      * project (Defined at lib/include/vm_vmx_type.h).
277f8bdc550SLiran Alon      *
278f8bdc550SLiran Alon      * Reasonable options:
279f8bdc550SLiran Alon      * 0 - Unset
280f8bdc550SLiran Alon      * 1 - VMware Express (deprecated)
281f8bdc550SLiran Alon      * 2 - VMware ESX Server
282f8bdc550SLiran Alon      * 3 - VMware Server (Deprecated)
283f8bdc550SLiran Alon      * 4 - VMware Workstation
284f8bdc550SLiran Alon      * 5 - ACE 1.x (Deprecated)
285f8bdc550SLiran Alon      */
286f8bdc550SLiran Alon     DEFINE_PROP_UINT8("vmware-vmx-type", VMPortState, vmware_vmx_type, 2),
2872fd2f799SLiran Alon 
288c9ab24ceSLiran Alon     DEFINE_PROP_END_OF_LIST(),
289c9ab24ceSLiran Alon };
290c9ab24ceSLiran Alon 
vmport_class_initfn(ObjectClass * klass,void * data)291323d7d1dSPhilippe Mathieu-Daudé static void vmport_class_initfn(ObjectClass *klass, void *data)
292323d7d1dSPhilippe Mathieu-Daudé {
293323d7d1dSPhilippe Mathieu-Daudé     DeviceClass *dc = DEVICE_CLASS(klass);
294323d7d1dSPhilippe Mathieu-Daudé 
295323d7d1dSPhilippe Mathieu-Daudé     dc->realize = vmport_realizefn;
296323d7d1dSPhilippe Mathieu-Daudé     /* Reason: realize sets global port_state */
297323d7d1dSPhilippe Mathieu-Daudé     dc->user_creatable = false;
298c9ab24ceSLiran Alon     device_class_set_props(dc, vmport_properties);
299323d7d1dSPhilippe Mathieu-Daudé }
300323d7d1dSPhilippe Mathieu-Daudé 
301323d7d1dSPhilippe Mathieu-Daudé static const TypeInfo vmport_info = {
302323d7d1dSPhilippe Mathieu-Daudé     .name          = TYPE_VMPORT,
303323d7d1dSPhilippe Mathieu-Daudé     .parent        = TYPE_ISA_DEVICE,
304323d7d1dSPhilippe Mathieu-Daudé     .instance_size = sizeof(VMPortState),
305323d7d1dSPhilippe Mathieu-Daudé     .class_init    = vmport_class_initfn,
306323d7d1dSPhilippe Mathieu-Daudé };
307323d7d1dSPhilippe Mathieu-Daudé 
vmport_register_types(void)308323d7d1dSPhilippe Mathieu-Daudé static void vmport_register_types(void)
309323d7d1dSPhilippe Mathieu-Daudé {
310323d7d1dSPhilippe Mathieu-Daudé     type_register_static(&vmport_info);
311323d7d1dSPhilippe Mathieu-Daudé }
312323d7d1dSPhilippe Mathieu-Daudé 
313323d7d1dSPhilippe Mathieu-Daudé type_init(vmport_register_types)
314