github.com/kata-containers/runtime@v0.0.0-20210505125100-04f29832a923/virtcontainers/acrn_arch_base.go (about)

     1  // Copyright (c) 2019 Intel Corporation
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  //
     5  
     6  package virtcontainers
     7  
     8  import (
     9  	"bytes"
    10  	"context"
    11  	"fmt"
    12  	"os"
    13  	"os/exec"
    14  	"strings"
    15  
    16  	"github.com/kata-containers/runtime/virtcontainers/device/config"
    17  	"github.com/kata-containers/runtime/virtcontainers/types"
    18  	"github.com/sirupsen/logrus"
    19  )
    20  
    21  type acrnArch interface {
    22  
    23  	// acrnPath returns the path to the acrn binary
    24  	acrnPath() (string, error)
    25  
    26  	// acrnctlPath returns the path to the acrnctl binary
    27  	acrnctlPath() (string, error)
    28  
    29  	// kernelParameters returns the kernel parameters
    30  	// if debug is true then kernel debug parameters are included
    31  	kernelParameters(debug bool) []Param
    32  
    33  	//capabilities returns the capabilities supported by acrn
    34  	capabilities() types.Capabilities
    35  
    36  	// memoryTopology returns the memory topology using the given amount of memoryMb and hostMemoryMb
    37  	memoryTopology(memMb uint64) Memory
    38  
    39  	// appendConsole appends a console to devices
    40  	appendConsole(devices []Device, path string) []Device
    41  
    42  	// appendImage appends an image to devices
    43  	appendImage(devices []Device, path string) ([]Device, error)
    44  
    45  	// appendBridges appends bridges to devices
    46  	appendBridges(devices []Device) []Device
    47  
    48  	// appendLPC appends LPC to devices
    49  	// UART device emulated by the acrn-dm is connected to the system by the LPC bus
    50  	appendLPC(devices []Device) []Device
    51  
    52  	// appendSocket appends a socket to devices
    53  	appendSocket(devices []Device, socket types.Socket) []Device
    54  
    55  	// appendNetwork appends a endpoint device to devices
    56  	appendNetwork(devices []Device, endpoint Endpoint) []Device
    57  
    58  	// appendBlockDevice appends a block drive to devices
    59  	appendBlockDevice(devices []Device, drive config.BlockDrive) []Device
    60  
    61  	// handleImagePath handles the Hypervisor Config image path
    62  	handleImagePath(config HypervisorConfig)
    63  }
    64  
    65  type acrnArchBase struct {
    66  	path                 string
    67  	ctlpath              string
    68  	kernelParamsNonDebug []Param
    69  	kernelParamsDebug    []Param
    70  	kernelParams         []Param
    71  }
    72  
    73  const acrnPath = "/usr/bin/acrn-dm"
    74  const acrnctlPath = "/usr/bin/acrnctl"
    75  
    76  // acrn GVT-g slot is harded code to 2 as there is
    77  // no simple way to pass arguments of PCI slots from
    78  // device model (acrn-dm) to ACRNGT module.
    79  const acrnGVTgReservedSlot = 2
    80  
    81  const acrnLPCDev = "lpc"
    82  const acrnHostBridge = "hostbridge"
    83  
    84  var baselogger *logrus.Entry
    85  
    86  // AcrnBlkDevPoolSz defines the number of dummy virtio-blk
    87  // device that will be created for hot-plugging container
    88  // rootfs. Since acrn doesn't support hot-plug, dummy virtio-blk
    89  // devices are added and later replaced with container-rootfs.
    90  var AcrnBlkDevPoolSz = 8
    91  
    92  // AcrnBlkdDevSlot array provides translation between
    93  // the vitio-blk device index and slot it is currently
    94  // attached.
    95  // Allocating extra 1 to accommodate for VM rootfs
    96  // which is at driveIndex 0
    97  var AcrnBlkdDevSlot = make([]int, AcrnBlkDevPoolSz+1)
    98  
    99  // acrnKernelParamsNonDebug is a list of the default kernel
   100  // parameters that will be used in standard (non-debug) mode.
   101  var acrnKernelParamsNonDebug = []Param{
   102  	{"quiet", ""},
   103  }
   104  
   105  // acrnKernelParamsSystemdNonDebug is a list of the default systemd related
   106  // kernel parameters that will be used in standard (non-debug) mode.
   107  var acrnKernelParamsSystemdNonDebug = []Param{
   108  	{"systemd.show_status", "false"},
   109  }
   110  
   111  // acrnKernelParamsDebug is a list of the default kernel
   112  // parameters that will be used in debug mode (as much boot output as
   113  // possible).
   114  var acrnKernelParamsDebug = []Param{
   115  	{"debug", ""},
   116  }
   117  
   118  // acrnKernelParamsSystemdDebug is a list of the default systemd related kernel
   119  // parameters that will be used in debug mode (as much boot output as
   120  // possible).
   121  var acrnKernelParamsSystemdDebug = []Param{
   122  	{"systemd.show_status", "true"},
   123  	{"systemd.log_level", "debug"},
   124  	{"systemd.log_target", "kmsg"},
   125  	{"printk.devkmsg", "on"},
   126  }
   127  
   128  var acrnKernelRootParams = []Param{
   129  	{"root", "/dev/vda1 rw rootwait"},
   130  }
   131  
   132  var acrnKernelParams = []Param{
   133  	{"tsc", "reliable"},
   134  	{"no_timer_check", ""},
   135  	{"nohpet", ""},
   136  	{"console", "tty0"},
   137  	{"console", "ttyS0"},
   138  	{"console", "hvc0"},
   139  	{"log_buf_len", "16M"},
   140  	{"consoleblank", "0"},
   141  	{"iommu", "off"},
   142  	{"i915.avail_planes_per_pipe", "0x070F00"},
   143  	{"i915.enable_hangcheck", "0"},
   144  	{"i915.nuclear_pageflip", "1"},
   145  	{"i915.enable_guc_loading", "0"},
   146  	{"i915.enable_guc_submission", "0"},
   147  	{"i915.enable_guc", "0"},
   148  }
   149  
   150  // Device is the acrn device interface.
   151  type Device interface {
   152  	Valid() bool
   153  	AcrnParams(slot int, config *Config) []string
   154  }
   155  
   156  // ConsoleDeviceBackend is the character device backend for acrn
   157  type ConsoleDeviceBackend string
   158  
   159  const (
   160  
   161  	// Socket creates a 2 way stream socket (TCP or Unix).
   162  	Socket ConsoleDeviceBackend = "socket"
   163  
   164  	// Stdio sends traffic from the guest to acrn's standard output.
   165  	Stdio ConsoleDeviceBackend = "console"
   166  
   167  	// File backend only supports console output to a file (no input).
   168  	File ConsoleDeviceBackend = "file"
   169  
   170  	// TTY is an alias for Serial.
   171  	TTY ConsoleDeviceBackend = "tty"
   172  
   173  	// PTY creates a new pseudo-terminal on the host and connect to it.
   174  	PTY ConsoleDeviceBackend = "pty"
   175  )
   176  
   177  // BEPortType marks the port as console port or virtio-serial port
   178  type BEPortType int
   179  
   180  const (
   181  	// SerialBE marks the port as serial port
   182  	SerialBE BEPortType = iota
   183  
   184  	//ConsoleBE marks the port as console port (append @)
   185  	ConsoleBE
   186  )
   187  
   188  // ConsoleDevice represents a acrn console device.
   189  type ConsoleDevice struct {
   190  	// Name of the socket
   191  	Name string
   192  
   193  	//Backend device used for virtio-console
   194  	Backend ConsoleDeviceBackend
   195  
   196  	// PortType marks the port as serial or console port (@)
   197  	PortType BEPortType
   198  
   199  	//Path to virtio-console backend (can be omitted for pty, tty, stdio)
   200  	Path string
   201  }
   202  
   203  // NetDeviceType is a acrn networking device type.
   204  type NetDeviceType string
   205  
   206  const (
   207  	// TAP is a TAP networking device type.
   208  	TAP NetDeviceType = "tap"
   209  
   210  	// MACVTAP is a macvtap networking device type.
   211  	MACVTAP NetDeviceType = "macvtap"
   212  )
   213  
   214  // NetDevice represents a guest networking device
   215  type NetDevice struct {
   216  	// Type is the netdev type (e.g. tap).
   217  	Type NetDeviceType
   218  
   219  	// IfName is the interface name
   220  	IFName string
   221  
   222  	//MACAddress is the networking device interface MAC address
   223  	MACAddress string
   224  }
   225  
   226  // BlockDevice represents a acrn block device.
   227  type BlockDevice struct {
   228  
   229  	// mem path to block device
   230  	FilePath string
   231  
   232  	//BlkIndex - Blk index corresponding to slot
   233  	Index int
   234  }
   235  
   236  // BridgeDevice represents a acrn bridge device like pci-bridge, pxb, etc.
   237  type BridgeDevice struct {
   238  
   239  	// Function is PCI function. Func can be from 0 to 7
   240  	Function int
   241  
   242  	// Emul is a string describing the type of PCI device e.g. virtio-net
   243  	Emul string
   244  
   245  	// Config is an optional string, depending on the device, that can be
   246  	// used for configuration
   247  	Config string
   248  }
   249  
   250  // LPCDevice represents a acrn LPC device
   251  type LPCDevice struct {
   252  
   253  	// Function is PCI function. Func can be from 0 to 7
   254  	Function int
   255  
   256  	// Emul is a string describing the type of PCI device e.g. virtio-net
   257  	Emul string
   258  }
   259  
   260  // Memory is the guest memory configuration structure.
   261  type Memory struct {
   262  	// Size is the amount of memory made available to the guest.
   263  	// It should be suffixed with M or G for sizes in megabytes or
   264  	// gigabytes respectively.
   265  	Size string
   266  }
   267  
   268  // Kernel is the guest kernel configuration structure.
   269  type Kernel struct {
   270  	// Path is the guest kernel path on the host filesystem.
   271  	Path string
   272  
   273  	// InitrdPath is the guest initrd path on the host filesystem.
   274  	ImagePath string
   275  
   276  	// Params is the kernel parameters string.
   277  	Params string
   278  }
   279  
   280  // Config is the acrn configuration structure.
   281  // It allows for passing custom settings and parameters to the acrn-dm API.
   282  type Config struct {
   283  
   284  	// Path is the acrn binary path.
   285  	Path string
   286  
   287  	// Path is the acrn binary path.
   288  	CtlPath string
   289  
   290  	// Name is the acrn guest name
   291  	Name string
   292  
   293  	// UUID is the acrn process UUID.
   294  	UUID string
   295  
   296  	// Devices is a list of devices for acrn to create and drive.
   297  	Devices []Device
   298  
   299  	// Kernel is the guest kernel configuration.
   300  	Kernel Kernel
   301  
   302  	// Memory is the guest memory configuration.
   303  	Memory Memory
   304  
   305  	acrnParams []string
   306  
   307  	// ACPI virtualization support
   308  	ACPIVirt bool
   309  }
   310  
   311  // MaxAcrnVCPUs returns the maximum number of vCPUs supported
   312  func MaxAcrnVCPUs() uint32 {
   313  	return uint32(8)
   314  }
   315  
   316  func newAcrnArch(config HypervisorConfig) acrnArch {
   317  	a := &acrnArchBase{
   318  		path:                 acrnPath,
   319  		ctlpath:              acrnctlPath,
   320  		kernelParamsNonDebug: acrnKernelParamsNonDebug,
   321  		kernelParamsDebug:    acrnKernelParamsDebug,
   322  		kernelParams:         acrnKernelParams,
   323  	}
   324  
   325  	a.handleImagePath(config)
   326  	return a
   327  }
   328  
   329  func (a *acrnArchBase) acrnPath() (string, error) {
   330  	p := a.path
   331  	return p, nil
   332  }
   333  
   334  func (a *acrnArchBase) acrnctlPath() (string, error) {
   335  	ctlpath := a.ctlpath
   336  	return ctlpath, nil
   337  }
   338  
   339  func (a *acrnArchBase) kernelParameters(debug bool) []Param {
   340  	params := a.kernelParams
   341  
   342  	if debug {
   343  		params = append(params, a.kernelParamsDebug...)
   344  	} else {
   345  		params = append(params, a.kernelParamsNonDebug...)
   346  	}
   347  
   348  	return params
   349  }
   350  
   351  func (a *acrnArchBase) memoryTopology(memoryMb uint64) Memory {
   352  	mem := fmt.Sprintf("%dM", memoryMb)
   353  	memory := Memory{
   354  		Size: mem,
   355  	}
   356  
   357  	return memory
   358  }
   359  
   360  func (a *acrnArchBase) capabilities() types.Capabilities {
   361  	var caps types.Capabilities
   362  
   363  	caps.SetBlockDeviceSupport()
   364  	caps.SetBlockDeviceHotplugSupport()
   365  
   366  	return caps
   367  }
   368  
   369  // Valid returns true if the CharDevice structure is valid and complete.
   370  func (cdev ConsoleDevice) Valid() bool {
   371  	if cdev.Backend != "tty" && cdev.Backend != "pty" &&
   372  		cdev.Backend != "console" && cdev.Backend != "socket" &&
   373  		cdev.Backend != "file" {
   374  		return false
   375  	} else if cdev.PortType != ConsoleBE && cdev.PortType != SerialBE {
   376  		return false
   377  	} else if cdev.Path == "" {
   378  		return false
   379  	} else {
   380  		return true
   381  	}
   382  }
   383  
   384  // AcrnParams returns the acrn parameters built out of this console device.
   385  func (cdev ConsoleDevice) AcrnParams(slot int, config *Config) []string {
   386  	var acrnParams []string
   387  	var deviceParams []string
   388  
   389  	acrnParams = append(acrnParams, "-s")
   390  	deviceParams = append(deviceParams, fmt.Sprintf("%d,virtio-console,", slot))
   391  
   392  	if cdev.PortType == ConsoleBE {
   393  		deviceParams = append(deviceParams, "@")
   394  	}
   395  
   396  	switch cdev.Backend {
   397  	case "pty":
   398  		deviceParams = append(deviceParams, "pty:pty_port")
   399  	case "tty":
   400  		deviceParams = append(deviceParams, fmt.Sprintf("tty:tty_port=%s", cdev.Path))
   401  	case "socket":
   402  		deviceParams = append(deviceParams, fmt.Sprintf("socket:%s=%s", cdev.Name, cdev.Path))
   403  	case "file":
   404  		deviceParams = append(deviceParams, fmt.Sprintf("file:file_port=%s", cdev.Path))
   405  	case "stdio":
   406  		deviceParams = append(deviceParams, "stdio:stdio_port")
   407  	default:
   408  		// do nothing. Error should be already caught
   409  	}
   410  
   411  	acrnParams = append(acrnParams, strings.Join(deviceParams, ""))
   412  	return acrnParams
   413  }
   414  
   415  // AcrnNetdevParam converts to the acrn type to string
   416  func (netdev NetDevice) AcrnNetdevParam() []string {
   417  	var deviceParams []string
   418  
   419  	switch netdev.Type {
   420  	case TAP:
   421  		deviceParams = append(deviceParams, netdev.IFName)
   422  		deviceParams = append(deviceParams, fmt.Sprintf(",mac=%s", netdev.MACAddress))
   423  	case MACVTAP:
   424  		deviceParams = append(deviceParams, netdev.IFName)
   425  		deviceParams = append(deviceParams, fmt.Sprintf(",mac=%s", netdev.MACAddress))
   426  	default:
   427  		deviceParams = append(deviceParams, netdev.IFName)
   428  
   429  	}
   430  
   431  	return deviceParams
   432  }
   433  
   434  // Valid returns true if the NetDevice structure is valid and complete.
   435  func (netdev NetDevice) Valid() bool {
   436  	if netdev.IFName == "" {
   437  		return false
   438  	} else if netdev.MACAddress == "" {
   439  		return false
   440  	} else if netdev.Type != TAP && netdev.Type != MACVTAP {
   441  		return false
   442  	} else {
   443  		return true
   444  	}
   445  }
   446  
   447  // AcrnParams returns the acrn parameters built out of this network device.
   448  func (netdev NetDevice) AcrnParams(slot int, config *Config) []string {
   449  	var acrnParams []string
   450  
   451  	acrnParams = append(acrnParams, "-s")
   452  	acrnParams = append(acrnParams, fmt.Sprintf("%d,virtio-net,%s", slot, strings.Join(netdev.AcrnNetdevParam(), "")))
   453  
   454  	return acrnParams
   455  }
   456  
   457  // Valid returns true if the BlockDevice structure is valid and complete.
   458  func (blkdev BlockDevice) Valid() bool {
   459  	return blkdev.FilePath != ""
   460  }
   461  
   462  // AcrnParams returns the acrn parameters built out of this block device.
   463  func (blkdev BlockDevice) AcrnParams(slot int, config *Config) []string {
   464  	var acrnParams []string
   465  
   466  	device := "virtio-blk"
   467  	acrnParams = append(acrnParams, "-s")
   468  	acrnParams = append(acrnParams, fmt.Sprintf("%d,%s,%s",
   469  		slot, device, blkdev.FilePath))
   470  
   471  	// Update the global array (BlkIndex<->slot)
   472  	// Used to identify slots for the hot-plugged virtio-blk devices
   473  	if blkdev.Index <= AcrnBlkDevPoolSz {
   474  		AcrnBlkdDevSlot[blkdev.Index] = slot
   475  	} else {
   476  		baselogger.WithFields(logrus.Fields{
   477  			"device": device,
   478  			"index":  blkdev.Index,
   479  		}).Info("Invalid index device")
   480  	}
   481  
   482  	return acrnParams
   483  }
   484  
   485  // Valid returns true if the BridgeDevice structure is valid and complete.
   486  func (bridgeDev BridgeDevice) Valid() bool {
   487  	if bridgeDev.Function != 0 || bridgeDev.Emul != acrnHostBridge {
   488  		return false
   489  	}
   490  	return true
   491  }
   492  
   493  // AcrnParams returns the acrn parameters built out of this bridge device.
   494  func (bridgeDev BridgeDevice) AcrnParams(slot int, config *Config) []string {
   495  	var acrnParams []string
   496  
   497  	acrnParams = append(acrnParams, "-s")
   498  	acrnParams = append(acrnParams, fmt.Sprintf("%d:%d,%s", slot,
   499  		bridgeDev.Function, bridgeDev.Emul))
   500  
   501  	return acrnParams
   502  }
   503  
   504  // Valid returns true if the BridgeDevice structure is valid and complete.
   505  func (lpcDev LPCDevice) Valid() bool {
   506  	return lpcDev.Emul == acrnLPCDev
   507  }
   508  
   509  // AcrnParams returns the acrn parameters built out of this bridge device.
   510  func (lpcDev LPCDevice) AcrnParams(slot int, config *Config) []string {
   511  	var acrnParams []string
   512  	var deviceParams []string
   513  
   514  	acrnParams = append(acrnParams, "-s")
   515  	acrnParams = append(acrnParams, fmt.Sprintf("%d:%d,%s", slot,
   516  		lpcDev.Function, lpcDev.Emul))
   517  
   518  	//define UART port
   519  	deviceParams = append(deviceParams, "-l")
   520  	deviceParams = append(deviceParams, "com1,stdio")
   521  	acrnParams = append(acrnParams, strings.Join(deviceParams, ""))
   522  
   523  	return acrnParams
   524  }
   525  
   526  func (config *Config) appendName() {
   527  	if config.Name != "" {
   528  		config.acrnParams = append(config.acrnParams, config.Name)
   529  	}
   530  }
   531  
   532  func (config *Config) appendDevices() {
   533  	slot := 0
   534  	for _, d := range config.Devices {
   535  		if !d.Valid() {
   536  			continue
   537  		}
   538  
   539  		if slot == acrnGVTgReservedSlot {
   540  			slot++ /*Slot 2 is assigned for GVT-g in acrn, so skip 2 */
   541  			baselogger.Info("Slot 2 is assigned for GVT-g in acrn, so skipping this slot")
   542  
   543  		}
   544  		config.acrnParams = append(config.acrnParams, d.AcrnParams(slot, config)...)
   545  		slot++
   546  	}
   547  }
   548  
   549  func (config *Config) appendUUID() {
   550  	if config.UUID != "" {
   551  		config.acrnParams = append(config.acrnParams, "-U")
   552  		config.acrnParams = append(config.acrnParams, config.UUID)
   553  	}
   554  }
   555  
   556  func (config *Config) appendACPI() {
   557  	if config.ACPIVirt {
   558  		config.acrnParams = append(config.acrnParams, "-A")
   559  	}
   560  }
   561  
   562  func (config *Config) appendMemory() {
   563  	if config.Memory.Size != "" {
   564  		config.acrnParams = append(config.acrnParams, "-m")
   565  		config.acrnParams = append(config.acrnParams, config.Memory.Size)
   566  	}
   567  }
   568  
   569  func (config *Config) appendKernel() {
   570  	if config.Kernel.Path == "" {
   571  		return
   572  	}
   573  	config.acrnParams = append(config.acrnParams, "-k")
   574  	config.acrnParams = append(config.acrnParams, config.Kernel.Path)
   575  
   576  	if config.Kernel.Params == "" {
   577  		return
   578  	}
   579  	config.acrnParams = append(config.acrnParams, "-B")
   580  	config.acrnParams = append(config.acrnParams, config.Kernel.Params)
   581  }
   582  
   583  // LaunchAcrn can be used to launch a new acrn instance.
   584  //
   585  // The Config parameter contains a set of acrn parameters and settings.
   586  //
   587  // This function writes its log output via logger parameter.
   588  func LaunchAcrn(config Config, logger *logrus.Entry) (int, string, error) {
   589  	baselogger = logger
   590  	config.appendUUID()
   591  	config.appendACPI()
   592  	config.appendMemory()
   593  	config.appendDevices()
   594  	config.appendKernel()
   595  	config.appendName()
   596  
   597  	return LaunchCustomAcrn(context.Background(), config.Path, config.acrnParams, logger)
   598  }
   599  
   600  // LaunchCustomAcrn can be used to launch a new acrn instance.
   601  //
   602  // The path parameter is used to pass the acrn executable path.
   603  //
   604  // params is a slice of options to pass to acrn-dm
   605  //
   606  // This function writes its log output via logger parameter.
   607  func LaunchCustomAcrn(ctx context.Context, path string, params []string,
   608  	logger *logrus.Entry) (int, string, error) {
   609  
   610  	errStr := ""
   611  
   612  	if path == "" {
   613  		path = "acrn-dm"
   614  	}
   615  
   616  	/* #nosec */
   617  	cmd := exec.CommandContext(ctx, path, params...)
   618  
   619  	var stderr bytes.Buffer
   620  	cmd.Stderr = &stderr
   621  	logger.WithFields(logrus.Fields{
   622  		"Path":   path,
   623  		"Params": params,
   624  	}).Info("launching acrn with:")
   625  
   626  	err := cmd.Start()
   627  	if err != nil {
   628  		logger.Errorf("Unable to launch %s: %v", path, err)
   629  		errStr = stderr.String()
   630  		logger.Errorf("%s", errStr)
   631  	}
   632  	return cmd.Process.Pid, errStr, err
   633  }
   634  
   635  func (a *acrnArchBase) appendImage(devices []Device, path string) ([]Device, error) {
   636  	if _, err := os.Stat(path); os.IsNotExist(err) {
   637  		return nil, err
   638  	}
   639  
   640  	ImgBlkdevice := BlockDevice{
   641  		FilePath: path,
   642  		Index:    0,
   643  	}
   644  
   645  	devices = append(devices, ImgBlkdevice)
   646  
   647  	return devices, nil
   648  }
   649  
   650  // appendBridges appends to devices the given bridges
   651  func (a *acrnArchBase) appendBridges(devices []Device) []Device {
   652  	devices = append(devices,
   653  		BridgeDevice{
   654  			Function: 0,
   655  			Emul:     acrnHostBridge,
   656  			Config:   "",
   657  		},
   658  	)
   659  
   660  	return devices
   661  }
   662  
   663  // appendBridges appends to devices the given bridges
   664  func (a *acrnArchBase) appendLPC(devices []Device) []Device {
   665  	devices = append(devices,
   666  		LPCDevice{
   667  			Function: 0,
   668  			Emul:     acrnLPCDev,
   669  		},
   670  	)
   671  
   672  	return devices
   673  }
   674  
   675  func (a *acrnArchBase) appendConsole(devices []Device, path string) []Device {
   676  	console := ConsoleDevice{
   677  		Name:     "console0",
   678  		Backend:  Socket,
   679  		PortType: ConsoleBE,
   680  		Path:     path,
   681  	}
   682  
   683  	devices = append(devices, console)
   684  	return devices
   685  }
   686  
   687  func (a *acrnArchBase) appendSocket(devices []Device, socket types.Socket) []Device {
   688  	serailsocket := ConsoleDevice{
   689  		Name:     socket.Name,
   690  		Backend:  Socket,
   691  		PortType: SerialBE,
   692  		Path:     socket.HostPath,
   693  	}
   694  
   695  	devices = append(devices, serailsocket)
   696  	return devices
   697  }
   698  
   699  func networkModelToAcrnType(model NetInterworkingModel) NetDeviceType {
   700  	switch model {
   701  	case NetXConnectMacVtapModel:
   702  		return MACVTAP
   703  	default:
   704  		//TAP should work for most other cases
   705  		return TAP
   706  	}
   707  }
   708  
   709  func (a *acrnArchBase) appendNetwork(devices []Device, endpoint Endpoint) []Device {
   710  	switch ep := endpoint.(type) {
   711  	case *VethEndpoint:
   712  		netPair := ep.NetworkPair()
   713  		devices = append(devices,
   714  			NetDevice{
   715  				Type:       networkModelToAcrnType(netPair.NetInterworkingModel),
   716  				IFName:     netPair.TAPIface.Name,
   717  				MACAddress: netPair.TAPIface.HardAddr,
   718  			},
   719  		)
   720  	case *MacvtapEndpoint:
   721  		devices = append(devices,
   722  			NetDevice{
   723  				Type:       MACVTAP,
   724  				IFName:     ep.Name(),
   725  				MACAddress: ep.HardwareAddr(),
   726  			},
   727  		)
   728  	default:
   729  		// Return devices as is for unsupported endpoint.
   730  		baselogger.WithField("Endpoint", endpoint).Error("Unsupported N/W Endpoint")
   731  	}
   732  
   733  	return devices
   734  }
   735  
   736  func (a *acrnArchBase) appendBlockDevice(devices []Device, drive config.BlockDrive) []Device {
   737  	if drive.File == "" {
   738  		return devices
   739  	}
   740  
   741  	devices = append(devices,
   742  		BlockDevice{
   743  			FilePath: drive.File,
   744  			Index:    drive.Index,
   745  		},
   746  	)
   747  
   748  	return devices
   749  }
   750  
   751  func (a *acrnArchBase) handleImagePath(config HypervisorConfig) {
   752  	if config.ImagePath != "" {
   753  		a.kernelParams = append(a.kernelParams, acrnKernelRootParams...)
   754  		a.kernelParamsNonDebug = append(a.kernelParamsNonDebug, acrnKernelParamsSystemdNonDebug...)
   755  		a.kernelParamsDebug = append(a.kernelParamsDebug, acrnKernelParamsSystemdDebug...)
   756  	}
   757  }