diff --git a/functional/lcow_test.go b/functional/lcow_test.go index 129b867209..290a5ca885 100644 --- a/functional/lcow_test.go +++ b/functional/lcow_test.go @@ -66,17 +66,38 @@ func testLCOWUVMNoSCSISingleVPMem(t *testing.T, opts *uvm.UVMOptions, expected s // TestLCOWTimeUVMStartVHD starts/terminates a utility VM booting from VPMem- // attached root filesystem a number of times. func TestLCOWTimeUVMStartVHD(t *testing.T) { - testLCOWTimeUVMStart(t, uvm.PreferredRootFSTypeVHD) + testutilities.RequiresBuild(t, osversion.RS5) + + testLCOWTimeUVMStart(t, false, uvm.PreferredRootFSTypeVHD) +} + +// TestLCOWUVMStart_KernelDirect_VHD starts/terminates a utility VM booting from +// VPMem- attached root filesystem a number of times starting from the Linux +// Kernel directly and skipping EFI. +func TestLCOWUVMStart_KernelDirect_VHD(t *testing.T) { + testutilities.RequiresBuild(t, 18286) + + testLCOWTimeUVMStart(t, true, uvm.PreferredRootFSTypeVHD) } // TestLCOWTimeUVMStartInitRD starts/terminates a utility VM booting from initrd- // attached root file system a number of times. func TestLCOWTimeUVMStartInitRD(t *testing.T) { - testLCOWTimeUVMStart(t, uvm.PreferredRootFSTypeInitRd) + testutilities.RequiresBuild(t, osversion.RS5) + + testLCOWTimeUVMStart(t, false, uvm.PreferredRootFSTypeInitRd) } -func testLCOWTimeUVMStart(t *testing.T, rfsType uvm.PreferredRootFSType) { - testutilities.RequiresBuild(t, osversion.RS5) +// TestLCOWUVMStart_KernelDirect_InitRd starts/terminates a utility VM booting +// from initrd- attached root file system a number of times starting from the +// Linux Kernel directly and skipping EFI. +func TestLCOWUVMStart_KernelDirect_InitRd(t *testing.T) { + testutilities.RequiresBuild(t, 18286) + + testLCOWTimeUVMStart(t, true, uvm.PreferredRootFSTypeInitRd) +} + +func testLCOWTimeUVMStart(t *testing.T, kernelDirect bool, rfsType uvm.PreferredRootFSType) { var vpmemCount uint32 = 32 for i := 0; i < 3; i++ { opts := &uvm.UVMOptions{ @@ -84,6 +105,7 @@ func testLCOWTimeUVMStart(t *testing.T, rfsType uvm.PreferredRootFSType) { ID: "uvm", VPMemDeviceCount: &vpmemCount, PreferredRootFSType: &rfsType, + KernelDirect: kernelDirect, } lcowUVM := testutilities.CreateLCOWUVMFromOpts(t, opts) lcowUVM.Close() diff --git a/internal/schema2/chipset.go b/internal/schema2/chipset.go index 3fb24e2505..ca75277a3f 100644 --- a/internal/schema2/chipset.go +++ b/internal/schema2/chipset.go @@ -10,7 +10,6 @@ package hcsschema type Chipset struct { - Uefi *Uefi `json:"Uefi,omitempty"` IsNumLockDisabled bool `json:"IsNumLockDisabled,omitempty"` @@ -22,4 +21,7 @@ type Chipset struct { ChassisAssetTag string `json:"ChassisAssetTag,omitempty"` UseUtc bool `json:"UseUtc,omitempty"` + + // LinuxKernelDirect - Added in v2.2 Builds >=181117 + LinuxKernelDirect *LinuxKernelDirect `json:"LinuxKernelDirect,omitempty"` } diff --git a/internal/schema2/linux_kernel_direct.go b/internal/schema2/linux_kernel_direct.go new file mode 100644 index 0000000000..0ab6c280fc --- /dev/null +++ b/internal/schema2/linux_kernel_direct.go @@ -0,0 +1,18 @@ +/* + * HCS API + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * API version: 2.2 + * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git) + */ + +package hcsschema + +type LinuxKernelDirect struct { + KernelFilePath string `json:"KernelFilePath,omitempty"` + + InitRdPath string `json:"InitRdPath,omitempty"` + + KernelCmdLine string `json:"KernelCmdLine,omitempty"` +} diff --git a/internal/uvm/create.go b/internal/uvm/create.go index e3bc524876..3399f70dc2 100644 --- a/internal/uvm/create.go +++ b/internal/uvm/create.go @@ -17,6 +17,7 @@ import ( "github.com/Microsoft/hcsshim/internal/uvmfolder" "github.com/Microsoft/hcsshim/internal/wclayer" "github.com/Microsoft/hcsshim/internal/wcow" + "github.com/Microsoft/hcsshim/osversion" "github.com/linuxkit/virtsock/pkg/hvsock" specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/sirupsen/logrus" @@ -46,6 +47,7 @@ type UVMOptions struct { // LCOW specific parameters BootFilesPath string // Folder in which kernel and root file system reside. Defaults to \Program Files\Linux Containers KernelFile string // Filename under BootFilesPath for the kernel. Defaults to `kernel` + KernelDirect bool // Skip UEFI and boot directly to `kernel` RootFSFile string // Filename under BootFilesPath for the UVMs root file system. Defaults are `initrd.img` or `rootfs.vhd`. KernelBootOptions string // Additional boot options for the kernel EnableGraphicsConsole bool // If true, enable a graphics console for the utility VM @@ -179,6 +181,9 @@ func Create(opts *UVMOptions) (_ *UtilityVM, err error) { uvm.vpmemMaxSizeBytes = *opts.VPMemSizeBytes } } + if opts.KernelDirect && osversion.Get().Build < 18286 { + return nil, fmt.Errorf("KernelDirectBoot is not support on builds older than 18286") + } scsi["0"] = hcsschema.Scsi{Attachments: attachments} uvm.scsiControllerCount = 1 @@ -333,19 +338,21 @@ func Create(opts *UVMOptions) (_ *UtilityVM, err error) { vmDebugging := false vm.GuestConnection.UseVsock = true vm.GuestConnection.UseConnectedSuspend = true - vm.Devices.VirtualSmb = &hcsschema.VirtualSmb{ - Shares: []hcsschema.VirtualSmbShare{ - { - Name: "os", - Path: opts.BootFilesPath, - Options: &hcsschema.VirtualSmbShareOptions{ - ReadOnly: true, - TakeBackupPrivilege: true, - CacheIo: true, - ShareRead: true, + if !opts.KernelDirect { + vm.Devices.VirtualSmb = &hcsschema.VirtualSmb{ + Shares: []hcsschema.VirtualSmbShare{ + { + Name: "os", + Path: opts.BootFilesPath, + Options: &hcsschema.VirtualSmbShareOptions{ + ReadOnly: true, + TakeBackupPrivilege: true, + CacheIo: true, + ShareRead: true, + }, }, }, - }, + } } if uvm.vpmemMaxCount > 0 { @@ -355,8 +362,13 @@ func Create(opts *UVMOptions) (_ *UtilityVM, err error) { } } - kernelArgs := "initrd=/" + opts.RootFSFile - if actualRootFSType == PreferredRootFSTypeVHD { + var kernelArgs string + switch actualRootFSType { + case PreferredRootFSTypeInitRd: + if !opts.KernelDirect { + kernelArgs = "initrd=/" + opts.RootFSFile + } + case PreferredRootFSTypeVHD: kernelArgs = "root=/dev/pmem0 init=/init" } @@ -428,10 +440,22 @@ func Create(opts *UVMOptions) (_ *UtilityVM, err error) { } kernelArgs += ` pci=off -- ` + initArgs - vm.Chipset.Uefi.BootThis = &hcsschema.UefiBootEntry{ - DevicePath: `\` + opts.KernelFile, - DeviceType: "VmbFs", - OptionalData: kernelArgs, + + if !opts.KernelDirect { + vm.Chipset.Uefi.BootThis = &hcsschema.UefiBootEntry{ + DevicePath: `\` + opts.KernelFile, + DeviceType: "VmbFs", + OptionalData: kernelArgs, + } + } else { + vm.Chipset.Uefi = nil + vm.Chipset.LinuxKernelDirect = &hcsschema.LinuxKernelDirect{ + KernelFilePath: filepath.Join(opts.BootFilesPath, opts.KernelFile), + KernelCmdLine: kernelArgs, + } + if actualRootFSType == PreferredRootFSTypeInitRd { + vm.Chipset.LinuxKernelDirect.InitRdPath = filepath.Join(opts.BootFilesPath, opts.RootFSFile) + } } }