diff --git a/kvm/kvm.go b/kvm/kvm.go index a5f2bd8..e2a6f87 100644 --- a/kvm/kvm.go +++ b/kvm/kvm.go @@ -18,6 +18,12 @@ const ( kvmGetRegs = 0x8090ae81 kvmSetRegs = 0x4090ae82 kvmSetUserMemoryRegion = 1075883590 + kvmSetTSSAddr = 0xae47 + kvmSetIdentityMapAddr = 0x4008AE48 + kvmCreateIRQChip = 0xAE60 + kvmCreatePIT2 = 0x4040AE77 + kvmGetSupportedCPUID = 0xC008AE05 + kvmSetCPUID2 = 0x4008AE90 EXITUNKNOWN = 0 EXITEXCEPTION = 1 @@ -42,6 +48,7 @@ const ( EXITIOOUT = 1 numInterrupts = 0x100 + CPUIDFeatures = 0x40000001 ) type Regs struct { @@ -212,6 +219,68 @@ func SetUserMemoryRegion(vmFd uintptr, region *UserspaceMemoryRegion) error { return err } +func SetTSSAddr(vmFd uintptr) error { + _, err := ioctl(vmFd, kvmSetTSSAddr, 0xffffd000) + + return err +} + +func SetIdentityMapAddr(vmFd uintptr) error { + var mapAddr uint64 = 0xffffc000 + _, err := ioctl(vmFd, kvmSetIdentityMapAddr, uintptr(unsafe.Pointer(&mapAddr))) + + return err +} + +func CreateIRQChip(vmFd uintptr) error { + _, err := ioctl(vmFd, kvmCreateIRQChip, 0) + + return err +} + +type PitConfig struct { + Flags uint32 + _ [15]uint32 +} + +func CreatePIT2(vmFd uintptr) error { + pit := PitConfig{ + Flags: 0, + } + _, err := ioctl(vmFd, kvmCreatePIT2, uintptr(unsafe.Pointer(&pit))) + + return err +} + +type CPUID struct { + Nent uint32 + Padding uint32 + Entries [100]CPUIDEntry2 +} + +type CPUIDEntry2 struct { + Function uint32 + Index uint32 + Flags uint32 + Eax uint32 + Ebx uint32 + Ecx uint32 + Edx uint32 + Padding [3]uint32 +} + +func GetSupportedCPUID(kvmFd uintptr, kvmCPUID *CPUID) error { + _, err := ioctl(kvmFd, kvmGetSupportedCPUID, uintptr(unsafe.Pointer(kvmCPUID))) + + return err +} + +func SetCPUID2(vcpuFd uintptr, kvmCPUID *CPUID) error { + _, err := ioctl(vcpuFd, kvmSetCPUID2, uintptr(unsafe.Pointer(kvmCPUID))) + + return err +} + const ( memSize = 1 << 30 diff --git a/kvm/kvm_test.go b/kvm/kvm_test.go index ff2b49e..13577cb 100644 --- a/kvm/kvm_test.go +++ b/kvm/kvm_test.go @@ -33,6 +33,51 @@ func TestCreateVM(t *testing.T) { t.Fatal(err) } + vmFd, err := kvm.CreateVM(devKVM.Fd()) + if err != nil { + t.Fatal(err) + } + + if err = kvm.SetTSSAddr(vmFd); err != nil { + t.Fatal(err) + } + + if err = kvm.SetIdentityMapAddr(vmFd); err != nil { + t.Fatal(err) + } + + vcpuFd, err := kvm.CreateVCPU(vmFd) + if err != nil { + t.Fatal(err) + } + + CPUID := kvm.CPUID{} + CPUID.Nent = 100 + + if err = kvm.GetSupportedCPUID(devKVM.Fd(), &CPUID); err != nil { + t.Fatal(err) + } + + for i := 0; i < 100; i++ { + CPUID.Entries[i].Eax = kvm.CPUIDFeatures + CPUID.Entries[i].Ebx = 0x4b4d564b // KVMK + CPUID.Entries[i].Ecx = 0x564b4d56 // VMKV + CPUID.Entries[i].Edx = 0x4d // M + } + + if err = kvm.SetCPUID2(vcpuFd, &CPUID); err != nil { + t.Fatal(err) + } +} + +func TestCPUID(t *testing.T) { + t.Parallel() + + devKVM, err := os.OpenFile("/dev/kvm", os.O_RDWR, 0644) + if err != nil { + t.Fatal(err) + } + defer devKVM.Close() _, err = kvm.CreateVM(devKVM.Fd()) @@ -56,6 +101,16 @@ func TestCreateVCPU(t *testing.T) { t.Fatal(err) } + err = kvm.CreateIRQChip(vmFd) + if err != nil { + t.Fatal(err) + } + + err = kvm.CreatePIT2(vmFd) + if err != nil { + t.Fatal(err) + } + vcpuFd, err := kvm.CreateVCPU(vmFd) if err != nil { t.Fatal(err)