From patchwork Mon Oct 7 15:13:04 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nick Rosbrook X-Patchwork-Id: 11177803 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AE433139A for ; Mon, 7 Oct 2019 15:16:09 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7D6782053B for ; Mon, 7 Oct 2019 15:16:09 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="JPttCl18" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7D6782053B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iHUig-0007Tn-9U; Mon, 07 Oct 2019 15:14:42 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iHUif-0007TH-PO for xen-devel@lists.xenproject.org; Mon, 07 Oct 2019 15:14:41 +0000 X-Inumbo-ID: 0903c88c-e915-11e9-8c93-bc764e2007e4 Received: from mail-qk1-x741.google.com (unknown [2607:f8b0:4864:20::741]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id 0903c88c-e915-11e9-8c93-bc764e2007e4; Mon, 07 Oct 2019 15:13:36 +0000 (UTC) Received: by mail-qk1-x741.google.com with SMTP id y144so12884170qkb.7 for ; Mon, 07 Oct 2019 08:13:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=2UsVtpDQx/GH4g6WuhNNT23rnCC0Le6n0pIDIcnnL7E=; b=JPttCl18A2aeL7ecgvuDjTs+fu/4pjUneLYmn0jRfWopDZiJRP5w4xyQukEZZvRZkg rwl5EluI9NLPOdjOYu361X8No0S3CgzS1judKDgjX1Fm5gl3fJTPmCqzAsxBnXRVO6vt BP0KzPwxHSTrL3NmqZwEob1OxfYm8phF93Fs91WW0A5pKXRJkbFELmRG/YvZTewQgiFg wBHXjjrOBozpIZV8LdRoYly8hxPL8FIgTmqWlWvb5AgiT4RjDge0twfhr6q0QEBnyyCf tc7ibV7Sm6JoIe+dZaMDpjKtM5x5rwIHLW+vpOdzeRQU4O5Qc4b+zy0/2lsmfyQnHTvq vYXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=2UsVtpDQx/GH4g6WuhNNT23rnCC0Le6n0pIDIcnnL7E=; b=rZc0Ss7f7iibdITorRVhkQvJWognPuXlcfjIaMKdht5iWVDssIU8x4ad25JGOrGq9g BJlVPZRhRWr7Jp6SJem5C7/1IutwiPeSTvpguOEolG2enfO6kcDfAfBtxv36Wj9Tv7/k eopVXAcOJ3WGboMI3MmwTnvFRl+yUGDpdFPZI0NTvZA0sBjXeDiT3R0KuoKEfyl/RSkw W4OOfy1O5sCqEvieNnBa3Lc65J0uS2r0CjoT4dsCx/6pMdOVljJvs86wiEU1ULrtu9e0 mJpj3udBls8NXgd4xXLBteUBLq5Xx+OMSVh73YCDi+1iFdzS5JVs8osHBYIKCQinvWH7 Mqxg== X-Gm-Message-State: APjAAAWq1Ju+dYbxaujZdjGSkL2B7k0DWZzQ466OntKmH4KbtZsDkUil 0CXp0GiKIqZiiPIFw+2xriG0FMxH X-Google-Smtp-Source: APXvYqwwXRCa1SmAcZN/CpupkYP3KVbGMdJVKIo297Fs/nk4B+hNA3vMU16k5gcZpJBARd3PT+xQYA== X-Received: by 2002:a37:a709:: with SMTP id q9mr23157083qke.135.1570461215790; Mon, 07 Oct 2019 08:13:35 -0700 (PDT) Received: from five.crux.rad.ainfosec.com (209-217-208-226.northland.net. [209.217.208.226]) by smtp.googlemail.com with ESMTPSA id c185sm8354313qkg.74.2019.10.07.08.13.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 07 Oct 2019 08:13:35 -0700 (PDT) From: Nick Rosbrook To: xen-devel@lists.xenproject.org Date: Mon, 7 Oct 2019 11:13:04 -0400 Message-Id: <1e92395f2f4ef59a1a4e9f3c6b926182ba113653.1570456846.git.rosbrookn@ainfosec.com> X-Mailer: git-send-email 2.19.1 In-Reply-To: References: MIME-Version: 1.0 Subject: [Xen-devel] [PATCH 17/24] golang/xenlight: implement keyed union C to Go marshaling X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Nick Rosbrook , Ian Jackson , kerriganb@ainfosec.com, George Dunlap , Wei Liu Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" From: Nick Rosbrook Switch over union key to determine how to populate 'union' in Go struct. Since the unions of C types cannot be directly accessed, add C structs in cgo preamble to assist in marshaling keyed unions. This allows the C type defined in the preamble to be populated first, and then accessed directly to populate the Go struct. Signed-off-by: Nick Rosbrook --- Cc: George Dunlap Cc: Ian Jackson Cc: Wei Liu tools/golang/xenlight/gengotypes.py | 136 ++++++- tools/golang/xenlight/xenlight_helpers.go | 440 ++++++++++++++++++++++ 2 files changed, 575 insertions(+), 1 deletion(-) diff --git a/tools/golang/xenlight/gengotypes.py b/tools/golang/xenlight/gengotypes.py index 75dcd01724..ececaafd72 100644 --- a/tools/golang/xenlight/gengotypes.py +++ b/tools/golang/xenlight/gengotypes.py @@ -28,6 +28,14 @@ go_builtin_types = ['bool', 'string', 'int', 'byte', # after a struct definition. type_extras = [] +# cgo preamble for xenlight_helpers.go, created during type generation and +# written later. +cgo_helpers_preamble = [] + +# List of strings that need to be written to a file +# after a helper func definition. +helper_extras = [] + def xenlight_golang_generate_types(path = None, types = None, comment = None): """ Generate a .go file (xenlight_types.go by default) @@ -159,6 +167,8 @@ def xenlight_golang_define_union(ty = None, structname = ''): s = xenlight_golang_define_struct(f.type, typename=name) type_extras.append(s) + xenlight_golang_union_cgo_preamble(f.type, name=name) + # Define function to implement 'union' interface name = xenlight_golang_fmt_name(name) s = 'func (x {}) is{}(){{}}\n'.format(name, interface_name) @@ -174,6 +184,18 @@ def xenlight_golang_define_union(ty = None, structname = ''): return s +def xenlight_golang_union_cgo_preamble(ty = None, name = ''): + s = '' + + s += 'typedef struct {} {{\n'.format(name) + + for f in ty.fields: + s += '\t{} {};\n'.format(f.type.typename, f.name) + + s += '}} {};\n'.format(name) + + cgo_helpers_preamble.append(s) + def xenlight_golang_generate_helpers(path = None, types = None, comment = None): """ Generate a .go file (xenlight_helpers.go by default) @@ -187,6 +209,7 @@ def xenlight_golang_generate_helpers(path = None, types = None, comment = None): if comment is not None: f.write(comment) f.write('package xenlight\n') + f.write('import (\n"unsafe"\n"errors"\n"fmt"\n)\n') # Cgo preamble f.write('/*\n') @@ -195,6 +218,10 @@ def xenlight_golang_generate_helpers(path = None, types = None, comment = None): f.write('#include \n') f.write('\n') + for s in cgo_helpers_preamble: + f.write(s) + f.write('\n') + f.write('*/\nimport "C"\n') for ty in types: @@ -204,6 +231,12 @@ def xenlight_golang_generate_helpers(path = None, types = None, comment = None): f.write(xenlight_golang_define_from_C(ty)) f.write('\n') + for extra in helper_extras: + f.write(extra) + f.write('\n') + + del helper_extras[:] + go_fmt(path) def xenlight_golang_define_from_C(ty = None, typename = None, nested = False): @@ -275,7 +308,7 @@ def xenlight_golang_define_from_C(ty = None, typename = None, nested = False): s += xenlight_golang_define_from_C(f.type, typename=f.name, nested=True) elif isinstance(f.type, idl.KeyedUnion): - pass + s += xenlight_golang_union_from_C(f.type, f.name, ty.typename) else: raise Exception('type {} not supported'.format(f.type)) @@ -286,6 +319,107 @@ def xenlight_golang_define_from_C(ty = None, typename = None, nested = False): return s +def xenlight_golang_union_from_C(ty = None, union_name = '', struct_name = ''): + keyname = ty.keyvar.name + gokeyname = xenlight_golang_fmt_name(keyname) + keytype = ty.keyvar.type.typename + gokeytype = xenlight_golang_fmt_name(keytype) + + interface_name = '{}_{}_union'.format(struct_name, keyname) + interface_name = xenlight_golang_fmt_name(interface_name, exported=False) + + cgo_keyname = keyname + if cgo_keyname in go_keywords: + cgo_keyname = '_' + cgo_keyname + + cases = {} + + for f in ty.fields: + val = '{}_{}'.format(keytype, f.name) + val = xenlight_golang_fmt_name(val) + + # Add to list of cases to make for the switch + # statement below. + if f.type is None: + continue + + cases[f.name] = val + + # Define fromC func for 'union' struct. + typename = '{}_{}_union_{}'.format(struct_name,keyname,f.name) + gotypename = xenlight_golang_fmt_name(typename) + + # Define the function here. The cases for keyed unions are a little + # different. + s = 'func (x *{}) fromC(xc *C.{}) error {{\n'.format(gotypename,struct_name) + s += 'if {}(xc.{}) != {} {{\n'.format(gokeytype,cgo_keyname,val) + err_string = '"expected union key {}"'.format(val) + s += 'return errors.New({})\n'.format(err_string) + s += '}\n\n' + s += 'tmp := (*C.{})(unsafe.Pointer(&xc.{}[0]))\n'.format(typename,union_name) + + s += xenlight_golang_union_fields_from_C(f.type) + s += 'return nil\n' + s += '}\n' + + helper_extras.append(s) + + s = 'x.{} = {}(xc.{})\n'.format(gokeyname,gokeytype,cgo_keyname) + s += 'switch x.{}{{\n'.format(gokeyname) + + # Create switch statement to determine which 'union element' + # to populate in the Go struct. + for case_name, case_val in cases.items(): + s += 'case {}:\n'.format(case_val) + + gotype = '{}_{}_union_{}'.format(struct_name,keyname,case_name) + gotype = xenlight_golang_fmt_name(gotype) + goname = '{}_{}'.format(keyname,case_name) + goname = xenlight_golang_fmt_name(goname,exported=False) + + s += 'var {} {}\n'.format(goname, gotype) + s += 'if err := {}.fromC(xc);'.format(goname) + s += 'err != nil {\n return err \n}\n' + + field_name = xenlight_golang_fmt_name('{}_union'.format(keyname)) + s += 'x.{} = {}\n'.format(field_name, goname) + + # End switch statement + s += 'default:\n' + err_string = '"invalid union key \'%v\'", x.{}'.format(gokeyname) + s += 'return fmt.Errorf({})'.format(err_string) + s += '}\n' + + return s + +def xenlight_golang_union_fields_from_C(ty = None): + s = '' + + for f in ty.fields: + gotypename = xenlight_golang_fmt_name(f.type.typename) + ctypename = f.type.typename + gofname = xenlight_golang_fmt_name(f.name) + cfname = f.name + + is_castable = (f.type.json_parse_type == 'JSON_INTEGER' or + isinstance(f.type, idl.Enumeration) or + gotypename in go_builtin_types) + + if not is_castable: + s += 'if err := x.{}.fromC(&tmp.{});'.format(gofname,cfname) + s += 'err != nil {\n return err \n}\n' + + # We just did an unsafe.Pointer cast from []byte to the 'union' type + # struct, so we need to make sure that any string fields are actually + # converted properly. + elif gotypename == 'string': + s += 'x.{} = C.GoString(tmp.{})\n'.format(gofname,cfname) + + else: + s += 'x.{} = {}(tmp.{})\n'.format(gofname,gotypename,cfname) + + return s + def xenlight_golang_fmt_name(name, exported = True): """ Take a given type name and return an diff --git a/tools/golang/xenlight/xenlight_helpers.go b/tools/golang/xenlight/xenlight_helpers.go index 4ece90dc6b..b8abef8068 100644 --- a/tools/golang/xenlight/xenlight_helpers.go +++ b/tools/golang/xenlight/xenlight_helpers.go @@ -5,11 +5,122 @@ // package xenlight +import ( + "errors" + "fmt" + "unsafe" +) + /* #cgo LDFLAGS: -lxenlight #include #include +typedef struct libxl_channelinfo_connection_union_pty { + char * path; +} libxl_channelinfo_connection_union_pty; + +typedef struct libxl_domain_build_info_type_union_hvm { + char * firmware; + libxl_bios_type bios; + libxl_defbool pae; + libxl_defbool apic; + libxl_defbool acpi; + libxl_defbool acpi_s3; + libxl_defbool acpi_s4; + libxl_defbool acpi_laptop_slate; + libxl_defbool nx; + libxl_defbool viridian; + libxl_bitmap viridian_enable; + libxl_bitmap viridian_disable; + char * timeoffset; + libxl_defbool hpet; + libxl_defbool vpt_align; + uint64_t mmio_hole_memkb; + libxl_timer_mode timer_mode; + libxl_defbool nested_hvm; + libxl_defbool altp2m; + char * system_firmware; + char * smbios_firmware; + char * acpi_firmware; + libxl_hdtype hdtype; + libxl_defbool nographic; + libxl_vga_interface_info vga; + libxl_vnc_info vnc; + char * keymap; + libxl_sdl_info sdl; + libxl_spice_info spice; + libxl_defbool gfx_passthru; + libxl_gfx_passthru_kind gfx_passthru_kind; + char * serial; + char * boot; + libxl_defbool usb; + int usbversion; + char * usbdevice; + libxl_defbool vkb_device; + char * soundhw; + libxl_defbool xen_platform_pci; + libxl_string_list usbdevice_list; + libxl_vendor_device vendor_device; + libxl_ms_vm_genid ms_vm_genid; + libxl_string_list serial_list; + libxl_rdm_reserve rdm; + uint64_t rdm_mem_boundary_memkb; + uint64_t mca_caps; +} libxl_domain_build_info_type_union_hvm; + +typedef struct libxl_domain_build_info_type_union_pv { + char * kernel; + uint64_t slack_memkb; + char * bootloader; + libxl_string_list bootloader_args; + char * cmdline; + char * ramdisk; + char * features; + libxl_defbool e820_host; +} libxl_domain_build_info_type_union_pv; + +typedef struct libxl_domain_build_info_type_union_pvh { + libxl_defbool pvshim; + char * pvshim_path; + char * pvshim_cmdline; + char * pvshim_extra; +} libxl_domain_build_info_type_union_pvh; + +typedef struct libxl_device_usbdev_type_union_hostdev { + uint8_t hostbus; + uint8_t hostaddr; +} libxl_device_usbdev_type_union_hostdev; + +typedef struct libxl_device_channel_connection_union_socket { + char * path; +} libxl_device_channel_connection_union_socket; + +typedef struct libxl_event_type_union_domain_shutdown { + uint8_t shutdown_reason; +} libxl_event_type_union_domain_shutdown; + +typedef struct libxl_event_type_union_disk_eject { + char * vdev; + libxl_device_disk disk; +} libxl_event_type_union_disk_eject; + +typedef struct libxl_event_type_union_operation_complete { + int rc; +} libxl_event_type_union_operation_complete; + +typedef struct libxl_psr_hw_info_type_union_cat { + uint32_t cos_max; + uint32_t cbm_len; + bool cdp_enabled; +} libxl_psr_hw_info_type_union_cat; + +typedef struct libxl_psr_hw_info_type_union_mba { + uint32_t cos_max; + uint32_t thrtl_max; + bool linear; +} libxl_psr_hw_info_type_union_mba; + */ import "C" @@ -151,6 +262,27 @@ func (x *Channelinfo) fromC(xc *C.libxl_channelinfo) error { x.State = int(xc.state) x.Evtch = int(xc.evtch) x.Rref = int(xc.rref) + x.Connection = ChannelConnection(xc.connection) + switch x.Connection { + case ChannelConnectionPty: + var connectionPty ChannelinfoConnectionUnionPty + if err := connectionPty.fromC(xc); err != nil { + return err + } + x.ConnectionUnion = connectionPty + default: + return fmt.Errorf("invalid union key '%v'", x.Connection) + } + return nil +} + +func (x *ChannelinfoConnectionUnionPty) fromC(xc *C.libxl_channelinfo) error { + if ChannelConnection(xc.connection) != ChannelConnectionPty { + return errors.New("expected union key ChannelConnectionPty") + } + + tmp := (*C.libxl_channelinfo_connection_union_pty)(unsafe.Pointer(&xc.u[0])) + x.Path = C.GoString(tmp.path) return nil } @@ -398,12 +530,180 @@ func (x *DomainBuildInfo) fromC(xc *C.libxl_domain_build_info) error { } x.DmRestrict = defboolDmRestrict x.Tee = TeeType(xc.tee) + x.Type = DomainType(xc._type) + switch x.Type { + case DomainTypePv: + var typePv DomainBuildInfoTypeUnionPv + if err := typePv.fromC(xc); err != nil { + return err + } + x.TypeUnion = typePv + case DomainTypeHvm: + var typeHvm DomainBuildInfoTypeUnionHvm + if err := typeHvm.fromC(xc); err != nil { + return err + } + x.TypeUnion = typeHvm + case DomainTypePvh: + var typePvh DomainBuildInfoTypeUnionPvh + if err := typePvh.fromC(xc); err != nil { + return err + } + x.TypeUnion = typePvh + default: + return fmt.Errorf("invalid union key '%v'", x.Type) + } x.ArchArm.GicVersion = GicVersion(xc.arch_arm.gic_version) x.ArchArm.Vuart = VuartType(xc.arch_arm.vuart) x.Altp2M = Altp2MMode(xc.altp2m) return nil } +func (x *DomainBuildInfoTypeUnionHvm) fromC(xc *C.libxl_domain_build_info) error { + if DomainType(xc._type) != DomainTypeHvm { + return errors.New("expected union key DomainTypeHvm") + } + + tmp := (*C.libxl_domain_build_info_type_union_hvm)(unsafe.Pointer(&xc.u[0])) + x.Firmware = C.GoString(tmp.firmware) + x.Bios = BiosType(tmp.bios) + if err := x.Pae.fromC(&tmp.pae); err != nil { + return err + } + if err := x.Apic.fromC(&tmp.apic); err != nil { + return err + } + if err := x.Acpi.fromC(&tmp.acpi); err != nil { + return err + } + if err := x.AcpiS3.fromC(&tmp.acpi_s3); err != nil { + return err + } + if err := x.AcpiS4.fromC(&tmp.acpi_s4); err != nil { + return err + } + if err := x.AcpiLaptopSlate.fromC(&tmp.acpi_laptop_slate); err != nil { + return err + } + if err := x.Nx.fromC(&tmp.nx); err != nil { + return err + } + if err := x.Viridian.fromC(&tmp.viridian); err != nil { + return err + } + if err := x.ViridianEnable.fromC(&tmp.viridian_enable); err != nil { + return err + } + if err := x.ViridianDisable.fromC(&tmp.viridian_disable); err != nil { + return err + } + x.Timeoffset = C.GoString(tmp.timeoffset) + if err := x.Hpet.fromC(&tmp.hpet); err != nil { + return err + } + if err := x.VptAlign.fromC(&tmp.vpt_align); err != nil { + return err + } + x.MmioHoleMemkb = uint64(tmp.mmio_hole_memkb) + x.TimerMode = TimerMode(tmp.timer_mode) + if err := x.NestedHvm.fromC(&tmp.nested_hvm); err != nil { + return err + } + if err := x.Altp2M.fromC(&tmp.altp2m); err != nil { + return err + } + x.SystemFirmware = C.GoString(tmp.system_firmware) + x.SmbiosFirmware = C.GoString(tmp.smbios_firmware) + x.AcpiFirmware = C.GoString(tmp.acpi_firmware) + x.Hdtype = Hdtype(tmp.hdtype) + if err := x.Nographic.fromC(&tmp.nographic); err != nil { + return err + } + if err := x.Vga.fromC(&tmp.vga); err != nil { + return err + } + if err := x.Vnc.fromC(&tmp.vnc); err != nil { + return err + } + x.Keymap = C.GoString(tmp.keymap) + if err := x.Sdl.fromC(&tmp.sdl); err != nil { + return err + } + if err := x.Spice.fromC(&tmp.spice); err != nil { + return err + } + if err := x.GfxPassthru.fromC(&tmp.gfx_passthru); err != nil { + return err + } + x.GfxPassthruKind = GfxPassthruKind(tmp.gfx_passthru_kind) + x.Serial = C.GoString(tmp.serial) + x.Boot = C.GoString(tmp.boot) + if err := x.Usb.fromC(&tmp.usb); err != nil { + return err + } + x.Usbversion = int(tmp.usbversion) + x.Usbdevice = C.GoString(tmp.usbdevice) + if err := x.VkbDevice.fromC(&tmp.vkb_device); err != nil { + return err + } + x.Soundhw = C.GoString(tmp.soundhw) + if err := x.XenPlatformPci.fromC(&tmp.xen_platform_pci); err != nil { + return err + } + if err := x.UsbdeviceList.fromC(&tmp.usbdevice_list); err != nil { + return err + } + x.VendorDevice = VendorDevice(tmp.vendor_device) + if err := x.MsVmGenid.fromC(&tmp.ms_vm_genid); err != nil { + return err + } + if err := x.SerialList.fromC(&tmp.serial_list); err != nil { + return err + } + if err := x.Rdm.fromC(&tmp.rdm); err != nil { + return err + } + x.RdmMemBoundaryMemkb = uint64(tmp.rdm_mem_boundary_memkb) + x.McaCaps = uint64(tmp.mca_caps) + return nil +} + +func (x *DomainBuildInfoTypeUnionPv) fromC(xc *C.libxl_domain_build_info) error { + if DomainType(xc._type) != DomainTypePv { + return errors.New("expected union key DomainTypePv") + } + + tmp := (*C.libxl_domain_build_info_type_union_pv)(unsafe.Pointer(&xc.u[0])) + x.Kernel = C.GoString(tmp.kernel) + x.SlackMemkb = uint64(tmp.slack_memkb) + x.Bootloader = C.GoString(tmp.bootloader) + if err := x.BootloaderArgs.fromC(&tmp.bootloader_args); err != nil { + return err + } + x.Cmdline = C.GoString(tmp.cmdline) + x.Ramdisk = C.GoString(tmp.ramdisk) + x.Features = C.GoString(tmp.features) + if err := x.E820Host.fromC(&tmp.e820_host); err != nil { + return err + } + return nil +} + +func (x *DomainBuildInfoTypeUnionPvh) fromC(xc *C.libxl_domain_build_info) error { + if DomainType(xc._type) != DomainTypePvh { + return errors.New("expected union key DomainTypePvh") + } + + tmp := (*C.libxl_domain_build_info_type_union_pvh)(unsafe.Pointer(&xc.u[0])) + if err := x.Pvshim.fromC(&tmp.pvshim); err != nil { + return err + } + x.PvshimPath = C.GoString(tmp.pvshim_path) + x.PvshimCmdline = C.GoString(tmp.pvshim_cmdline) + x.PvshimExtra = C.GoString(tmp.pvshim_extra) + return nil +} + func (x *DeviceVfb) fromC(xc *C.libxl_device_vfb) error { x.BackendDomid = Domid(xc.backend_domid) x.BackendDomname = C.GoString(xc.backend_domname) @@ -582,6 +882,28 @@ func (x *DeviceUsbctrl) fromC(xc *C.libxl_device_usbctrl) error { func (x *DeviceUsbdev) fromC(xc *C.libxl_device_usbdev) error { x.Ctrl = Devid(xc.ctrl) x.Port = int(xc.port) + x.Type = UsbdevType(xc._type) + switch x.Type { + case UsbdevTypeHostdev: + var typeHostdev DeviceUsbdevTypeUnionHostdev + if err := typeHostdev.fromC(xc); err != nil { + return err + } + x.TypeUnion = typeHostdev + default: + return fmt.Errorf("invalid union key '%v'", x.Type) + } + return nil +} + +func (x *DeviceUsbdevTypeUnionHostdev) fromC(xc *C.libxl_device_usbdev) error { + if UsbdevType(xc._type) != UsbdevTypeHostdev { + return errors.New("expected union key UsbdevTypeHostdev") + } + + tmp := (*C.libxl_device_usbdev_type_union_hostdev)(unsafe.Pointer(&xc.u[0])) + x.Hostbus = byte(tmp.hostbus) + x.Hostaddr = byte(tmp.hostaddr) return nil } @@ -624,6 +946,27 @@ func (x *DeviceChannel) fromC(xc *C.libxl_device_channel) error { x.BackendDomname = C.GoString(xc.backend_domname) x.Devid = Devid(xc.devid) x.Name = C.GoString(xc.name) + x.Connection = ChannelConnection(xc.connection) + switch x.Connection { + case ChannelConnectionSocket: + var connectionSocket DeviceChannelConnectionUnionSocket + if err := connectionSocket.fromC(xc); err != nil { + return err + } + x.ConnectionUnion = connectionSocket + default: + return fmt.Errorf("invalid union key '%v'", x.Connection) + } + return nil +} + +func (x *DeviceChannelConnectionUnionSocket) fromC(xc *C.libxl_device_channel) error { + if ChannelConnection(xc.connection) != ChannelConnectionSocket { + return errors.New("expected union key ChannelConnectionSocket") + } + + tmp := (*C.libxl_device_channel_connection_union_socket)(unsafe.Pointer(&xc.u[0])) + x.Path = C.GoString(tmp.path) return nil } @@ -950,6 +1293,62 @@ func (x *Event) fromC(xc *C.libxl_event) error { } x.Domuuid = uuidDomuuid x.ForUser = uint64(xc.for_user) + x.Type = EventType(xc._type) + switch x.Type { + case EventTypeOperationComplete: + var typeOperationComplete EventTypeUnionOperationComplete + if err := typeOperationComplete.fromC(xc); err != nil { + return err + } + x.TypeUnion = typeOperationComplete + case EventTypeDomainShutdown: + var typeDomainShutdown EventTypeUnionDomainShutdown + if err := typeDomainShutdown.fromC(xc); err != nil { + return err + } + x.TypeUnion = typeDomainShutdown + case EventTypeDiskEject: + var typeDiskEject EventTypeUnionDiskEject + if err := typeDiskEject.fromC(xc); err != nil { + return err + } + x.TypeUnion = typeDiskEject + default: + return fmt.Errorf("invalid union key '%v'", x.Type) + } + return nil +} + +func (x *EventTypeUnionDomainShutdown) fromC(xc *C.libxl_event) error { + if EventType(xc._type) != EventTypeDomainShutdown { + return errors.New("expected union key EventTypeDomainShutdown") + } + + tmp := (*C.libxl_event_type_union_domain_shutdown)(unsafe.Pointer(&xc.u[0])) + x.ShutdownReason = byte(tmp.shutdown_reason) + return nil +} + +func (x *EventTypeUnionDiskEject) fromC(xc *C.libxl_event) error { + if EventType(xc._type) != EventTypeDiskEject { + return errors.New("expected union key EventTypeDiskEject") + } + + tmp := (*C.libxl_event_type_union_disk_eject)(unsafe.Pointer(&xc.u[0])) + x.Vdev = C.GoString(tmp.vdev) + if err := x.Disk.fromC(&tmp.disk); err != nil { + return err + } + return nil +} + +func (x *EventTypeUnionOperationComplete) fromC(xc *C.libxl_event) error { + if EventType(xc._type) != EventTypeOperationComplete { + return errors.New("expected union key EventTypeOperationComplete") + } + + tmp := (*C.libxl_event_type_union_operation_complete)(unsafe.Pointer(&xc.u[0])) + x.Rc = int(tmp.rc) return nil } @@ -963,5 +1362,46 @@ func (x *PsrCatInfo) fromC(xc *C.libxl_psr_cat_info) error { func (x *PsrHwInfo) fromC(xc *C.libxl_psr_hw_info) error { x.Id = uint32(xc.id) + x.Type = PsrFeatType(xc._type) + switch x.Type { + case PsrFeatTypeMba: + var typeMba PsrHwInfoTypeUnionMba + if err := typeMba.fromC(xc); err != nil { + return err + } + x.TypeUnion = typeMba + case PsrFeatTypeCat: + var typeCat PsrHwInfoTypeUnionCat + if err := typeCat.fromC(xc); err != nil { + return err + } + x.TypeUnion = typeCat + default: + return fmt.Errorf("invalid union key '%v'", x.Type) + } + return nil +} + +func (x *PsrHwInfoTypeUnionCat) fromC(xc *C.libxl_psr_hw_info) error { + if PsrFeatType(xc._type) != PsrFeatTypeCat { + return errors.New("expected union key PsrFeatTypeCat") + } + + tmp := (*C.libxl_psr_hw_info_type_union_cat)(unsafe.Pointer(&xc.u[0])) + x.CosMax = uint32(tmp.cos_max) + x.CbmLen = uint32(tmp.cbm_len) + x.CdpEnabled = bool(tmp.cdp_enabled) + return nil +} + +func (x *PsrHwInfoTypeUnionMba) fromC(xc *C.libxl_psr_hw_info) error { + if PsrFeatType(xc._type) != PsrFeatTypeMba { + return errors.New("expected union key PsrFeatTypeMba") + } + + tmp := (*C.libxl_psr_hw_info_type_union_mba)(unsafe.Pointer(&xc.u[0])) + x.CosMax = uint32(tmp.cos_max) + x.ThrtlMax = uint32(tmp.thrtl_max) + x.Linear = bool(tmp.linear) return nil }