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