mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-04-29 12:14:48 +00:00
acrn: Enable ACRN hypervisor support for Kata 2.x release
Currently ACRN hypervisor support in Kata2.x releases is broken. This commit re-enables ACRN hypervisor support and also refactors the code so as to remove dependency on Sandbox. Fixes #3027 Signed-off-by: Vijay Dhanraj <vijay.dhanraj@intel.com>
This commit is contained in:
parent
ff62cedd26
commit
435c8f181a
@ -328,7 +328,8 @@ ifneq (,$(ACRNCMD))
|
|||||||
DEFMAXVCPUS_ACRN := 1
|
DEFMAXVCPUS_ACRN := 1
|
||||||
DEFBLOCKSTORAGEDRIVER_ACRN := virtio-blk
|
DEFBLOCKSTORAGEDRIVER_ACRN := virtio-blk
|
||||||
DEFNETWORKMODEL_ACRN := macvtap
|
DEFNETWORKMODEL_ACRN := macvtap
|
||||||
KERNEL_NAME_ACRN = $(call MAKE_KERNEL_NAME,$(KERNELTYPE))
|
KERNELTYPE_ACRN = compressed
|
||||||
|
KERNEL_NAME_ACRN = $(call MAKE_KERNEL_NAME,$(KERNELTYPE_ACRN))
|
||||||
KERNELPATH_ACRN = $(KERNELDIR)/$(KERNEL_NAME_ACRN)
|
KERNELPATH_ACRN = $(KERNELDIR)/$(KERNEL_NAME_ACRN)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -30,7 +30,6 @@ const (
|
|||||||
cpuFlagLM = "lm"
|
cpuFlagLM = "lm"
|
||||||
cpuFlagSVM = "svm"
|
cpuFlagSVM = "svm"
|
||||||
cpuFlagSSE4_1 = "sse4_1"
|
cpuFlagSSE4_1 = "sse4_1"
|
||||||
kernelModvhm = "vhm_dev"
|
|
||||||
kernelModvhost = "vhost"
|
kernelModvhost = "vhost"
|
||||||
kernelModvhostnet = "vhost_net"
|
kernelModvhostnet = "vhost_net"
|
||||||
kernelModvhostvsock = "vhost_vsock"
|
kernelModvhostvsock = "vhost_vsock"
|
||||||
@ -46,7 +45,7 @@ const (
|
|||||||
cpuTypeUnknown = -1
|
cpuTypeUnknown = -1
|
||||||
)
|
)
|
||||||
|
|
||||||
const acrnDevice = "/dev/acrn_vhm"
|
const acrnDevice = "/dev/acrn_hsm"
|
||||||
|
|
||||||
// ioctl_ACRN_CREATE_VM is the IOCTL to create VM in ACRN.
|
// ioctl_ACRN_CREATE_VM is the IOCTL to create VM in ACRN.
|
||||||
// Current Linux mainstream kernel doesn't have support for ACRN.
|
// Current Linux mainstream kernel doesn't have support for ACRN.
|
||||||
@ -54,18 +53,31 @@ const acrnDevice = "/dev/acrn_vhm"
|
|||||||
// Until the support is available, directly use the value instead
|
// Until the support is available, directly use the value instead
|
||||||
// of macros.
|
// of macros.
|
||||||
//https://github.com/kata-containers/runtime/issues/1784
|
//https://github.com/kata-containers/runtime/issues/1784
|
||||||
const ioctl_ACRN_CREATE_VM = 0x43000010 //nolint
|
const ioctl_ACRN_CREATE_VM = 0xC030A210 //nolint
|
||||||
const ioctl_ACRN_DESTROY_VM = 0x43000011 //nolint
|
const ioctl_ACRN_PAUSE_VM = 0xA213 //nolint
|
||||||
|
const ioctl_ACRN_DESTROY_VM = 0xA211 //nolint
|
||||||
|
|
||||||
type acrn_create_vm struct { //nolint
|
type acrn_vm_creation struct { //nolint
|
||||||
vmid uint16 //nolint
|
vmid uint16 //nolint
|
||||||
reserved0 uint16 //nolint
|
reserved0 uint16 //nolint
|
||||||
vcpu_num uint16 //nolint
|
vcpu_num uint16 //nolint
|
||||||
reserved1 uint16 //nolint
|
reserved1 uint16 //nolint
|
||||||
uuid [16]uint8
|
name [16]uint8
|
||||||
vm_flag uint64 //nolint
|
vm_flag uint64 //nolint
|
||||||
req_buf uint64 //nolint
|
ioreq_buf uint64 //nolint
|
||||||
reserved2 [16]uint8 //nolint
|
cpu_affinity uint64 //nolint
|
||||||
|
}
|
||||||
|
|
||||||
|
var io_request_page [4096]byte
|
||||||
|
|
||||||
|
type acrn_io_request struct { // nolint
|
||||||
|
io_type uint32 // nolint
|
||||||
|
completion_polling uint32 // nolint
|
||||||
|
reserved0 [14]uint32 // nolint
|
||||||
|
data [8]uint64 // nolint
|
||||||
|
reserved1 uint32 // nolint
|
||||||
|
kernel_handled uint32 // nolint
|
||||||
|
processed uint32 // nolint
|
||||||
}
|
}
|
||||||
|
|
||||||
// cpuType save the CPU type
|
// cpuType save the CPU type
|
||||||
@ -150,10 +162,6 @@ func setCPUtype(hypervisorType vc.HypervisorType) error {
|
|||||||
archGenuineIntel: "Intel Architecture CPU",
|
archGenuineIntel: "Intel Architecture CPU",
|
||||||
}
|
}
|
||||||
archRequiredKernelModules = map[string]kernelModule{
|
archRequiredKernelModules = map[string]kernelModule{
|
||||||
kernelModvhm: {
|
|
||||||
desc: "Intel ACRN",
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
kernelModvhost: {
|
kernelModvhost: {
|
||||||
desc: msgKernelVirtio,
|
desc: msgKernelVirtio,
|
||||||
required: false,
|
required: false,
|
||||||
@ -162,6 +170,10 @@ func setCPUtype(hypervisorType vc.HypervisorType) error {
|
|||||||
desc: msgKernelVirtioNet,
|
desc: msgKernelVirtioNet,
|
||||||
required: false,
|
required: false,
|
||||||
},
|
},
|
||||||
|
kernelModvhostvsock: {
|
||||||
|
desc: msgKernelVirtioVhostVsock,
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
case "mock":
|
case "mock":
|
||||||
archRequiredCPUFlags = map[string]string{
|
archRequiredCPUFlags = map[string]string{
|
||||||
@ -247,19 +259,10 @@ func acrnIsUsable() error {
|
|||||||
defer syscall.Close(f)
|
defer syscall.Close(f)
|
||||||
kataLog.WithField("device", acrnDevice).Info("device available")
|
kataLog.WithField("device", acrnDevice).Info("device available")
|
||||||
|
|
||||||
acrnInst := vc.Acrn{}
|
var createVM acrn_vm_creation
|
||||||
uuidStr, err := acrnInst.GetNextAvailableUUID()
|
copy(createVM.name[:], "KataACRNVM")
|
||||||
if err != nil {
|
ioreq_buf := (*acrn_io_request)(unsafe.Pointer(&io_request_page))
|
||||||
return err
|
createVM.ioreq_buf = uint64(uintptr(unsafe.Pointer(ioreq_buf)))
|
||||||
}
|
|
||||||
|
|
||||||
uuid, err := acrnInst.GetACRNUUIDBytes(uuidStr)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Converting UUID str to bytes failed, Err:%s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var createVM acrn_create_vm
|
|
||||||
createVM.uuid = uuid
|
|
||||||
|
|
||||||
ret, _, errno := syscall.Syscall(syscall.SYS_IOCTL,
|
ret, _, errno := syscall.Syscall(syscall.SYS_IOCTL,
|
||||||
uintptr(f),
|
uintptr(f),
|
||||||
@ -269,10 +272,23 @@ func acrnIsUsable() error {
|
|||||||
if errno == syscall.EBUSY {
|
if errno == syscall.EBUSY {
|
||||||
kataLog.WithField("reason", "another hypervisor running").Error("cannot create VM")
|
kataLog.WithField("reason", "another hypervisor running").Error("cannot create VM")
|
||||||
}
|
}
|
||||||
|
kataLog.WithFields(logrus.Fields{
|
||||||
|
"ret": ret,
|
||||||
|
"errno": errno,
|
||||||
|
"VM_name": createVM.name,
|
||||||
|
}).Info("Create VM Error")
|
||||||
|
return errno
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, _, errno = syscall.Syscall(syscall.SYS_IOCTL,
|
||||||
|
uintptr(f),
|
||||||
|
uintptr(ioctl_ACRN_PAUSE_VM),
|
||||||
|
0)
|
||||||
|
if ret != 0 || errno != 0 {
|
||||||
kataLog.WithFields(logrus.Fields{
|
kataLog.WithFields(logrus.Fields{
|
||||||
"ret": ret,
|
"ret": ret,
|
||||||
"errno": errno,
|
"errno": errno,
|
||||||
}).Info("Create VM Error")
|
}).Info("PAUSE VM Error")
|
||||||
return errno
|
return errno
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +60,12 @@ func (device *BlockDevice) Attach(ctx context.Context, devReceiver api.DeviceRec
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hypervisorType := devReceiver.GetHypervisorType()
|
||||||
|
if hypervisorType == "acrn" {
|
||||||
|
deviceLogger().Debug("Special casing for ACRN to increment BlockIndex")
|
||||||
|
index = index + 1
|
||||||
|
}
|
||||||
|
|
||||||
drive := &config.BlockDrive{
|
drive := &config.BlockDrive{
|
||||||
File: device.DeviceInfo.HostPath,
|
File: device.DeviceInfo.HostPath,
|
||||||
Format: "raw",
|
Format: "raw",
|
||||||
|
@ -14,18 +14,18 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/prometheus/procfs"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/kata-containers/kata-containers/src/runtime/pkg/device/config"
|
"github.com/kata-containers/kata-containers/src/runtime/pkg/device/config"
|
||||||
hv "github.com/kata-containers/kata-containers/src/runtime/pkg/hypervisors"
|
hv "github.com/kata-containers/kata-containers/src/runtime/pkg/hypervisors"
|
||||||
"github.com/kata-containers/kata-containers/src/runtime/pkg/katautils/katatrace"
|
"github.com/kata-containers/kata-containers/src/runtime/pkg/katautils/katatrace"
|
||||||
"github.com/kata-containers/kata-containers/src/runtime/pkg/uuid"
|
|
||||||
persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api"
|
persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api"
|
||||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types"
|
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types"
|
||||||
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils"
|
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils"
|
||||||
@ -39,56 +39,9 @@ var acrnTracingTags = map[string]string{
|
|||||||
"type": "acrn",
|
"type": "acrn",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since ACRN is using the store in a quite abnormal way, let's first draw it back from store to here
|
|
||||||
|
|
||||||
/*
|
|
||||||
// UUIDPathSuffix is the suffix used for uuid storage
|
|
||||||
const (
|
|
||||||
UUIDPathSuffix = "uuid"
|
|
||||||
uuidFile = "uuid.json"
|
|
||||||
)
|
|
||||||
*/
|
|
||||||
|
|
||||||
// ACRN currently supports only known UUIDs for security
|
|
||||||
// reasons (FuSa). When launching VM, only these pre-defined
|
|
||||||
// UUID should be used else VM launch will fail. The main
|
|
||||||
// of purpose UUID is is not used for image identification
|
|
||||||
// but generating vSeed (virtual seed which takes UUID
|
|
||||||
// as one of the parameter) which is used during VM boot.
|
|
||||||
|
|
||||||
// acrnUUIDsToIdx lists Idx corresponding to the UUID
|
|
||||||
var acrnUUIDsToIdx = map[string]uint8{
|
|
||||||
"a7ada506-1ab0-4b6b-a0da-e513ca9b8c2f": 0,
|
|
||||||
"dbeae168-26e4-4084-9227-622193e56325": 1,
|
|
||||||
"18ed60cd-e9ea-4bf4-8f87-8523fc8347a3": 2,
|
|
||||||
"3f90b6f8-449a-4e72-b99c-063a889fc422": 3,
|
|
||||||
"1ae8587b-e599-4b59-8260-6d14ac166a55": 4,
|
|
||||||
"75f3b94b-49ed-48fc-b019-577ef45adf2b": 5,
|
|
||||||
"ca62cf3c-8359-47e8-a3f7-de2d682dfb02": 6,
|
|
||||||
"e3189497-c3f6-4b97-9e2c-18ac0ab9064d": 7,
|
|
||||||
}
|
|
||||||
|
|
||||||
// acrnIdxToUUIDs lists UUIDs corresponding to the Idx
|
|
||||||
var acrnIdxToUUIDs = map[uint8]string{
|
|
||||||
0: "a7ada506-1ab0-4b6b-a0da-e513ca9b8c2f",
|
|
||||||
1: "dbeae168-26e4-4084-9227-622193e56325",
|
|
||||||
2: "18ed60cd-e9ea-4bf4-8f87-8523fc8347a3",
|
|
||||||
3: "3f90b6f8-449a-4e72-b99c-063a889fc422",
|
|
||||||
4: "1ae8587b-e599-4b59-8260-6d14ac166a55",
|
|
||||||
5: "75f3b94b-49ed-48fc-b019-577ef45adf2b",
|
|
||||||
6: "ca62cf3c-8359-47e8-a3f7-de2d682dfb02",
|
|
||||||
7: "e3189497-c3f6-4b97-9e2c-18ac0ab9064d",
|
|
||||||
}
|
|
||||||
|
|
||||||
// AcrnInfo keeps track of UUID availability
|
|
||||||
type AcrnInfo struct {
|
|
||||||
UUIDAvailability [8]uint8
|
|
||||||
}
|
|
||||||
|
|
||||||
// AcrnState keeps track of VM UUID, PID.
|
// AcrnState keeps track of VM UUID, PID.
|
||||||
type AcrnState struct {
|
type AcrnState struct {
|
||||||
UUID string
|
PID int
|
||||||
PID int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Acrn is an Hypervisor interface implementation for the Linux acrn hypervisor.
|
// Acrn is an Hypervisor interface implementation for the Linux acrn hypervisor.
|
||||||
@ -98,41 +51,16 @@ type Acrn struct {
|
|||||||
arch acrnArch
|
arch acrnArch
|
||||||
store persistapi.PersistDriver
|
store persistapi.PersistDriver
|
||||||
id string
|
id string
|
||||||
state AcrnState
|
|
||||||
acrnConfig Config
|
acrnConfig Config
|
||||||
config HypervisorConfig
|
config HypervisorConfig
|
||||||
info AcrnInfo
|
state AcrnState
|
||||||
}
|
}
|
||||||
|
|
||||||
type acrnPlatformInfo struct {
|
|
||||||
cpuNum uint16 //nolint
|
|
||||||
reserved0 [126]uint8 //nolint
|
|
||||||
maxVCPUsPerVM uint16 //nolint
|
|
||||||
maxKataContainers uint8
|
|
||||||
reserved1 [125]uint8 //nolint
|
|
||||||
}
|
|
||||||
|
|
||||||
const acrnDevice = "/dev/acrn_vhm"
|
|
||||||
|
|
||||||
// ioctl_ACRN_CREATE_VM is the IOCTL to create VM in ACRN.
|
|
||||||
// Current Linux mainstream kernel doesn't have support for ACRN.
|
|
||||||
// Due to this several macros are not defined in Linux headers.
|
|
||||||
// Until the support is available, directly use the value instead
|
|
||||||
// of macros.
|
|
||||||
//https://github.com/kata-containers/runtime/issues/1784
|
|
||||||
const ioctl_ACRN_GET_PLATFORM_INFO = 0x43000003 //nolint
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
acrnConsoleSocket = "console.sock"
|
acrnConsoleSocket = "console.sock"
|
||||||
acrnStopSandboxTimeoutSecs = 15
|
acrnStopSandboxTimeoutSecs = 15
|
||||||
)
|
)
|
||||||
|
|
||||||
//UUIDBusy marks a particular UUID as busy
|
|
||||||
const UUIDBusy = 1
|
|
||||||
|
|
||||||
//UUIDFree marks a particular UUID as free
|
|
||||||
const UUIDFree = 0
|
|
||||||
|
|
||||||
// agnostic list of kernel parameters
|
// agnostic list of kernel parameters
|
||||||
var acrnDefaultKernelParameters = []Param{
|
var acrnDefaultKernelParameters = []Param{
|
||||||
{"panic", "1"},
|
{"panic", "1"},
|
||||||
@ -170,6 +98,49 @@ func (a *Acrn) HypervisorConfig() HypervisorConfig {
|
|||||||
return a.config
|
return a.config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get cpu apicid to identify vCPU that will be assigned for a VM by reading `proc/cpuinfo`
|
||||||
|
func (a *Acrn) getNextApicid() (string, error) {
|
||||||
|
fs, err := procfs.NewFS("/proc")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
cpuinfo, err := fs.CPUInfo()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
prevIdx := -1
|
||||||
|
fileName := filepath.Join(a.config.VMStorePath, "cpu_affinity_idx")
|
||||||
|
_, err = os.Stat(fileName)
|
||||||
|
if err == nil {
|
||||||
|
data, err := os.ReadFile(fileName)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger().Error("Loading cpu affinity index from file failed!")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
prevIdx, err = strconv.Atoi(string(data))
|
||||||
|
if err != nil {
|
||||||
|
a.Logger().Error("CreateVM: Convert from []byte to integer failed!")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if prevIdx >= (len(cpuinfo) - 1) {
|
||||||
|
prevIdx = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
currentIdx := prevIdx + 1
|
||||||
|
err = os.WriteFile(fileName, []byte(strconv.Itoa(currentIdx)), defaultFilePerms)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger().Error("Storing cpu affinity index from file failed!")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cpuinfo[currentIdx].APICID, nil
|
||||||
|
}
|
||||||
|
|
||||||
// get the acrn binary path
|
// get the acrn binary path
|
||||||
func (a *Acrn) acrnPath() (string, error) {
|
func (a *Acrn) acrnPath() (string, error) {
|
||||||
p, err := a.config.HypervisorAssetPath()
|
p, err := a.config.HypervisorAssetPath()
|
||||||
@ -228,15 +199,7 @@ func (a *Acrn) appendImage(devices []Device, imagePath string) ([]Device, error)
|
|||||||
return nil, fmt.Errorf("Image path is empty: %s", imagePath)
|
return nil, fmt.Errorf("Image path is empty: %s", imagePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get sandbox and increment the globalIndex.
|
|
||||||
// This is to make sure the VM rootfs occupies
|
|
||||||
// the first Index which is /dev/vda.
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if _, err = a.sandbox.GetAndSetSandboxBlockIndex(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
devices, err = a.arch.appendImage(devices, imagePath)
|
devices, err = a.arch.appendImage(devices, imagePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -295,36 +258,6 @@ func (a *Acrn) setup(ctx context.Context, id string, hypervisorConfig *Hyperviso
|
|||||||
a.id = id
|
a.id = id
|
||||||
a.arch = newAcrnArch(a.config)
|
a.arch = newAcrnArch(a.config)
|
||||||
|
|
||||||
var create bool
|
|
||||||
var uuid string
|
|
||||||
|
|
||||||
if a.state.UUID == "" {
|
|
||||||
create = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if create {
|
|
||||||
a.Logger().Debug("Setting UUID")
|
|
||||||
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if uuid, err = a.GetNextAvailableUUID(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
a.state.UUID = uuid
|
|
||||||
Idx := acrnUUIDsToIdx[uuid]
|
|
||||||
a.info.UUIDAvailability[Idx] = UUIDBusy
|
|
||||||
|
|
||||||
// The path might already exist, but in case of VM templating,
|
|
||||||
// we have to create it since the sandbox has not created it yet.
|
|
||||||
if err = os.MkdirAll(filepath.Join(a.config.RunStorePath, id), DirMode); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = a.storeInfo(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,10 +319,6 @@ func (a *Acrn) CreateVM(ctx context.Context, id string, network Network, hypervi
|
|||||||
Params: a.kernelParameters(),
|
Params: a.kernelParameters(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.state.UUID == "" {
|
|
||||||
return fmt.Errorf("ACRN UUID should not be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
devices, err := a.buildDevices(ctx, imagePath)
|
devices, err := a.buildDevices(ctx, imagePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -405,15 +334,25 @@ func (a *Acrn) CreateVM(ctx context.Context, id string, network Network, hypervi
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vmName := fmt.Sprintf("sbx-%s", a.id)
|
||||||
|
if len(vmName) > 15 {
|
||||||
|
return fmt.Errorf("VM Name len is %d but ACRN supports max VM name len of 15.", len(vmName))
|
||||||
|
}
|
||||||
|
|
||||||
|
apicID, err := a.getNextApicid()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
acrnConfig := Config{
|
acrnConfig := Config{
|
||||||
UUID: a.state.UUID,
|
|
||||||
ACPIVirt: true,
|
ACPIVirt: true,
|
||||||
Path: acrnPath,
|
Path: acrnPath,
|
||||||
CtlPath: acrnctlPath,
|
CtlPath: acrnctlPath,
|
||||||
Memory: memory,
|
Memory: memory,
|
||||||
Devices: devices,
|
Devices: devices,
|
||||||
Kernel: kernel,
|
Kernel: kernel,
|
||||||
Name: fmt.Sprintf("sandbox-%s", a.id),
|
Name: vmName,
|
||||||
|
ApicID: apicID,
|
||||||
}
|
}
|
||||||
|
|
||||||
a.acrnConfig = acrnConfig
|
a.acrnConfig = acrnConfig
|
||||||
@ -453,6 +392,7 @@ func (a *Acrn) StartVM(ctx context.Context, timeoutSecs int) error {
|
|||||||
|
|
||||||
var strErr string
|
var strErr string
|
||||||
var PID int
|
var PID int
|
||||||
|
a.Logger().Error("StartVM: LaunchAcrn() function called")
|
||||||
PID, strErr, err = LaunchAcrn(a.acrnConfig, virtLog.WithField("subsystem", "acrn-dm"))
|
PID, strErr, err = LaunchAcrn(a.acrnConfig, virtLog.WithField("subsystem", "acrn-dm"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%s", strErr)
|
return fmt.Errorf("%s", strErr)
|
||||||
@ -496,19 +436,23 @@ func (a *Acrn) StopVM(ctx context.Context, waitOnly bool) (err error) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Mark the UUID as free
|
fileName := filepath.Join(a.config.VMStorePath, "cpu_affinity_idx")
|
||||||
uuid := a.state.UUID
|
data, err := os.ReadFile(fileName)
|
||||||
Idx := acrnUUIDsToIdx[uuid]
|
if err != nil {
|
||||||
|
a.Logger().Error("Loading cpu affinity index from file failed!")
|
||||||
if err = a.loadInfo(); err != nil {
|
|
||||||
a.Logger().Info("Failed to Load UUID availabiity info")
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
a.info.UUIDAvailability[Idx] = UUIDFree
|
currentIdx, err := strconv.Atoi(string(data))
|
||||||
|
if err != nil {
|
||||||
|
a.Logger().Error("Converting from []byte to integer failed!")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if err = a.storeInfo(); err != nil {
|
currentIdx = currentIdx - 1
|
||||||
a.Logger().Info("Failed to store UUID availabiity info")
|
err = os.WriteFile(fileName, []byte(strconv.Itoa(currentIdx)), defaultFilePerms)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger().Error("Storing cpu affinity index from file failed!")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -608,8 +552,7 @@ func (a *Acrn) AddDevice(ctx context.Context, devInfo interface{}, devType Devic
|
|||||||
case types.Socket:
|
case types.Socket:
|
||||||
a.acrnConfig.Devices = a.arch.appendSocket(a.acrnConfig.Devices, v)
|
a.acrnConfig.Devices = a.arch.appendSocket(a.acrnConfig.Devices, v)
|
||||||
case types.VSock:
|
case types.VSock:
|
||||||
// Not supported. return success
|
a.acrnConfig.Devices = a.arch.appendVSock(a.acrnConfig.Devices, v)
|
||||||
err = nil
|
|
||||||
case Endpoint:
|
case Endpoint:
|
||||||
a.acrnConfig.Devices = a.arch.appendNetwork(a.acrnConfig.Devices, v)
|
a.acrnConfig.Devices = a.arch.appendNetwork(a.acrnConfig.Devices, v)
|
||||||
case config.BlockDrive:
|
case config.BlockDrive:
|
||||||
@ -635,7 +578,9 @@ func (a *Acrn) GetVMConsole(ctx context.Context, id string) (string, string, err
|
|||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
consoleURL, err := utils.BuildSocketPath(a.config.VMStorePath, id, acrnConsoleSocket)
|
consoleURL, err := utils.BuildSocketPath(a.config.VMStorePath, id, acrnConsoleSocket)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
a.Logger().Error("GetVMConsole returned error")
|
||||||
return consoleProtoUnix, "", err
|
return consoleProtoUnix, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -705,13 +650,11 @@ func (a *Acrn) toGrpc(ctx context.Context) ([]byte, error) {
|
|||||||
func (a *Acrn) Save() (s hv.HypervisorState) {
|
func (a *Acrn) Save() (s hv.HypervisorState) {
|
||||||
s.Pid = a.state.PID
|
s.Pid = a.state.PID
|
||||||
s.Type = string(AcrnHypervisor)
|
s.Type = string(AcrnHypervisor)
|
||||||
s.UUID = a.state.UUID
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Acrn) Load(s hv.HypervisorState) {
|
func (a *Acrn) Load(s hv.HypervisorState) {
|
||||||
a.state.PID = s.Pid
|
a.state.PID = s.Pid
|
||||||
a.state.UUID = s.UUID
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Acrn) Check() error {
|
func (a *Acrn) Check() error {
|
||||||
@ -723,97 +666,14 @@ func (a *Acrn) Check() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *Acrn) GenerateSocket(id string) (interface{}, error) {
|
func (a *Acrn) GenerateSocket(id string) (interface{}, error) {
|
||||||
return generateVMSocket(id, a.config.VMStorePath)
|
socket, err := generateVMSocket(id, a.config.VMStorePath)
|
||||||
}
|
|
||||||
|
|
||||||
// GetACRNUUIDBytes returns UUID bytes that is used for VM creation
|
|
||||||
func (a *Acrn) GetACRNUUIDBytes(uid string) (uuid.UUID, error) {
|
|
||||||
return uuid.Parse(uid)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetNextAvailableUUID returns next available UUID VM creation
|
|
||||||
// If no valid UUIDs are available it returns err.
|
|
||||||
func (a *Acrn) GetNextAvailableUUID() (string, error) {
|
|
||||||
var MaxVMSupported uint8
|
|
||||||
var Idx uint8
|
|
||||||
var uuidStr string
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if err = a.loadInfo(); err != nil {
|
|
||||||
a.Logger().Infof("Load UUID store failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
if MaxVMSupported, err = a.GetMaxSupportedACRNVM(); err != nil {
|
|
||||||
return "", fmt.Errorf("IOCTL GetMaxSupportedACRNVM failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
for Idx = 0; Idx < MaxVMSupported; Idx++ {
|
|
||||||
if a.info.UUIDAvailability[Idx] == UUIDFree {
|
|
||||||
uuidStr = acrnIdxToUUIDs[Idx]
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if uuidStr == "" {
|
|
||||||
return "", fmt.Errorf("Invalid UUID: Max VMs reached")
|
|
||||||
}
|
|
||||||
|
|
||||||
return uuidStr, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMaxSupportedACRNVM checks the max number of VMs that can be
|
|
||||||
// launched from kata-runtime.
|
|
||||||
func (a *Acrn) GetMaxSupportedACRNVM() (uint8, error) {
|
|
||||||
flags := syscall.O_RDWR | syscall.O_CLOEXEC
|
|
||||||
|
|
||||||
f, err := syscall.Open(acrnDevice, flags, 0)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return "", err
|
||||||
}
|
}
|
||||||
defer syscall.Close(f)
|
vsock, _ := socket.(types.VSock)
|
||||||
|
vsock.VhostFd.Close()
|
||||||
|
|
||||||
var platformInfo acrnPlatformInfo
|
return socket, err
|
||||||
|
|
||||||
ret, _, errno := syscall.Syscall(syscall.SYS_IOCTL,
|
|
||||||
uintptr(f),
|
|
||||||
uintptr(ioctl_ACRN_GET_PLATFORM_INFO),
|
|
||||||
uintptr(unsafe.Pointer(&platformInfo)))
|
|
||||||
if ret != 0 || errno != 0 {
|
|
||||||
return 0, errno
|
|
||||||
}
|
|
||||||
|
|
||||||
return platformInfo.maxKataContainers, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Acrn) storeInfo() error {
|
|
||||||
/*
|
|
||||||
relPath := filepath.Join(UUIDPathSuffix, uuidFile)
|
|
||||||
|
|
||||||
jsonOut, err := json.Marshal(a.info)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Could not marshal data: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := a.store.GlobalWrite(relPath, jsonOut); err != nil {
|
|
||||||
return fmt.Errorf("failed to write uuid to file: %v", err)
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Acrn) loadInfo() error {
|
|
||||||
/*
|
|
||||||
relPath := filepath.Join(UUIDPathSuffix, uuidFile)
|
|
||||||
data, err := a.store.GlobalRead(relPath)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to read uuid from file: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(data, &a.info); err != nil {
|
|
||||||
return fmt.Errorf("failed to unmarshal uuid info: %v", err)
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Acrn) IsRateLimiterBuiltin() bool {
|
func (a *Acrn) IsRateLimiterBuiltin() bool {
|
||||||
|
@ -55,6 +55,9 @@ type acrnArch interface {
|
|||||||
// appendSocket appends a socket to devices
|
// appendSocket appends a socket to devices
|
||||||
appendSocket(devices []Device, socket types.Socket) []Device
|
appendSocket(devices []Device, socket types.Socket) []Device
|
||||||
|
|
||||||
|
// appendVSock appends a vsock PCI to devices
|
||||||
|
appendVSock(devices []Device, vsock types.VSock) []Device
|
||||||
|
|
||||||
// appendNetwork appends a endpoint device to devices
|
// appendNetwork appends a endpoint device to devices
|
||||||
appendNetwork(devices []Device, endpoint Endpoint) []Device
|
appendNetwork(devices []Device, endpoint Endpoint) []Device
|
||||||
|
|
||||||
@ -141,13 +144,6 @@ var acrnKernelParams = []Param{
|
|||||||
{"console", "hvc0"},
|
{"console", "hvc0"},
|
||||||
{"log_buf_len", "16M"},
|
{"log_buf_len", "16M"},
|
||||||
{"consoleblank", "0"},
|
{"consoleblank", "0"},
|
||||||
{"iommu", "off"},
|
|
||||||
{"i915.avail_planes_per_pipe", "0x070F00"},
|
|
||||||
{"i915.enable_hangcheck", "0"},
|
|
||||||
{"i915.nuclear_pageflip", "1"},
|
|
||||||
{"i915.enable_guc_loading", "0"},
|
|
||||||
{"i915.enable_guc_submission", "0"},
|
|
||||||
{"i915.enable_guc", "0"},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Device is the acrn device interface.
|
// Device is the acrn device interface.
|
||||||
@ -203,6 +199,12 @@ type ConsoleDevice struct {
|
|||||||
PortType BEPortType
|
PortType BEPortType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VSOCKDevice represents a AF_VSOCK socket.
|
||||||
|
type VSOCKDevice struct {
|
||||||
|
//Guest CID assigned by Host.
|
||||||
|
ContextID uint64
|
||||||
|
}
|
||||||
|
|
||||||
// NetDeviceType is a acrn networking device type.
|
// NetDeviceType is a acrn networking device type.
|
||||||
type NetDeviceType string
|
type NetDeviceType string
|
||||||
|
|
||||||
@ -293,8 +295,8 @@ type Config struct {
|
|||||||
// Name is the acrn guest name
|
// Name is the acrn guest name
|
||||||
Name string
|
Name string
|
||||||
|
|
||||||
// UUID is the acrn process UUID.
|
// APICID to identify vCPU that will be assigned for this VM.
|
||||||
UUID string
|
ApicID string
|
||||||
|
|
||||||
// Kernel is the guest kernel configuration.
|
// Kernel is the guest kernel configuration.
|
||||||
Kernel Kernel
|
Kernel Kernel
|
||||||
@ -431,6 +433,33 @@ func (netdev NetDevice) AcrnNetdevParam() []string {
|
|||||||
return deviceParams
|
return deviceParams
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// MinimalGuestCID is the smallest valid context ID for a guest.
|
||||||
|
MinimalGuestCID uint64 = 3
|
||||||
|
|
||||||
|
// MaxGuestCID is the largest valid context ID for a guest.
|
||||||
|
MaxGuestCID uint64 = 1<<32 - 1
|
||||||
|
)
|
||||||
|
|
||||||
|
// Valid returns true if the VSOCKDevice structure is valid and complete.
|
||||||
|
func (vsock VSOCKDevice) Valid() bool {
|
||||||
|
if vsock.ContextID < MinimalGuestCID || vsock.ContextID > MaxGuestCID {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// AcrnParams returns the acrn parameters built out of this vsock device.
|
||||||
|
func (vsock VSOCKDevice) AcrnParams(slot int, config *Config) []string {
|
||||||
|
var acrnParams []string
|
||||||
|
|
||||||
|
acrnParams = append(acrnParams, "-s")
|
||||||
|
acrnParams = append(acrnParams, fmt.Sprintf("%d,vhost-vsock,cid=%d", slot, uint32(vsock.ContextID)))
|
||||||
|
|
||||||
|
return acrnParams
|
||||||
|
}
|
||||||
|
|
||||||
// Valid returns true if the NetDevice structure is valid and complete.
|
// Valid returns true if the NetDevice structure is valid and complete.
|
||||||
func (netdev NetDevice) Valid() bool {
|
func (netdev NetDevice) Valid() bool {
|
||||||
if netdev.IFName == "" {
|
if netdev.IFName == "" {
|
||||||
@ -546,13 +575,6 @@ func (config *Config) appendDevices() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config *Config) appendUUID() {
|
|
||||||
if config.UUID != "" {
|
|
||||||
config.acrnParams = append(config.acrnParams, "-U")
|
|
||||||
config.acrnParams = append(config.acrnParams, config.UUID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (config *Config) appendACPI() {
|
func (config *Config) appendACPI() {
|
||||||
if config.ACPIVirt {
|
if config.ACPIVirt {
|
||||||
config.acrnParams = append(config.acrnParams, "-A")
|
config.acrnParams = append(config.acrnParams, "-A")
|
||||||
@ -566,10 +588,20 @@ func (config *Config) appendMemory() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (config *Config) appendCPUAffinity() {
|
||||||
|
if config.ApicID == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
config.acrnParams = append(config.acrnParams, "--cpu_affinity")
|
||||||
|
config.acrnParams = append(config.acrnParams, config.ApicID)
|
||||||
|
}
|
||||||
|
|
||||||
func (config *Config) appendKernel() {
|
func (config *Config) appendKernel() {
|
||||||
if config.Kernel.Path == "" {
|
if config.Kernel.Path == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
config.acrnParams = append(config.acrnParams, "-k")
|
config.acrnParams = append(config.acrnParams, "-k")
|
||||||
config.acrnParams = append(config.acrnParams, config.Kernel.Path)
|
config.acrnParams = append(config.acrnParams, config.Kernel.Path)
|
||||||
|
|
||||||
@ -587,10 +619,10 @@ func (config *Config) appendKernel() {
|
|||||||
// This function writes its log output via logger parameter.
|
// This function writes its log output via logger parameter.
|
||||||
func LaunchAcrn(config Config, logger *logrus.Entry) (int, string, error) {
|
func LaunchAcrn(config Config, logger *logrus.Entry) (int, string, error) {
|
||||||
baselogger = logger
|
baselogger = logger
|
||||||
config.appendUUID()
|
|
||||||
config.appendACPI()
|
config.appendACPI()
|
||||||
config.appendMemory()
|
config.appendMemory()
|
||||||
config.appendDevices()
|
config.appendDevices()
|
||||||
|
config.appendCPUAffinity()
|
||||||
config.appendKernel()
|
config.appendKernel()
|
||||||
config.appendName()
|
config.appendName()
|
||||||
|
|
||||||
@ -696,6 +728,15 @@ func (a *acrnArchBase) appendSocket(devices []Device, socket types.Socket) []Dev
|
|||||||
return devices
|
return devices
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *acrnArchBase) appendVSock(devices []Device, vsock types.VSock) []Device {
|
||||||
|
vmsock := VSOCKDevice{
|
||||||
|
ContextID: vsock.ContextID,
|
||||||
|
}
|
||||||
|
|
||||||
|
devices = append(devices, vmsock)
|
||||||
|
return devices
|
||||||
|
}
|
||||||
|
|
||||||
func networkModelToAcrnType(model NetInterworkingModel) NetDeviceType {
|
func networkModelToAcrnType(model NetInterworkingModel) NetDeviceType {
|
||||||
switch model {
|
switch model {
|
||||||
case NetXConnectMacVtapModel:
|
case NetXConnectMacVtapModel:
|
||||||
|
@ -243,9 +243,7 @@ func TestAcrnCreateVM(t *testing.T) {
|
|||||||
|
|
||||||
a.sandbox = sandbox
|
a.sandbox = sandbox
|
||||||
|
|
||||||
//set PID to 1 to ignore hypercall to get UUID and set a random UUID
|
|
||||||
a.state.PID = 1
|
a.state.PID = 1
|
||||||
a.state.UUID = "f81d4fae-7dec-11d0-a765-00a0c91e6bf6"
|
|
||||||
network, err := NewNetwork()
|
network, err := NewNetwork()
|
||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
err = a.CreateVM(context.Background(), sandbox.id, network, &sandbox.config.HypervisorConfig)
|
err = a.CreateVM(context.Background(), sandbox.id, network, &sandbox.config.HypervisorConfig)
|
||||||
|
@ -405,7 +405,11 @@ func (f *FilesystemShare) ShareRootFilesystem(ctx context.Context, c *Container)
|
|||||||
rootfsStorage.Source = blockDrive.DevNo
|
rootfsStorage.Source = blockDrive.DevNo
|
||||||
case f.sandbox.config.HypervisorConfig.BlockDeviceDriver == config.VirtioBlock:
|
case f.sandbox.config.HypervisorConfig.BlockDeviceDriver == config.VirtioBlock:
|
||||||
rootfsStorage.Driver = kataBlkDevType
|
rootfsStorage.Driver = kataBlkDevType
|
||||||
rootfsStorage.Source = blockDrive.PCIPath.String()
|
if f.sandbox.config.HypervisorType == AcrnHypervisor {
|
||||||
|
rootfsStorage.Source = blockDrive.VirtPath
|
||||||
|
} else {
|
||||||
|
rootfsStorage.Source = blockDrive.PCIPath.String()
|
||||||
|
}
|
||||||
case f.sandbox.config.HypervisorConfig.BlockDeviceDriver == config.VirtioSCSI:
|
case f.sandbox.config.HypervisorConfig.BlockDeviceDriver == config.VirtioSCSI:
|
||||||
rootfsStorage.Driver = kataSCSIDevType
|
rootfsStorage.Driver = kataSCSIDevType
|
||||||
rootfsStorage.Source = blockDrive.SCSIAddr
|
rootfsStorage.Source = blockDrive.SCSIAddr
|
||||||
|
Loading…
Reference in New Issue
Block a user